From b069e5d5386a58dd5ca981d373646bd7a1fa63a2 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Wed, 7 Dec 2011 05:16:30 +0000 Subject: [PATCH] [Usp10] - Sync up to wine head. This will be needed for edit controls. Waiting for Pierres patched to be added! svn path=/trunk/; revision=54603 --- reactos/dll/win32/usp10/CMakeLists.txt | 6 +- reactos/dll/win32/usp10/bidi.c | 75 +- reactos/dll/win32/usp10/breaking.c | 410 ++++ reactos/dll/win32/usp10/indic.c | 378 +++ reactos/dll/win32/usp10/indicsyllable.c | 341 +++ reactos/dll/win32/usp10/linebreak.c | 862 +++++++ reactos/dll/win32/usp10/mirror.c | 2 +- reactos/dll/win32/usp10/shape.c | 2838 +++++++++++++++++++++- reactos/dll/win32/usp10/shaping.c | 1111 +-------- reactos/dll/win32/usp10/usp10.c | 2514 ++++++++++++++----- reactos/dll/win32/usp10/usp10.rbuild | 6 + reactos/dll/win32/usp10/usp10.spec | 11 +- reactos/dll/win32/usp10/usp10_internal.h | 121 +- reactos/dll/win32/usp10/usp10_ros.diff | 26 +- reactos/include/psdk/usp10.h | 53 +- reactos/include/psdk/winnt.h | 1 + 16 files changed, 6923 insertions(+), 1832 deletions(-) create mode 100644 reactos/dll/win32/usp10/breaking.c create mode 100644 reactos/dll/win32/usp10/indic.c create mode 100644 reactos/dll/win32/usp10/indicsyllable.c create mode 100644 reactos/dll/win32/usp10/linebreak.c diff --git a/reactos/dll/win32/usp10/CMakeLists.txt b/reactos/dll/win32/usp10/CMakeLists.txt index 17b66b15783..6d2ac1d1b41 100644 --- a/reactos/dll/win32/usp10/CMakeLists.txt +++ b/reactos/dll/win32/usp10/CMakeLists.txt @@ -6,6 +6,10 @@ spec2def(usp10.dll usp10.spec) list(APPEND SOURCE bidi.c + breaking.c + indic.c + indicsyllable.c + linebreak.c usp10.c mirror.c shape.c @@ -19,7 +23,7 @@ set_module_type(usp10 win32dll) target_link_libraries(usp10 wine) -add_importlibs(usp10 gdi32 msvcrt kernel32 ntdll) +add_importlibs(usp10 advapi32 user32 gdi32 msvcrt kernel32 ntdll) add_importlib_target(usp10.spec) add_cd_file(TARGET usp10 DESTINATION reactos/system32 FOR all) diff --git a/reactos/dll/win32/usp10/bidi.c b/reactos/dll/win32/usp10/bidi.c index 9c5884d2602..a2edfa6c730 100644 --- a/reactos/dll/win32/usp10/bidi.c +++ b/reactos/dll/win32/usp10/bidi.c @@ -289,11 +289,11 @@ static int resolveExplicit(int level, int dir, WORD *pcls, WORD *plevel, int cch enum states /* possible states */ { - xa, /* arabic letter */ + xa, /* Arabic letter */ xr, /* right letter */ xl, /* left letter */ - ao, /* arabic lett. foll by ON */ + ao, /* Arabic lett. foll by ON */ ro, /* right lett. foll by ON */ lo, /* left lett. foll by ON */ @@ -301,10 +301,10 @@ enum states /* possible states */ lt, /* ET following L */ cn, /* EN, AN following AL */ - ra, /* arabic number foll R */ - re, /* european number foll R */ - la, /* arabic number foll L */ - le, /* european number foll L */ + ra, /* Arabic number foll R */ + re, /* European number foll R */ + la, /* Arabic number foll L */ + le, /* European number foll L */ ac, /* CS following cn */ rc, /* CS following ra */ @@ -319,11 +319,11 @@ enum states /* possible states */ static const int stateWeak[][10] = { /* N, L, R, AN, EN, AL,NSM, CS, ES, ET */ -/*xa*/ { ao, xl, xr, cn, cn, xa, xa, ao, ao, ao }, /* arabic letter */ +/*xa*/ { ao, xl, xr, cn, cn, xa, xa, ao, ao, ao }, /* Arabic letter */ /*xr*/ { ro, xl, xr, ra, re, xa, xr, ro, ro, rt }, /* right letter */ /*xl*/ { lo, xl, xr, la, le, xa, xl, lo, lo, lt }, /* left letter */ -/*ao*/ { ao, xl, xr, cn, cn, xa, ao, ao, ao, ao }, /* arabic lett. foll by ON*/ +/*ao*/ { ao, xl, xr, cn, cn, xa, ao, ao, ao, ao }, /* Arabic lett. foll by ON*/ /*ro*/ { ro, xl, xr, ra, re, xa, ro, ro, ro, rt }, /* right lett. foll by ON */ /*lo*/ { lo, xl, xr, la, le, xa, lo, lo, lo, lt }, /* left lett. foll by ON */ @@ -331,10 +331,10 @@ static const int stateWeak[][10] = /*lt*/ { lo, xl, xr, la, le, xa, lt, lo, lo, lt }, /* ET following L */ /*cn*/ { ao, xl, xr, cn, cn, xa, cn, ac, ao, ao }, /* EN, AN following AL */ -/*ra*/ { ro, xl, xr, ra, re, xa, ra, rc, ro, rt }, /* arabic number foll R */ -/*re*/ { ro, xl, xr, ra, re, xa, re, rs, rs,ret }, /* european number foll R */ -/*la*/ { lo, xl, xr, la, le, xa, la, lc, lo, lt }, /* arabic number foll L */ -/*le*/ { lo, xl, xr, la, le, xa, le, ls, ls,let }, /* european number foll L */ +/*ra*/ { ro, xl, xr, ra, re, xa, ra, rc, ro, rt }, /* Arabic number foll R */ +/*re*/ { ro, xl, xr, ra, re, xa, re, rs, rs,ret }, /* European number foll R */ +/*la*/ { lo, xl, xr, la, le, xa, la, lc, lo, lt }, /* Arabic number foll L */ +/*le*/ { lo, xl, xr, la, le, xa, le, ls, ls,let }, /* European number foll L */ /*ac*/ { ao, xl, xr, cn, cn, xa, ao, ao, ao, ao }, /* CS following cn */ /*rc*/ { ro, xl, xr, ra, re, xa, ro, ro, ro, rt }, /* CS following ra */ @@ -376,11 +376,11 @@ enum actions /* possible actions */ static const int actionWeak[][10] = { /* N, L, R, AN, EN, AL, NSM, CS, ES, ET */ -/*xa*/ { xxx, xxx, xxx, xxx, xxA, xxR, xxR, xxN, xxN, xxN }, /* arabic letter */ +/*xa*/ { xxx, xxx, xxx, xxx, xxA, xxR, xxR, xxN, xxN, xxN }, /* Arabic letter */ /*xr*/ { xxx, xxx, xxx, xxx, xxE, xxR, xxR, xxN, xxN, xIx }, /* right letter */ /*xl*/ { xxx, xxx, xxx, xxx, xxL, xxR, xxL, xxN, xxN, xIx }, /* left letter */ -/*ao*/ { xxx, xxx, xxx, xxx, xxA, xxR, xxN, xxN, xxN, xxN }, /* arabic lett. foll by ON */ +/*ao*/ { xxx, xxx, xxx, xxx, xxA, xxR, xxN, xxN, xxN, xxN }, /* Arabic lett. foll by ON */ /*ro*/ { xxx, xxx, xxx, xxx, xxE, xxR, xxN, xxN, xxN, xIx }, /* right lett. foll by ON */ /*lo*/ { xxx, xxx, xxx, xxx, xxL, xxR, xxN, xxN, xxN, xIx }, /* left lett. foll by ON */ @@ -388,10 +388,10 @@ static const int actionWeak[][10] = /*lt*/ { Nxx, Nxx, Nxx, Nxx, LxL, NxR, xIx, NxN, NxN, xIx }, /* ET following L */ /*cn*/ { xxx, xxx, xxx, xxx, xxA, xxR, xxA, xIx, xxN, xxN }, /* EN, AN following AL */ -/*ra*/ { xxx, xxx, xxx, xxx, xxE, xxR, xxA, xIx, xxN, xIx }, /* arabic number foll R */ -/*re*/ { xxx, xxx, xxx, xxx, xxE, xxR, xxE, xIx, xIx, xxE }, /* european number foll R */ -/*la*/ { xxx, xxx, xxx, xxx, xxL, xxR, xxA, xIx, xxN, xIx }, /* arabic number foll L */ -/*le*/ { xxx, xxx, xxx, xxx, xxL, xxR, xxL, xIx, xIx, xxL }, /* european number foll L */ +/*ra*/ { xxx, xxx, xxx, xxx, xxE, xxR, xxA, xIx, xxN, xIx }, /* Arabic number foll R */ +/*re*/ { xxx, xxx, xxx, xxx, xxE, xxR, xxE, xIx, xIx, xxE }, /* European number foll R */ +/*la*/ { xxx, xxx, xxx, xxx, xxL, xxR, xxA, xIx, xxN, xIx }, /* Arabic number foll L */ +/*le*/ { xxx, xxx, xxx, xxx, xxL, xxR, xxL, xIx, xIx, xxL }, /* European number foll L */ /*ac*/ { Nxx, Nxx, Nxx, Axx, AxA, NxR, NxN, NxN, NxN, NxN }, /* CS following cn */ /*rc*/ { Nxx, Nxx, Nxx, Axx, NxE, NxR, NxN, NxN, NxN, NIx }, /* CS following ra */ @@ -883,3 +883,42 @@ int BIDI_ReorderL2vLevel(int level, int *pIndexs, const BYTE* plevel, int cch, B return ich; } + +BOOL BIDI_GetStrengths(LPCWSTR lpString, INT uCount, const SCRIPT_CONTROL *c, + WORD* lpStrength) +{ + int i; + classify(lpString, lpStrength, uCount, c); + + for ( i = 0; i < uCount; i++) + { + switch(lpStrength[i]) + { + case L: + case LRE: + case LRO: + case R: + case AL: + case RLE: + case RLO: + lpStrength[i] = BIDI_STRONG; + break; + case PDF: + case EN: + case ES: + case ET: + case AN: + case CS: + case BN: + lpStrength[i] = BIDI_WEAK; + break; + case B: + case S: + case WS: + case ON: + default: /* Neutrals and NSM */ + lpStrength[i] = BIDI_NEUTRAL; + } + } + return TRUE; +} diff --git a/reactos/dll/win32/usp10/breaking.c b/reactos/dll/win32/usp10/breaking.c new file mode 100644 index 00000000000..3efc3dac553 --- /dev/null +++ b/reactos/dll/win32/usp10/breaking.c @@ -0,0 +1,410 @@ +/* + * Implementation of line breaking algorithm for the Uniscribe Script Processor + * + * Copyright 2011 CodeWeavers, Aric Stewart + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +#include "config.h" +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "wingdi.h" +#include "winnls.h" +#include "usp10.h" +#include "winternl.h" + +#include "wine/debug.h" +#include "usp10_internal.h" + +WINE_DEFAULT_DEBUG_CHANNEL(uniscribe); + +extern const unsigned short wine_linebreak_table[]; + +enum breaking_types { b_BK=1, b_CR, b_LF, b_CM, b_SG, b_GL, b_CB, b_SP, b_ZW, b_NL, b_WJ, b_JL, b_JV, b_JT, b_H2, b_H3, b_XX, b_OP, b_CL, b_CP, b_QU, b_NS, b_EX, b_SY, b_IS, b_PR, b_PO, b_NU, b_AL, b_ID, b_IN, b_HY, b_BB, b_BA, b_SA, b_AI, b_B2}; + +enum breaking_class {b_r=1, b_s, b_x}; + +static void debug_output_breaks(const short* breaks, int count) +{ + if (TRACE_ON(uniscribe)) + { + int i; + TRACE("["); + for (i = 0; i < count && i < 200; i++) + { + switch (breaks[i]) + { + case b_x: TRACE("x"); break; + case b_r: TRACE("!"); break; + case b_s: TRACE("+"); break; + default: TRACE("*"); + } + } + if (i == 200) + TRACE("..."); + TRACE("]\n"); + } +} + +static inline void else_break(short* before, short class) +{ + if (*before == 0) *before = class; +} + +void BREAK_line(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la) +{ + int i,j; + short *break_class; + short *break_before; + + TRACE("In %s\n",debugstr_wn(chars,count)); + + break_class = HeapAlloc(GetProcessHeap(),0, count * sizeof(short)); + break_before = HeapAlloc(GetProcessHeap(),0, count * sizeof(short)); + + for (i = 0; i < count; i++) + { + break_class[i] = get_table_entry( wine_linebreak_table, chars[i] ); + break_before[i] = 0; + + memset(&la[i],0,sizeof(SCRIPT_LOGATTR)); + + la[i].fCharStop = TRUE; + switch (break_class[i]) + { + case b_BK: + case b_ZW: + case b_SP: + la[i].fWhiteSpace = TRUE; + break; + case b_CM: + la[i].fCharStop = FALSE; + } + } + + /* LB1 */ + /* TODO: Have outside algorithms for these scripts */ + for (i = 0; i < count; i++) + { + switch(break_class[i]) + { + case b_AI: + case b_SA: + case b_SG: + case b_XX: + break_class[i] = b_AL; + } + } + + /* LB2 - LB3 */ + break_before[0] = b_x; + for (i = 0; i < count; i++) + { + switch(break_class[i]) + { + /* LB4 - LB6 */ + case b_CR: + if (i < count-1 && break_class[i+1] == b_LF) + { + else_break(&break_before[i],b_x); + else_break(&break_before[i+1],b_x); + break; + } + case b_LF: + case b_NL: + case b_BK: + if (i < count-1) else_break(&break_before[i+1],b_r); + else_break(&break_before[i],b_x); + break; + /* LB7 */ + case b_SP: + else_break(&break_before[i],b_x); + break; + case b_ZW: + else_break(&break_before[i],b_x); + /* LB8 */ + while (i < count-1 && break_class[i+1] == b_SP) + i++; + else_break(&break_before[i],b_s); + break; + } + } + + debug_output_breaks(break_before,count); + + /* LB9 - LB10 */ + for (i = 0; i < count; i++) + { + if (break_class[i] == b_CM) + { + if (i > 0) + { + switch (break_class[i-1]) + { + case b_SP: + case b_BK: + case b_CR: + case b_LF: + case b_NL: + case b_ZW: + break_class[i] = b_AL; + break; + default: + break_class[i] = break_class[i-1]; + } + } + else break_class[i] = b_AL; + } + } + + for (i = 0; i < count; i++) + { + switch(break_class[i]) + { + /* LB11 */ + case b_WJ: + else_break(&break_before[i],b_x); + if (i < count-1) + else_break(&break_before[i+1],b_x); + break; + /* LB12 */ + case b_GL: + if (i < count-1) + else_break(&break_before[i+1],b_x); + /* LB12a */ + if (i > 0) + { + if (break_class[i-1] != b_SP && + break_class[i-1] != b_BA && + break_class[i-1] != b_HY) + else_break(&break_before[i],b_x); + } + break; + /* LB13 */ + case b_CL: + case b_CP: + case b_EX: + case b_IS: + case b_SY: + else_break(&break_before[i],b_x); + break; + /* LB14 */ + case b_OP: + while (i < count-1 && break_class[i+1] == b_SP) + { + else_break(&break_before[i+1],b_x); + i++; + } + else_break(&break_before[i+1],b_x); + break; + /* LB15 */ + case b_QU: + j = i+1; + while (j < count-1 && break_class[j] == b_SP) + j++; + if (break_class[j] == b_OP) + { + for (; j > i; j--) + else_break(&break_before[j],b_x); + } + break; + /* LB16 */ + case b_NS: + j = i-1; + while(j > 0 && break_class[j] == b_SP) + j--; + if (break_class[j] == b_CL || break_class[j] == b_CP) + { + for (j++; j <= i; j++) + else_break(&break_before[j],b_x); + } + break; + /* LB17 */ + case b_B2: + j = i+1; + while (j < count && break_class[j] == b_SP) + j++; + if (break_class[j] == b_B2) + { + for (; j > i; j--) + else_break(&break_before[j],b_x); + } + break; + } + } + + debug_output_breaks(break_before,count); + + for (i = 0; i < count; i++) + { + switch(break_class[i]) + { + /* LB18 */ + case b_SP: + if (i < count-1) + else_break(&break_before[i+1],b_s); + break; + /* LB19 */ + case b_QU: + else_break(&break_before[i],b_x); + if (i < count-1) + else_break(&break_before[i+1],b_x); + break; + /* LB20 */ + case b_CB: + else_break(&break_before[i],b_s); + if (i < count-1) + else_break(&break_before[i+1],b_s); + /* LB21 */ + case b_BA: + case b_HY: + case b_NS: + else_break(&break_before[i],b_x); + break; + case b_BB: + if (i < count-1) + else_break(&break_before[i+1],b_x); + break; + /* LB22 */ + case b_IN: + if (i > 0) + { + switch (break_class[i-1]) + { + case b_AL: + case b_ID: + case b_IN: + case b_NU: + else_break(&break_before[i], b_x); + } + } + break; + } + + if (i < count-1) + { + /* LB23 */ + if ((break_class[i] == b_ID && break_class[i+1] == b_PO) || + (break_class[i] == b_AL && break_class[i+1] == b_NU) || + (break_class[i] == b_NU && break_class[i+1] == b_AL)) + else_break(&break_before[i+1],b_x); + /* LB24 */ + if ((break_class[i] == b_PR && break_class[i+1] == b_ID) || + (break_class[i] == b_PR && break_class[i+1] == b_AL) || + (break_class[i] == b_PO && break_class[i+1] == b_AL)) + else_break(&break_before[i+1],b_x); + + /* LB25 */ + if ((break_class[i] == b_CL && break_class[i+1] == b_PO) || + (break_class[i] == b_CP && break_class[i+1] == b_PO) || + (break_class[i] == b_CL && break_class[i+1] == b_PR) || + (break_class[i] == b_CP && break_class[i+1] == b_PR) || + (break_class[i] == b_NU && break_class[i+1] == b_PO) || + (break_class[i] == b_NU && break_class[i+1] == b_PR) || + (break_class[i] == b_PO && break_class[i+1] == b_OP) || + (break_class[i] == b_PO && break_class[i+1] == b_NU) || + (break_class[i] == b_PR && break_class[i+1] == b_OP) || + (break_class[i] == b_PR && break_class[i+1] == b_NU) || + (break_class[i] == b_HY && break_class[i+1] == b_NU) || + (break_class[i] == b_IS && break_class[i+1] == b_NU) || + (break_class[i] == b_NU && break_class[i+1] == b_NU) || + (break_class[i] == b_SY && break_class[i+1] == b_NU)) + else_break(&break_before[i+1],b_x); + + /* LB26 */ + if (break_class[i] == b_JL) + { + switch (break_class[i+1]) + { + case b_JL: + case b_JV: + case b_H2: + case b_H3: + else_break(&break_before[i+1],b_x); + } + } + if ((break_class[i] == b_JV || break_class[i] == b_H2) && + (break_class[i+1] == b_JV || break_class[i+1] == b_JT)) + else_break(&break_before[i+1],b_x); + if ((break_class[i] == b_JT || break_class[i] == b_H3) && + break_class[i+1] == b_JT) + else_break(&break_before[i+1],b_x); + + /* LB27 */ + switch (break_class[i]) + { + case b_JL: + case b_JV: + case b_JT: + case b_H2: + case b_H3: + if (break_class[i+1] == b_IN || break_class[i+1] == b_PO) + else_break(&break_before[i+1],b_x); + } + if (break_class[i] == b_PO) + { + switch (break_class[i+1]) + { + case b_JL: + case b_JV: + case b_JT: + case b_H2: + case b_H3: + else_break(&break_before[i+1],b_x); + } + } + + /* LB28 */ + if (break_class[i] == b_AL && break_class[i+1] == b_AL) + else_break(&break_before[i+1],b_x); + + /* LB29 */ + if (break_class[i] == b_IS && break_class[i+1] == b_AL) + else_break(&break_before[i+1],b_x); + + /* LB30 */ + if ((break_class[i] == b_AL || break_class[i] == b_NU) && + break_class[i+1] == b_OP) + else_break(&break_before[i+1],b_x); + if (break_class[i] == b_CP && + (break_class[i+1] == b_AL || break_class[i] == b_NU)) + else_break(&break_before[i+1],b_x); + } + } + debug_output_breaks(break_before,count); + + /* LB31 */ + for (i = 0; i < count-1; i++) + else_break(&break_before[i+1],b_s); + + debug_output_breaks(break_before,count); + for (i = 0; i < count; i++) + { + if (break_before[i] != b_x) + { + la[i].fSoftBreak = TRUE; + la[i].fWordStop = TRUE; + } + } + + HeapFree(GetProcessHeap(), 0, break_before); + HeapFree(GetProcessHeap(), 0, break_class); +} diff --git a/reactos/dll/win32/usp10/indic.c b/reactos/dll/win32/usp10/indic.c new file mode 100644 index 00000000000..df2a977e8ad --- /dev/null +++ b/reactos/dll/win32/usp10/indic.c @@ -0,0 +1,378 @@ +/* + * Implementation of Indic Syllables for the Uniscribe Script Processor + * + * Copyright 2011 CodeWeavers, Aric Stewart + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + */ +#include "config.h" +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "wingdi.h" +#include "winnls.h" +#include "usp10.h" +#include "winternl.h" + +#include "wine/debug.h" +#include "usp10_internal.h" + +WINE_DEFAULT_DEBUG_CHANNEL(uniscribe); + +static void debug_output_string(LPCWSTR str, int cChar, lexical_function f) +{ + int i; + if (TRACE_ON(uniscribe)) + { + for (i = 0; i < cChar; i++) + { + switch (f(str[i])) + { + case lex_Consonant: TRACE("C"); break; + case lex_Ra: TRACE("Ra"); break; + case lex_Vowel: TRACE("V"); break; + case lex_Nukta: TRACE("N"); break; + case lex_Halant: TRACE("H"); break; + case lex_ZWNJ: TRACE("Zwnj"); break; + case lex_ZWJ: TRACE("Zwj"); break; + case lex_Matra_post: TRACE("Mp");break; + case lex_Matra_above: TRACE("Ma");break; + case lex_Matra_below: TRACE("Mb");break; + case lex_Matra_pre: TRACE("Mm");break; + case lex_Modifier: TRACE("Sm"); break; + case lex_Vedic: TRACE("Vd"); break; + case lex_Anudatta: TRACE("A"); break; + case lex_Composed_Vowel: TRACE("t"); break; + default: + TRACE("X"); break; + } + } + TRACE("\n"); + } +} + +static inline BOOL is_matra( int type ) +{ + return (type == lex_Matra_above || type == lex_Matra_below || + type == lex_Matra_pre || type == lex_Matra_post || + type == lex_Composed_Vowel); +} + +static inline BOOL is_joiner( int type ) +{ + return (type == lex_ZWJ || type == lex_ZWNJ); +} + +static INT consonant_header(LPCWSTR input, INT cChar, INT start, INT next, + lexical_function lex) +{ + if (!is_consonant( lex(input[next]) )) return -1; + next++; + if ((next < cChar) && lex(input[next]) == lex_Nukta) + next++; + if ((next < cChar) && lex(input[next])==lex_Halant) + { + next++; + if((next < cChar) && is_joiner( lex(input[next]) )) + next++; + if ((next < cChar) && is_consonant( lex(input[next]) )) + return next; + } + else if ((next < cChar) && is_joiner( lex(input[next]) ) && lex(input[next+1])==lex_Halant) + { + next+=2; + if ((next < cChar) && is_consonant( lex(input[next]) )) + return next; + } + return -1; +} + +static INT parse_consonant_syllable(LPCWSTR input, INT cChar, INT start, + INT *main, INT next, lexical_function lex) +{ + int check; + int headers = 0; + do + { + check = consonant_header(input,cChar,start,next,lex); + if (check != -1) + { + next = check; + headers++; + } + } while (check != -1); + if (headers || is_consonant( lex(input[next]) )) + { + *main = next; + next++; + } + else + return -1; + if ((next < cChar) && lex(input[next]) == lex_Nukta) + next++; + if ((next < cChar) && lex(input[next]) == lex_Anudatta) + next++; + + if ((next < cChar) && lex(input[next]) == lex_Halant) + { + next++; + if((next < cChar) && is_joiner( lex(input[next]) )) + next++; + } + else if (next < cChar) + { + while((next < cChar) && is_matra( lex(input[next]) )) + next++; + if ((next < cChar) && lex(input[next]) == lex_Nukta) + next++; + if ((next < cChar) && lex(input[next]) == lex_Halant) + next++; + } + if ((next < cChar) && lex(input[next]) == lex_Modifier) + next++; + if ((next < cChar) && lex(input[next]) == lex_Vedic) + next++; + return next; +} + +static INT parse_vowel_syllable(LPCWSTR input, INT cChar, INT start, + INT next, lexical_function lex) +{ + if ((next < cChar) && lex(input[next]) == lex_Nukta) + next++; + if ((next < cChar) && is_joiner( lex(input[next]) ) && lex(input[next+1])==lex_Halant && is_consonant( lex(input[next+2]) )) + next+=3; + else if ((next < cChar) && lex(input[next])==lex_Halant && is_consonant( lex(input[next+1]) )) + next+=2; + else if ((next < cChar) && lex(input[next])==lex_ZWJ && is_consonant( lex(input[next+1]) )) + next+=2; + + if ((next < cChar) && is_matra( lex(input[next]) )) + { + while((next < cChar) && is_matra( lex(input[next]) )) + next++; + if ((next < cChar) && lex(input[next]) == lex_Nukta) + next++; + if ((next < cChar) && lex(input[next]) == lex_Halant) + next++; + } + + if ((next < cChar) && lex(input[next]) == lex_Modifier) + next++; + if ((next < cChar) && lex(input[next]) == lex_Vedic) + next++; + return next; +} + +static INT Indic_process_next_syllable( LPCWSTR input, INT cChar, INT start, INT* main, INT next, lexical_function lex ) +{ + if (lex(input[next])==lex_Vowel) + { + *main = next; + return parse_vowel_syllable(input, cChar, start, next+1, lex); + } + else if ((cChar > next+3) && lex(input[next]) == lex_Ra && lex(input[next+1]) == lex_Halant && lex(input[next+2]) == lex_Vowel) + { + *main = next+2; + return parse_vowel_syllable(input, cChar, start, next+3, lex); + } + + else if (start == next && lex(input[next])==lex_NBSP) + { + *main = next; + return parse_vowel_syllable(input, cChar, start, next+1, lex); + } + else if (start == next && (cChar > next+3) && lex(input[next]) == lex_Ra && lex(input[next+1]) == lex_Halant && lex(input[next+2]) == lex_NBSP) + { + *main = next+2; + return parse_vowel_syllable(input, cChar, start, next+3, lex); + } + + return parse_consonant_syllable(input, cChar, start, main, next, lex); +} + +static BOOL Consonent_is_post_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR pwChar, IndicSyllable *s, lexical_function lexical, BOOL modern) +{ + if (is_consonant(lexical(pwChar[s->base])) && s->base > s->start && lexical(pwChar[s->base-1]) == lex_Halant) + { + if (modern) + return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, &pwChar[s->base-1], 1, 2, "pstf") > 0); + else + { + WCHAR cc[2]; + cc[0] = pwChar[s->base]; + cc[1] = pwChar[s->base-1]; + return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, cc, 1, 2, "pstf") > 0); + } + } + return FALSE; +} + +static BOOL Consonent_is_below_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR pwChar, IndicSyllable *s, lexical_function lexical, BOOL modern) +{ + if (is_consonant(lexical(pwChar[s->base])) && s->base > s->start && lexical(pwChar[s->base-1]) == lex_Halant) + { + if (modern) + return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, &pwChar[s->base-1], 1, 2, "blwf") > 0); + else + { + WCHAR cc[2]; + cc[0] = pwChar[s->base]; + cc[1] = pwChar[s->base-1]; + return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, cc, 1, 2, "blwf") > 0); + } + } + return FALSE; +} + +static BOOL Consonent_is_pre_base_form(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR pwChar, IndicSyllable *s, lexical_function lexical, BOOL modern) +{ + if (is_consonant(lexical(pwChar[s->base])) && s->base > s->start && lexical(pwChar[s->base-1]) == lex_Halant) + { + if (modern) + return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, &pwChar[s->base-1], 1, 2, "pref") > 0); + else + { + WCHAR cc[2]; + cc[0] = pwChar[s->base]; + cc[1] = pwChar[s->base-1]; + return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, cc, 1, 2, "pref") > 0); + } + } + return FALSE; +} + +static BOOL Consonent_is_ralf(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR pwChar, IndicSyllable *s, lexical_function lexical) +{ + if ((lexical(pwChar[s->start])==lex_Ra) && s->end > s->start && lexical(pwChar[s->start+1]) == lex_Halant) + return (SHAPE_does_GSUB_feature_apply_to_chars(hdc, psa, psc, &pwChar[s->start], 1, 2, "rphf") > 0); + return FALSE; +} + +static int FindBaseConsonant(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR input, IndicSyllable *s, lexical_function lex, BOOL modern) +{ + int i; + BOOL blwf = FALSE; + BOOL pref = FALSE; + + /* remove ralf from consideration */ + if (Consonent_is_ralf(hdc, psa, psc, input, s, lex)) + { + s->ralf = s->start; + s->start+=2; + } + + /* try to find a base consonant */ + if (!is_consonant( lex(input[s->base]) )) + { + for (i = s->end; i >= s->start; i--) + if (is_consonant( lex(input[i]) )) + { + s->base = i; + break; + } + } + + while ((blwf = Consonent_is_below_base_form(hdc, psa, psc, input, s, lex, modern)) || Consonent_is_post_base_form(hdc, psa, psc, input, s, lex, modern) || (pref = Consonent_is_pre_base_form(hdc, psa, psc, input, s, lex, modern))) + { + if (blwf && s->blwf == -1) + s->blwf = s->base - 1; + if (pref && s->pref == -1) + s->pref = s->base - 1; + + for (i = s->base-1; i >= s->start; i--) + if (is_consonant( lex(input[i]) )) + { + s->base = i; + break; + } + } + + if (s->ralf >= 0) + s->start = s->ralf; + + if (s->ralf == s->base) + s->ralf = -1; + + return s->base; +} + +void Indic_ParseSyllables( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR input, const int cChar, IndicSyllable **syllables, int *syllable_count, lexical_function lex, BOOL modern) +{ + int index = 0; + int next = 0; + int center = 0; + + *syllable_count = 0; + + if (!lex) + { + ERR("Failure to have required functions\n"); + return; + } + + debug_output_string(input, cChar, lex); + while (next != -1) + { + while((next < cChar) && lex(input[next]) == lex_Generic) + next++; + index = next; + if (next >= cChar) + break; + next = Indic_process_next_syllable(input, cChar, 0, ¢er, index, lex); + if (next != -1) + { + if (*syllable_count) + *syllables = HeapReAlloc(GetProcessHeap(),0,*syllables, sizeof(IndicSyllable)*(*syllable_count+1)); + else + *syllables = HeapAlloc(GetProcessHeap(),0,sizeof(IndicSyllable)); + (*syllables)[*syllable_count].start = index; + (*syllables)[*syllable_count].base = center; + (*syllables)[*syllable_count].ralf = -1; + (*syllables)[*syllable_count].blwf = -1; + (*syllables)[*syllable_count].pref = -1; + (*syllables)[*syllable_count].end = next-1; + FindBaseConsonant(hdc, psa, psc, input, &(*syllables)[*syllable_count], lex, modern); + index = next; + *syllable_count = (*syllable_count)+1; + } + else if (index < cChar) + { + TRACE("Processing failed at %i\n",index); + next = ++index; + } + } + TRACE("Processed %i of %i characters into %i syllables\n",index,cChar,*syllable_count); +} + +void Indic_ReorderCharacters( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPWSTR input, int cChar, IndicSyllable **syllables, int *syllable_count, lexical_function lex, reorder_function reorder_f, BOOL modern) +{ + int i; + + if (!reorder_f) + { + ERR("Failure to have required functions\n"); + return; + } + + Indic_ParseSyllables(hdc, psa, psc, input, cChar, syllables, syllable_count, lex, modern); + for (i = 0; i < *syllable_count; i++) + reorder_f(input, &(*syllables)[i], lex); +} diff --git a/reactos/dll/win32/usp10/indicsyllable.c b/reactos/dll/win32/usp10/indicsyllable.c new file mode 100644 index 00000000000..0a10784b18c --- /dev/null +++ b/reactos/dll/win32/usp10/indicsyllable.c @@ -0,0 +1,341 @@ +/* Unicode Indic Syllabic Category */ +/* generated from http://www.unicode.org/Public/6.0.0/ucd/IndicSyllabicCategory.txt */ +/* and from http://www.unicode.org/Public/6.0.0/ucd/IndicMatraCategory.txt */ +/* DO NOT EDIT!! */ + +#include "wine/unicode.h" + +const unsigned short indic_syllabic_table[2624] = +{ + /* level 1 offsets */ + 0x0100, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0120, 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x0180, + 0x0190, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x01a0, + 0x0110, 0x01b0, 0x01c0, 0x01d0, 0x01e0, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x01f0, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0200, 0x0210, 0x0220, 0x0230, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + /* level 2 offsets */ + 0x0240, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, + 0x0250, 0x0250, 0x0260, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, + 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, + 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, + 0x0270, 0x0280, 0x0290, 0x02a0, 0x02b0, 0x02c0, 0x02d0, 0x02e0, + 0x02f0, 0x0300, 0x0310, 0x0320, 0x0330, 0x0340, 0x02d0, 0x0350, + 0x0360, 0x0300, 0x0310, 0x0370, 0x0380, 0x0390, 0x0250, 0x03a0, + 0x03b0, 0x03c0, 0x0310, 0x03d0, 0x03e0, 0x0250, 0x02d0, 0x0250, + 0x02f0, 0x0300, 0x0310, 0x03f0, 0x0400, 0x0410, 0x02d0, 0x0420, + 0x0430, 0x0440, 0x0450, 0x0460, 0x0470, 0x0480, 0x0250, 0x0250, + 0x0490, 0x04a0, 0x0310, 0x04b0, 0x04c0, 0x04d0, 0x02d0, 0x0250, + 0x04e0, 0x04a0, 0x0310, 0x04f0, 0x0500, 0x0510, 0x02d0, 0x0250, + 0x04e0, 0x04a0, 0x0290, 0x0520, 0x0530, 0x0480, 0x02d0, 0x0540, + 0x0550, 0x0560, 0x0290, 0x0570, 0x0580, 0x0590, 0x0250, 0x05a0, + 0x05b0, 0x0290, 0x05c0, 0x05d0, 0x05e0, 0x0250, 0x0250, 0x0250, + 0x05f0, 0x0600, 0x0610, 0x0620, 0x0630, 0x0640, 0x0250, 0x0250, + 0x0250, 0x0250, 0x0250, 0x0250, 0x0650, 0x0290, 0x0660, 0x0670, + 0x0680, 0x0690, 0x06a0, 0x06b0, 0x0250, 0x0250, 0x0250, 0x0250, + 0x0290, 0x0290, 0x06c0, 0x06d0, 0x0250, 0x06e0, 0x06f0, 0x0700, + 0x0710, 0x0720, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, + 0x0730, 0x0740, 0x0750, 0x0740, 0x0750, 0x0760, 0x0730, 0x0770, + 0x0290, 0x0290, 0x0780, 0x0790, 0x07a0, 0x07b0, 0x0250, 0x0250, + 0x07c0, 0x0660, 0x07d0, 0x07e0, 0x0250, 0x0290, 0x07f0, 0x0800, + 0x0250, 0x0250, 0x0250, 0x0810, 0x0820, 0x0250, 0x0250, 0x0250, + 0x0250, 0x0830, 0x0250, 0x0250, 0x0250, 0x0840, 0x0850, 0x0860, + 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, + 0x0870, 0x0250, 0x0250, 0x0880, 0x0890, 0x0250, 0x0250, 0x0250, + 0x08a0, 0x0250, 0x08b0, 0x0250, 0x0250, 0x0250, 0x08c0, 0x08d0, + 0x0250, 0x0250, 0x08e0, 0x08f0, 0x0250, 0x0250, 0x0250, 0x0250, + 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, + 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, + 0x0250, 0x0250, 0x0250, 0x0250, 0x0900, 0x0250, 0x0250, 0x0250, + 0x0910, 0x0250, 0x0920, 0x0250, 0x0250, 0x0250, 0x0930, 0x0940, + 0x0950, 0x0250, 0x0250, 0x0960, 0x0970, 0x0250, 0x0250, 0x0250, + 0x0250, 0x0250, 0x0250, 0x0250, 0x0980, 0x0990, 0x0250, 0x0250, + 0x09a0, 0x0250, 0x0250, 0x09b0, 0x09c0, 0x0250, 0x0250, 0x0250, + 0x0250, 0x0250, 0x09d0, 0x09e0, 0x09f0, 0x0250, 0x0250, 0x0a00, + 0x0250, 0x0250, 0x0250, 0x0a10, 0x0a20, 0x0250, 0x0250, 0x0250, + 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, + 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0250, 0x0a30, 0x0250, + /* values */ + 0x4d00, 0x8700, 0x8000, 0x8000, 0x7100, 0x7100, 0x7100, 0x7100, + 0x6900, 0x5900, 0x4800, 0x3f00, 0x3000, 0x1f00, 0x1300, 0x0a00, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0001, 0x0001, 0x0002, 0x0006, 0x0006, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x0507, 0x0107, 0x0004, 0x0003, 0x0107, 0x0207, + 0x0107, 0x0607, 0x0607, 0x0607, 0x0607, 0x0507, 0x0507, 0x0507, + 0x0507, 0x0107, 0x0107, 0x0107, 0x0107, 0x0605, 0x0207, 0x0107, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0507, 0x0607, 0x0607, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x0006, 0x0006, 0x0607, 0x0607, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, + 0x0000, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x0000, 0x0001, 0x0001, 0x0002, 0x0000, 0x0006, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0000, 0x0000, 0x0006, + 0x0006, 0x0000, 0x0000, 0x0006, 0x0006, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x0000, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x0000, 0x000a, 0x0000, 0x0000, 0x0000, 0x000a, 0x000a, + 0x000a, 0x000a, 0x0000, 0x0000, 0x0004, 0x0003, 0x0107, 0x0207, + 0x0107, 0x0607, 0x0607, 0x0607, 0x0607, 0x0000, 0x0000, 0x0207, + 0x0207, 0x0000, 0x0000, 0x0407, 0x0407, 0x0605, 0x000b, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0107, + 0x0000, 0x0000, 0x0000, 0x0000, 0x000a, 0x000a, 0x0000, 0x000a, + 0x000a, 0x000a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0001, 0x0001, 0x0002, 0x0000, 0x0006, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0000, 0x0000, 0x0000, 0x0000, 0x0006, + 0x000a, 0x0000, 0x000a, 0x000a, 0x0000, 0x000a, 0x000a, 0x0000, + 0x000a, 0x000a, 0x0000, 0x0000, 0x0004, 0x0000, 0x0107, 0x0207, + 0x0107, 0x0607, 0x0607, 0x0000, 0x0000, 0x0000, 0x0000, 0x0507, + 0x0507, 0x0000, 0x0000, 0x0507, 0x0507, 0x0605, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x000a, 0x000a, 0x000a, 0x000a, 0x0000, 0x000a, 0x0000, + 0x0001, 0x0000, 0x0009, 0x0009, 0x0000, 0x000e, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0001, 0x0001, 0x0002, 0x0000, 0x0006, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0000, 0x0006, + 0x0006, 0x0006, 0x0000, 0x0006, 0x0006, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x0000, 0x000a, 0x000a, 0x0000, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x0000, 0x0000, 0x0004, 0x0003, 0x0107, 0x0207, + 0x0107, 0x0607, 0x0607, 0x0607, 0x0607, 0x0507, 0x0000, 0x0507, + 0x0507, 0x0007, 0x0000, 0x0107, 0x0107, 0x0605, 0x0000, 0x0000, + 0x000a, 0x0000, 0x000a, 0x000a, 0x0000, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x0000, 0x0000, 0x0004, 0x0003, 0x0107, 0x0507, + 0x0107, 0x0607, 0x0607, 0x0607, 0x0607, 0x0000, 0x0000, 0x0207, + 0x0007, 0x0000, 0x0000, 0x0007, 0x0007, 0x0605, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0507, 0x0007, + 0x0000, 0x0000, 0x0000, 0x0000, 0x000a, 0x000a, 0x0000, 0x000a, + 0x0000, 0x000a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0001, 0x0011, 0x0000, 0x0006, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0000, 0x0000, 0x0000, 0x0006, 0x0006, + 0x0006, 0x0000, 0x0006, 0x0006, 0x0006, 0x000a, 0x0000, 0x0000, + 0x0000, 0x000a, 0x000a, 0x0000, 0x000a, 0x0000, 0x000a, 0x000a, + 0x0000, 0x0000, 0x0000, 0x000a, 0x000a, 0x0000, 0x0000, 0x0000, + 0x000a, 0x000a, 0x000a, 0x0000, 0x0000, 0x0000, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0107, 0x0107, + 0x0507, 0x0607, 0x0607, 0x0000, 0x0000, 0x0000, 0x0207, 0x0207, + 0x0207, 0x0000, 0x0407, 0x0407, 0x0407, 0x0505, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0107, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0001, 0x0001, 0x0002, 0x0000, 0x0006, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0000, 0x0006, 0x0006, + 0x0006, 0x0000, 0x0006, 0x0006, 0x0006, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x0000, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x0000, 0x0000, 0x0000, 0x0003, 0x0507, 0x0507, + 0x0507, 0x0107, 0x0107, 0x0107, 0x0107, 0x0000, 0x0507, 0x0507, + 0x0007, 0x0000, 0x0507, 0x0507, 0x0507, 0x0505, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0507, 0x0607, 0x0000, + 0x000a, 0x000a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0001, 0x0002, 0x0000, 0x0006, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0000, 0x0006, 0x0006, + 0x000a, 0x000a, 0x000a, 0x000a, 0x0000, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x0000, 0x0000, 0x0004, 0x0003, 0x0107, 0x0507, + 0x0007, 0x0107, 0x0107, 0x0107, 0x0107, 0x0000, 0x0507, 0x0807, + 0x0807, 0x0000, 0x0807, 0x0807, 0x0507, 0x0505, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0107, 0x0107, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x000a, 0x0000, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x0000, 0x0000, 0x0003, 0x0107, 0x0107, + 0x0107, 0x0107, 0x0107, 0x0607, 0x0607, 0x0000, 0x0207, 0x0207, + 0x0207, 0x0000, 0x0407, 0x0407, 0x0407, 0x0505, 0x000c, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x000b, 0x000b, 0x000b, 0x000b, 0x000b, 0x000b, + 0x0000, 0x0000, 0x0001, 0x0002, 0x0000, 0x0006, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0000, + 0x0000, 0x0000, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x0000, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x0000, 0x000a, 0x0000, 0x0000, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x0000, + 0x0000, 0x0000, 0x0505, 0x0000, 0x0000, 0x0000, 0x0000, 0x0107, + 0x0107, 0x0107, 0x0507, 0x0507, 0x0607, 0x0000, 0x0607, 0x0000, + 0x0107, 0x0207, 0x0007, 0x0207, 0x0407, 0x0407, 0x0407, 0x0107, + 0x0000, 0x0000, 0x0107, 0x0107, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x0000, + 0x0107, 0x0507, 0x0107, 0x0107, 0x0507, 0x0507, 0x0507, 0x0507, + 0x0607, 0x0607, 0x0605, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0307, 0x0307, 0x0307, 0x0307, 0x0307, 0x0107, 0x0000, 0x0507, + 0x0013, 0x0013, 0x0013, 0x0013, 0x0000, 0x0001, 0x0505, 0x0000, + 0x0000, 0x000a, 0x000a, 0x0000, 0x000a, 0x0000, 0x0000, 0x000a, + 0x000a, 0x0000, 0x000a, 0x0000, 0x0000, 0x000a, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x000a, 0x000a, 0x000a, 0x000a, + 0x0000, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x0000, 0x000a, 0x000a, 0x000a, 0x0000, 0x000a, 0x0000, 0x000a, + 0x0000, 0x0000, 0x000a, 0x000a, 0x0000, 0x000a, 0x000a, 0x0000, + 0x0107, 0x0507, 0x0107, 0x0107, 0x0507, 0x0507, 0x0507, 0x0507, + 0x0607, 0x0607, 0x0000, 0x0507, 0x000e, 0x000e, 0x0000, 0x0000, + 0x0307, 0x0307, 0x0307, 0x0307, 0x0307, 0x0000, 0x0000, 0x0000, + 0x0013, 0x0013, 0x0013, 0x0013, 0x0000, 0x0001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x000a, 0x000a, 0x0000, 0x0000, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x0000, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0607, 0x0507, 0x0007, 0x0607, 0x0607, 0x0707, 0x0707, + 0x0707, 0x0707, 0x0507, 0x0507, 0x0507, 0x0507, 0x0001, 0x0002, + 0x0507, 0x0007, 0x0001, 0x0001, 0x0605, 0x0003, 0x0000, 0x0000, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x000d, 0x000d, 0x000d, + 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, + 0x0000, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, + 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, + 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, + 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, + 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x0000, 0x0000, 0x0000, + 0x000a, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0107, 0x0107, 0x0507, 0x0507, 0x0607, + 0x0607, 0x0207, 0x0507, 0x0507, 0x0507, 0x0507, 0x0001, 0x0013, + 0x0002, 0x0e05, 0x0505, 0x000e, 0x000e, 0x000e, 0x000e, 0x000a, + 0x000a, 0x000a, 0x0006, 0x0006, 0x0006, 0x0006, 0x0107, 0x0107, + 0x0607, 0x0607, 0x000a, 0x000a, 0x000a, 0x000a, 0x000e, 0x000e, + 0x000e, 0x000a, 0x0107, 0x0013, 0x0013, 0x000a, 0x000a, 0x0107, + 0x0107, 0x0013, 0x0013, 0x0013, 0x0013, 0x0013, 0x000a, 0x000a, + 0x000a, 0x0507, 0x0507, 0x0507, 0x0507, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000e, 0x0107, 0x0207, 0x0507, 0x0507, 0x0013, + 0x0013, 0x0013, 0x0013, 0x0013, 0x0013, 0x0013, 0x000a, 0x0013, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0013, 0x0013, 0x0107, 0x0507, 0x0000, 0x0000, + 0x0006, 0x0006, 0x0006, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x0000, 0x000a, 0x000a, + 0x000a, 0x000a, 0x0507, 0x0607, 0x0605, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0006, 0x0006, 0x0006, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x0507, 0x0607, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x000a, 0x0000, 0x0507, 0x0607, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x000a, 0x000a, 0x000a, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0006, 0x0000, 0x0000, 0x0107, 0x0507, + 0x0507, 0x0507, 0x0507, 0x0607, 0x0607, 0x0607, 0x0007, 0x0007, + 0x0007, 0x0207, 0x0207, 0x0207, 0x0407, 0x0407, 0x0001, 0x0002, + 0x0107, 0x0014, 0x0014, 0x0000, 0x000c, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0505, 0x0e05, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0003, 0x0000, 0x0000, 0x0000, + 0x0009, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, + 0x0507, 0x0507, 0x0607, 0x0107, 0x0107, 0x0807, 0x0807, 0x0507, + 0x0507, 0x000d, 0x000d, 0x000d, 0x0000, 0x0000, 0x0000, 0x0000, + 0x000f, 0x000f, 0x0001, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f, + 0x000f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x000a, 0x000a, 0x000a, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, + 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0000, 0x0000, + 0x0012, 0x0012, 0x0012, 0x0012, 0x0012, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0200, 0x0200, 0x0200, + 0x0100, 0x0100, 0x0200, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0500, + 0x0600, 0x0200, 0x0100, 0x0200, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x000e, 0x000e, 0x000f, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0e05, 0x0107, 0x0507, 0x0100, 0x0100, 0x0500, 0x0500, 0x0500, + 0x0500, 0x0600, 0x0600, 0x0500, 0x0600, 0x0100, 0x0200, 0x0200, + 0x0200, 0x0200, 0x0200, 0x0500, 0x0500, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x000c, 0x0002, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0107, 0x0500, 0x0500, + 0x0600, 0x0600, 0x0600, 0x0007, 0x0007, 0x0000, 0x0200, 0x0200, + 0x0400, 0x0400, 0x0507, 0x0007, 0x0105, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x000c, 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x000d, 0x0000, 0x0000, 0x0500, 0x0600, 0x0200, 0x0100, + 0x0500, 0x0500, 0x0105, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, 0x0007, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0007, 0x0007, 0x0007, + 0x0000, 0x0000, 0x0100, 0x0100, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0100, 0x0200, + 0x0200, 0x0000, 0x0100, 0x0100, 0x0607, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0004, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0009, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0505, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0100, 0x0100, 0x0600, 0x0500, 0x0107, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x000d, 0x000a, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0001, 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x000f, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0605, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0600, + 0x0600, 0x0600, 0x0500, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, + 0x0000, 0x0000, 0x000f, 0x0105, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x000c, 0x0002, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0004, 0x0100, 0x0100, 0x0500, 0x0500, + 0x0600, 0x0600, 0x0200, 0x0200, 0x0507, 0x000d, 0x0000, 0x0000, + 0x0005, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0500, 0x0500, 0x0500, 0x0500, 0x0600, 0x0500, 0x0200, + 0x0200, 0x0500, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x000f, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x000f, 0x000f, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x000a, 0x0013, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0507, 0x0107, 0x0500, 0x0500, 0x0600, 0x0300, 0x0300, 0x0500, + 0x0500, 0x0000, 0x0100, 0x0300, 0x0300, 0x0100, 0x0507, 0x0013, + 0x0012, 0x0013, 0x0012, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0100, 0x0100, 0x0507, 0x0100, 0x0100, + 0x0607, 0x0100, 0x0100, 0x0000, 0x0013, 0x0605, 0x0000, 0x0000 +}; diff --git a/reactos/dll/win32/usp10/linebreak.c b/reactos/dll/win32/usp10/linebreak.c new file mode 100644 index 00000000000..96d680af484 --- /dev/null +++ b/reactos/dll/win32/usp10/linebreak.c @@ -0,0 +1,862 @@ +/* Unicode Line Break Properties */ +/* generated from http://www.unicode.org/Public/6.0.0/ucd/LineBreak.txt */ +/* DO NOT EDIT!! */ + +#include "wine/unicode.h" + +const unsigned short wine_linebreak_table[6800] = +{ + /* level 1 offsets */ + 0x0100, 0x0110, 0x0120, 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, + 0x0180, 0x0190, 0x01a0, 0x01b0, 0x01c0, 0x01d0, 0x01e0, 0x01f0, + 0x0200, 0x0210, 0x0220, 0x0230, 0x0240, 0x0110, 0x0250, 0x0260, + 0x0270, 0x0280, 0x0290, 0x02a0, 0x02b0, 0x02c0, 0x0110, 0x02d0, + 0x02e0, 0x02f0, 0x0300, 0x0310, 0x0320, 0x0330, 0x0340, 0x0350, + 0x0110, 0x0360, 0x0110, 0x0370, 0x0380, 0x0390, 0x03a0, 0x03b0, + 0x03c0, 0x03d0, 0x03e0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, + 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, + 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, + 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x0400, 0x03f0, 0x03f0, + 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, + 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, + 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, + 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, + 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, + 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, + 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, + 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, + 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, + 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, 0x03f0, + 0x0410, 0x03f0, 0x03f0, 0x03f0, 0x0420, 0x0110, 0x0430, 0x0440, + 0x0450, 0x0460, 0x0470, 0x0480, 0x0490, 0x04a0, 0x04b0, 0x04c0, + 0x04d0, 0x04e0, 0x04f0, 0x0490, 0x04a0, 0x04b0, 0x04c0, 0x04d0, + 0x04e0, 0x04f0, 0x0490, 0x04a0, 0x04b0, 0x04c0, 0x04d0, 0x04e0, + 0x04f0, 0x0490, 0x04a0, 0x04b0, 0x04c0, 0x04d0, 0x04e0, 0x04f0, + 0x0490, 0x04a0, 0x04b0, 0x04c0, 0x04d0, 0x04e0, 0x04f0, 0x0490, + 0x04a0, 0x04b0, 0x04c0, 0x04d0, 0x04e0, 0x04f0, 0x0490, 0x0500, + 0x0510, 0x0510, 0x0510, 0x0510, 0x0510, 0x0510, 0x0510, 0x0510, + 0x0520, 0x0520, 0x0520, 0x0520, 0x0520, 0x0520, 0x0520, 0x0520, + 0x0520, 0x0520, 0x0520, 0x0520, 0x0520, 0x0520, 0x0520, 0x0520, + 0x0520, 0x0520, 0x0520, 0x0520, 0x0520, 0x0520, 0x0520, 0x0520, + 0x0520, 0x03f0, 0x03f0, 0x0530, 0x0110, 0x0540, 0x0550, 0x0560, + /* level 2 offsets */ + 0x0570, 0x0580, 0x0590, 0x05a0, 0x05b0, 0x05c0, 0x05b0, 0x05d0, + 0x05e0, 0x0580, 0x05f0, 0x0600, 0x05b0, 0x0610, 0x05b0, 0x0610, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x0620, 0x0630, 0x05b0, 0x05b0, + 0x0580, 0x0580, 0x0580, 0x0580, 0x0640, 0x0650, 0x0660, 0x0670, + 0x0680, 0x05b0, 0x0690, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, + 0x06a0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, + 0x05b0, 0x05b0, 0x06b0, 0x06c0, 0x05b0, 0x06d0, 0x06c0, 0x05b0, + 0x06e0, 0x06f0, 0x0580, 0x0700, 0x0710, 0x05b0, 0x0720, 0x0730, + 0x0740, 0x0750, 0x05b0, 0x05b0, 0x0760, 0x0580, 0x0770, 0x0780, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x0790, 0x07a0, 0x07b0, + 0x07c0, 0x07d0, 0x05b0, 0x0580, 0x07e0, 0x05b0, 0x05b0, 0x05b0, + 0x05b0, 0x05b0, 0x07f0, 0x0800, 0x07b0, 0x05b0, 0x0760, 0x0810, + 0x05b0, 0x0820, 0x0830, 0x0840, 0x05b0, 0x0850, 0x0860, 0x0860, + 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, + 0x0870, 0x05b0, 0x05b0, 0x0880, 0x0580, 0x0890, 0x08a0, 0x08b0, + 0x08c0, 0x08d0, 0x08e0, 0x08f0, 0x0900, 0x0910, 0x0920, 0x0930, + 0x0940, 0x08d0, 0x08e0, 0x0950, 0x0960, 0x0970, 0x0980, 0x0990, + 0x09a0, 0x0690, 0x08e0, 0x09b0, 0x09c0, 0x09d0, 0x0920, 0x09e0, + 0x08c0, 0x08d0, 0x08e0, 0x09b0, 0x09f0, 0x0a00, 0x0920, 0x06b0, + 0x0a10, 0x0a20, 0x0a30, 0x0a40, 0x0a50, 0x0a60, 0x0980, 0x0a70, + 0x0a80, 0x0a90, 0x08e0, 0x0aa0, 0x0ab0, 0x0ac0, 0x0920, 0x0ad0, + 0x0ae0, 0x0a90, 0x08e0, 0x0af0, 0x0ab0, 0x0b00, 0x0920, 0x0b10, + 0x0ae0, 0x0a90, 0x05b0, 0x0b20, 0x0b30, 0x0b40, 0x0920, 0x0b50, + 0x0b60, 0x0b70, 0x05b0, 0x0b80, 0x0b90, 0x0ba0, 0x0860, 0x0bb0, + 0x0bc0, 0x0bd0, 0x0bd0, 0x0be0, 0x0bf0, 0x0c00, 0x0860, 0x0860, + 0x0c10, 0x0c20, 0x0c30, 0x0c40, 0x0c50, 0x0c60, 0x0860, 0x0860, + 0x0c70, 0x0c80, 0x07b0, 0x0c90, 0x08b0, 0x05b0, 0x0ca0, 0x0cb0, + 0x0cc0, 0x0cd0, 0x0580, 0x0ce0, 0x0cf0, 0x0d00, 0x0860, 0x0860, + 0x0bd0, 0x0bd0, 0x0bd0, 0x0bd0, 0x0d10, 0x0bd0, 0x0bd0, 0x0bd0, + 0x0bd0, 0x0d20, 0x05b0, 0x05b0, 0x0d30, 0x05b0, 0x05b0, 0x0ca0, + 0x0d40, 0x0d40, 0x0d40, 0x0d40, 0x0d40, 0x0d40, 0x0d50, 0x0d50, + 0x0d50, 0x0d50, 0x0d60, 0x0d70, 0x0d70, 0x0d70, 0x0d70, 0x0d70, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x0d80, 0x0d90, 0x05b0, 0x05b0, + 0x0d80, 0x05b0, 0x05b0, 0x0da0, 0x0db0, 0x0dc0, 0x05b0, 0x05b0, + 0x05b0, 0x0db0, 0x05b0, 0x05b0, 0x05b0, 0x0dd0, 0x0de0, 0x0ca0, + 0x05b0, 0x0df0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x0730, + 0x0e00, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, + 0x0e00, 0x0e10, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x0e20, 0x09d0, + 0x0e30, 0x0e40, 0x05b0, 0x0e50, 0x05b0, 0x0e60, 0x0e30, 0x0e70, + 0x0bd0, 0x0bd0, 0x0bd0, 0x0bd0, 0x0bd0, 0x0e80, 0x0e90, 0x0df0, + 0x0ea0, 0x0e90, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x06b0, + 0x05b0, 0x05b0, 0x0eb0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x0d30, + 0x05b0, 0x0ca0, 0x0ec0, 0x0ec0, 0x0ed0, 0x0bd0, 0x0ee0, 0x0ef0, + 0x0bd0, 0x0bd0, 0x0f00, 0x0bd0, 0x0f10, 0x0f20, 0x05b0, 0x05b0, + 0x05b0, 0x0f30, 0x0bd0, 0x0bd0, 0x0bd0, 0x0f40, 0x0bd0, 0x0f50, + 0x0e90, 0x0e90, 0x0ee0, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, + 0x0f60, 0x05b0, 0x05b0, 0x0f70, 0x0f80, 0x0f90, 0x0fa0, 0x0fb0, + 0x0fc0, 0x05b0, 0x0fd0, 0x0e90, 0x05b0, 0x05b0, 0x07f0, 0x0fe0, + 0x05b0, 0x05b0, 0x0f70, 0x0ff0, 0x1000, 0x07b0, 0x05b0, 0x1010, + 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x1020, 0x1030, 0x1040, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x0580, 0x0580, 0x1050, 0x1060, + 0x05b0, 0x1070, 0x05b0, 0x05b0, 0x1070, 0x1080, 0x05b0, 0x1090, + 0x05b0, 0x05b0, 0x05b0, 0x10a0, 0x10a0, 0x10b0, 0x05b0, 0x10c0, + 0x10d0, 0x10e0, 0x10f0, 0x1100, 0x1110, 0x1120, 0x1130, 0x1140, + 0x1150, 0x0ca0, 0x1160, 0x1170, 0x0860, 0x0580, 0x0580, 0x1180, + 0x1190, 0x11a0, 0x11b0, 0x05b0, 0x05b0, 0x11c0, 0x11d0, 0x11e0, + 0x11f0, 0x11e0, 0x05b0, 0x05b0, 0x05b0, 0x1200, 0x05b0, 0x05b0, + 0x1210, 0x1220, 0x1230, 0x1240, 0x1250, 0x1260, 0x1270, 0x05b0, + 0x1280, 0x1290, 0x12a0, 0x12b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, + 0x05b0, 0x1260, 0x12c0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x12d0, + 0x05b0, 0x05b0, 0x12e0, 0x0860, 0x0720, 0x0860, 0x12f0, 0x12f0, + 0x12f0, 0x12f0, 0x12f0, 0x12f0, 0x12f0, 0x12f0, 0x12f0, 0x1300, + 0x12f0, 0x12f0, 0x12f0, 0x12f0, 0x11d0, 0x12f0, 0x12f0, 0x1310, + 0x12f0, 0x1320, 0x1330, 0x1340, 0x1350, 0x1360, 0x1370, 0x05b0, + 0x1380, 0x1390, 0x05b0, 0x05b0, 0x13a0, 0x05b0, 0x13b0, 0x05b0, + 0x05b0, 0x13c0, 0x05b0, 0x13c0, 0x13d0, 0x12f0, 0x13e0, 0x12f0, + 0x06c0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x13f0, 0x1400, 0x1410, + 0x12f0, 0x1420, 0x05b0, 0x05b0, 0x1430, 0x05b0, 0x1440, 0x05b0, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, + 0x1450, 0x1460, 0x05b0, 0x05b0, 0x05b0, 0x1470, 0x05b0, 0x1480, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x0ca0, 0x1490, 0x0860, 0x0860, + 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, + 0x05b0, 0x05b0, 0x0840, 0x05b0, 0x05b0, 0x0840, 0x05b0, 0x05b0, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x14a0, 0x14b0, + 0x05b0, 0x05b0, 0x0d30, 0x05b0, 0x05b0, 0x05b0, 0x14c0, 0x14d0, + 0x05b0, 0x12e0, 0x14e0, 0x14e0, 0x14e0, 0x14e0, 0x0580, 0x0580, + 0x14f0, 0x1500, 0x1510, 0x1520, 0x0860, 0x0860, 0x0860, 0x0860, + 0x1530, 0x1540, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1550, + 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, + 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1560, 0x0860, 0x1570, + 0x1580, 0x1590, 0x15a0, 0x15b0, 0x15c0, 0x1530, 0x15d0, 0x1530, + 0x15e0, 0x15f0, 0x1600, 0x1530, 0x15d0, 0x1530, 0x15e0, 0x1610, + 0x1620, 0x1530, 0x1630, 0x1640, 0x1530, 0x1530, 0x1530, 0x1530, + 0x1650, 0x1530, 0x1530, 0x1660, 0x1530, 0x1530, 0x1550, 0x1670, + 0x1530, 0x1650, 0x1530, 0x1530, 0x1680, 0x1530, 0x1530, 0x1530, + 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1650, + 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, + 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, + 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, + 0x1530, 0x1530, 0x1530, 0x1530, 0x05b0, 0x05b0, 0x05b0, 0x05b0, + 0x1530, 0x1690, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, + 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, + 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, 0x1530, + 0x16a0, 0x1530, 0x1530, 0x1530, 0x16b0, 0x05b0, 0x05b0, 0x1010, + 0x16c0, 0x05b0, 0x16d0, 0x0860, 0x05b0, 0x05b0, 0x14a0, 0x16e0, + 0x05b0, 0x06b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x16f0, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, + 0x0840, 0x1700, 0x0df0, 0x0860, 0x0860, 0x0860, 0x0860, 0x1710, + 0x1720, 0x05b0, 0x1730, 0x1740, 0x05b0, 0x05b0, 0x05b0, 0x1750, + 0x1760, 0x05b0, 0x05b0, 0x0f70, 0x1770, 0x0e90, 0x0580, 0x1780, + 0x07b0, 0x05b0, 0x1790, 0x05b0, 0x17a0, 0x17b0, 0x0d40, 0x17c0, + 0x0870, 0x05b0, 0x05b0, 0x17d0, 0x17e0, 0x17f0, 0x0860, 0x0860, + 0x05b0, 0x05b0, 0x1800, 0x1050, 0x1810, 0x1820, 0x0bd0, 0x0f00, + 0x0bd0, 0x0bd0, 0x0bd0, 0x0bd0, 0x1830, 0x1840, 0x0860, 0x0860, + 0x1850, 0x1860, 0x14e0, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, + 0x0860, 0x0860, 0x0860, 0x0860, 0x05b0, 0x05b0, 0x1870, 0x0e90, + 0x1880, 0x1890, 0x18a0, 0x18b0, 0x18a0, 0x18c0, 0x18a0, 0x1880, + 0x1890, 0x18a0, 0x18b0, 0x18a0, 0x18c0, 0x18a0, 0x1880, 0x1890, + 0x18a0, 0x18b0, 0x18a0, 0x18c0, 0x18a0, 0x1880, 0x1890, 0x18a0, + 0x18b0, 0x18a0, 0x18c0, 0x18a0, 0x1880, 0x1890, 0x18a0, 0x18b0, + 0x18a0, 0x18c0, 0x18a0, 0x1880, 0x1890, 0x18a0, 0x18b0, 0x18a0, + 0x18c0, 0x18a0, 0x1880, 0x1890, 0x18a0, 0x18b0, 0x18a0, 0x18c0, + 0x18a0, 0x1880, 0x1890, 0x18a0, 0x18b0, 0x18a0, 0x18c0, 0x18a0, + 0x1880, 0x1890, 0x18a0, 0x18b0, 0x18a0, 0x18c0, 0x18a0, 0x1880, + 0x1890, 0x18a0, 0x18b0, 0x18a0, 0x18c0, 0x18a0, 0x1880, 0x1890, + 0x18a0, 0x18b0, 0x18a0, 0x18c0, 0x18a0, 0x1880, 0x1890, 0x18a0, + 0x18b0, 0x18a0, 0x18c0, 0x18a0, 0x1880, 0x1890, 0x18a0, 0x18b0, + 0x18a0, 0x18c0, 0x18a0, 0x1880, 0x1890, 0x18a0, 0x18b0, 0x18a0, + 0x18c0, 0x18a0, 0x1880, 0x1890, 0x18a0, 0x18b0, 0x18a0, 0x18c0, + 0x18a0, 0x1880, 0x1890, 0x18a0, 0x18b0, 0x18a0, 0x18c0, 0x18a0, + 0x18a0, 0x18b0, 0x18a0, 0x18c0, 0x18a0, 0x1880, 0x1890, 0x18a0, + 0x18b0, 0x18a0, 0x18d0, 0x0d50, 0x18e0, 0x0d70, 0x0d70, 0x18f0, + 0x1900, 0x1900, 0x1900, 0x1900, 0x1900, 0x1900, 0x1900, 0x1900, + 0x1900, 0x1900, 0x1900, 0x1900, 0x1900, 0x1900, 0x1900, 0x1900, + 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, + 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, + 0x12e0, 0x1910, 0x05b0, 0x1920, 0x1930, 0x05b0, 0x05b0, 0x05b0, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x1700, 0x1940, 0x05b0, 0x05b0, + 0x05b0, 0x05b0, 0x05b0, 0x1950, 0x0860, 0x05b0, 0x05b0, 0x05b0, + 0x05b0, 0x1960, 0x05b0, 0x05b0, 0x06b0, 0x0860, 0x0860, 0x1970, + 0x0580, 0x1980, 0x1050, 0x1990, 0x19a0, 0x19b0, 0x19c0, 0x10a0, + 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x05b0, 0x19d0, + 0x19e0, 0x19f0, 0x1530, 0x1a00, 0x1530, 0x1a10, 0x1a20, 0x1a30, + 0x05b0, 0x1a40, 0x05b0, 0x0840, 0x1a50, 0x1a60, 0x1a70, 0x1a80, + /* values */ + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0022, 0x0003, 0x0001, 0x0001, 0x0002, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0008, 0x0017, 0x0015, 0x001d, 0x001a, 0x001b, 0x001d, 0x0015, + 0x0012, 0x0014, 0x001d, 0x001a, 0x0019, 0x0020, 0x0019, 0x0018, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x001c, 0x001c, 0x0019, 0x0019, 0x001d, 0x001d, 0x001d, 0x0017, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0012, 0x001a, 0x0014, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0012, 0x0022, 0x0013, 0x001d, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x000a, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0006, 0x0012, 0x001b, 0x001a, 0x001a, 0x001a, 0x001d, 0x0024, + 0x0024, 0x001d, 0x0024, 0x0015, 0x001d, 0x0022, 0x001d, 0x001d, + 0x001b, 0x001a, 0x0024, 0x0024, 0x0021, 0x001d, 0x0024, 0x0024, + 0x0024, 0x0024, 0x0024, 0x0015, 0x0024, 0x0024, 0x0024, 0x0012, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, + 0x0021, 0x0024, 0x0024, 0x0024, 0x0021, 0x0024, 0x001d, 0x001d, + 0x0024, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0024, 0x0024, 0x0024, 0x0024, 0x001d, 0x0024, 0x001d, 0x0021, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0006, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0006, 0x0006, 0x0006, 0x0006, + 0x0006, 0x0006, 0x0006, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0011, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x0019, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0011, 0x001d, 0x0011, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, + 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0011, 0x0019, 0x0022, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0022, 0x0004, + 0x001d, 0x0004, 0x0004, 0x001d, 0x0004, 0x0004, 0x0017, 0x0004, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x001d, 0x001d, + 0x001d, 0x001b, 0x001b, 0x001b, 0x0019, 0x0019, 0x001d, 0x001d, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0017, 0x0011, 0x0011, 0x0017, 0x0017, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x001c, 0x001c, 0x001b, 0x001c, 0x001c, 0x001d, 0x001d, 0x001d, + 0x0004, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0017, 0x001d, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x001d, 0x001d, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x001d, 0x001d, 0x0004, + 0x0004, 0x001d, 0x0004, 0x0004, 0x0004, 0x0004, 0x001d, 0x001d, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x001c, 0x001c, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x001d, + 0x001d, 0x0004, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0004, 0x0004, 0x0004, 0x0004, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0019, 0x0017, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0004, 0x0004, + 0x0004, 0x0004, 0x001d, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x001d, 0x0004, 0x0004, 0x0004, + 0x001d, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, 0x001d, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0004, 0x0004, 0x0004, 0x0004, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0004, 0x0004, 0x0004, 0x001d, 0x0004, 0x0004, + 0x001d, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0004, 0x0004, 0x0022, 0x0022, 0x001c, 0x001c, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0011, 0x0004, 0x0004, 0x0004, 0x0011, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x001d, + 0x001d, 0x0011, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x0011, 0x001d, 0x0011, 0x0011, 0x0011, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0011, 0x0011, 0x0004, 0x001d, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, 0x0004, + 0x0004, 0x0011, 0x0011, 0x0004, 0x0004, 0x0004, 0x001d, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0004, + 0x0011, 0x0011, 0x0011, 0x0011, 0x001d, 0x001d, 0x0011, 0x001d, + 0x001d, 0x001d, 0x0004, 0x0004, 0x0011, 0x0011, 0x001c, 0x001c, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x001d, 0x001d, 0x001b, 0x001b, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001b, 0x001d, 0x001a, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0004, 0x0004, 0x0004, 0x0011, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, 0x001d, + 0x001d, 0x0011, 0x001d, 0x001d, 0x0011, 0x001d, 0x001d, 0x0011, + 0x001d, 0x001d, 0x0011, 0x0011, 0x0004, 0x0011, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, 0x0011, 0x0011, 0x0004, + 0x0004, 0x0011, 0x0011, 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, + 0x0011, 0x0004, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x001d, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x001c, 0x001c, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x0004, 0x0004, 0x001d, 0x001d, 0x001d, 0x0004, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0004, 0x0004, 0x0004, 0x0011, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x001d, + 0x001d, 0x0011, 0x001d, 0x001d, 0x0011, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0011, 0x0011, 0x0004, 0x001d, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0011, 0x0004, + 0x0004, 0x0004, 0x0011, 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, + 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x001a, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, 0x0004, + 0x0004, 0x0011, 0x0011, 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0004, 0x0004, + 0x0011, 0x0011, 0x0011, 0x0011, 0x001d, 0x001d, 0x0011, 0x001d, + 0x0011, 0x0011, 0x0004, 0x001d, 0x0011, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, 0x001d, 0x001d, + 0x001d, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, + 0x0011, 0x001d, 0x001d, 0x0011, 0x001d, 0x0011, 0x001d, 0x001d, + 0x0011, 0x0011, 0x0011, 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, 0x0011, 0x0004, 0x0004, + 0x0004, 0x0011, 0x0004, 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, + 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0004, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001a, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0004, 0x0004, 0x0004, 0x0011, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x001d, 0x001d, + 0x001d, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, 0x001d, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0011, 0x0004, 0x0004, + 0x0004, 0x0011, 0x0004, 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0004, 0x0004, 0x0011, + 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0011, 0x0011, 0x0004, 0x0004, 0x0011, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0011, 0x0011, 0x0004, 0x001d, 0x0004, 0x0004, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0004, 0x0004, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x001d, 0x0011, + 0x0011, 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x001d, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0011, 0x0004, 0x0004, + 0x0004, 0x0011, 0x0004, 0x0004, 0x0004, 0x0004, 0x001d, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0004, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, + 0x0011, 0x001b, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0011, 0x0011, 0x0004, 0x0004, 0x0011, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, + 0x0011, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x001d, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, + 0x0011, 0x0011, 0x0004, 0x0011, 0x0011, 0x0011, 0x0011, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0011, 0x0004, 0x0011, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0011, 0x0011, 0x0004, 0x0004, 0x001d, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, + 0x0023, 0x0023, 0x0023, 0x0011, 0x0011, 0x0011, 0x0011, 0x001a, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x001d, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x001c, 0x001c, 0x0022, 0x0022, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0023, 0x0023, 0x0011, 0x0023, 0x0011, 0x0011, 0x0023, + 0x0023, 0x0011, 0x0023, 0x0011, 0x0011, 0x0023, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0023, 0x0023, 0x0023, 0x0023, + 0x0011, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, + 0x0011, 0x0023, 0x0023, 0x0023, 0x0011, 0x0023, 0x0011, 0x0023, + 0x0011, 0x0011, 0x0023, 0x0023, 0x0011, 0x0023, 0x0023, 0x0023, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, + 0x0023, 0x0023, 0x0011, 0x0023, 0x0023, 0x0023, 0x0011, 0x0011, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0011, 0x0023, 0x0011, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0011, 0x0011, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x001c, 0x001c, 0x0011, 0x0011, 0x0023, 0x0023, 0x0011, 0x0011, + 0x001d, 0x0021, 0x0021, 0x0021, 0x0021, 0x001d, 0x0021, 0x0021, + 0x0006, 0x0021, 0x0021, 0x0022, 0x0006, 0x0017, 0x0017, 0x0017, + 0x0017, 0x0017, 0x0006, 0x001d, 0x0017, 0x001d, 0x001d, 0x001d, + 0x0004, 0x0004, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0022, 0x0004, 0x001d, 0x0004, + 0x001d, 0x0004, 0x0012, 0x0013, 0x0012, 0x0013, 0x0004, 0x0004, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0022, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0022, 0x0004, 0x0004, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0011, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0011, 0x0022, 0x0022, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0004, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x001d, 0x001d, + 0x0021, 0x0021, 0x0022, 0x0021, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x0006, 0x0006, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x001c, 0x001c, 0x0022, 0x0022, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x001c, 0x001c, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, + 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, + 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, + 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, + 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, + 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, + 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, + 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, + 0x001d, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, + 0x001d, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, + 0x001d, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x0004, 0x0004, 0x0004, + 0x001d, 0x0022, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0022, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0012, 0x0013, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0022, 0x0022, 0x0022, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x0004, 0x0004, 0x0004, 0x0022, 0x0022, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x0004, 0x0004, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x0011, 0x0004, 0x0004, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0022, 0x0022, 0x0016, 0x0023, + 0x0022, 0x001d, 0x0022, 0x001a, 0x0023, 0x0023, 0x0011, 0x0011, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x001c, 0x001c, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x0017, 0x0017, 0x0022, 0x0022, 0x0021, 0x001d, + 0x0017, 0x0017, 0x001d, 0x0004, 0x0004, 0x0004, 0x0006, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x0004, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x0011, 0x0011, 0x0011, 0x0017, 0x0017, 0x001c, 0x001c, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0011, 0x0011, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, + 0x0023, 0x0023, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x001c, 0x001c, 0x0023, 0x0011, 0x0011, 0x0011, 0x0023, 0x0023, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, 0x001d, 0x001d, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0011, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, + 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0011, 0x0011, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x001c, 0x001c, 0x0022, 0x0022, 0x001d, 0x0022, 0x0022, 0x0022, + 0x0022, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, + 0x0004, 0x0004, 0x0004, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, 0x0011, 0x001d, 0x001d, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0011, 0x0011, 0x0011, 0x0022, 0x0022, 0x0022, 0x0022, 0x0022, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x001c, 0x001c, 0x0011, 0x0011, 0x0011, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0022, 0x0022, + 0x0004, 0x0004, 0x0004, 0x001d, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x001d, 0x001d, 0x001d, 0x001d, 0x0004, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0004, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0004, 0x0004, 0x0004, 0x0004, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0011, 0x001d, 0x0011, 0x001d, 0x0011, 0x001d, 0x0011, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x001d, 0x001d, 0x001d, + 0x0011, 0x0011, 0x001d, 0x001d, 0x001d, 0x0011, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0021, 0x001d, 0x0011, + 0x0022, 0x0022, 0x0022, 0x0022, 0x0022, 0x0022, 0x0022, 0x0006, + 0x0022, 0x0022, 0x0022, 0x0009, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0022, 0x0006, 0x0022, 0x0022, 0x0025, 0x0024, 0x0024, 0x001d, + 0x0015, 0x0015, 0x0012, 0x0015, 0x0015, 0x0015, 0x0012, 0x0015, + 0x0024, 0x0024, 0x001d, 0x001d, 0x001f, 0x001f, 0x001f, 0x0022, + 0x0001, 0x0001, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0006, + 0x001b, 0x001b, 0x001b, 0x001b, 0x001b, 0x001b, 0x001b, 0x001b, + 0x001d, 0x0015, 0x0015, 0x0024, 0x0016, 0x0016, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0019, 0x0012, 0x0013, 0x0016, + 0x0016, 0x0016, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0022, 0x001d, + 0x0022, 0x0022, 0x0022, 0x0022, 0x001d, 0x0022, 0x0022, 0x0022, + 0x000b, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x001d, 0x001d, 0x0011, 0x0011, 0x0024, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0012, 0x0013, 0x0024, + 0x001d, 0x0024, 0x0024, 0x0024, 0x0024, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0012, 0x0013, 0x0011, + 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001b, + 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, + 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001a, 0x001b, 0x001a, + 0x001a, 0x001a, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0004, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001b, 0x001d, 0x0024, 0x001d, 0x001d, + 0x001d, 0x001b, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0024, 0x001d, 0x001d, 0x001a, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x0024, 0x0024, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0024, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, 0x0024, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0024, 0x001d, 0x001d, 0x0024, 0x001d, + 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, + 0x0024, 0x0024, 0x0024, 0x0024, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, + 0x0024, 0x0024, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x0024, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x0024, 0x001d, 0x0024, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0024, 0x001d, 0x0024, 0x0024, 0x001d, 0x001d, 0x001d, 0x0024, + 0x0024, 0x001d, 0x001d, 0x0024, 0x001d, 0x001d, 0x001d, 0x0024, + 0x001d, 0x0024, 0x001a, 0x001a, 0x001d, 0x0024, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0024, 0x001d, 0x001d, 0x0024, 0x0024, 0x0024, + 0x0024, 0x001d, 0x001d, 0x0024, 0x001d, 0x0024, 0x001d, 0x0024, + 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x001d, 0x0024, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, 0x0024, 0x0024, 0x0024, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, 0x0024, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0024, 0x001d, 0x001d, 0x001d, 0x0024, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0024, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0024, 0x0024, 0x001d, 0x001d, 0x0024, 0x0024, 0x0024, 0x0024, + 0x001d, 0x001d, 0x0024, 0x0024, 0x001d, 0x001d, 0x0024, 0x0024, + 0x001d, 0x001d, 0x0024, 0x0024, 0x001d, 0x001d, 0x0024, 0x0024, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, 0x001d, 0x001d, + 0x001d, 0x0024, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x0012, 0x0013, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, + 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, + 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, + 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x001d, + 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0024, 0x0024, 0x0024, 0x0024, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0024, 0x0024, 0x001d, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, + 0x0024, 0x0024, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0024, 0x0024, 0x001d, 0x001d, 0x0024, 0x0024, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, 0x0024, 0x001d, 0x001d, + 0x0024, 0x0024, 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, 0x0024, + 0x0024, 0x001d, 0x001d, 0x0024, 0x001d, 0x001d, 0x0024, 0x0024, + 0x0024, 0x0024, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0024, 0x0024, 0x0024, 0x0024, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, 0x0024, 0x001d, + 0x001d, 0x0024, 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, 0x0024, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, 0x0024, 0x0024, 0x0024, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, 0x001d, 0x0024, 0x001d, + 0x0024, 0x001d, 0x0024, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0024, 0x0024, 0x001d, 0x0024, 0x0024, 0x0024, 0x001d, 0x0024, + 0x0024, 0x0024, 0x0024, 0x001d, 0x0024, 0x0024, 0x001d, 0x0024, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, 0x0024, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, 0x0024, 0x0024, 0x0024, + 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x001d, 0x0024, + 0x0024, 0x0024, 0x001d, 0x0024, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, + 0x001d, 0x001d, 0x001d, 0x0015, 0x0015, 0x0015, 0x0015, 0x001d, + 0x001d, 0x001d, 0x0017, 0x0017, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0012, 0x0013, 0x0012, 0x0013, 0x0012, 0x0013, 0x0012, 0x0013, + 0x0012, 0x0013, 0x0012, 0x0013, 0x0012, 0x0013, 0x0024, 0x0024, + 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, + 0x0024, 0x0024, 0x0024, 0x0024, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0012, 0x0013, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0011, 0x001d, 0x0011, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0012, 0x0013, + 0x0012, 0x0013, 0x0012, 0x0013, 0x0012, 0x0013, 0x0012, 0x0013, + 0x001d, 0x001d, 0x001d, 0x0012, 0x0013, 0x0012, 0x0013, 0x0012, + 0x0013, 0x0012, 0x0013, 0x0012, 0x0013, 0x0012, 0x0013, 0x0012, + 0x0013, 0x0012, 0x0013, 0x0012, 0x0013, 0x0012, 0x0013, 0x0012, + 0x0013, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0012, 0x0013, 0x0012, 0x0013, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0012, 0x0013, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0024, 0x0024, 0x0024, + 0x0024, 0x0024, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0004, + 0x0004, 0x0004, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0017, 0x0022, 0x0022, 0x0022, 0x001d, 0x0017, 0x0022, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x001d, + 0x0022, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0004, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, + 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, + 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0022, 0x0022, + 0x0022, 0x0022, 0x0022, 0x0022, 0x0022, 0x0022, 0x001d, 0x0022, + 0x0012, 0x0022, 0x001d, 0x001d, 0x0015, 0x0015, 0x001d, 0x001d, + 0x0015, 0x0015, 0x0012, 0x0013, 0x0012, 0x0013, 0x0012, 0x0013, + 0x0012, 0x0013, 0x0022, 0x0022, 0x0022, 0x0022, 0x0017, 0x001d, + 0x0022, 0x0022, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x0011, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001e, 0x0013, 0x0013, 0x001e, 0x001e, 0x0016, 0x001e, 0x001e, + 0x0012, 0x0013, 0x0012, 0x0013, 0x0012, 0x0013, 0x0012, 0x0013, + 0x0012, 0x0013, 0x001e, 0x001e, 0x0012, 0x0013, 0x0012, 0x0013, + 0x0012, 0x0013, 0x0012, 0x0013, 0x0016, 0x0012, 0x0013, 0x0013, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x0016, 0x0016, 0x001e, 0x001e, 0x001e, + 0x0011, 0x0016, 0x001e, 0x0016, 0x001e, 0x0016, 0x001e, 0x0016, + 0x001e, 0x0016, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x0016, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x0016, 0x001e, 0x0016, 0x001e, 0x0016, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x0016, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x0016, 0x0016, 0x0011, + 0x0011, 0x0004, 0x0004, 0x0016, 0x0016, 0x0016, 0x0016, 0x001e, + 0x0016, 0x0016, 0x001e, 0x0016, 0x001e, 0x0016, 0x001e, 0x0016, + 0x001e, 0x0016, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x0016, 0x0016, 0x001e, + 0x001e, 0x001e, 0x001e, 0x0016, 0x0016, 0x0016, 0x0016, 0x001e, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x0011, 0x0011, + 0x0011, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x0011, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, + 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, 0x0024, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x0016, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x0011, 0x0011, 0x0011, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0022, 0x0017, 0x0022, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x001c, 0x001c, 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0004, 0x0004, 0x0004, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0004, 0x0004, 0x001d, 0x001d, + 0x0004, 0x0004, 0x001d, 0x0022, 0x0022, 0x0022, 0x0022, 0x0022, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x0004, 0x001d, 0x001d, 0x001d, 0x0004, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0004, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001b, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0021, 0x0021, 0x0017, 0x0017, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0004, 0x0004, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0022, 0x0022, + 0x0004, 0x0004, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0022, 0x0022, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x001d, + 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, + 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0022, + 0x0022, 0x0022, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x001d, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x001c, 0x001c, 0x0011, 0x0011, 0x0011, 0x0011, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x001d, 0x001d, 0x001d, 0x0004, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x0004, 0x0004, 0x0011, 0x0011, + 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, 0x001c, + 0x001c, 0x001c, 0x0011, 0x0011, 0x001d, 0x0022, 0x0022, 0x0022, + 0x0023, 0x0023, 0x0023, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, + 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, + 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, + 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, + 0x0004, 0x0004, 0x0004, 0x0022, 0x0004, 0x0004, 0x0011, 0x0011, + 0x000f, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x000f, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x000f, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x000f, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, + 0x0010, 0x0010, 0x0010, 0x0010, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x0011, + 0x0011, 0x0011, 0x0011, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, + 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, + 0x000e, 0x000e, 0x000e, 0x000e, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, + 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, + 0x0011, 0x0011, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x001d, 0x0004, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x001d, 0x0011, + 0x001d, 0x001d, 0x0011, 0x001d, 0x001d, 0x0011, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0011, 0x0011, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0012, 0x0013, + 0x0011, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001b, 0x001d, 0x0011, 0x0011, + 0x0019, 0x0013, 0x0013, 0x0019, 0x0019, 0x0017, 0x0017, 0x0012, + 0x0013, 0x001f, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x0012, 0x0013, 0x0012, + 0x0013, 0x0012, 0x0013, 0x0012, 0x0013, 0x0012, 0x0013, 0x0012, + 0x0013, 0x0012, 0x0013, 0x0012, 0x0013, 0x001e, 0x001e, 0x0012, + 0x0013, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x0013, 0x001e, 0x0013, 0x0011, 0x0016, 0x0016, 0x0017, 0x0017, + 0x001e, 0x0012, 0x0013, 0x0012, 0x0013, 0x0012, 0x0013, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x0011, + 0x001e, 0x001a, 0x001b, 0x001e, 0x0011, 0x0011, 0x0011, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x000b, + 0x0011, 0x0017, 0x001e, 0x001e, 0x001a, 0x001b, 0x001e, 0x001e, + 0x0012, 0x0013, 0x001e, 0x001e, 0x0013, 0x001e, 0x0013, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x0016, 0x0016, 0x001e, 0x001e, 0x001e, 0x0017, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x0012, 0x001e, 0x0013, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, + 0x001e, 0x001e, 0x001e, 0x0012, 0x001e, 0x0013, 0x001e, 0x0012, + 0x0013, 0x0013, 0x0012, 0x0013, 0x0013, 0x0016, 0x001d, 0x0016, + 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, 0x0016, + 0x0016, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0016, 0x0016, + 0x0011, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0011, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0011, 0x0011, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, + 0x0011, 0x0011, 0x001d, 0x001d, 0x001d, 0x0011, 0x0011, 0x0011, + 0x001b, 0x001a, 0x001e, 0x001e, 0x001e, 0x001a, 0x001a, 0x0011, + 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x001d, 0x0011, + 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011, + 0x0011, 0x0004, 0x0004, 0x0004, 0x0007, 0x0024, 0x0011, 0x0011 +}; diff --git a/reactos/dll/win32/usp10/mirror.c b/reactos/dll/win32/usp10/mirror.c index 65a5a280ec8..c87162b25d7 100644 --- a/reactos/dll/win32/usp10/mirror.c +++ b/reactos/dll/win32/usp10/mirror.c @@ -1,5 +1,5 @@ /* Unicode BiDi mirroring */ -/* generated from http://www.unicode.org/Public/5.2.0/ucd/BidiMirroring.txt */ +/* generated from http://www.unicode.org/Public/6.0.0/ucd/BidiMirroring.txt */ /* DO NOT EDIT!! */ #include "wine/unicode.h" diff --git a/reactos/dll/win32/usp10/shape.c b/reactos/dll/win32/usp10/shape.c index 0018ae5f691..8d3a355fffa 100644 --- a/reactos/dll/win32/usp10/shape.c +++ b/reactos/dll/win32/usp10/shape.c @@ -37,6 +37,42 @@ WINE_DEFAULT_DEBUG_CHANNEL(uniscribe); #define FIRST_ARABIC_CHAR 0x0600 #define LAST_ARABIC_CHAR 0x06ff +typedef VOID (*ContextualShapingProc)(HDC, ScriptCache*, SCRIPT_ANALYSIS*, + WCHAR*, INT, WORD*, INT*, INT, WORD*); + +static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static void ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static void ContextualShape_Sinhala(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static void ContextualShape_Devanagari(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static void ContextualShape_Bengali(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static void ContextualShape_Gurmukhi(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static void ContextualShape_Gujarati(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static void ContextualShape_Oriya(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static void ContextualShape_Tamil(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static void ContextualShape_Telugu(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static void ContextualShape_Kannada(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); +static void ContextualShape_Malayalam(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust); + +typedef VOID (*ShapeCharGlyphPropProc)( HDC , ScriptCache*, SCRIPT_ANALYSIS*, const WCHAR*, const INT, const WORD*, const INT, WORD*, SCRIPT_CHARPROP*, SCRIPT_GLYPHPROP*); + +static void ShapeCharGlyphProp_Default( HDC hdc, ScriptCache* psc, SCRIPT_ANALYSIS* psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD* pwLogClust, SCRIPT_CHARPROP* pCharProp, SCRIPT_GLYPHPROP* pGlyphProp); +static void ShapeCharGlyphProp_Arabic( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP* pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); +static void ShapeCharGlyphProp_Thai( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); +static void ShapeCharGlyphProp_None( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); +static void ShapeCharGlyphProp_Tibet( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); +static void ShapeCharGlyphProp_Sinhala( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); +static void ShapeCharGlyphProp_Devanagari( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); +static void ShapeCharGlyphProp_Bengali( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); +static void ShapeCharGlyphProp_Gurmukhi( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); +static void ShapeCharGlyphProp_Gujarati( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); +static void ShapeCharGlyphProp_Oriya( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); +static void ShapeCharGlyphProp_Tamil( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); +static void ShapeCharGlyphProp_Telugu( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); +static void ShapeCharGlyphProp_Kannada( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); +static void ShapeCharGlyphProp_Malayalam( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ); + +extern const unsigned short indic_syllabic_table[]; extern const unsigned short wine_shaping_table[]; extern const unsigned short wine_shaping_forms[LAST_ARABIC_CHAR - FIRST_ARABIC_CHAR + 1][4]; @@ -53,7 +89,11 @@ enum joined_forms { Xn=0, Xr, Xl, - Xm + Xm, + /* Syriac Alaph */ + Afj, + Afn, + Afx }; #ifdef WORDS_BIGENDIAN @@ -63,12 +103,6 @@ enum joined_forms { #endif /* These are all structures needed for the GSUB table */ -#define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \ - ( ( (ULONG)_x4 << 24 ) | \ - ( (ULONG)_x3 << 16 ) | \ - ( (ULONG)_x2 << 8 ) | \ - (ULONG)_x1 ) - #define GSUB_TAG MS_MAKE_TAG('G', 'S', 'U', 'B') #define GSUB_E_NOFEATURE -2 #define GSUB_E_NOGLYPH -1 @@ -167,6 +201,18 @@ typedef struct { WORD Substitute[1]; }GSUB_SingleSubstFormat2; +typedef struct { + WORD SubstFormat; /* = 1 */ + WORD Coverage; + WORD SequenceCount; + WORD Sequence[1]; +}GSUB_MultipleSubstFormat1; + +typedef struct { + WORD GlyphCount; + WORD Substitute[1]; +}GSUB_Sequence; + typedef struct { WORD SubstFormat; /* = 1 */ WORD Coverage; @@ -219,28 +265,341 @@ typedef struct{ GSUB_SubstLookupRecord SubstLookupRecord[1]; }GSUB_ChainContextSubstFormat3_4; +typedef struct { + WORD SubstFormat; /* = 1 */ + WORD Coverage; + WORD AlternateSetCount; + WORD AlternateSet[1]; +} GSUB_AlternateSubstFormat1; + +typedef struct{ + WORD GlyphCount; + WORD Alternate[1]; +} GSUB_AlternateSet; + +/* These are all structures needed for the GDEF table */ +#define GDEF_TAG MS_MAKE_TAG('G', 'D', 'E', 'F') + +enum {BaseGlyph=1, LigatureGlyph, MarkGlyph, ComponentGlyph}; + +typedef struct { + DWORD Version; + WORD GlyphClassDef; + WORD AttachList; + WORD LigCaretList; + WORD MarkAttachClassDef; +} GDEF_Header; + +typedef struct { + WORD ClassFormat; + WORD StartGlyph; + WORD GlyphCount; + WORD ClassValueArray[1]; +} GDEF_ClassDefFormat1; + +typedef struct { + WORD Start; + WORD End; + WORD Class; +} GDEF_ClassRangeRecord; + +typedef struct { + WORD ClassFormat; + WORD ClassRangeCount; + GDEF_ClassRangeRecord ClassRangeRecord[1]; +} GDEF_ClassDefFormat2; + static INT GSUB_apply_lookup(const GSUB_LookupList* lookup, INT lookup_index, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count); +typedef struct tagVowelComponents +{ + WCHAR base; + WCHAR parts[3]; +} VowelComponents; + +typedef struct tagConsonantComponents +{ + WCHAR parts[3]; + WCHAR output; +} ConsonantComponents; + +typedef void (*second_reorder_function)(LPWSTR pwChar, IndicSyllable *syllable,WORD* pwGlyphs, IndicSyllable* glyph_index, lexical_function lex); + /* the orders of joined_forms and contextual_features need to line up */ static const char* contextual_features[] = { "isol", "fina", "init", - "medi" + "medi", + /* Syriac Alaph */ + "med2", + "fin2", + "fin3" }; -static const char* arabic_GSUB_features[] = +static OPENTYPE_FEATURE_RECORD standard_features[] = { + { MS_MAKE_TAG('c','c','m','p'), 1}, + { MS_MAKE_TAG('l','o','c','l'), 1}, +}; + +static OPENTYPE_FEATURE_RECORD latin_features[] = +{ + { MS_MAKE_TAG('l','i','g','a'), 1}, + { MS_MAKE_TAG('c','l','i','g'), 1}, +}; + +static OPENTYPE_FEATURE_RECORD arabic_features[] = +{ + { MS_MAKE_TAG('r','l','i','g'), 1}, + { MS_MAKE_TAG('c','a','l','t'), 1}, + { MS_MAKE_TAG('l','i','g','a'), 1}, + { MS_MAKE_TAG('d','l','i','g'), 1}, + { MS_MAKE_TAG('c','s','w','h'), 1}, + { MS_MAKE_TAG('m','s','e','t'), 1}, +}; + +static const char* required_arabic_features[] = +{ + "fina", + "init", + "medi", "rlig", - "calt", - "liga", - "dlig", - "cswh", - "mset", NULL }; +static OPENTYPE_FEATURE_RECORD hebrew_features[] = +{ + { MS_MAKE_TAG('d','l','i','g'), 0}, +}; + +static OPENTYPE_FEATURE_RECORD syriac_features[] = +{ + { MS_MAKE_TAG('r','l','i','g'), 1}, + { MS_MAKE_TAG('c','a','l','t'), 1}, + { MS_MAKE_TAG('l','i','g','a'), 1}, + { MS_MAKE_TAG('d','l','i','g'), 1}, +}; + +static const char* required_syriac_features[] = +{ + "fina", + "fin2", + "fin3", + "init", + "medi", + "med2", + "rlig", + NULL +}; + +static OPENTYPE_FEATURE_RECORD sinhala_features[] = +{ + /* Presentation forms */ + { MS_MAKE_TAG('b','l','w','s'), 1}, + { MS_MAKE_TAG('a','b','v','s'), 1}, + { MS_MAKE_TAG('p','s','t','s'), 1}, +}; + +static OPENTYPE_FEATURE_RECORD tibetan_features[] = +{ + { MS_MAKE_TAG('a','b','v','s'), 1}, + { MS_MAKE_TAG('b','l','w','s'), 1}, +}; + +static OPENTYPE_FEATURE_RECORD phags_features[] = +{ + { MS_MAKE_TAG('a','b','v','s'), 1}, + { MS_MAKE_TAG('b','l','w','s'), 1}, + { MS_MAKE_TAG('c','a','l','t'), 1}, +}; + +static OPENTYPE_FEATURE_RECORD thai_features[] = +{ + { MS_MAKE_TAG('c','c','m','p'), 1}, +}; + +static const char* required_lao_features[] = +{ + "ccmp", + NULL +}; + +static const char* required_devanagari_features[] = +{ + "nukt", + "akhn", + "rphf", + "blwf", + "half", + "vatu", + "pres", + "abvs", + "blws", + "psts", + "haln", + NULL +}; + +static OPENTYPE_FEATURE_RECORD devanagari_features[] = +{ + { MS_MAKE_TAG('p','r','e','s'), 1}, + { MS_MAKE_TAG('a','b','v','s'), 1}, + { MS_MAKE_TAG('b','l','w','s'), 1}, + { MS_MAKE_TAG('p','s','t','s'), 1}, + { MS_MAKE_TAG('h','a','l','n'), 1}, + { MS_MAKE_TAG('c','a','l','t'), 1}, +}; + +static const char* required_bengali_features[] = +{ + "nukt", + "akhn", + "rphf", + "blwf", + "half", + "vatu", + "pstf", + "init", + "abvs", + "blws", + "psts", + "haln", + NULL +}; + +static const char* required_gurmukhi_features[] = +{ + "nukt", + "akhn", + "rphf", + "blwf", + "half", + "pstf", + "vatu", + "cjct", + "pres", + "abvs", + "blws", + "psts", + "haln", + "calt", + NULL +}; + +static const char* required_oriya_features[] = +{ + "nukt", + "akhn", + "rphf", + "blwf", + "pstf", + "cjct", + "pres", + "abvs", + "blws", + "psts", + "haln", + "calt", + NULL +}; + +static const char* required_tamil_features[] = +{ + "nukt", + "akhn", + "rphf", + "pref", + "half", + "pres", + "abvs", + "blws", + "psts", + "haln", + "calt", + NULL +}; + +static const char* required_telugu_features[] = +{ + "nukt", + "akhn", + "rphf", + "pref", + "half", + "pstf", + "cjct", + "pres", + "abvs", + "blws", + "psts", + "haln", + "calt", + NULL +}; + +typedef struct ScriptShapeDataTag { + TEXTRANGE_PROPERTIES defaultTextRange; + const char** requiredFeatures; + CHAR otTag[5]; + CHAR newOtTag[5]; + ContextualShapingProc contextProc; + ShapeCharGlyphPropProc charGlyphPropProc; +} ScriptShapeData; + +/* in order of scripts */ +static const ScriptShapeData ShapingData[] = +{ + {{ standard_features, 2}, NULL, "", "", NULL, NULL}, + {{ latin_features, 2}, NULL, "latn", "", NULL, NULL}, + {{ latin_features, 2}, NULL, "latn", "", NULL, NULL}, + {{ latin_features, 2}, NULL, "latn", "", NULL, NULL}, + {{ standard_features, 2}, NULL, "" , "", NULL, NULL}, + {{ latin_features, 2}, NULL, "latn", "", NULL, NULL}, + {{ arabic_features, 6}, required_arabic_features, "arab", "", ContextualShape_Arabic, ShapeCharGlyphProp_Arabic}, + {{ arabic_features, 6}, required_arabic_features, "arab", "", ContextualShape_Arabic, ShapeCharGlyphProp_Arabic}, + {{ hebrew_features, 1}, NULL, "hebr", "", NULL, NULL}, + {{ syriac_features, 4}, required_syriac_features, "syrc", "", ContextualShape_Syriac, ShapeCharGlyphProp_None}, + {{ arabic_features, 6}, required_arabic_features, "arab", "", ContextualShape_Arabic, ShapeCharGlyphProp_Arabic}, + {{ NULL, 0}, NULL, "thaa", "", NULL, ShapeCharGlyphProp_None}, + {{ standard_features, 2}, NULL, "grek", "", NULL, NULL}, + {{ standard_features, 2}, NULL, "cyrl", "", NULL, NULL}, + {{ standard_features, 2}, NULL, "armn", "", NULL, NULL}, + {{ standard_features, 2}, NULL, "geor", "", NULL, NULL}, + {{ sinhala_features, 3}, NULL, "sinh", "", ContextualShape_Sinhala, ShapeCharGlyphProp_Sinhala}, + {{ tibetan_features, 2}, NULL, "tibt", "", NULL, ShapeCharGlyphProp_Tibet}, + {{ tibetan_features, 2}, NULL, "tibt", "", NULL, ShapeCharGlyphProp_Tibet}, + {{ phags_features, 3}, NULL, "phag", "", ContextualShape_Phags_pa, ShapeCharGlyphProp_Thai}, + {{ thai_features, 1}, NULL, "thai", "", NULL, ShapeCharGlyphProp_Thai}, + {{ thai_features, 1}, NULL, "thai", "", NULL, ShapeCharGlyphProp_Thai}, + {{ thai_features, 1}, required_lao_features, "lao", "", NULL, ShapeCharGlyphProp_Thai}, + {{ thai_features, 1}, required_lao_features, "lao", "", NULL, ShapeCharGlyphProp_Thai}, + {{ devanagari_features, 6}, required_devanagari_features, "deva", "dev2", ContextualShape_Devanagari, ShapeCharGlyphProp_Devanagari}, + {{ devanagari_features, 6}, required_devanagari_features, "deva", "dev2", ContextualShape_Devanagari, ShapeCharGlyphProp_Devanagari}, + {{ devanagari_features, 6}, required_bengali_features, "beng", "bng2", ContextualShape_Bengali, ShapeCharGlyphProp_Bengali}, + {{ devanagari_features, 6}, required_bengali_features, "beng", "bng2", ContextualShape_Bengali, ShapeCharGlyphProp_Bengali}, + {{ devanagari_features, 6}, required_bengali_features, "beng", "bng2", ContextualShape_Bengali, ShapeCharGlyphProp_Bengali}, + {{ devanagari_features, 6}, required_gurmukhi_features, "guru", "gur2", ContextualShape_Gurmukhi, ShapeCharGlyphProp_Gurmukhi}, + {{ devanagari_features, 6}, required_gurmukhi_features, "guru", "gur2", ContextualShape_Gurmukhi, ShapeCharGlyphProp_Gurmukhi}, + {{ devanagari_features, 6}, required_devanagari_features, "gujr", "gjr2", ContextualShape_Gujarati, ShapeCharGlyphProp_Gujarati}, + {{ devanagari_features, 6}, required_devanagari_features, "gujr", "gjr2", ContextualShape_Gujarati, ShapeCharGlyphProp_Gujarati}, + {{ devanagari_features, 6}, required_devanagari_features, "gujr", "gjr2", ContextualShape_Gujarati, ShapeCharGlyphProp_Gujarati}, + {{ devanagari_features, 6}, required_oriya_features, "orya", "ory2", ContextualShape_Oriya, ShapeCharGlyphProp_Oriya}, + {{ devanagari_features, 6}, required_oriya_features, "orya", "ory2", ContextualShape_Oriya, ShapeCharGlyphProp_Oriya}, + {{ devanagari_features, 6}, required_tamil_features, "taml", "tam2", ContextualShape_Tamil, ShapeCharGlyphProp_Tamil}, + {{ devanagari_features, 6}, required_tamil_features, "taml", "tam2", ContextualShape_Tamil, ShapeCharGlyphProp_Tamil}, + {{ devanagari_features, 6}, required_telugu_features, "telu", "tel2", ContextualShape_Telugu, ShapeCharGlyphProp_Telugu}, + {{ devanagari_features, 6}, required_telugu_features, "telu", "tel2", ContextualShape_Telugu, ShapeCharGlyphProp_Telugu}, + {{ devanagari_features, 6}, required_telugu_features, "knda", "knd2", ContextualShape_Kannada, ShapeCharGlyphProp_Kannada}, + {{ devanagari_features, 6}, required_telugu_features, "knda", "knd2", ContextualShape_Kannada, ShapeCharGlyphProp_Kannada}, + {{ devanagari_features, 6}, required_telugu_features, "mlym", "mlm2", ContextualShape_Malayalam, ShapeCharGlyphProp_Malayalam}, + {{ devanagari_features, 6}, required_telugu_features, "mlym", "mlm2", ContextualShape_Malayalam, ShapeCharGlyphProp_Malayalam}, + {{ standard_features, 2}, NULL, "" , "", NULL, NULL}, + {{ latin_features, 2}, NULL, "latn" , "", NULL, NULL}, + {{ standard_features, 2}, NULL, "" , "", NULL, NULL}, +}; + static INT GSUB_is_glyph_covered(LPCVOID table , UINT glyph) { const GSUB_CoverageFormat1* cf1; @@ -374,7 +733,7 @@ static INT GSUB_apply_SingleSubst(const GSUB_LookupTable *look, WORD *glyphs, IN TRACE(" Glyph 0x%x ->",glyphs[glyph_index]); glyphs[glyph_index] = glyphs[glyph_index] + GET_BE_WORD(ssf1->DeltaGlyphID); TRACE(" 0x%x\n",glyphs[glyph_index]); - return glyph_index + 1; + return glyph_index + write_dir; } } else @@ -390,16 +749,101 @@ static INT GSUB_apply_SingleSubst(const GSUB_LookupTable *look, WORD *glyphs, IN TRACE(" Coverage index %i\n",index); if (index != -1) { + if (glyphs[glyph_index] == GET_BE_WORD(ssf2->Substitute[index])) + return GSUB_E_NOGLYPH; + TRACE(" Glyph is 0x%x ->",glyphs[glyph_index]); glyphs[glyph_index] = GET_BE_WORD(ssf2->Substitute[index]); TRACE("0x%x\n",glyphs[glyph_index]); - return glyph_index + 1; + return glyph_index + write_dir; } } } return GSUB_E_NOGLYPH; } +static INT GSUB_apply_MultipleSubst(const GSUB_LookupTable *look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count) +{ + int j; + TRACE("Multiple Substitution Subtable\n"); + + for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++) + { + int offset, index; + const GSUB_MultipleSubstFormat1 *msf1; + offset = GET_BE_WORD(look->SubTable[j]); + msf1 = (const GSUB_MultipleSubstFormat1*)((const BYTE*)look+offset); + + offset = GET_BE_WORD(msf1->Coverage); + index = GSUB_is_glyph_covered((const BYTE*)msf1+offset, glyphs[glyph_index]); + if (index != -1) + { + const GSUB_Sequence *seq; + int sub_count; + int j; + offset = GET_BE_WORD(msf1->Sequence[index]); + seq = (const GSUB_Sequence*)((const BYTE*)msf1+offset); + sub_count = GET_BE_WORD(seq->GlyphCount); + TRACE(" Glyph 0x%x (+%i)->",glyphs[glyph_index],(sub_count-1)); + + for (j = (*glyph_count)+(sub_count-1); j > glyph_index; j--) + glyphs[j] =glyphs[j-(sub_count-1)]; + + for (j = 0; j < sub_count; j++) + if (write_dir < 0) + glyphs[glyph_index + (sub_count-1) - j] = GET_BE_WORD(seq->Substitute[j]); + else + glyphs[glyph_index + j] = GET_BE_WORD(seq->Substitute[j]); + + *glyph_count = *glyph_count + (sub_count - 1); + + if (TRACE_ON(uniscribe)) + { + for (j = 0; j < sub_count; j++) + TRACE(" 0x%x",glyphs[glyph_index+j]); + TRACE("\n"); + } + + return glyph_index + (sub_count * write_dir); + } + } + return GSUB_E_NOGLYPH; +} + +static INT GSUB_apply_AlternateSubst(const GSUB_LookupTable *look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count) +{ + int j; + TRACE("Alternate Substitution Subtable\n"); + + for (j = 0; j < GET_BE_WORD(look->SubTableCount); j++) + { + int offset; + const GSUB_AlternateSubstFormat1 *asf1; + INT index; + + offset = GET_BE_WORD(look->SubTable[j]); + asf1 = (const GSUB_AlternateSubstFormat1*)((const BYTE*)look+offset); + offset = GET_BE_WORD(asf1->Coverage); + + index = GSUB_is_glyph_covered((const BYTE*)asf1+offset, glyphs[glyph_index]); + if (index != -1) + { + const GSUB_AlternateSet *as; + offset = GET_BE_WORD(asf1->AlternateSet[index]); + as = (const GSUB_AlternateSet*)((const BYTE*)asf1+offset); + FIXME("%i alternates, picking index 0\n",GET_BE_WORD(as->GlyphCount)); + if (glyphs[glyph_index] == GET_BE_WORD(as->Alternate[0])) + return GSUB_E_NOGLYPH; + + TRACE(" Glyph 0x%x ->",glyphs[glyph_index]); + glyphs[glyph_index] = GET_BE_WORD(as->Alternate[0]); + TRACE(" 0x%x\n",glyphs[glyph_index]); + return glyph_index + write_dir; + } + } + return GSUB_E_NOGLYPH; +} + static INT GSUB_apply_LigatureSubst(const GSUB_LookupTable *look, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count) { int j; @@ -457,7 +901,7 @@ static INT GSUB_apply_LigatureSubst(const GSUB_LookupTable *look, WORD *glyphs, glyphs[j] =glyphs[j+CompCount]; *glyph_count = *glyph_count - CompCount; } - return replaceIdx + 1; + return replaceIdx + write_dir; } } } @@ -483,12 +927,12 @@ static INT GSUB_apply_ChainContextSubst(const GSUB_LookupList* lookup, const GSU if (GET_BE_WORD(ccsf1->SubstFormat) == 1) { FIXME(" TODO: subtype 1 (Simple context glyph substitution)\n"); - return -1; + continue; } else if (GET_BE_WORD(ccsf1->SubstFormat) == 2) { FIXME(" TODO: subtype 2 (Class-based Chaining Context Glyph Substitution)\n"); - return -1; + continue; } else if (GET_BE_WORD(ccsf1->SubstFormat) == 3) { @@ -511,7 +955,7 @@ static INT GSUB_apply_ChainContextSubst(const GSUB_LookupList* lookup, const GSU break; } if (k != GET_BE_WORD(ccsf3_1->BacktrackGlyphCount)) - return -1; + continue; TRACE("Matched Backtrack\n"); ccsf3_2 = (const GSUB_ChainContextSubstFormat3_2 *)(((LPBYTE)ccsf1)+sizeof(GSUB_ChainContextSubstFormat3_1) + (sizeof(WORD) * (GET_BE_WORD(ccsf3_1->BacktrackGlyphCount)-1))); @@ -524,7 +968,7 @@ static INT GSUB_apply_ChainContextSubst(const GSUB_LookupList* lookup, const GSU break; } if (k != indexGlyphs) - return -1; + continue; TRACE("Matched IndexGlyphs\n"); ccsf3_3 = (const GSUB_ChainContextSubstFormat3_3 *)(((LPBYTE)ccsf3_2)+sizeof(GSUB_ChainContextSubstFormat3_2) + (sizeof(WORD) * (GET_BE_WORD(ccsf3_2->InputGlyphCount)-1))); @@ -532,29 +976,33 @@ static INT GSUB_apply_ChainContextSubst(const GSUB_LookupList* lookup, const GSU for (k = 0; k < GET_BE_WORD(ccsf3_3->LookaheadGlyphCount); k++) { offset = GET_BE_WORD(ccsf3_3->Coverage[k]); - if (GSUB_is_glyph_covered((const BYTE*)ccsf3_1+offset, glyphs[glyph_index + (dirLookahead * (indexGlyphs + k+1))]) == -1) + if (GSUB_is_glyph_covered((const BYTE*)ccsf3_1+offset, glyphs[glyph_index + (dirLookahead * (indexGlyphs + k))]) == -1) break; } if (k != GET_BE_WORD(ccsf3_3->LookaheadGlyphCount)) - return -1; + continue; TRACE("Matched LookAhead\n"); ccsf3_4 = (const GSUB_ChainContextSubstFormat3_4 *)(((LPBYTE)ccsf3_3)+sizeof(GSUB_ChainContextSubstFormat3_3) + (sizeof(WORD) * (GET_BE_WORD(ccsf3_3->LookaheadGlyphCount)-1))); - for (k = 0; k < GET_BE_WORD(ccsf3_4->SubstCount); k++) + if (GET_BE_WORD(ccsf3_4->SubstCount)) { - int lookupIndex = GET_BE_WORD(ccsf3_4->SubstLookupRecord[k].LookupListIndex); - int SequenceIndex = GET_BE_WORD(ccsf3_4->SubstLookupRecord[k].SequenceIndex) * write_dir; - - TRACE("SUBST: %i -> %i %i\n",k, SequenceIndex, lookupIndex); - newIndex = GSUB_apply_lookup(lookup, lookupIndex, glyphs, glyph_index + SequenceIndex, write_dir, glyph_count); - if (newIndex == -1) + for (k = 0; k < GET_BE_WORD(ccsf3_4->SubstCount); k++) { - ERR("Chain failed to generate a glyph\n"); - return -1; + int lookupIndex = GET_BE_WORD(ccsf3_4->SubstLookupRecord[k].LookupListIndex); + int SequenceIndex = GET_BE_WORD(ccsf3_4->SubstLookupRecord[k].SequenceIndex) * write_dir; + + TRACE("SUBST: %i -> %i %i\n",k, SequenceIndex, lookupIndex); + newIndex = GSUB_apply_lookup(lookup, lookupIndex, glyphs, glyph_index + SequenceIndex, write_dir, glyph_count); + if (newIndex == -1) + { + ERR("Chain failed to generate a glyph\n"); + continue; + } } + return newIndex; } - return newIndex + 1; + else return GSUB_E_NOGLYPH; } } return -1; @@ -572,6 +1020,10 @@ static INT GSUB_apply_lookup(const GSUB_LookupList* lookup, INT lookup_index, WO { case 1: return GSUB_apply_SingleSubst(look, glyphs, glyph_index, write_dir, glyph_count); + case 2: + return GSUB_apply_MultipleSubst(look, glyphs, glyph_index, write_dir, glyph_count); + case 3: + return GSUB_apply_AlternateSubst(look, glyphs, glyph_index, write_dir, glyph_count); case 4: return GSUB_apply_LigatureSubst(look, glyphs, glyph_index, write_dir, glyph_count); case 6: @@ -582,7 +1034,7 @@ static INT GSUB_apply_lookup(const GSUB_LookupList* lookup, INT lookup_index, WO return GSUB_E_NOGLYPH; } -static INT GSUB_apply_feature(const GSUB_Header * header, const GSUB_Feature* feature, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count) +static INT GSUB_apply_feature_all_lookups(const GSUB_Header * header, const GSUB_Feature* feature, WORD *glyphs, INT glyph_index, INT write_dir, INT *glyph_count) { int i; int out_index = GSUB_E_NOGLYPH; @@ -599,28 +1051,34 @@ static INT GSUB_apply_feature(const GSUB_Header * header, const GSUB_Feature* fe } if (out_index == GSUB_E_NOGLYPH) TRACE("lookups found no glyphs\n"); + else + { + int out2; + out2 = GSUB_apply_feature_all_lookups(header, feature, glyphs, glyph_index, write_dir, glyph_count); + if (out2!=GSUB_E_NOGLYPH) + out_index = out2; + } return out_index; } -static const char* get_opentype_script(HDC hdc, SCRIPT_ANALYSIS *psa) +static const char* get_opentype_script(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, BOOL tryNew) { UINT charset; - switch (psa->eScript) + if (psc->userScript != 0) { - case Script_Arabic: - return "arab"; - case Script_Syriac: - return "syrc"; - case Script_Hebrew: - return "hebr"; - case Script_Latin: - case Script_Numeric: - case Script_CR: - case Script_LF: - return "latn"; + if (tryNew && ShapingData[psa->eScript].newOtTag[0] != 0 && strncmp((char*)&psc->userScript,ShapingData[psa->eScript].otTag,4)==0) + return ShapingData[psa->eScript].newOtTag; + else + return (char*)&psc->userScript; } + if (tryNew && ShapingData[psa->eScript].newOtTag[0] != 0) + return ShapingData[psa->eScript].newOtTag; + + if (ShapingData[psa->eScript].otTag[0] != 0) + return ShapingData[psa->eScript].otTag; + /* * fall back to the font charset */ @@ -646,38 +1104,81 @@ static const char* get_opentype_script(HDC hdc, SCRIPT_ANALYSIS *psa) } } -static INT apply_GSUB_feature_to_glyph(HDC hdc, SCRIPT_ANALYSIS *psa, void* GSUB_Table, WORD *glyphs, INT index, INT write_dir, INT* glyph_count, const char* feat) +static LPCVOID load_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache *psc, const char* feat) +{ + const GSUB_Feature *feature; + const char* script; + int i; + + script = get_opentype_script(hdc,psa,psc,FALSE); + + for (i = 0; i < psc->feature_count; i++) + { + if (strncmp(psc->features[i].tag,feat,4)==0 && strncmp(psc->features[i].script,script,4)==0) + return psc->features[i].feature; + } + + feature = NULL; + + if (psc->GSUB_Table) + { + const GSUB_Script *script; + const GSUB_LangSys *language; + int attempt = 2; + + do + { + script = GSUB_get_script_table(psc->GSUB_Table, get_opentype_script(hdc,psa,psc,(attempt==2))); + attempt--; + if (script) + { + if (psc->userLang != 0) + language = GSUB_get_lang_table(script,(char*)&psc->userLang); + else + language = GSUB_get_lang_table(script, "xxxx"); /* Need to get Lang tag */ + if (language) + feature = GSUB_get_feature(psc->GSUB_Table, language, feat); + } + } while(attempt && !feature); + + /* try in the default (latin) table */ + if (!feature) + { + script = GSUB_get_script_table(psc->GSUB_Table, "latn"); + if (script) + { + language = GSUB_get_lang_table(script, "xxxx"); /* Need to get Lang tag */ + if (language) + feature = GSUB_get_feature(psc->GSUB_Table, language, feat); + } + } + } + + TRACE("Feature %s located at %p\n",debugstr_an(feat,4),feature); + + psc->feature_count++; + + if (psc->features) + psc->features = HeapReAlloc(GetProcessHeap(), 0, psc->features, psc->feature_count * sizeof(LoadedFeature)); + else + psc->features = HeapAlloc(GetProcessHeap(), 0, psc->feature_count * sizeof(LoadedFeature)); + + lstrcpynA(psc->features[psc->feature_count - 1].tag, feat, 5); + lstrcpynA(psc->features[psc->feature_count - 1].script, script, 5); + psc->features[psc->feature_count - 1].feature = feature; + return feature; +} + +static INT apply_GSUB_feature_to_glyph(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, WORD *glyphs, INT index, INT write_dir, INT* glyph_count, const char* feat) { - const GSUB_Header *header; - const GSUB_Script *script; - const GSUB_LangSys *language; const GSUB_Feature *feature; - if (!GSUB_Table) - return GSUB_E_NOFEATURE; - - header = GSUB_Table; - - script = GSUB_get_script_table(header, get_opentype_script(hdc,psa)); - if (!script) - { - TRACE("Script not found\n"); - return GSUB_E_NOFEATURE; - } - language = GSUB_get_lang_table(script, "xxxx"); /* Need to get Lang tag */ - if (!language) - { - TRACE("Language not found\n"); - return GSUB_E_NOFEATURE; - } - feature = GSUB_get_feature(header, language, feat); + feature = load_GSUB_feature(hdc, psa, psc, feat); if (!feature) - { - TRACE("%s feature not found\n",feat); return GSUB_E_NOFEATURE; - } + TRACE("applying feature %s\n",feat); - return GSUB_apply_feature(header, feature, glyphs, index, write_dir, glyph_count); + return GSUB_apply_feature_all_lookups(psc->GSUB_Table, feature, glyphs, index, write_dir, glyph_count); } static VOID *load_gsub_table(HDC hdc) @@ -693,57 +1194,316 @@ static VOID *load_gsub_table(HDC hdc) return GSUB_Table; } -static int apply_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, void* GSUB_Table, WORD *pwOutGlyphs, int write_dir, INT* pcGlyphs, const char* feat) +INT SHAPE_does_GSUB_feature_apply_to_chars(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, const WCHAR *chars, INT write_dir, INT count, const char* feature) +{ + WORD *glyphs; + INT glyph_count = count; + INT rc; + + glyphs = HeapAlloc(GetProcessHeap(),0,sizeof(WORD)*(count*2)); + GetGlyphIndicesW(hdc, chars, count, glyphs, 0); + rc = apply_GSUB_feature_to_glyph(hdc, psa, psc, glyphs, 0, write_dir, &glyph_count, feature); + if (rc > GSUB_E_NOGLYPH) + rc = count - glyph_count; + else + rc = 0; + + HeapFree(GetProcessHeap(),0,glyphs); + return rc; +} + +static WORD GDEF_get_glyph_class(const GDEF_Header *header, WORD glyph) +{ + int offset; + WORD class = 0; + const GDEF_ClassDefFormat1 *cf1; + + if (!header) + return 0; + + offset = GET_BE_WORD(header->GlyphClassDef); + if (!offset) + return 0; + + cf1 = (GDEF_ClassDefFormat1*)(((BYTE*)header)+offset); + if (GET_BE_WORD(cf1->ClassFormat) == 1) + { + if (glyph >= GET_BE_WORD(cf1->StartGlyph)) + { + int index = glyph - GET_BE_WORD(cf1->StartGlyph); + if (index < GET_BE_WORD(cf1->GlyphCount)) + class = GET_BE_WORD(cf1->ClassValueArray[index]); + } + } + else if (GET_BE_WORD(cf1->ClassFormat) == 2) + { + const GDEF_ClassDefFormat2 *cf2 = (GDEF_ClassDefFormat2*)cf1; + int i, top; + top = GET_BE_WORD(cf2->ClassRangeCount); + for (i = 0; i < top; i++) + { + if (glyph >= GET_BE_WORD(cf2->ClassRangeRecord[i].Start) && + glyph <= GET_BE_WORD(cf2->ClassRangeRecord[i].End)) + { + class = GET_BE_WORD(cf2->ClassRangeRecord[i].Class); + break; + } + } + } + else + ERR("Unknown Class Format %i\n",GET_BE_WORD(cf1->ClassFormat)); + + return class; +} + +static VOID *load_gdef_table(HDC hdc) +{ + VOID* GDEF_Table = NULL; + int length = GetFontData(hdc, GDEF_TAG , 0, NULL, 0); + if (length != GDI_ERROR) + { + GDEF_Table = HeapAlloc(GetProcessHeap(),0,length); + GetFontData(hdc, GDEF_TAG , 0, GDEF_Table, length); + TRACE("Loaded GDEF table of %i bytes\n",length); + } + return GDEF_Table; +} + +static void GDEF_UpdateGlyphProps(HDC hdc, ScriptCache *psc, const WORD *pwGlyphs, const WORD cGlyphs, WORD* pwLogClust, const WORD cChars, SCRIPT_GLYPHPROP *pGlyphProp) { int i; - if (GSUB_Table) + if (!psc->GDEF_Table) + psc->GDEF_Table = load_gdef_table(hdc); + + for (i = 0; i < cGlyphs; i++) { - const GSUB_Header *header; - const GSUB_Script *script; - const GSUB_LangSys *language; - const GSUB_Feature *feature; + WORD class; + int char_count = 0; + int k; - if (!GSUB_Table) - return GSUB_E_NOFEATURE; + for (k = 0; k < cChars; k++) + if (pwLogClust[k] == i) + char_count++; - header = GSUB_Table; + class = GDEF_get_glyph_class(psc->GDEF_Table, pwGlyphs[i]); - script = GSUB_get_script_table(header, get_opentype_script(hdc,psa)); - if (!script) + switch (class) { - TRACE("Script not found\n"); - return GSUB_E_NOFEATURE; - } - language = GSUB_get_lang_table(script, "xxxx"); - if (!language) - { - TRACE("Language not found\n"); - return GSUB_E_NOFEATURE; - } - feature = GSUB_get_feature(header, language, feat); - if (!feature) - { - TRACE("%s feature not found\n",feat); - return GSUB_E_NOFEATURE; + case 0: + case BaseGlyph: + pGlyphProp[i].sva.fClusterStart = 1; + pGlyphProp[i].sva.fDiacritic = 0; + pGlyphProp[i].sva.fZeroWidth = 0; + break; + case LigatureGlyph: + pGlyphProp[i].sva.fClusterStart = 1; + pGlyphProp[i].sva.fDiacritic = 0; + pGlyphProp[i].sva.fZeroWidth = 0; + break; + case MarkGlyph: + pGlyphProp[i].sva.fClusterStart = 0; + pGlyphProp[i].sva.fDiacritic = 1; + pGlyphProp[i].sva.fZeroWidth = 1; + break; + case ComponentGlyph: + pGlyphProp[i].sva.fClusterStart = 0; + pGlyphProp[i].sva.fDiacritic = 0; + pGlyphProp[i].sva.fZeroWidth = 0; + break; + default: + ERR("Unknown glyph class %i\n",class); + pGlyphProp[i].sva.fClusterStart = 1; + pGlyphProp[i].sva.fDiacritic = 0; + pGlyphProp[i].sva.fZeroWidth = 0; } - i = 0; - TRACE("applying feature %s\n",feat); - while(i < *pcGlyphs) + if (char_count == 0) + pGlyphProp[i].sva.fClusterStart = 0; + } +} + +static void UpdateClustersFromGlyphProp(const int cGlyphs, const int cChars, WORD* pwLogClust, SCRIPT_GLYPHPROP *pGlyphProp) +{ + int i; + + for (i = 0; i < cGlyphs; i++) + { + if (!pGlyphProp[i].sva.fClusterStart) { - INT nextIndex; - nextIndex = GSUB_apply_feature(header, feature, pwOutGlyphs, i, write_dir, pcGlyphs); - if (nextIndex > GSUB_E_NOGLYPH) - i = nextIndex; + int j; + for (j = 0; j < cChars; j++) + { + if (pwLogClust[j] == i) + { + int k = j; + while (!pGlyphProp[pwLogClust[k]].sva.fClusterStart && k >= 0 && k 0) + { + if (write_dir > 0) + target_glyph = nextIndex - changeCount; + else + target_glyph = nextIndex + (changeCount + 1); + } + + seeking_glyph = target_glyph; + for (i = 0; i < chars; i++) + if (pwLogClust[i] > top_logclust) + top_logclust = pwLogClust[i]; + + do { + if (write_dir > 0) + for (i = 0; i < chars; i++) + { + if (pwLogClust[i] == seeking_glyph) + { + target_index = i; + break; + } + } + else + for (i = chars - 1; i >= 0; i--) + { + if (pwLogClust[i] == seeking_glyph) + { + target_index = i; + break; + } + } + if (target_index == -1) + seeking_glyph ++; + } + while (target_index == -1 && seeking_glyph <= top_logclust); + + if (target_index == -1) + { + ERR("Unable to find target glyph\n"); + return; + } + + if (changeCount < 0) + { + /* merge glyphs */ + for(i = target_index; i < chars && i >= 0; i+=write_dir) + { + if (pwLogClust[i] == target_glyph) + continue; + if(pwLogClust[i] == replacing_glyph) + pwLogClust[i] = target_glyph; else - i++; + { + changed--; + if (changed >= changeCount) + { + replacing_glyph = pwLogClust[i]; + pwLogClust[i] = target_glyph; + } + else + break; + } + } + + /* renumber trailing indexes*/ + for(i = target_index; i < chars && i >= 0; i+=write_dir) + { + if (pwLogClust[i] != target_glyph) + pwLogClust[i] += changeCount; + } + } + else + { + for(i = target_index; i < chars && i >= 0; i+=write_dir) + pwLogClust[i] += changeCount; + } + } +} + +static int apply_GSUB_feature(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, WORD *pwOutGlyphs, int write_dir, INT* pcGlyphs, INT cChars, const char* feat, WORD *pwLogClust ) +{ + if (psc->GSUB_Table) + { + const GSUB_Feature *feature; + const GSUB_LookupList *lookup; + const GSUB_Header *header = psc->GSUB_Table; + int lookup_index, lookup_count; + + feature = load_GSUB_feature(hdc, psa, psc, feat); + if (!feature) + return GSUB_E_NOFEATURE; + + TRACE("applying feature %s\n",debugstr_an(feat,4)); + lookup = (const GSUB_LookupList*)((const BYTE*)header + GET_BE_WORD(header->LookupList)); + lookup_count = GET_BE_WORD(feature->LookupCount); + TRACE("%i lookups\n", lookup_count); + for (lookup_index = 0; lookup_index < lookup_count; lookup_index++) + { + int i; + + if (write_dir > 0) + i = 0; + else + i = *pcGlyphs-1; + TRACE("applying lookup (%i/%i)\n",lookup_index,lookup_count); + while(i < *pcGlyphs && i >= 0) + { + INT nextIndex; + INT prevCount = *pcGlyphs; + + nextIndex = GSUB_apply_lookup(lookup, GET_BE_WORD(feature->LookupListIndex[lookup_index]), pwOutGlyphs, i, write_dir, pcGlyphs); + if (*pcGlyphs != prevCount) + { + UpdateClusters(nextIndex, *pcGlyphs - prevCount, write_dir, cChars, pwLogClust); + i = nextIndex; + } + else + i+=write_dir; + } } return *pcGlyphs; } return GSUB_E_NOFEATURE; } +static inline BOOL get_GSUB_Indic2(SCRIPT_ANALYSIS *psa, ScriptCache *psc) +{ + return(GSUB_get_script_table(psc->GSUB_Table,ShapingData[psa->eScript].newOtTag)!=NULL); +} + +static WCHAR neighbour_char(int i, int delta, const WCHAR* chars, INT cchLen) +{ + if (i + delta < 0) + return 0; + if ( i+ delta >= cchLen) + return 0; + + i += delta; + + return chars[i]; +} + static CHAR neighbour_joining_type(int i, int delta, const CHAR* context_type, INT cchLen, SCRIPT_ANALYSIS *psa) { if (i + delta < 0) @@ -779,25 +1539,30 @@ static inline BOOL left_join_causing(CHAR joining_type) return (joining_type == jtR || joining_type == jtD || joining_type == jtC); } -/* SHAPE_ShapeArabicGlyphs +static inline BOOL word_break_causing(WCHAR chr) +{ + /* we are working within a string of characters already guareented to + be within one script, Syriac, so we do not worry about any character + other than the space character outside of that range */ + return (chr == 0 || chr == 0x20 ); +} + +/* + * ContextualShape_Arabic */ -void SHAPE_ShapeArabicGlyphs(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs) +static void ContextualShape_Arabic(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) { CHAR *context_type; INT *context_shape; INT dirR, dirL; int i; - if (psa->eScript != Script_Arabic) - return; - if (*pcGlyphs != cChars) { ERR("Number of Glyphs and Chars need to match at the beginning\n"); return; } - if (!psa->fLogicalOrder && psa->fRTL) { dirR = 1; @@ -816,7 +1581,7 @@ void SHAPE_ShapeArabicGlyphs(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WC context_shape = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * cChars); for (i = 0; i < cChars; i++) - context_type[i] = wine_shaping_table[wine_shaping_table[pwcChars[i] >> 8] + (pwcChars[i] & 0xff)]; + context_type[i] = get_table_entry( wine_shaping_table, pwcChars[i] ); for (i = 0; i < cChars; i++) { @@ -843,33 +1608,1858 @@ void SHAPE_ShapeArabicGlyphs(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WC if (psc->GSUB_Table) { INT nextIndex; - nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc->GSUB_Table, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]); + INT prevCount = *pcGlyphs; + nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]); if (nextIndex > GSUB_E_NOGLYPH) + { i = nextIndex; + UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust); + } shaped = (nextIndex > GSUB_E_NOGLYPH); } if (!shaped) { - WORD newGlyph = pwOutGlyphs[i]; - if (pwcChars[i] >= FIRST_ARABIC_CHAR && pwcChars[i] <= LAST_ARABIC_CHAR) + if (context_shape[i] == Xn) { - /* fall back to presentation form B */ - WCHAR context_char = wine_shaping_forms[pwcChars[i] - FIRST_ARABIC_CHAR][context_shape[i]]; - if (context_char != pwcChars[i] && GetGlyphIndicesW(hdc, &context_char, 1, &newGlyph, 0) != GDI_ERROR && newGlyph != 0x0000) - pwOutGlyphs[i] = newGlyph; + WORD newGlyph = pwOutGlyphs[i]; + if (pwcChars[i] >= FIRST_ARABIC_CHAR && pwcChars[i] <= LAST_ARABIC_CHAR) + { + /* fall back to presentation form B */ + WCHAR context_char = wine_shaping_forms[pwcChars[i] - FIRST_ARABIC_CHAR][context_shape[i]]; + if (context_char != pwcChars[i] && GetGlyphIndicesW(hdc, &context_char, 1, &newGlyph, 0) != GDI_ERROR && newGlyph != 0x0000) + pwOutGlyphs[i] = newGlyph; + } } i++; } } - i = 0; - while (arabic_GSUB_features[i] != NULL) + HeapFree(GetProcessHeap(),0,context_shape); + HeapFree(GetProcessHeap(),0,context_type); +} + +/* + * ContextualShape_Syriac + */ + +#define ALAPH 0x710 +#define DALATH 0x715 +#define RISH 0x72A + +static void ContextualShape_Syriac(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +{ + CHAR *context_type; + INT *context_shape; + INT dirR, dirL; + int i; + + if (*pcGlyphs != cChars) { - apply_GSUB_feature(hdc, psa, psc->GSUB_Table, pwOutGlyphs, dirL, pcGlyphs, arabic_GSUB_features[i]); - i++; + ERR("Number of Glyphs and Chars need to match at the beginning\n"); + return; + } + + if (!psa->fLogicalOrder && psa->fRTL) + { + dirR = 1; + dirL = -1; + } + else + { + dirR = -1; + dirL = 1; + } + + if (!psc->GSUB_Table) + psc->GSUB_Table = load_gsub_table(hdc); + + if (!psc->GSUB_Table) + return; + + context_type = HeapAlloc(GetProcessHeap(),0,cChars); + context_shape = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * cChars); + + for (i = 0; i < cChars; i++) + context_type[i] = get_table_entry( wine_shaping_table, pwcChars[i] ); + + for (i = 0; i < cChars; i++) + { + if (pwcChars[i] == ALAPH) + { + WCHAR rchar = neighbour_char(i,dirR,pwcChars,cChars); + + if (left_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)) && word_break_causing(neighbour_char(i,dirL,pwcChars,cChars))) + context_shape[i] = Afj; + else if ( rchar != DALATH && rchar != RISH && +!left_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa)) && +word_break_causing(neighbour_char(i,dirL,pwcChars,cChars))) + context_shape[i] = Afn; + else if ( (rchar == DALATH || rchar == RISH) && word_break_causing(neighbour_char(i,dirL,pwcChars,cChars))) + context_shape[i] = Afx; + else + context_shape[i] = Xn; + } + else if (context_type[i] == jtR && +right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa))) + context_shape[i] = Xr; + else if (context_type[i] == jtL && left_join_causing(neighbour_joining_type(i,dirL,context_type,cChars,psa))) + context_shape[i] = Xl; + else if (context_type[i] == jtD && left_join_causing(neighbour_joining_type(i,dirL,context_type,cChars,psa)) && right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa))) + context_shape[i] = Xm; + else if (context_type[i] == jtD && right_join_causing(neighbour_joining_type(i,dirR,context_type,cChars,psa))) + context_shape[i] = Xr; + else if (context_type[i] == jtD && left_join_causing(neighbour_joining_type(i,dirL,context_type,cChars,psa))) + context_shape[i] = Xl; + else + context_shape[i] = Xn; + } + + /* Contextual Shaping */ + i = 0; + while(i < *pcGlyphs) + { + INT nextIndex; + INT prevCount = *pcGlyphs; + nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]); + if (nextIndex > GSUB_E_NOGLYPH) + { + UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust); + i = nextIndex; + } + else + i++; } HeapFree(GetProcessHeap(),0,context_shape); HeapFree(GetProcessHeap(),0,context_type); } + +/* + * ContextualShape_Phags_pa + */ + +#define phags_pa_CANDRABINDU 0xA873 +#define phags_pa_START 0xA840 +#define phags_pa_END 0xA87F + +static void ContextualShape_Phags_pa(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +{ + INT *context_shape; + INT dirR, dirL; + int i; + + if (*pcGlyphs != cChars) + { + ERR("Number of Glyphs and Chars need to match at the beginning\n"); + return; + } + + if (!psa->fLogicalOrder && psa->fRTL) + { + dirR = 1; + dirL = -1; + } + else + { + dirR = -1; + dirL = 1; + } + + if (!psc->GSUB_Table) + psc->GSUB_Table = load_gsub_table(hdc); + + if (!psc->GSUB_Table) + return; + + context_shape = HeapAlloc(GetProcessHeap(),0,sizeof(INT) * cChars); + + for (i = 0; i < cChars; i++) + { + if (pwcChars[i] >= phags_pa_START && pwcChars[i] <= phags_pa_END) + { + WCHAR rchar = neighbour_char(i,dirR,pwcChars,cChars); + WCHAR lchar = neighbour_char(i,dirL,pwcChars,cChars); + BOOL jrchar = (rchar != phags_pa_CANDRABINDU && rchar >= phags_pa_START && rchar <= phags_pa_END); + BOOL jlchar = (lchar != phags_pa_CANDRABINDU && lchar >= phags_pa_START && lchar <= phags_pa_END); + + if (jrchar && jlchar) + context_shape[i] = Xm; + else if (jrchar) + context_shape[i] = Xr; + else if (jlchar) + context_shape[i] = Xl; + else + context_shape[i] = Xn; + } + else + context_shape[i] = -1; + } + + /* Contextual Shaping */ + i = 0; + while(i < *pcGlyphs) + { + if (context_shape[i] >= 0) + { + INT nextIndex; + INT prevCount = *pcGlyphs; + nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, i, dirL, pcGlyphs, contextual_features[context_shape[i]]); + if (nextIndex > GSUB_E_NOGLYPH) + { + UpdateClusters(nextIndex, *pcGlyphs - prevCount, dirL, cChars, pwLogClust); + i = nextIndex; + } + else + i++; + } + else + i++; + } + + HeapFree(GetProcessHeap(),0,context_shape); +} + +static void ReplaceInsertChars(HDC hdc, INT cWalk, INT* pcChars, WCHAR *pwOutChars, const WCHAR *replacements) +{ + int i; + + /* Replace */ + pwOutChars[cWalk] = replacements[0]; + cWalk=cWalk+1; + + /* Insert */ + for (i = 1; replacements[i] != 0x0000 && i < 3; i++) + { + int j; + for (j = *pcChars; j > cWalk; j--) + pwOutChars[j] = pwOutChars[j-1]; + *pcChars= *pcChars+1; + pwOutChars[cWalk] = replacements[i]; + cWalk = cWalk+1; + } +} + +static void DecomposeVowels(HDC hdc, WCHAR *pwOutChars, INT *pcChars, const VowelComponents vowels[], WORD* pwLogClust, INT cChars) +{ + int i; + int cWalk; + + for (cWalk = 0; cWalk < *pcChars; cWalk++) + { + for (i = 0; vowels[i].base != 0x0; i++) + { + if (pwOutChars[cWalk] == vowels[i].base) + { + int o = 0; + ReplaceInsertChars(hdc, cWalk, pcChars, pwOutChars, vowels[i].parts); + if (vowels[i].parts[1]) { cWalk++; o++; } + if (vowels[i].parts[2]) { cWalk++; o++; } + UpdateClusters(cWalk, o, 1, cChars, pwLogClust); + break; + } + } + } +} + +static void ComposeConsonants(HDC hdc, WCHAR *pwOutChars, INT *pcChars, const ConsonantComponents consonants[], WORD* pwLogClust) +{ + int i; + int offset = 0; + int cWalk; + + for (cWalk = 0; cWalk < *pcChars; cWalk++) + { + for (i = 0; consonants[i].output!= 0x0; i++) + { + int j; + for (j = 0; j + cWalk < *pcChars && consonants[i].parts[j]!=0x0; j++) + if (pwOutChars[cWalk+j] != consonants[i].parts[j]) + break; + + if (consonants[i].parts[j]==0x0) /* matched all */ + { + int k; + j--; + pwOutChars[cWalk] = consonants[i].output; + for(k = cWalk+1; k < *pcChars - j; k++) + pwOutChars[k] = pwOutChars[k+j]; + *pcChars = *pcChars - j; + for (k = j ; k > 0; k--) + pwLogClust[cWalk + k + offset] = pwLogClust[cWalk + offset]; + offset += j; + for (k = cWalk + j + offset; k < *pcChars + offset; k++) + pwLogClust[k]--; + break; + } + } + cWalk++; + } +} + +static void Reorder_Ra_follows_base(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +{ + if (s->ralf >= 0) + { + int j; + WORD Ra = pwChar[s->start]; + WORD H = pwChar[s->start+1]; + + TRACE("Doing reorder of Ra to %i\n",s->base); + for (j = s->start; j < s->base-1; j++) + pwChar[j] = pwChar[j+2]; + pwChar[s->base-1] = Ra; + pwChar[s->base] = H; + + s->ralf = s->base-1; + s->base -= 2; + } +} + +static void Reorder_Ra_follows_matra(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +{ + if (s->ralf >= 0) + { + int j,loc; + int stop = (s->blwf >=0)? s->blwf+1 : s->base; + WORD Ra = pwChar[s->start]; + WORD H = pwChar[s->start+1]; + for (loc = s->end; loc > stop; loc--) + if (lexical(pwChar[loc]) == lex_Matra_post || lexical(pwChar[loc]) == lex_Matra_below) + break; + + TRACE("Doing reorder of Ra to %i\n",loc); + for (j = s->start; j < loc-1; j++) + pwChar[j] = pwChar[j+2]; + pwChar[loc-1] = Ra; + pwChar[loc] = H; + + s->ralf = loc-1; + s->base -= 2; + if (s->blwf >= 0) s->blwf -= 2; + if (s->pref >= 0) s->pref -= 2; + } +} + +static void Reorder_Ra_follows_syllable(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +{ + if (s->ralf >= 0) + { + int j; + WORD Ra = pwChar[s->start]; + WORD H = pwChar[s->start+1]; + + TRACE("Doing reorder of Ra to %i\n",s->end-1); + for (j = s->start; j < s->end-1; j++) + pwChar[j] = pwChar[j+2]; + pwChar[s->end-1] = Ra; + pwChar[s->end] = H; + + s->ralf = s->end-1; + s->base -= 2; + if (s->blwf >= 0) s->blwf -= 2; + if (s->pref >= 0) s->pref -= 2; + } +} + +static void Reorder_Matra_precede_base(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +{ + int i; + + /* reorder Matras */ + if (s->end > s->base) + { + for (i = 1; i <= s->end-s->base; i++) + { + if (lexical(pwChar[s->base+i]) == lex_Matra_pre) + { + int j; + WCHAR c = pwChar[s->base+i]; + TRACE("Doing reorder of %x %x\n",c,pwChar[s->base]); + for (j = s->base+i; j > s->base; j--) + pwChar[j] = pwChar[j-1]; + pwChar[s->base] = c; + + if (s->ralf >= s->base) s->ralf++; + if (s->blwf >= s->base) s->blwf++; + if (s->pref >= s->base) s->pref++; + s->base ++; + } + } + } +} + +static void Reorder_Matra_precede_syllable(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +{ + int i; + + /* reorder Matras */ + if (s->end > s->base) + { + for (i = 1; i <= s->end-s->base; i++) + { + if (lexical(pwChar[s->base+i]) == lex_Matra_pre) + { + int j; + WCHAR c = pwChar[s->base+i]; + TRACE("Doing reorder of %x to %i\n",c,s->start); + for (j = s->base+i; j > s->start; j--) + pwChar[j] = pwChar[j-1]; + pwChar[s->start] = c; + + if (s->ralf >= 0) s->ralf++; + if (s->blwf >= 0) s->blwf++; + if (s->pref >= 0) s->pref++; + s->base ++; + } + } + } +} + +static void SecondReorder_Blwf_follows_matra(LPWSTR pwChar, IndicSyllable *s, WORD *glyphs, IndicSyllable *g, lexical_function lexical) +{ + if (s->blwf >= 0 && g->blwf > g->base) + { + int j,loc; + int g_offset; + for (loc = s->end; loc > s->blwf; loc--) + if (lexical(pwChar[loc]) == lex_Matra_below || lexical(pwChar[loc]) == lex_Matra_above || lexical(pwChar[loc]) == lex_Matra_post) + break; + + g_offset = (loc - s->blwf) - 1; + + if (loc != s->blwf) + { + WORD blwf = glyphs[g->blwf]; + TRACE("Doing reorder of Below-base to %i (glyph offset %i)\n",loc,g_offset); + /* do not care about the pwChar array anymore, just the glyphs */ + for (j = 0; j < g_offset; j++) + glyphs[g->blwf + j] = glyphs[g->blwf + j + 1]; + glyphs[g->blwf + g_offset] = blwf; + } + } +} + +static void SecondReorder_Matra_precede_base(LPWSTR pwChar, IndicSyllable *s, WORD *glyphs, IndicSyllable *g, lexical_function lexical) +{ + int i; + + /* reorder previously moved Matras to correct position*/ + for (i = s->start; i < s->base; i++) + { + if (lexical(pwChar[i]) == lex_Matra_pre) + { + int j; + int g_start = g->start + i - s->start; + if (g_start < g->base -1 ) + { + WCHAR og = glyphs[g_start]; + TRACE("Doing reorder of matra from %i to %i\n",g_start,g->base); + for (j = g_start; j < g->base-1; j++) + glyphs[j] = glyphs[j+1]; + glyphs[g->base-1] = og; + } + } + } +} + +static void SecondReorder_Pref_precede_base(LPWSTR pwChar, IndicSyllable *s, WORD *glyphs, IndicSyllable *g, lexical_function lexical) +{ + if (s->pref >= 0 && g->pref > g->base) + { + int j; + WCHAR og = glyphs[g->pref]; + TRACE("Doing reorder of pref from %i to %i\n",g->pref,g->base); + for (j = g->pref; j > g->base; j--) + glyphs[j] = glyphs[j-1]; + glyphs[g->base] = og; + } +} + +static void Reorder_Like_Sinhala(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +{ + TRACE("Syllable (%i..%i..%i)\n",s->start,s->base,s->end); + if (s->start == s->base && s->base == s->end) return; + if (lexical(pwChar[s->base]) == lex_Vowel) return; + + Reorder_Ra_follows_base(pwChar, s, lexical); + Reorder_Matra_precede_base(pwChar, s, lexical); +} + +static void Reorder_Like_Devanagari(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +{ + TRACE("Syllable (%i..%i..%i)\n",s->start,s->base,s->end); + if (s->start == s->base && s->base == s->end) return; + if (lexical(pwChar[s->base]) == lex_Vowel) return; + + Reorder_Ra_follows_matra(pwChar, s, lexical); + Reorder_Matra_precede_syllable(pwChar, s, lexical); +} + +static void Reorder_Like_Bengali(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +{ + TRACE("Syllable (%i..%i..%i)\n",s->start,s->base,s->end); + if (s->start == s->base && s->base == s->end) return; + if (lexical(pwChar[s->base]) == lex_Vowel) return; + + Reorder_Ra_follows_base(pwChar, s, lexical); + Reorder_Matra_precede_syllable(pwChar, s, lexical); +} + +static void Reorder_Like_Kannada(LPWSTR pwChar, IndicSyllable *s, lexical_function lexical) +{ + TRACE("Syllable (%i..%i..%i)\n",s->start,s->base,s->end); + if (s->start == s->base && s->base == s->end) return; + if (lexical(pwChar[s->base]) == lex_Vowel) return; + + Reorder_Ra_follows_syllable(pwChar, s, lexical); + Reorder_Matra_precede_syllable(pwChar, s, lexical); +} + +static void SecondReorder_Like_Telugu(LPWSTR pwChar, IndicSyllable *s, WORD* pwGlyphs, IndicSyllable *g, lexical_function lexical) +{ + TRACE("Syllable (%i..%i..%i)\n",s->start,s->base,s->end); + TRACE("Glyphs (%i..%i..%i)\n",g->start,g->base,g->end); + if (s->start == s->base && s->base == s->end) return; + if (lexical(pwChar[s->base]) == lex_Vowel) return; + + SecondReorder_Blwf_follows_matra(pwChar, s, pwGlyphs, g, lexical); +} + +static void SecondReorder_Like_Tamil(LPWSTR pwChar, IndicSyllable *s, WORD* pwGlyphs, IndicSyllable *g, lexical_function lexical) +{ + TRACE("Syllable (%i..%i..%i)\n",s->start,s->base,s->end); + TRACE("Glyphs (%i..%i..%i)\n",g->start,g->base,g->end); + if (s->start == s->base && s->base == s->end) return; + if (lexical(pwChar[s->base]) == lex_Vowel) return; + + SecondReorder_Matra_precede_base(pwChar, s, pwGlyphs, g, lexical); + SecondReorder_Pref_precede_base(pwChar, s, pwGlyphs, g, lexical); +} + + +static inline void shift_syllable_glyph_indexs(IndicSyllable *glyph_index, INT index, INT shift) +{ + if (shift == 0) + return; + + if (glyph_index->start > index) + glyph_index->start += shift; + if (glyph_index->base > index) + glyph_index->base+= shift; + if (glyph_index->end > index) + glyph_index->end+= shift; + if (glyph_index->ralf > index) + glyph_index->ralf+= shift; + if (glyph_index->blwf > index) + glyph_index->blwf+= shift; + if (glyph_index->pref > index) + glyph_index->pref+= shift; +} + +static void Apply_Indic_BasicForm(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index, const GSUB_Feature *feature ) +{ + int index = glyph_index->start; + + if (!feature) + return; + + while(index <= glyph_index->end) + { + INT nextIndex; + INT prevCount = *pcGlyphs; + nextIndex = GSUB_apply_feature_all_lookups(psc->GSUB_Table, feature, pwOutGlyphs, index, 1, pcGlyphs); + if (nextIndex > GSUB_E_NOGLYPH) + { + UpdateClusters(nextIndex, *pcGlyphs - prevCount, 1, cChars, pwLogClust); + shift_syllable_glyph_indexs(glyph_index,index,*pcGlyphs - prevCount); + index = nextIndex; + } + else + index++; + } +} + +static inline INT find_consonant_halant(WCHAR* pwChars, INT index, INT end, lexical_function lexical) +{ + int i = 0; + while (i + index < end - 1 && !(is_consonant(lexical(pwChars[index+i])) && (lexical(pwChars[index+i+1]) == lex_Halant || (index + i < end - 2 && lexical(pwChars[index+i+1]) == lex_Nukta && lexical(pwChars[index+i+2] == lex_Halant))))) + i++; + if (index + i <= end-1) + return index + i; + else + return -1; +} + +static void Apply_Indic_PreBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index, const char* feature) +{ + INT index, nextIndex; + INT count,g_offset; + + count = syllable->base - syllable->start; + + g_offset = 0; + index = find_consonant_halant(&pwChars[syllable->start], 0, count, lexical); + while (index >= 0 && index + g_offset < (glyph_index->base - glyph_index->start)) + { + INT prevCount = *pcGlyphs; + nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, index+glyph_index->start+g_offset, 1, pcGlyphs, feature); + if (nextIndex > GSUB_E_NOGLYPH) + { + UpdateClusters(nextIndex, *pcGlyphs - prevCount, 1, cChars, pwLogClust); + shift_syllable_glyph_indexs(glyph_index, index + glyph_index->start + g_offset, (*pcGlyphs - prevCount)); + g_offset += (*pcGlyphs - prevCount); + } + + index+=2; + index = find_consonant_halant(&pwChars[syllable->start], index, count, lexical); + } +} + +static void Apply_Indic_Rphf(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index) +{ + INT nextIndex; + INT prevCount = *pcGlyphs; + + if (syllable->ralf >= 0) + { + nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, glyph_index->ralf, 1, pcGlyphs, "rphf"); + if (nextIndex > GSUB_E_NOGLYPH) + { + UpdateClusters(nextIndex, *pcGlyphs - prevCount, 1, cChars, pwLogClust); + shift_syllable_glyph_indexs(glyph_index,glyph_index->ralf,*pcGlyphs - prevCount); + } + } +} + +static inline INT find_halant_consonant(WCHAR* pwChars, INT index, INT end, lexical_function lexical) +{ + int i = 0; + while (index + i < end-1 && !(lexical(pwChars[index+i]) == lex_Halant && + ((index + i < end-2 && lexical(pwChars[index+i]) == lex_Nukta && is_consonant(lexical(pwChars[index+i+1]))) || + is_consonant(lexical(pwChars[index+i+1]))))) + i++; + if (index + i <= end-1) + return index+i; + else + return -1; +} + +static void Apply_Indic_PostBase(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllable, WORD *pwOutGlyphs, INT* pcGlyphs, WORD *pwLogClust, lexical_function lexical, IndicSyllable *glyph_index, BOOL modern, const char* feat) +{ + INT index, nextIndex; + INT count, g_offset=0; + INT ralf = syllable->ralf; + + count = syllable->end - syllable->base; + + index = find_halant_consonant(&pwChars[syllable->base], 0, count, lexical); + + while (index >= 0) + { + INT prevCount = *pcGlyphs; + if (ralf >=0 && ralf < index) + { + g_offset--; + ralf = -1; + } + + if (!modern) + { + WORD g = pwOutGlyphs[index+glyph_index->base+g_offset]; + pwOutGlyphs[index+glyph_index->base+g_offset] = pwOutGlyphs[index+glyph_index->base+g_offset+1]; + pwOutGlyphs[index+glyph_index->base+g_offset+1] = g; + } + + nextIndex = apply_GSUB_feature_to_glyph(hdc, psa, psc, pwOutGlyphs, index+glyph_index->base+g_offset, 1, pcGlyphs, feat); + if (nextIndex > GSUB_E_NOGLYPH) + { + UpdateClusters(nextIndex, *pcGlyphs - prevCount, 1, cChars, pwLogClust); + shift_syllable_glyph_indexs(glyph_index,index+glyph_index->start+g_offset, (*pcGlyphs - prevCount)); + g_offset += (*pcGlyphs - prevCount); + } + else if (!modern) + { + WORD g = pwOutGlyphs[index+glyph_index->base+g_offset]; + pwOutGlyphs[index+glyph_index->base+g_offset] = pwOutGlyphs[index+glyph_index->base+g_offset+1]; + pwOutGlyphs[index+glyph_index->base+g_offset+1] = g; + } + + index+=2; + index = find_halant_consonant(&pwChars[syllable->base], index, count, lexical); + } +} + +static void ShapeIndicSyllables(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwChars, INT cChars, IndicSyllable *syllables, INT syllable_count, WORD *pwOutGlyphs, INT* pcGlyphs, WORD *pwLogClust, lexical_function lexical, second_reorder_function second_reorder, BOOL modern) +{ + int c; + int overall_shift = 0; + const GSUB_Feature *locl = (modern)?load_GSUB_feature(hdc, psa, psc, "locl"):NULL; + const GSUB_Feature *nukt = load_GSUB_feature(hdc, psa, psc, "nukt"); + const GSUB_Feature *akhn = load_GSUB_feature(hdc, psa, psc, "akhn"); + const GSUB_Feature *rkrf = (modern)?load_GSUB_feature(hdc, psa, psc, "rkrf"):NULL; + const GSUB_Feature *pstf = load_GSUB_feature(hdc, psa, psc, "pstf"); + const GSUB_Feature *vatu = (!rkrf)?load_GSUB_feature(hdc, psa, psc, "vatu"):NULL; + const GSUB_Feature *cjct = (modern)?load_GSUB_feature(hdc, psa, psc, "cjct"):NULL; + BOOL rphf = (load_GSUB_feature(hdc, psa, psc, "rphf") != NULL); + BOOL pref = (load_GSUB_feature(hdc, psa, psc, "pref") != NULL); + BOOL blwf = (load_GSUB_feature(hdc, psa, psc, "blwf") != NULL); + BOOL half = (load_GSUB_feature(hdc, psa, psc, "half") != NULL); + IndicSyllable glyph_indexs; + + for (c = 0; c < syllable_count; c++) + { + int old_end; + memcpy(&glyph_indexs, &syllables[c], sizeof(IndicSyllable)); + shift_syllable_glyph_indexs(&glyph_indexs, -1, overall_shift); + old_end = glyph_indexs.end; + + if (locl) + { + TRACE("applying feature locl\n"); + Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indexs, locl); + } + if (nukt) + { + TRACE("applying feature nukt\n"); + Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indexs, nukt); + } + if (akhn) + { + TRACE("applying feature akhn\n"); + Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indexs, akhn); + } + + if (rphf) + Apply_Indic_Rphf(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indexs); + if (rkrf) + { + TRACE("applying feature rkrf\n"); + Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indexs, rkrf); + } + if (pref) + Apply_Indic_PostBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indexs, modern, "pref"); + if (blwf) + { + if (!modern) + Apply_Indic_PreBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indexs, "blwf"); + + Apply_Indic_PostBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indexs, modern, "blwf"); + + } + if (half) + Apply_Indic_PreBase(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indexs, "half"); + if (pstf) + { + TRACE("applying feature pstf\n"); + Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indexs, pstf); + } + if (vatu) + { + TRACE("applying feature vatu\n"); + Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indexs, vatu); + } + if (cjct) + { + TRACE("applying feature cjct\n"); + Apply_Indic_BasicForm(hdc, psc, psa, pwChars, cChars, &syllables[c], pwOutGlyphs, pcGlyphs, pwLogClust, lexical, &glyph_indexs, cjct); + } + + if (second_reorder) + second_reorder(pwChars, &syllables[c], pwOutGlyphs, &glyph_indexs, lexical); + + overall_shift += glyph_indexs.end - old_end; + } +} + +static inline int unicode_lex(WCHAR c) +{ + int type; + + if (!c) return lex_Generic; + if (c == 0x200D) return lex_ZWJ; + if (c == 0x200C) return lex_ZWNJ; + if (c == 0x00A0) return lex_NBSP; + + type = get_table_entry( indic_syllabic_table, c ); + + if ((type & 0x00ff) != 0x0007) type = type & 0x00ff; + + switch( type ) + { + case 0x0d07: /* Unknown */ + case 0x0e07: /* Unknwon */ + default: return lex_Generic; + case 0x0001: + case 0x0002: + case 0x0011: + case 0x0012: + case 0x0013: + case 0x0014: return lex_Modifier; + case 0x0003: + case 0x0009: + case 0x000a: + case 0x000b: + case 0x000d: + case 0x000e: + case 0x000f: + case 0x0010: return lex_Consonant; + case 0x0004: return lex_Nukta; + case 0x0005: return lex_Halant; + case 0x0006: + case 0x0008: return lex_Vowel; + case 0x0007: + case 0x0107: return lex_Matra_post; + case 0x0207: + case 0x0307: return lex_Matra_pre; + case 0x0807: + case 0x0907: + case 0x0a07: + case 0x0b07: + case 0x0c07: + case 0x0407: return lex_Composed_Vowel; + case 0x0507: return lex_Matra_above; + case 0x0607: return lex_Matra_below; + case 0x000c: return lex_Ra; + }; +} + +static int sinhala_lex(WCHAR c) +{ + switch (c) + { + case 0x0DDA: + case 0x0DDD: + case 0x0DDC: + case 0x0DDE: return lex_Matra_post; + default: + return unicode_lex(c); + } +} + +static const VowelComponents Sinhala_vowels[] = { + {0x0DDA, {0x0DD9,0x0DDA,0x0}}, + {0x0DDC, {0x0DD9,0x0DDC,0x0}}, + {0x0DDD, {0x0DD9,0x0DDD,0x0}}, + {0x0DDE, {0x0DD9,0x0DDE,0x0}}, + {0x0000, {0x0000,0x0000,0x0}}}; + +static void ContextualShape_Sinhala(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +{ + int cCount = cChars; + int i; + WCHAR *input; + IndicSyllable *syllables = NULL; + int syllable_count = 0; + + if (*pcGlyphs != cChars) + { + ERR("Number of Glyphs and Chars need to match at the beginning\n"); + return; + } + + input = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR) * (cChars * 3)); + + memcpy(input, pwcChars, cChars * sizeof(WCHAR)); + + /* Step 1: Decompose multi part vowels */ + DecomposeVowels(hdc, input, &cCount, Sinhala_vowels, pwLogClust, cChars); + + TRACE("New double vowel expanded string %s (%i)\n",debugstr_wn(input,cCount),cCount); + + /* Step 2: Reorder within Syllables */ + Indic_ReorderCharacters( hdc, psa, psc, input, cCount, &syllables, &syllable_count, sinhala_lex, Reorder_Like_Sinhala, TRUE); + TRACE("reordered string %s\n",debugstr_wn(input,cCount)); + + /* Step 3: Strip dangling joiners */ + for (i = 0; i < cCount; i++) + { + if ((input[i] == 0x200D || input[i] == 0x200C) && + (i == 0 || input[i-1] == 0x0020 || i == cCount-1 || input[i+1] == 0x0020)) + input[i] = 0x0020; + } + + /* Step 4: Base Form application to syllables */ + GetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0); + *pcGlyphs = cCount; + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, sinhala_lex, NULL, TRUE); + + HeapFree(GetProcessHeap(),0,input); + HeapFree(GetProcessHeap(),0,syllables); +} + +static int devanagari_lex(WCHAR c) +{ + switch (c) + { + case 0x0930: return lex_Ra; + default: + return unicode_lex(c); + } +} + +static const ConsonantComponents Devanagari_consonants[] ={ + {{0x0928, 0x093C, 0x00000}, 0x0929}, + {{0x0930, 0x093C, 0x00000}, 0x0931}, + {{0x0933, 0x093C, 0x00000}, 0x0934}, + {{0x0915, 0x093C, 0x00000}, 0x0958}, + {{0x0916, 0x093C, 0x00000}, 0x0959}, + {{0x0917, 0x093C, 0x00000}, 0x095A}, + {{0x091C, 0x093C, 0x00000}, 0x095B}, + {{0x0921, 0x093C, 0x00000}, 0x095C}, + {{0x0922, 0x093C, 0x00000}, 0x095D}, + {{0x092B, 0x093C, 0x00000}, 0x095E}, + {{0x092F, 0x093C, 0x00000}, 0x095F}}; + +static void ContextualShape_Devanagari(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +{ + int cCount = cChars; + WCHAR *input; + IndicSyllable *syllables = NULL; + int syllable_count = 0; + BOOL modern = get_GSUB_Indic2(psa, psc); + + if (*pcGlyphs != cChars) + { + ERR("Number of Glyphs and Chars need to match at the beginning\n"); + return; + } + + input = HeapAlloc(GetProcessHeap(), 0, cChars * sizeof(WCHAR)); + memcpy(input, pwcChars, cChars * sizeof(WCHAR)); + + /* Step 1: Compose Consonant and Nukta */ + ComposeConsonants(hdc, input, &cCount, Devanagari_consonants, pwLogClust); + TRACE("New composed string %s (%i)\n",debugstr_wn(input,cCount),cCount); + + /* Step 2: Reorder within Syllables */ + Indic_ReorderCharacters( hdc, psa, psc, input, cCount, &syllables, &syllable_count, devanagari_lex, Reorder_Like_Devanagari, modern); + TRACE("reordered string %s\n",debugstr_wn(input,cCount)); + GetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0); + *pcGlyphs = cCount; + + /* Step 3: Base Form application to syllables */ + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, devanagari_lex, NULL, modern); + + HeapFree(GetProcessHeap(),0,input); + HeapFree(GetProcessHeap(),0,syllables); +} + +static int bengali_lex(WCHAR c) +{ + switch (c) + { + case 0x09B0: return lex_Ra; + default: + return unicode_lex(c); + } +} + +static const VowelComponents Bengali_vowels[] = { + {0x09CB, {0x09C7,0x09BE,0x0000}}, + {0x09CC, {0x09C7,0x09D7,0x0000}}, + {0x0000, {0x0000,0x0000,0x0000}}}; + +static const ConsonantComponents Bengali_consonants[] = { + {{0x09A4,0x09CD,0x200D}, 0x09CE}, + {{0x09A1,0x09BC,0x0000}, 0x09DC}, + {{0x09A2,0x09BC,0x0000}, 0x09DD}, + {{0x09AF,0x09BC,0x0000}, 0x09DF}, + {{0x0000,0x0000,0x0000}, 0x0000}}; + +static void ContextualShape_Bengali(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +{ + int cCount = cChars; + WCHAR *input; + IndicSyllable *syllables = NULL; + int syllable_count = 0; + BOOL modern = get_GSUB_Indic2(psa, psc); + + if (*pcGlyphs != cChars) + { + ERR("Number of Glyphs and Chars need to match at the beginning\n"); + return; + } + + input = HeapAlloc(GetProcessHeap(), 0, (cChars * 2) * sizeof(WCHAR)); + memcpy(input, pwcChars, cChars * sizeof(WCHAR)); + + /* Step 1: Decompose Vowels and Compose Consonents */ + DecomposeVowels(hdc, input, &cCount, Bengali_vowels, pwLogClust, cChars); + ComposeConsonants(hdc, input, &cCount, Bengali_consonants, pwLogClust); + TRACE("New composed string %s (%i)\n",debugstr_wn(input,cCount),cCount); + + /* Step 2: Reorder within Syllables */ + Indic_ReorderCharacters( hdc, psa, psc, input, cCount, &syllables, &syllable_count, bengali_lex, Reorder_Like_Bengali, modern); + TRACE("reordered string %s\n",debugstr_wn(input,cCount)); + GetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0); + *pcGlyphs = cCount; + + /* Step 3: Initial form is only applied to the beginning of words */ + for (cCount = cCount - 1 ; cCount >= 0; cCount --) + { + if (cCount == 0 || input[cCount] == 0x0020) /* space */ + { + int index = cCount; + int gCount = 1; + if (index > 0) index++; + + apply_GSUB_feature_to_glyph(hdc, psa, psc, &pwOutGlyphs[index], 0, 1, &gCount, "init"); + } + } + + /* Step 4: Base Form application to syllables */ + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, bengali_lex, NULL, modern); + + HeapFree(GetProcessHeap(),0,input); + HeapFree(GetProcessHeap(),0,syllables); +} + +static int gurmukhi_lex(WCHAR c) +{ + if (c == 0x0A71) + return lex_Modifier; + else + return unicode_lex(c); +} + +static const ConsonantComponents Gurmukhi_consonants[] = { + {{0x0A32,0x0A3C,0x0000}, 0x0A33}, + {{0x0A38,0x0A3C,0x0000}, 0x0A36}, + {{0x0A16,0x0A3C,0x0000}, 0x0A59}, + {{0x0A17,0x0A3C,0x0000}, 0x0A5A}, + {{0x0A1C,0x0A3C,0x0000}, 0x0A5B}, + {{0x0A2B,0x0A3C,0x0000}, 0x0A5E}, + {{0x0000,0x0000,0x0000}, 0x0000}}; + +static void ContextualShape_Gurmukhi(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +{ + int cCount = cChars; + WCHAR *input; + IndicSyllable *syllables = NULL; + int syllable_count = 0; + BOOL modern = get_GSUB_Indic2(psa, psc); + + if (*pcGlyphs != cChars) + { + ERR("Number of Glyphs and Chars need to match at the beginning\n"); + return; + } + + input = HeapAlloc(GetProcessHeap(), 0, cChars * sizeof(WCHAR)); + memcpy(input, pwcChars, cChars * sizeof(WCHAR)); + + /* Step 1: Compose Consonents */ + ComposeConsonants(hdc, input, &cCount, Gurmukhi_consonants, pwLogClust); + TRACE("New composed string %s (%i)\n",debugstr_wn(input,cCount),cCount); + + /* Step 2: Reorder within Syllables */ + Indic_ReorderCharacters( hdc, psa, psc, input, cCount, &syllables, &syllable_count, gurmukhi_lex, Reorder_Like_Bengali, modern); + TRACE("reordered string %s\n",debugstr_wn(input,cCount)); + GetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0); + *pcGlyphs = cCount; + + /* Step 3: Base Form application to syllables */ + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, gurmukhi_lex, NULL, modern); + + HeapFree(GetProcessHeap(),0,input); + HeapFree(GetProcessHeap(),0,syllables); +} + +static int gujarati_lex(WCHAR c) +{ + switch (c) + { + case 0x0AB0: return lex_Ra; + default: + return unicode_lex(c); + } +} + +static void ContextualShape_Gujarati(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +{ + int cCount = cChars; + WCHAR *input; + IndicSyllable *syllables = NULL; + int syllable_count = 0; + BOOL modern = get_GSUB_Indic2(psa, psc); + + if (*pcGlyphs != cChars) + { + ERR("Number of Glyphs and Chars need to match at the beginning\n"); + return; + } + + input = HeapAlloc(GetProcessHeap(), 0, cChars * sizeof(WCHAR)); + memcpy(input, pwcChars, cChars * sizeof(WCHAR)); + + /* Step 1: Reorder within Syllables */ + Indic_ReorderCharacters( hdc, psa, psc, input, cCount, &syllables, &syllable_count, gujarati_lex, Reorder_Like_Devanagari, modern); + TRACE("reordered string %s\n",debugstr_wn(input,cCount)); + GetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0); + *pcGlyphs = cCount; + + /* Step 2: Base Form application to syllables */ + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, gujarati_lex, NULL, modern); + + HeapFree(GetProcessHeap(),0,input); + HeapFree(GetProcessHeap(),0,syllables); +} + +static int oriya_lex(WCHAR c) +{ + switch (c) + { + case 0x0B30: return lex_Ra; + default: + return unicode_lex(c); + } +} + +static const VowelComponents Oriya_vowels[] = { + {0x0B48, {0x0B47,0x0B56,0x0000}}, + {0x0B4B, {0x0B47,0x0B3E,0x0000}}, + {0x0B4C, {0x0B47,0x0B57,0x0000}}, + {0x0000, {0x0000,0x0000,0x0000}}}; + +static const ConsonantComponents Oriya_consonants[] = { + {{0x0B21,0x0B3C,0x0000}, 0x0B5C}, + {{0x0B22,0x0B3C,0x0000}, 0x0B5D}, + {{0x0000,0x0000,0x0000}, 0x0000}}; + +static void ContextualShape_Oriya(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +{ + int cCount = cChars; + WCHAR *input; + IndicSyllable *syllables = NULL; + int syllable_count = 0; + BOOL modern = get_GSUB_Indic2(psa, psc); + + if (*pcGlyphs != cChars) + { + ERR("Number of Glyphs and Chars need to match at the beginning\n"); + return; + } + + input = HeapAlloc(GetProcessHeap(), 0, (cChars*2) * sizeof(WCHAR)); + memcpy(input, pwcChars, cChars * sizeof(WCHAR)); + + /* Step 1: Decompose Vowels and Compose Consonents */ + DecomposeVowels(hdc, input, &cCount, Oriya_vowels, pwLogClust, cChars); + ComposeConsonants(hdc, input, &cCount, Oriya_consonants, pwLogClust); + TRACE("New composed string %s (%i)\n",debugstr_wn(input,cCount),cCount); + + /* Step 2: Reorder within Syllables */ + Indic_ReorderCharacters( hdc, psa, psc, input, cCount, &syllables, &syllable_count, oriya_lex, Reorder_Like_Bengali, modern); + TRACE("reordered string %s\n",debugstr_wn(input,cCount)); + GetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0); + *pcGlyphs = cCount; + + /* Step 3: Base Form application to syllables */ + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, oriya_lex, NULL, modern); + + HeapFree(GetProcessHeap(),0,input); + HeapFree(GetProcessHeap(),0,syllables); +} + +static int tamil_lex(WCHAR c) +{ + return unicode_lex(c); +} + +static const VowelComponents Tamil_vowels[] = { + {0x0BCA, {0x0BC6,0x0BBE,0x0000}}, + {0x0BCB, {0x0BC7,0x0BBE,0x0000}}, + {0x0BCB, {0x0BC6,0x0BD7,0x0000}}, + {0x0000, {0x0000,0x0000,0x0000}}}; + +static const ConsonantComponents Tamil_consonants[] = { + {{0x0B92,0x0BD7,0x0000}, 0x0B94}, + {{0x0000,0x0000,0x0000}, 0x0000}}; + +static void ContextualShape_Tamil(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +{ + int cCount = cChars; + WCHAR *input; + IndicSyllable *syllables = NULL; + int syllable_count = 0; + BOOL modern = get_GSUB_Indic2(psa, psc); + + if (*pcGlyphs != cChars) + { + ERR("Number of Glyphs and Chars need to match at the beginning\n"); + return; + } + + input = HeapAlloc(GetProcessHeap(), 0, (cChars*2) * sizeof(WCHAR)); + memcpy(input, pwcChars, cChars * sizeof(WCHAR)); + + /* Step 1: Decompose Vowels and Compose Consonents */ + DecomposeVowels(hdc, input, &cCount, Tamil_vowels, pwLogClust, cChars); + ComposeConsonants(hdc, input, &cCount, Tamil_consonants, pwLogClust); + TRACE("New composed string %s (%i)\n",debugstr_wn(input,cCount),cCount); + + /* Step 2: Reorder within Syllables */ + Indic_ReorderCharacters( hdc, psa, psc, input, cCount, &syllables, &syllable_count, tamil_lex, Reorder_Like_Bengali, modern); + TRACE("reordered string %s\n",debugstr_wn(input,cCount)); + GetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0); + *pcGlyphs = cCount; + + /* Step 3: Base Form application to syllables */ + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, tamil_lex, SecondReorder_Like_Tamil, modern); + + HeapFree(GetProcessHeap(),0,input); + HeapFree(GetProcessHeap(),0,syllables); +} + +static int telugu_lex(WCHAR c) +{ + switch (c) + { + case 0x0C43: + case 0x0C44: return lex_Modifier; + default: + return unicode_lex(c); + } +} + +static const VowelComponents Telugu_vowels[] = { + {0x0C48, {0x0C46,0x0C56,0x0000}}, + {0x0000, {0x0000,0x0000,0x0000}}}; + +static void ContextualShape_Telugu(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +{ + int cCount = cChars; + WCHAR *input; + IndicSyllable *syllables = NULL; + int syllable_count = 0; + BOOL modern = get_GSUB_Indic2(psa, psc); + + if (*pcGlyphs != cChars) + { + ERR("Number of Glyphs and Chars need to match at the beginning\n"); + return; + } + + input = HeapAlloc(GetProcessHeap(), 0, (cChars*2) * sizeof(WCHAR)); + memcpy(input, pwcChars, cChars * sizeof(WCHAR)); + + /* Step 1: Decompose Vowels */ + DecomposeVowels(hdc, input, &cCount, Telugu_vowels, pwLogClust, cChars); + TRACE("New composed string %s (%i)\n",debugstr_wn(input,cCount),cCount); + + /* Step 2: Reorder within Syllables */ + Indic_ReorderCharacters( hdc, psa, psc, input, cCount, &syllables, &syllable_count, telugu_lex, Reorder_Like_Bengali, modern); + TRACE("reordered string %s\n",debugstr_wn(input,cCount)); + GetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0); + *pcGlyphs = cCount; + + /* Step 3: Base Form application to syllables */ + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, telugu_lex, SecondReorder_Like_Telugu, modern); + + HeapFree(GetProcessHeap(),0,input); + HeapFree(GetProcessHeap(),0,syllables); +} + +static int kannada_lex(WCHAR c) +{ + switch (c) + { + case 0x0CB0: return lex_Ra; + default: + return unicode_lex(c); + } +} + +static const VowelComponents Kannada_vowels[] = { + {0x0CC0, {0x0CBF,0x0CD5,0x0000}}, + {0x0CC7, {0x0CC6,0x0CD5,0x0000}}, + {0x0CC8, {0x0CC6,0x0CD6,0x0000}}, + {0x0CCA, {0x0CC6,0x0CC2,0x0000}}, + {0x0CCB, {0x0CC6,0x0CC2,0x0CD5}}, + {0x0000, {0x0000,0x0000,0x0000}}}; + +static void ContextualShape_Kannada(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +{ + int cCount = cChars; + WCHAR *input; + IndicSyllable *syllables = NULL; + int syllable_count = 0; + BOOL modern = get_GSUB_Indic2(psa, psc); + + if (*pcGlyphs != cChars) + { + ERR("Number of Glyphs and Chars need to match at the beginning\n"); + return; + } + + input = HeapAlloc(GetProcessHeap(), 0, (cChars*3) * sizeof(WCHAR)); + memcpy(input, pwcChars, cChars * sizeof(WCHAR)); + + /* Step 1: Decompose Vowels */ + DecomposeVowels(hdc, input, &cCount, Kannada_vowels, pwLogClust, cChars); + TRACE("New composed string %s (%i)\n",debugstr_wn(input,cCount),cCount); + + /* Step 2: Reorder within Syllables */ + Indic_ReorderCharacters( hdc, psa, psc, input, cCount, &syllables, &syllable_count, kannada_lex, Reorder_Like_Kannada, modern); + TRACE("reordered string %s\n",debugstr_wn(input,cCount)); + GetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0); + *pcGlyphs = cCount; + + /* Step 3: Base Form application to syllables */ + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, kannada_lex, SecondReorder_Like_Telugu, modern); + + HeapFree(GetProcessHeap(),0,input); + HeapFree(GetProcessHeap(),0,syllables); +} + +static int malayalam_lex(WCHAR c) +{ + return unicode_lex(c); +} + +static const VowelComponents Malayalam_vowels[] = { + {0x0D4A, {0x0D46,0x0D3E,0x0000}}, + {0x0D4B, {0x0D47,0x0D3E,0x0000}}, + {0x0D4C, {0x0D46,0x0D57,0x0000}}, + {0x0000, {0x0000,0x0000,0x0000}}}; + +static void ContextualShape_Malayalam(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +{ + int cCount = cChars; + WCHAR *input; + IndicSyllable *syllables = NULL; + int syllable_count = 0; + BOOL modern = get_GSUB_Indic2(psa, psc); + + if (*pcGlyphs != cChars) + { + ERR("Number of Glyphs and Chars need to match at the beginning\n"); + return; + } + + input = HeapAlloc(GetProcessHeap(), 0, (cChars*2) * sizeof(WCHAR)); + memcpy(input, pwcChars, cChars * sizeof(WCHAR)); + + /* Step 1: Decompose Vowels */ + DecomposeVowels(hdc, input, &cCount, Malayalam_vowels, pwLogClust, cChars); + TRACE("New composed string %s (%i)\n",debugstr_wn(input,cCount),cCount); + + /* Step 2: Reorder within Syllables */ + Indic_ReorderCharacters( hdc, psa, psc, input, cCount, &syllables, &syllable_count, malayalam_lex, Reorder_Like_Devanagari, modern); + TRACE("reordered string %s\n",debugstr_wn(input,cCount)); + GetGlyphIndicesW(hdc, input, cCount, pwOutGlyphs, 0); + *pcGlyphs = cCount; + + /* Step 3: Base Form application to syllables */ + ShapeIndicSyllables(hdc, psc, psa, input, cChars, syllables, syllable_count, pwOutGlyphs, pcGlyphs, pwLogClust, malayalam_lex, SecondReorder_Like_Tamil, modern); + + HeapFree(GetProcessHeap(),0,input); + HeapFree(GetProcessHeap(),0,syllables); +} + +static void ShapeCharGlyphProp_Default( HDC hdc, ScriptCache* psc, SCRIPT_ANALYSIS* psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD* pwLogClust, SCRIPT_CHARPROP* pCharProp, SCRIPT_GLYPHPROP* pGlyphProp) +{ + int i,k; + + for (i = 0; i < cGlyphs; i++) + { + int char_index[20]; + int char_count = 0; + + for (k = 0; k < cChars; k++) + { + if (pwLogClust[k] == i) + { + char_index[char_count] = k; + char_count++; + } + } + + if (char_count == 0) + continue; + + if (char_count ==1 && pwcChars[char_index[0]] == 0x0020) /* space */ + { + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_BLANK; + pCharProp[char_index[0]].fCanGlyphAlone = 1; + } + else + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_CHARACTER; + } + + GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); +} + +static void ShapeCharGlyphProp_Arabic( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) +{ + int i,k; + int initGlyph, finaGlyph; + INT dirR, dirL; + BYTE *spaces; + + spaces = HeapAlloc(GetProcessHeap(),0,cGlyphs); + memset(spaces,0,cGlyphs); + + if (!psa->fLogicalOrder && psa->fRTL) + { + initGlyph = cGlyphs-1; + finaGlyph = 0; + dirR = 1; + dirL = -1; + } + else + { + initGlyph = 0; + finaGlyph = cGlyphs-1; + dirR = -1; + dirL = 1; + } + + for (i = 0; i < cGlyphs; i++) + { + for (k = 0; k < cChars; k++) + if (pwLogClust[k] == i) + { + if (pwcChars[k] == 0x0020) + spaces[i] = 1; + } + } + + for (i = 0; i < cGlyphs; i++) + { + int char_index[20]; + int char_count = 0; + BOOL isInit, isFinal; + + for (k = 0; k < cChars; k++) + { + if (pwLogClust[k] == i) + { + char_index[char_count] = k; + char_count++; + } + } + + isInit = (i == initGlyph || (i+dirR > 0 && i+dirR < cGlyphs && spaces[i+dirR])); + isFinal = (i == finaGlyph || (i+dirL > 0 && i+dirL < cGlyphs && spaces[i+dirL])); + + if (char_count == 0) + continue; + + if (char_count == 1) + { + if (pwcChars[char_index[0]] == 0x0020) /* space */ + { + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_BLANK; + pCharProp[char_index[0]].fCanGlyphAlone = 1; + } + else if (pwcChars[char_index[0]] == 0x0640) /* kashida */ + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_KASHIDA; + else if (pwcChars[char_index[0]] == 0x0633) /* SEEN */ + { + if (!isInit && !isFinal) + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_SEEN_M; + else if (isInit) + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_SEEN; + else + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE; + } + else if (!isInit) + { + if (pwcChars[char_index[0]] == 0x0628 ) /* BA */ + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_BA; + else if (pwcChars[char_index[0]] == 0x0631 ) /* RA */ + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_RA; + else if (pwcChars[char_index[0]] == 0x0647 ) /* HA */ + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_HA; + else if ((pwcChars[char_index[0]] == 0x0627 || pwcChars[char_index[0]] == 0x0625 || pwcChars[char_index[0]] == 0x0623 || pwcChars[char_index[0]] == 0x0622) ) /* alef-like */ + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_ALEF; + else + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE; + } + else if (!isInit && !isFinal) + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_NORMAL; + else + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE; + } + else if (char_count == 2) + { + if ((pwcChars[char_index[0]] == 0x0628 && pwcChars[char_index[1]]== 0x0631) || (pwcChars[char_index[0]] == 0x0631 && pwcChars[char_index[1]]== 0x0628)) /* BA+RA */ + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_BARA; + else if (!isInit) + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_NORMAL; + else + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE; + } + else if (!isInit && !isFinal) + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_ARABIC_NORMAL; + else + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE; + } + + GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); + HeapFree(GetProcessHeap(),0,spaces); +} + +static void ShapeCharGlyphProp_Thai( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) +{ + int i,k; + int finaGlyph; + INT dirL; + BYTE *spaces; + + spaces = HeapAlloc(GetProcessHeap(),0,cGlyphs); + memset(spaces,0,cGlyphs); + + if (!psa->fLogicalOrder && psa->fRTL) + { + finaGlyph = 0; + dirL = -1; + } + else + { + finaGlyph = cGlyphs-1; + dirL = 1; + } + + for (i = 0; i < cGlyphs; i++) + { + for (k = 0; k < cChars; k++) + if (pwLogClust[k] == i) + { + if (pwcChars[k] == 0x0020) + spaces[i] = 1; + } + } + + GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + + for (i = 0; i < cGlyphs; i++) + { + int char_index[20]; + int char_count = 0; + + for (k = 0; k < cChars; k++) + { + if (pwLogClust[k] == i) + { + char_index[char_count] = k; + char_count++; + } + } + + if (char_count == 0) + continue; + + if (char_count ==1 && pwcChars[char_index[0]] == 0x0020) /* space */ + { + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_CHARACTER; + pCharProp[char_index[0]].fCanGlyphAlone = 1; + } + else if (i == finaGlyph) + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE; + else + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_CHARACTER; + + /* handle Thai SARA AM (U+0E33) differently than GDEF */ + if (char_count == 1 && pwcChars[char_index[0]] == 0x0e33) + pGlyphProp[i].sva.fClusterStart = 0; + } + + HeapFree(GetProcessHeap(),0,spaces); + UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); + + /* Do not allow justification between marks and their base */ + for (i = 0; i < cGlyphs; i++) + { + if (!pGlyphProp[i].sva.fClusterStart) + pGlyphProp[i-dirL].sva.uJustification = SCRIPT_JUSTIFY_NONE; + } +} + +static void ShapeCharGlyphProp_None( HDC hdc, ScriptCache* psc, SCRIPT_ANALYSIS* psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD* pwLogClust, SCRIPT_CHARPROP* pCharProp, SCRIPT_GLYPHPROP* pGlyphProp) +{ + int i,k; + + for (i = 0; i < cGlyphs; i++) + { + int char_index[20]; + int char_count = 0; + + for (k = 0; k < cChars; k++) + { + if (pwLogClust[k] == i) + { + char_index[char_count] = k; + char_count++; + } + } + + if (char_count == 0) + continue; + + if (char_count ==1 && pwcChars[char_index[0]] == 0x0020) /* space */ + { + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_CHARACTER; + pCharProp[char_index[0]].fCanGlyphAlone = 1; + } + else + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE; + } + GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); +} + +static void ShapeCharGlyphProp_Tibet( HDC hdc, ScriptCache* psc, SCRIPT_ANALYSIS* psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD* pwLogClust, SCRIPT_CHARPROP* pCharProp, SCRIPT_GLYPHPROP* pGlyphProp) +{ + int i,k; + + for (i = 0; i < cGlyphs; i++) + { + int char_index[20]; + int char_count = 0; + + for (k = 0; k < cChars; k++) + { + if (pwLogClust[k] == i) + { + char_index[char_count] = k; + char_count++; + } + } + + if (char_count == 0) + continue; + + if (char_count ==1 && pwcChars[char_index[0]] == 0x0020) /* space */ + { + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_BLANK; + pCharProp[char_index[0]].fCanGlyphAlone = 1; + } + else + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE; + } + GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); + + /* Tibeten script does not set sva.fDiacritic or sva.fZeroWidth */ + for (i = 0; i < cGlyphs; i++) + { + if (!pGlyphProp[i].sva.fClusterStart) + { + pGlyphProp[i].sva.fDiacritic = 0; + pGlyphProp[i].sva.fZeroWidth = 0; + } + } +} + +static void ShapeCharGlyphProp_BaseIndic( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp, lexical_function lexical, BOOL use_syllables) +{ + int i,k; + + GDEF_UpdateGlyphProps(hdc, psc, pwGlyphs, cGlyphs, pwLogClust, cChars, pGlyphProp); + for (i = 0; i < cGlyphs; i++) + { + int char_index[20]; + int char_count = 0; + + for (k = 0; k < cChars; k++) + { + if (pwLogClust[k] == i) + { + char_index[char_count] = k; + char_count++; + } + } + + /* Indic scripts do not set fDiacritic or fZeroWidth */ + pGlyphProp[i].sva.fDiacritic = FALSE; + pGlyphProp[i].sva.fZeroWidth = FALSE; + + if (char_count == 0) + continue; + + if (char_count ==1 && pwcChars[char_index[0]] == 0x0020) /* space */ + { + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_BLANK; + pCharProp[char_index[0]].fCanGlyphAlone = 1; + } + else + pGlyphProp[i].sva.uJustification = SCRIPT_JUSTIFY_NONE; + + pGlyphProp[i].sva.fClusterStart = 0; + for (k = 0; k < char_count && !pGlyphProp[i].sva.fClusterStart; k++) + switch (lexical(pwcChars[char_index[k]])) + { + case lex_Matra_pre: + case lex_Matra_post: + case lex_Matra_above: + case lex_Matra_below: + case lex_Modifier: + case lex_Halant: + break; + case lex_ZWJ: + case lex_ZWNJ: + k = char_count; + break; + default: + pGlyphProp[i].sva.fClusterStart = 1; + break; + } + } + + if (use_syllables) + { + IndicSyllable *syllables = NULL; + int syllable_count = 0; + BOOL modern = get_GSUB_Indic2(psa, psc); + + Indic_ParseSyllables( hdc, psa, psc, pwcChars, cChars, &syllables, &syllable_count, lexical, modern); + + for (i = 0; i < syllable_count; i++) + { + int j; + WORD g = pwLogClust[syllables[i].start]; + for (j = syllables[i].start+1; j <= syllables[i].end; j++) + { + if (pwLogClust[j] != g) + { + pGlyphProp[pwLogClust[j]].sva.fClusterStart = 0; + pwLogClust[j] = g; + } + } + } + + HeapFree(GetProcessHeap(), 0, syllables); + } + + UpdateClustersFromGlyphProp(cGlyphs, cChars, pwLogClust, pGlyphProp); +} + +static void ShapeCharGlyphProp_Sinhala( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) +{ + ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, sinhala_lex, FALSE); +} + +static void ShapeCharGlyphProp_Devanagari( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) +{ + ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, devanagari_lex, TRUE); +} + +static void ShapeCharGlyphProp_Bengali( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) +{ + ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, bengali_lex, TRUE); +} + +static void ShapeCharGlyphProp_Gurmukhi( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) +{ + ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, gurmukhi_lex, TRUE); +} + +static void ShapeCharGlyphProp_Gujarati( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) +{ + ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, gujarati_lex, TRUE); +} + +static void ShapeCharGlyphProp_Oriya( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) +{ + ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, oriya_lex, TRUE); +} + +static void ShapeCharGlyphProp_Tamil( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) +{ + ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, tamil_lex, TRUE); +} + +static void ShapeCharGlyphProp_Telugu( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) +{ + ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, telugu_lex, TRUE); +} + +static void ShapeCharGlyphProp_Kannada( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) +{ + ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, kannada_lex, TRUE); +} + +static void ShapeCharGlyphProp_Malayalam( HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp ) +{ + ShapeCharGlyphProp_BaseIndic(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp, malayalam_lex, TRUE); +} + +void SHAPE_CharGlyphProp(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp) +{ + if (ShapingData[psa->eScript].charGlyphPropProc) + ShapingData[psa->eScript].charGlyphPropProc(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp); + else + ShapeCharGlyphProp_Default(hdc, psc, psa, pwcChars, cChars, pwGlyphs, cGlyphs, pwLogClust, pCharProp, pGlyphProp); +} + +void SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) +{ + if (!psc->GSUB_Table) + psc->GSUB_Table = load_gsub_table(hdc); + + if (ShapingData[psa->eScript].contextProc) + ShapingData[psa->eScript].contextProc(hdc, psc, psa, pwcChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust); +} + +static void SHAPE_ApplyOpenTypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, INT cChars, const TEXTRANGE_PROPERTIES *rpRangeProperties, WORD *pwLogClust) +{ + int i; + INT dirL; + + if (!rpRangeProperties) + return; + + if (!psc->GSUB_Table) + psc->GSUB_Table = load_gsub_table(hdc); + + if (!psc->GSUB_Table) + return; + + if (!psa->fLogicalOrder && psa->fRTL) + dirL = -1; + else + dirL = 1; + + for (i = 0; i < rpRangeProperties->cotfRecords; i++) + { + if (rpRangeProperties->potfRecords[i].lParameter > 0) + apply_GSUB_feature(hdc, psa, psc, pwOutGlyphs, dirL, pcGlyphs, cChars, (const char*)&rpRangeProperties->potfRecords[i].tagFeature, pwLogClust); + } +} + +void SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, INT cChars, WORD *pwLogClust) +{ +const TEXTRANGE_PROPERTIES *rpRangeProperties; +rpRangeProperties = &ShapingData[psa->eScript].defaultTextRange; + + SHAPE_ApplyOpenTypeFeatures(hdc, psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, cChars, rpRangeProperties, pwLogClust); +} + +HRESULT SHAPE_CheckFontForRequiredFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa) +{ + const GSUB_Feature *feature; + int i; + + if (!ShapingData[psa->eScript].requiredFeatures) + return S_OK; + + if (!psc->GSUB_Table) + psc->GSUB_Table = load_gsub_table(hdc); + + /* we need to have at least one of the required features */ + i = 0; + while (ShapingData[psa->eScript].requiredFeatures[i]) + { + feature = load_GSUB_feature(hdc, psa, psc, ShapingData[psa->eScript].requiredFeatures[i]); + if (feature) + return S_OK; + i++; + } + + return USP_E_SCRIPT_NOT_IN_FONT; +} diff --git a/reactos/dll/win32/usp10/shaping.c b/reactos/dll/win32/usp10/shaping.c index ec9abbdedec..1ce255a092b 100644 --- a/reactos/dll/win32/usp10/shaping.c +++ b/reactos/dll/win32/usp10/shaping.c @@ -1,221 +1,144 @@ /* Unicode Arabic shaping */ -/* generated from http://www.unicode.org/Public/5.2.0/ucd/ArabicShaping.txt */ +/* generated from http://www.unicode.org/Public/6.0.0/ucd/ArabicShaping.txt */ /* DO NOT EDIT!! */ #include "wine/unicode.h" -const unsigned short wine_shaping_table[9472] = +const unsigned short wine_shaping_table[2656] = { - /* offsets */ - 0x0100, 0x0200, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700, - 0x0800, 0x0900, 0x0a00, 0x0b00, 0x0c00, 0x0d00, 0x0e00, 0x0f00, - 0x1000, 0x0200, 0x0200, 0x1100, 0x0200, 0x0200, 0x0200, 0x1200, - 0x1300, 0x1400, 0x1500, 0x1600, 0x1700, 0x1800, 0x0200, 0x0200, - 0x1900, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x1a00, 0x1b00, 0x0200, 0x0200, - 0x1c00, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x1d00, 0x0200, - 0x1e00, 0x1f00, 0x2000, 0x2100, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x2200, 0x0200, 0x0200, 0x2300, 0x2400, + /* level 1 offsets */ + 0x0100, 0x0110, 0x0110, 0x0120, 0x0130, 0x0140, 0x0150, 0x0160, + 0x0170, 0x0180, 0x0190, 0x01a0, 0x01b0, 0x01c0, 0x01d0, 0x01e0, + 0x01f0, 0x0110, 0x0110, 0x0200, 0x0110, 0x0110, 0x0110, 0x0210, + 0x0220, 0x0230, 0x0240, 0x0250, 0x0260, 0x0270, 0x0110, 0x0110, + 0x0280, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0290, 0x02a0, 0x0110, 0x0110, + 0x02b0, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x02c0, 0x0110, + 0x02d0, 0x02e0, 0x02f0, 0x0300, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, 0x0110, + 0x0110, 0x0110, 0x0110, 0x0310, 0x0110, 0x0110, 0x0320, 0x0330, + /* level 2 offsets */ + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0350, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0360, 0x0360, 0x0360, 0x0360, 0x0360, 0x0360, 0x0360, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0370, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0380, 0x0360, 0x0390, 0x03a0, 0x0340, 0x0340, 0x0340, + 0x0340, 0x03b0, 0x03c0, 0x03d0, 0x03e0, 0x0360, 0x03f0, 0x0400, + 0x0410, 0x0420, 0x0430, 0x0440, 0x0450, 0x0460, 0x0470, 0x0480, + 0x0490, 0x04a0, 0x04b0, 0x0360, 0x04c0, 0x04d0, 0x04e0, 0x04f0, + 0x0340, 0x0340, 0x0500, 0x0510, 0x0520, 0x0530, 0x0540, 0x0550, + 0x0340, 0x0560, 0x0570, 0x0340, 0x0340, 0x0580, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0590, 0x0340, 0x0340, 0x05a0, 0x05b0, 0x05c0, 0x05d0, 0x0340, + 0x05e0, 0x0340, 0x0340, 0x05f0, 0x0600, 0x0340, 0x05d0, 0x0340, + 0x0610, 0x0340, 0x0340, 0x05f0, 0x0620, 0x05e0, 0x0340, 0x0630, + 0x0610, 0x0340, 0x0340, 0x05f0, 0x0640, 0x0340, 0x05d0, 0x0340, + 0x05e0, 0x0340, 0x0340, 0x0650, 0x0600, 0x0660, 0x05d0, 0x0340, + 0x0670, 0x0340, 0x0340, 0x0340, 0x0680, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0690, 0x06a0, 0x06b0, 0x05d0, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0650, 0x06c0, 0x0340, 0x05d0, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0600, 0x0340, 0x05d0, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x06d0, 0x06e0, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x06f0, 0x0700, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0710, 0x0720, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0730, 0x0340, 0x0740, 0x0340, 0x0340, 0x0340, 0x0750, + 0x0760, 0x0770, 0x0360, 0x0780, 0x0660, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0790, 0x07a0, 0x0340, 0x07b0, 0x0510, 0x07c0, + 0x07d0, 0x0350, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0790, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x07e0, 0x0340, 0x07e0, 0x0340, 0x05d0, 0x0340, 0x05d0, + 0x0340, 0x0340, 0x0340, 0x07f0, 0x0800, 0x0810, 0x0340, 0x0340, + 0x0820, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0830, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0840, 0x0850, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0860, 0x0340, 0x0340, 0x0340, 0x0870, 0x0880, 0x0890, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x08a0, 0x0340, 0x0340, 0x08b0, 0x0670, 0x0340, 0x08c0, 0x08a0, + 0x08d0, 0x0340, 0x08e0, 0x0340, 0x0340, 0x0340, 0x08f0, 0x08d0, + 0x0340, 0x0340, 0x0900, 0x0910, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0920, 0x0930, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0360, 0x0360, 0x0940, 0x0900, + 0x0950, 0x0340, 0x0960, 0x0340, 0x0340, 0x0340, 0x0970, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0360, 0x0360, 0x0510, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0490, 0x08d0, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0490, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0360, 0x0360, + 0x0340, 0x0340, 0x0980, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0990, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0490, 0x09a0, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x08d0, + 0x09b0, 0x0340, 0x06b0, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x09c0, 0x0340, 0x0360, 0x08d0, + 0x0340, 0x0340, 0x09d0, 0x0340, 0x09e0, 0x08d0, 0x0340, 0x0340, + 0x0590, 0x0340, 0x0340, 0x09f0, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0a00, 0x0a10, 0x0a20, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0a30, 0x05e0, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0a40, 0x0340, + 0x0340, 0x0a50, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0360, 0x0340, 0x0940, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0490, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, + 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0340, 0x0580, /* values */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0102, 0x0102, 0x0202, 0x0102, 0x0304, 0x0102, + 0x0104, 0x0000, 0x0202, 0x0202, 0x0302, 0x0202, 0x0104, 0x0202, 0x0404, 0x0502, 0x0404, 0x0404, 0x0604, 0x0604, 0x0604, 0x0702, 0x0702, 0x0802, 0x0802, 0x0904, 0x0904, 0x0a04, 0x0a04, 0x0b04, 0x0b04, 0x0c04, 0x0c04, 0x0d04, 0x0d04, 0x0e04, 0x0e04, 0x0e04, 0x0005, 0x0f04, 0x1004, 0x1104, 0x1204, 0x1304, 0x1404, 0x1504, - 0x0202, 0x0304, 0x0304, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, + 0x0302, 0x0104, 0x0104, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x1004, - 0x0001, 0x0102, 0x0102, 0x0102, 0x0000, 0x0102, 0x0202, 0x0202, - 0x0304, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, + 0x0001, 0x0202, 0x0202, 0x0202, 0x0000, 0x0202, 0x0302, 0x0302, + 0x0104, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0604, 0x0604, 0x0604, 0x0604, 0x0604, 0x0604, 0x0604, 0x0702, 0x0702, 0x0702, 0x0702, 0x0702, 0x0702, 0x0702, 0x0702, 0x0702, 0x0802, 0x0802, 0x0802, 0x0802, 0x0802, 0x0802, 0x0802, @@ -224,34 +147,28 @@ const unsigned short wine_shaping_table[9472] = 0x1004, 0x0d04, 0x1604, 0x0d04, 0x1104, 0x1104, 0x1104, 0x0d04, 0x0d04, 0x0d04, 0x0d04, 0x0d04, 0x0d04, 0x1204, 0x1204, 0x1204, 0x1204, 0x1404, 0x1404, 0x1404, 0x1404, 0x1704, 0x1804, 0x0604, - 0x0502, 0x1504, 0x1504, 0x1902, 0x0202, 0x0202, 0x0202, 0x0202, - 0x0202, 0x0202, 0x0202, 0x0202, 0x0e04, 0x0302, 0x0e04, 0x0202, - 0x0304, 0x0304, 0x0302, 0x0302, 0x0000, 0x0502, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, + 0x0502, 0x1504, 0x1504, 0x0502, 0x0302, 0x0302, 0x0302, 0x0302, + 0x0302, 0x0302, 0x0302, 0x0302, 0x0e04, 0x0102, 0x0e04, 0x0302, + 0x0104, 0x0104, 0x0102, 0x0102, 0x0000, 0x0502, 0x0001, 0x0001, + 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0702, 0x0802, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0904, 0x0a04, 0x0c04, 0x0000, 0x0000, 0x1804, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, - 0x1a02, 0x0001, 0x1b04, 0x1c04, 0x1c04, 0x1d02, 0x1d02, 0x1e02, - 0x1f02, 0x2002, 0x2104, 0x2204, 0x2204, 0x2304, 0x2302, 0x2404, - 0x2504, 0x2604, 0x2704, 0x2804, 0x2904, 0x2a04, 0x2b04, 0x2c04, - 0x2d02, 0x2e04, 0x1d02, 0x2f04, 0x3002, 0x1b04, 0x1c04, 0x1d02, + 0x1902, 0x0001, 0x1a04, 0x1b04, 0x1b04, 0x1c02, 0x1c02, 0x1d02, + 0x1e02, 0x1f02, 0x2004, 0x2104, 0x2104, 0x2204, 0x2202, 0x2304, + 0x2404, 0x2504, 0x2604, 0x2704, 0x2804, 0x2904, 0x2a04, 0x2b04, + 0x2c02, 0x2d04, 0x1c02, 0x2e04, 0x2f02, 0x1a04, 0x1b04, 0x1c02, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x3102, 0x3204, 0x3304, + 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x3002, 0x3104, 0x3204, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0404, 0x0604, 0x0604, 0x0702, 0x0702, 0x0802, 0x0904, 0x0c04, 0x0c04, 0x0c04, 0x0f04, 0x0f04, 0x0d04, 0x0d04, 0x0d04, 0x1304, 0x1304, 0x1404, 0x1404, 0x1404, 0x1204, 0x0802, 0x0802, 0x0904, 0x0604, 0x0604, - 0x0904, 0x0802, 0x0604, 0x0102, 0x0102, 0x0e04, 0x0e04, 0x0304, - 0x0202, 0x0202, 0x3404, 0x3404, 0x0604, 0x0904, 0x0904, 0x1104, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0904, 0x0802, 0x0604, 0x0202, 0x0202, 0x0e04, 0x0e04, 0x0104, + 0x0302, 0x0302, 0x3304, 0x3304, 0x0604, 0x0904, 0x0904, 0x1104, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, @@ -264,348 +181,88 @@ const unsigned short wine_shaping_table[9472] = 0x0004, 0x0004, 0x0004, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0005, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, - 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, + 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, - 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0001, - 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, - 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, @@ -613,585 +270,77 @@ const unsigned short wine_shaping_table[9472] = 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, + 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0005, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, - 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, - 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000 + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000 }; const unsigned short wine_shaping_forms[256][4] = diff --git a/reactos/dll/win32/usp10/usp10.c b/reactos/dll/win32/usp10/usp10.c index 51fbbc0c7d9..73a7fad4e00 100644 --- a/reactos/dll/win32/usp10/usp10.c +++ b/reactos/dll/win32/usp10/usp10.c @@ -31,6 +31,7 @@ #include "wingdi.h" #include "winuser.h" #include "winnls.h" +#include "winreg.h" #include "usp10.h" #include "usp10_internal.h" @@ -40,108 +41,373 @@ WINE_DEFAULT_DEBUG_CHANNEL(uniscribe); -static const SCRIPT_PROPERTIES props[] = +typedef struct _scriptRange { - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, - { 9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, - { 8, 0, 0, 0, 0, 161, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 25, 0, 0, 0, 0, 204, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, - { 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, - { 42, 0, 0, 0, 0, 163, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 9, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, - { 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0 }, - { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, - { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, - { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, - { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, - { 18, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, - { 18, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, - { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, - { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, - { 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, - { 9, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0 }, - { 13, 0, 1, 0, 1, 177, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 13, 0, 1, 0, 0, 177, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 1, 0, 1, 0, 0, 178, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, - { 1, 1, 1, 0, 0, 178, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, - { 41, 1, 1, 0, 0, 178, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 32, 1, 1, 0, 0, 178, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 90, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0 }, - { 30, 0, 1, 1, 1, 222, 0, 0, 1, 0, 1, 0, 0, 0, 1 }, - { 30, 1, 1, 0, 0, 222, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 30, 0, 1, 0, 0, 222, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 57, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, - { 57, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 73, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, - { 73, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 69, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, - { 69, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 69, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 70, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, - { 70, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 71, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, - { 71, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 72, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, - { 72, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 74, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, - { 74, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 75, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, - { 75, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 76, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, - { 76, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 81, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0 }, - { 81, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 84, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0 }, - { 84, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 83, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, - { 83, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 85, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0 }, - { 85, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 80, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 80, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 94, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 94, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 101, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 93, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 92, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 9, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 91, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 9, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 }, - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + WORD script; + WORD rangeFirst; + WORD rangeLast; + WORD numericScript; + WORD punctScript; +} scriptRange; + +static const scriptRange scriptRanges[] = { + /* Basic Latin: U+0000–U+007A */ + { Script_Latin, 0x00, 0x07a , Script_Numeric, Script_Punctuation}, + /* Latin-1 Supplement: U+0080–U+00FF */ + /* Latin Extended-A: U+0100–U+017F */ + /* Latin Extended-B: U+0180–U+024F */ + /* IPA Extensions: U+0250–U+02AF */ + { Script_Latin, 0x80, 0x2af , Script_Numeric2, Script_Punctuation}, + /* Combining Diacritical Marks : U+0300–U+036F */ + { Script_Diacritical,0x300, 0x36f, 0, 0}, + /* Greek: U+0370–U+03FF */ + { Script_Greek, 0x370, 0x3ff, 0, 0}, + /* Cyrillic: U+0400–U+04FF */ + /* Cyrillic Supplement: U+0500–U+052F */ + { Script_Cyrillic, 0x400, 0x52f, 0, 0}, + /* Armenian: U+0530–U+058F */ + { Script_Armenian, 0x530, 0x58f, 0, 0}, + /* Hebrew: U+0590–U+05FF */ + { Script_Hebrew, 0x590, 0x5ff, 0, 0}, + /* Arabic: U+0600–U+06FF */ + { Script_Arabic, 0x600, 0x6ef, Script_Arabic_Numeric, 0}, + /* Defined by Windows */ + { Script_Persian, 0x6f0, 0x6f9, 0, 0}, + /* Continue Arabic: U+0600–U+06FF */ + { Script_Arabic, 0x6fa, 0x6ff, 0, 0}, + /* Syriac: U+0700–U+074F*/ + { Script_Syriac, 0x700, 0x74f, 0, 0}, + /* Arabic Supplement: U+0750–U+077F */ + { Script_Arabic, 0x750, 0x77f, 0, 0}, + /* Thaana: U+0780–U+07BF */ + { Script_Thaana, 0x780, 0x7bf, 0, 0}, + /* Devanagari: U+0900–U+097F */ + { Script_Devanagari, 0x900, 0x97f, Script_Devanagari_Numeric, 0}, + /* Bengali: U+0980–U+09FF */ + { Script_Bengali, 0x980, 0x9ff, Script_Bengali_Numeric, 0}, + /* Gurmukhi: U+0A00–U+0A7F*/ + { Script_Gurmukhi, 0xa00, 0xa7f, Script_Gurmukhi_Numeric, 0}, + /* Gujarati: U+0A80–U+0AFF*/ + { Script_Gujarati, 0xa80, 0xaff, Script_Gujarati_Numeric, 0}, + /* Oriya: U+0B00–U+0B7F */ + { Script_Oriya, 0xb00, 0xb7f, Script_Oriya_Numeric, 0}, + /* Tamil: U+0B80–U+0BFF */ + { Script_Tamil, 0xb80, 0xbff, Script_Tamil_Numeric, 0}, + /* Telugu: U+0C00–U+0C7F */ + { Script_Telugu, 0xc00, 0xc7f, Script_Telugu_Numeric, 0}, + /* Kannada: U+0C80–U+0CFF */ + { Script_Kannada, 0xc80, 0xcff, Script_Kannada_Numeric, 0}, + /* Malayalam: U+0D00–U+0D7F */ + { Script_Malayalam, 0xd00, 0xd7f, Script_Malayalam_Numeric, 0}, + /* Sinhala: U+0D80–U+0DFF */ + { Script_Sinhala, 0xd80, 0xdff, 0, 0}, + /* Thai: U+0E00–U+0E7F */ + { Script_Thai, 0xe00, 0xe7f, Script_Thai_Numeric, 0}, + /* Lao: U+0E80–U+0EFF */ + { Script_Lao, 0xe80, 0xeff, Script_Lao_Numeric, 0}, + /* Tibetan: U+0F00–U+0FFF */ + { Script_Tibetan, 0xf00, 0xfff, 0, 0}, + /* Georgian: U+10A0–U+10FF */ + { Script_Georgian, 0x10a0, 0x10ff, 0, 0}, + /* Vedic Extensions: U+1CD0-U+1CFF */ + { Script_Devanagari, 0x1cd0, 0x1cff, Script_Devanagari_Numeric, 0}, + /* Phonetic Extensions: U+1D00–U+1DBF */ + { Script_Latin, 0x1d00, 0x1dbf, 0, 0}, + /* Combining Diacritical Marks Supplement: U+1DC0–U+1DFF */ + { Script_Diacritical,0x1dc0, 0x1dff, 0, 0}, + /* Latin Extended Additional: U+1E00–U+1EFF */ + { Script_Latin, 0x1e00, 0x1eff, 0, 0}, + /* Greek Extended: U+1F00–U+1FFF */ + { Script_Greek, 0x1f00, 0x1fff, 0, 0}, + /* General Punctuation: U+2000 –U+206f */ + { Script_Latin, 0x2000, 0x206f, 0, 0}, + /* Superscripts and Subscripts : U+2070 –U+209f */ + /* Currency Symbols : U+20a0 –U+20cf */ + { Script_Numeric2, 0x2070, 0x2070, 0, 0}, + { Script_Latin, 0x2071, 0x2073, 0, 0}, + { Script_Numeric2, 0x2074, 0x2079, 0, 0}, + { Script_Latin, 0x207a, 0x207f, 0, 0}, + { Script_Numeric2, 0x2080, 0x2089, 0, 0}, + { Script_Latin, 0x208a, 0x20cf, 0, 0}, + /* Letterlike Symbols : U+2100 –U+214f */ + /* Number Forms : U+2150 –U+218f */ + /* Arrows : U+2190 –U+21ff */ + /* Mathematical Operators : U+2200 –U+22ff */ + /* Miscellaneous Technical : U+2300 –U+23ff */ + /* Control Pictures : U+2400 –U+243f */ + /* Optical Character Recognition : U+2440 –U+245f */ + /* Enclosed Alphanumerics : U+2460 –U+24ff */ + /* Box Drawing : U+2500 –U+25ff */ + /* Block Elements : U+2580 –U+259f */ + /* Geometric Shapes : U+25a0 –U+25ff */ + /* Miscellaneous Symbols : U+2600 –U+26ff */ + /* Dingbats : U+2700 –U+27bf */ + /* Miscellaneous Mathematical Symbols-A : U+27c0 –U+27ef */ + /* Supplemental Arrows-A : U+27f0 –U+27ff */ + { Script_Latin, 0x2100, 0x27ff, 0, 0}, + /* Supplemental Arrows-B : U+2900 –U+297f */ + /* Miscellaneous Mathematical Symbols-B : U+2980 –U+29ff */ + /* Supplemental Mathematical Operators : U+2a00 –U+2aff */ + /* Miscellaneous Symbols and Arrows : U+2b00 –U+2bff */ + { Script_Latin, 0x2900, 0x2bff, 0, 0}, + /* Latin Extended-C: U+2C60–U+2C7F */ + { Script_Latin, 0x2c60, 0x2c7f, 0, 0}, + /* Georgian: U+2D00–U+2D2F */ + { Script_Georgian, 0x2d00, 0x2d2f, 0, 0}, + /* Cyrillic Extended-A: U+2DE0–U+2DFF */ + { Script_Cyrillic, 0x2de0, 0x2dff, 0, 0}, + /* Cyrillic Extended-B: U+A640–U+A69F */ + { Script_Cyrillic, 0xa640, 0xa69f, 0, 0}, + /* Modifier Tone Letters: U+A700–U+A71F */ + /* Latin Extended-D: U+A720–U+A7FF */ + { Script_Latin, 0xa700, 0xa7ff, 0, 0}, + /* Phags-pa: U+A840–U+A87F */ + { Script_Phags_pa, 0xa840, 0xa87f, 0, 0}, + /* Devanagari Extended: U+A8E0-U+A8FF */ + { Script_Devanagari, 0xa8e0, 0xa8ff, Script_Devanagari_Numeric, 0}, + /* Latin Ligatures: U+FB00–U+FB06 */ + { Script_Latin, 0xfb00, 0xfb06, 0, 0}, + /* Armenian ligatures U+FB13..U+FB17 */ + { Script_Armenian, 0xfb13, 0xfb17, 0, 0}, + /* Alphabetic Presentation Forms: U+FB1D–U+FB4F */ + { Script_Hebrew, 0xfb1d, 0xfb4f, 0, 0}, + /* Arabic Presentation Forms-A: U+FB50–U+FDFF*/ + { Script_Arabic, 0xfb50, 0xfdff, 0, 0}, + /* Arabic Presentation Forms-B: U+FE70–U+FEFF*/ + { Script_Arabic, 0xfe70, 0xfeff, 0, 0}, + /* END */ + { SCRIPT_UNDEFINED, 0, 0, 0} +}; + +typedef struct _scriptData +{ + SCRIPT_ANALYSIS a; + SCRIPT_PROPERTIES props; + OPENTYPE_TAG scriptTag; + WCHAR fallbackFont[LF_FACESIZE]; +} scriptData; + +/* the must be in order so that the index matches the Script value */ +static const scriptData scriptInformation[] = { + {{SCRIPT_UNDEFINED, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_NEUTRAL, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + 0x00000000, + {0}}, + {{Script_Latin, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_ENGLISH, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0}, + MS_MAKE_TAG('l','a','t','n'), + {0}}, + {{Script_CR, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_NEUTRAL, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + 0x00000000, + {0}}, + {{Script_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_ENGLISH, 1, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + 0x00000000, + {0}}, + {{Script_Control, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_ENGLISH, 0, 1, 0, 0, ANSI_CHARSET, 1, 0, 0, 0, 0, 0, 1, 0, 0}, + 0x00000000, + {0}}, + {{Script_Punctuation, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_NEUTRAL, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + 0x00000000, + {0}}, + {{Script_Arabic, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}}, + {LANG_ARABIC, 0, 1, 0, 0, ARABIC_CHARSET, 0, 0, 0, 0, 0, 0, 1, 1, 0}, + MS_MAKE_TAG('a','r','a','b'), + {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, + {{Script_Arabic_Numeric, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}}, + {LANG_ARABIC, 1, 1, 0, 0, ARABIC_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0}, + MS_MAKE_TAG('a','r','a','b'), + {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, + {{Script_Hebrew, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}}, + {LANG_HEBREW, 0, 1, 0, 1, HEBREW_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('h','e','b','r'), + {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, + {{Script_Syriac, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}}, + {LANG_SYRIAC, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 1, 0}, + MS_MAKE_TAG('s','y','r','c'), + {'E','s','t','r','a','n','g','e','l','o',' ','E','d','e','s','s','a',0}}, + {{Script_Persian, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}}, + {LANG_PERSIAN, 1, 1, 0, 0, ARABIC_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('s','y','r','c'), + {'E','s','t','r','a','n','g','e','l','o',' ','E','d','e','s','s','a',0}}, + {{Script_Thaana, 1, 1, 0, 0, 0, 0, { 1,0,0,0,0,0,0,0,0,0,0}}, + {LANG_DIVEHI, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('t','h','a','a'), + {'M','V',' ','B','o','l','i',0}}, + {{Script_Greek, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_GREEK, 0, 0, 0, 0, GREEK_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('g','r','e','k'), + {0}}, + {{Script_Cyrillic, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_RUSSIAN, 0, 0, 0, 0, RUSSIAN_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('c','y','r','l'), + {0}}, + {{Script_Armenian, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_ARMENIAN, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0}, + MS_MAKE_TAG('a','r','m','n'), + {'S','y','l','f','a','e','n',0}}, + {{Script_Georgian, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_GEORGIAN, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0}, + MS_MAKE_TAG('g','e','o','r'), + {'S','y','l','f','a','e','n',0}}, + {{Script_Sinhala, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_SINHALESE, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('s','i','n','h'), + {'I','s','k','o','o','l','a',' ','P','o','t','a',0}}, + {{Script_Tibetan, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_TIBETAN, 0, 1, 1, 1, DEFAULT_CHARSET, 0, 0, 1, 0, 1, 0, 0, 0, 0}, + MS_MAKE_TAG('t','i','b','t'), + {'M','i','c','r','o','s','o','f','t',' ','H','i','m','a','l','a','y','a',0}}, + {{Script_Tibetan_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_TIBETAN, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('t','i','b','t'), + {'M','i','c','r','o','s','o','f','t',' ','H','i','m','a','l','a','y','a',0}}, + {{Script_Phags_pa, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_MONGOLIAN, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('p','h','a','g'), + {'M','i','c','r','o','s','o','f','t',' ','P','h','a','g','s','P','a',0}}, + {{Script_Thai, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_THAI, 0, 1, 1, 1, THAI_CHARSET, 0, 0, 1, 0, 1, 0, 0, 0, 1}, + MS_MAKE_TAG('t','h','a','i'), + {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, + {{Script_Thai_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_THAI, 1, 1, 0, 0, THAI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('t','h','a','i'), + {'M','i','c','r','o','s','o','f','t',' ','S','a','n','s',' ','S','e','r','i','f',0}}, + {{Script_Lao, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_LAO, 0, 1, 1, 1, DEFAULT_CHARSET, 0, 0, 1, 0, 1, 0, 0, 0, 0}, + MS_MAKE_TAG('l','a','o',' '), + {'D','o','k','C','h','a','m','p','a',0}}, + {{Script_Lao_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_LAO, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('l','a','o',' '), + {'D','o','k','C','h','a','m','p','a',0}}, + {{Script_Devanagari, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_HINDI, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + MS_MAKE_TAG('d','e','v','a'), + {'M','a','n','g','a','l',0}}, + {{Script_Devanagari_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_HINDI, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('d','e','v','a'), + {'M','a','n','g','a','l',0}}, + {{Script_Bengali, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_BENGALI, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + MS_MAKE_TAG('b','e','n','g'), + {'V','r','i','n','d','a',0}}, + {{Script_Bengali_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_BENGALI, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('b','e','n','g'), + {'V','r','i','n','d','a',0}}, + {{Script_Bengali_Currency, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_BENGALI, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('b','e','n','g'), + {'V','r','i','n','d','a',0}}, + {{Script_Gurmukhi, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_PUNJABI, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + MS_MAKE_TAG('g','u','r','u'), + {'R','a','a','v','i',0}}, + {{Script_Gurmukhi_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_PUNJABI, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('g','u','r','u'), + {'R','a','a','v','i',0}}, + {{Script_Gujarati, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_GUJARATI, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + MS_MAKE_TAG('g','u','j','r'), + {'S','h','r','u','t','i',0}}, + {{Script_Gujarati_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_GUJARATI, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('g','u','j','r'), + {'S','h','r','u','t','i',0}}, + {{Script_Gujarati_Currency, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_GUJARATI, 0, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('g','u','j','r'), + {'S','h','r','u','t','i',0}}, + {{Script_Oriya, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_ORIYA, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + MS_MAKE_TAG('o','r','y','a'), + {'K','a','l','i','n','g','a',0}}, + {{Script_Oriya_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_ORIYA, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('o','r','y','a'), + {'K','a','l','i','n','g','a',0}}, + {{Script_Tamil, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_TAMIL, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + MS_MAKE_TAG('t','a','m','l'), + {'L','a','t','h','a',0}}, + {{Script_Tamil_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_TAMIL, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('t','a','m','l'), + {'L','a','t','h','a',0}}, + {{Script_Telugu, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_TELUGU, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + MS_MAKE_TAG('t','e','l','u'), + {'G','a','u','t','a','m','i',0}}, + {{Script_Telugu_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_TELUGU, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('t','e','l','u'), + {'G','a','u','t','a','m','i',0}}, + {{Script_Kannada, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_KANNADA, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + MS_MAKE_TAG('k','n','d','a'), + {'T','u','n','g','a',0}}, + {{Script_Kannada_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_KANNADA, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('k','n','d','a'), + {'T','u','n','g','a',0}}, + {{Script_Malayalam, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_MALAYALAM, 0, 1, 0, 1, DEFAULT_CHARSET, 0, 0, 0, 0, 1, 0, 0, 0, 0}, + MS_MAKE_TAG('m','l','y','m'), + {'K','a','r','t','i','k','a',0}}, + {{Script_Malayalam_Numeric, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_MALAYALAM, 1, 1, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('m','l','y','m'), + {'K','a','r','t','i','k','a',0}}, + {{Script_Diacritical, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_ENGLISH, 0, 1, 0, 1, ANSI_CHARSET, 0, 0, 0, 0, 0, 1, 1, 0, 0}, + 0x00000000, + {0}}, + {{Script_Punctuation2, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_ENGLISH, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + MS_MAKE_TAG('l','a','t','n'), + {0}}, + {{Script_Numeric2, 0, 0, 0, 0, 0, 0, { 0,0,0,0,0,0,0,0,0,0,0}}, + {LANG_ENGLISH, 1, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 1, 0, 0}, + 0x00000000, + {0}}, }; static const SCRIPT_PROPERTIES *script_props[] = { - &props[0], &props[1], &props[2], &props[3], - &props[4], &props[5], &props[6], &props[7], - &props[8], &props[9], &props[11], &props[12], - &props[13], &props[14], &props[15], &props[16], - &props[17], &props[18], &props[19], &props[20], - &props[21], &props[22], &props[23], &props[24], - &props[25], &props[26], &props[27], &props[28], - &props[29], &props[30], &props[31], &props[32], - &props[33], &props[34], &props[35], &props[36], - &props[37], &props[38], &props[39], &props[40], - &props[41], &props[42], &props[43], &props[44], - &props[45], &props[46], &props[47], &props[48], - &props[49], &props[50], &props[51], &props[52], - &props[53], &props[54], &props[55], &props[56], - &props[57], &props[58], &props[59], &props[60], - &props[61], &props[62], &props[63], &props[64], - &props[65], &props[66], &props[67], &props[68], - &props[69], &props[70], &props[71], &props[72], - &props[73] + &scriptInformation[0].props, &scriptInformation[1].props, + &scriptInformation[2].props, &scriptInformation[3].props, + &scriptInformation[4].props, &scriptInformation[5].props, + &scriptInformation[6].props, &scriptInformation[7].props, + &scriptInformation[8].props, &scriptInformation[9].props, + &scriptInformation[10].props, &scriptInformation[11].props, + &scriptInformation[12].props, &scriptInformation[13].props, + &scriptInformation[14].props, &scriptInformation[15].props, + &scriptInformation[16].props, &scriptInformation[17].props, + &scriptInformation[18].props, &scriptInformation[19].props, + &scriptInformation[20].props, &scriptInformation[21].props, + &scriptInformation[22].props, &scriptInformation[23].props, + &scriptInformation[24].props, &scriptInformation[25].props, + &scriptInformation[26].props, &scriptInformation[27].props, + &scriptInformation[28].props, &scriptInformation[29].props, + &scriptInformation[30].props, &scriptInformation[31].props, + &scriptInformation[32].props, &scriptInformation[33].props, + &scriptInformation[34].props, &scriptInformation[35].props, + &scriptInformation[36].props, &scriptInformation[37].props, + &scriptInformation[38].props, &scriptInformation[39].props, + &scriptInformation[40].props, &scriptInformation[41].props, + &scriptInformation[42].props, &scriptInformation[43].props, + &scriptInformation[44].props, &scriptInformation[45].props }; typedef struct { + ScriptCache *sc; int numGlyphs; WORD* glyphs; WORD* pwLogClust; @@ -149,13 +415,15 @@ typedef struct { SCRIPT_VISATTR* psva; GOFFSET* pGoffset; ABC* abc; + int iMaxPosX; + HFONT fallbackFont; } StringGlyphs; typedef struct { HDC hdc; + DWORD dwFlags; BOOL invalid; int clip_len; - ScriptCache *sc; int cItems; int cMaxGlyphs; SCRIPT_ITEM* pItem; @@ -163,6 +431,7 @@ typedef struct { StringGlyphs* glyphs; SCRIPT_LOGATTR* logattrs; SIZE* sz; + int* logical2visual; } StringAnalysis; static inline void *heap_alloc(SIZE_T size) @@ -254,6 +523,7 @@ static HRESULT init_script_cache(const HDC hdc, SCRIPT_CACHE *psc) heap_free(sc); return E_INVALIDARG; } + sc->sfnt = (GetFontData(hdc, MS_MAKE_TAG('h','e','a','d'), 0, NULL, 0)!=GDI_ERROR); *psc = sc; TRACE("<- %p\n", sc); return S_OK; @@ -265,6 +535,51 @@ static WCHAR mirror_char( WCHAR ch ) return ch + wine_mirror_map[wine_mirror_map[ch >> 8] + (ch & 0xff)]; } +static WORD get_char_script( WCHAR ch) +{ + static const WCHAR latin_punc[] = {'#','$','&','\'',',',';','<','>','?','@','\\','^','_','`','{','|','}','~', 0x00a0, 0}; + WORD type = 0; + int i; + + if (ch == 0xc || ch == 0x20 || ch == 0x202f) + return Script_CR; + + /* These punctuation are separated out as Latin punctuation */ + if (strchrW(latin_punc,ch)) + return Script_Punctuation2; + + /* These chars are itemized as Punctuation by Windows */ + if (ch == 0x2212 || ch == 0x2044) + return Script_Punctuation; + + GetStringTypeW(CT_CTYPE1, &ch, 1, &type); + + if (type == 0) + return SCRIPT_UNDEFINED; + + if (type & C1_CNTRL) + return Script_Control; + + i = 0; + do + { + if (ch < scriptRanges[i].rangeFirst || scriptRanges[i].script == SCRIPT_UNDEFINED) + break; + + if (ch >= scriptRanges[i].rangeFirst && ch <= scriptRanges[i].rangeLast) + { + if (scriptRanges[i].numericScript && type & C1_DIGIT) + return scriptRanges[i].numericScript; + if (scriptRanges[i].punctScript && type & C1_PUNCT) + return scriptRanges[i].punctScript; + return scriptRanges[i].script; + } + i++; + } while (1); + + return SCRIPT_UNDEFINED; +} + /*********************************************************************** * DllMain * @@ -307,6 +622,8 @@ HRESULT WINAPI ScriptFreeCache(SCRIPT_CACHE *psc) heap_free(((ScriptCache *)*psc)->widths[i]); } heap_free(((ScriptCache *)*psc)->GSUB_Table); + heap_free(((ScriptCache *)*psc)->GDEF_Table); + heap_free(((ScriptCache *)*psc)->features); heap_free(*psc); *psc = NULL; } @@ -484,6 +801,392 @@ HRESULT WINAPI ScriptApplyDigitSubstitution(const SCRIPT_DIGITSUBSTITUTE *sds, } } +static inline BOOL is_indic(WORD script) +{ + return (script >= Script_Devanagari && script <= Script_Malayalam_Numeric); +} + +static inline WORD base_indic(WORD script) +{ + switch (script) + { + case Script_Devanagari: + case Script_Devanagari_Numeric: return Script_Devanagari; + case Script_Bengali: + case Script_Bengali_Numeric: + case Script_Bengali_Currency: return Script_Bengali; + case Script_Gurmukhi: + case Script_Gurmukhi_Numeric: return Script_Gurmukhi; + case Script_Gujarati: + case Script_Gujarati_Numeric: + case Script_Gujarati_Currency: return Script_Gujarati; + case Script_Oriya: + case Script_Oriya_Numeric: return Script_Oriya; + case Script_Tamil: + case Script_Tamil_Numeric: return Script_Tamil; + case Script_Telugu: + case Script_Telugu_Numeric: return Script_Telugu; + case Script_Kannada: + case Script_Kannada_Numeric: return Script_Kannada; + case Script_Malayalam: + case Script_Malayalam_Numeric: return Script_Malayalam; + default: + return -1; + }; +} + +/*********************************************************************** + * ScriptItemizeOpenType (USP10.@) + * + * Split a Unicode string into shapeable parts. + * + * PARAMS + * pwcInChars [I] String to split. + * cInChars [I] Number of characters in pwcInChars. + * cMaxItems [I] Maximum number of items to return. + * psControl [I] Pointer to a SCRIPT_CONTROL structure. + * psState [I] Pointer to a SCRIPT_STATE structure. + * pItems [O] Buffer to receive SCRIPT_ITEM structures. + * pScriptTags [O] Buffer to receive OPENTYPE_TAGs. + * pcItems [O] Number of script items returned. + * + * RETURNS + * Success: S_OK + * Failure: Non-zero HRESULT value. + */ +HRESULT WINAPI ScriptItemizeOpenType(const WCHAR *pwcInChars, int cInChars, int cMaxItems, + const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState, + SCRIPT_ITEM *pItems, OPENTYPE_TAG *pScriptTags, int *pcItems) +{ + +#define Numeric_space 0x0020 +#define ZWNJ 0x200C +#define ZWJ 0x200D + + int cnt = 0, index = 0, str = 0; + int New_Script = -1; + int i; + WORD *levels = NULL; + WORD *strength = NULL; + WORD *scripts = NULL; + WORD baselevel = 0; + BOOL new_run; + WORD last_indic = -1; + WORD layoutRTL = 0; + BOOL forceLevels = FALSE; + + TRACE("%s,%d,%d,%p,%p,%p,%p\n", debugstr_wn(pwcInChars, cInChars), cInChars, cMaxItems, + psControl, psState, pItems, pcItems); + + if (!pwcInChars || !cInChars || !pItems || cMaxItems < 2) + return E_INVALIDARG; + + scripts = heap_alloc(cInChars * sizeof(WORD)); + if (!scripts) + return E_OUTOFMEMORY; + + for (i = 0; i < cInChars; i++) + { + scripts[i] = get_char_script(pwcInChars[i]); + /* Devanagari danda (U+0964) and double danda (U+0965) are used for + all Indic scripts */ + if ((pwcInChars[i] == 0x964 || pwcInChars[i] ==0x965) && last_indic > 0) + scripts[i] = last_indic; + else if (is_indic(scripts[i])) + last_indic = base_indic(scripts[i]); + + /* Some unicode points (Zero Width Space U+200B - + Right-to-Left Mark U+200F) will force us into bidi mode */ + if (!forceLevels && pwcInChars[i] >= 0x200B && pwcInChars[i] <= 0x200F) + forceLevels = TRUE; + + /* Diacritical marks merge with other scripts */ + if (scripts[i] == Script_Diacritical && i > 0) + scripts[i] = scripts[i-1]; + } + + for (i = 0; i < cInChars; i++) + { + /* Joiners get merged preferencially right */ + if (i > 0 && (pwcInChars[i] == ZWJ || pwcInChars[i] == ZWNJ)) + { + int j; + if (i+1 == cInChars) + scripts[i] = scripts[i-1]; + else + { + for (j = i+1; j < cInChars; j++) + { + if (pwcInChars[j] != ZWJ && pwcInChars[j] != ZWNJ && pwcInChars[j] != Numeric_space) + { + scripts[i] = scripts[j]; + break; + } + } + } + } + } + + if (psState && psControl) + { + levels = heap_alloc_zero(cInChars * sizeof(WORD)); + if (!levels) + { + heap_free(scripts); + return E_OUTOFMEMORY; + } + + BIDI_DetermineLevels(pwcInChars, cInChars, psState, psControl, levels); + baselevel = levels[0]; + for (i = 0; i < cInChars; i++) + if (levels[i]!=levels[0]) + break; + if (i >= cInChars && !odd(baselevel) && !odd(psState->uBidiLevel) && !forceLevels) + { + heap_free(levels); + levels = NULL; + } + else + { + BOOL inNumber = FALSE; + static WCHAR math_punc[] = {'#','$','%','+',',','-','.','/',':',0x2212, 0x2044, 0x00a0,0}; + + strength = heap_alloc_zero(cInChars * sizeof(WORD)); + if (!strength) + { + heap_free(scripts); + heap_free(levels); + return E_OUTOFMEMORY; + } + BIDI_GetStrengths(pwcInChars, cInChars, psControl, strength); + + /* We currently mis-level leading Diacriticals */ + if (scripts[0] == Script_Diacritical) + for (i = 0; i < cInChars && scripts[0] == Script_Diacritical; i++) + { + levels[i] = odd(levels[i])?levels[i]+1:levels[i]; + strength[i] = BIDI_STRONG; + } + + for (i = 0; i < cInChars; i++) + { + /* Script_Numeric and select puncuation at level 0 get bumped to level 2 */ + if ((levels[i] == 0 || (odd(psState->uBidiLevel) && levels[i] == psState->uBidiLevel+1)) && inNumber && strchrW(math_punc,pwcInChars[i])) + { + scripts[i] = Script_Numeric; + levels[i] = 2; + } + else if ((levels[i] == 0 || (odd(psState->uBidiLevel) && levels[i] == psState->uBidiLevel+1)) && scripts[i] == Script_Numeric) + { + levels[i] = 2; + inNumber = TRUE; + } + else + inNumber = FALSE; + + /* Joiners get merged preferencially right */ + if (i > 0 && (pwcInChars[i] == ZWJ || pwcInChars[i] == ZWNJ)) + { + int j; + if (i+1 == cInChars && levels[i-1] == levels[i]) + strength[i] = strength[i-1]; + else + for (j = i+1; j < cInChars && levels[i] == levels[j]; j++) + if (pwcInChars[j] != ZWJ && pwcInChars[j] != ZWNJ && pwcInChars[j] != Numeric_space) + { + strength[i] = strength[j]; + break; + } + } + } + if (psControl->fMergeNeutralItems) + { + /* Merge the neutrals */ + for (i = 0; i < cInChars; i++) + { + if (strength[i] == BIDI_NEUTRAL || strength[i] == BIDI_WEAK) + { + int j; + for (j = i; j > 0; j--) + { + if (levels[i] != levels[j]) + break; + if ((strength[j] == BIDI_STRONG) || (strength[i] == BIDI_NEUTRAL && strength[j] == BIDI_WEAK)) + { + scripts[i] = scripts[j]; + strength[i] = strength[j]; + break; + } + } + } + /* Try going the other way */ + if (strength[i] == BIDI_NEUTRAL || strength[i] == BIDI_WEAK) + { + int j; + for (j = i; j < cInChars; j++) + { + if (levels[i] != levels[j]) + break; + if ((strength[j] == BIDI_STRONG) || (strength[i] == BIDI_NEUTRAL && strength[j] == BIDI_WEAK)) + { + scripts[i] = scripts[j]; + strength[i] = strength[j]; + break; + } + } + } + } + } + } + } + + while ((!levels || (levels && levels[cnt+1] == levels[0])) && (pwcInChars[cnt] == Numeric_space) && cnt < cInChars) + cnt++; + + if (cnt == cInChars) /* All Spaces */ + { + cnt = 0; + New_Script = scripts[cnt]; + } + + pItems[index].iCharPos = 0; + pItems[index].a = scriptInformation[scripts[cnt]].a; + pScriptTags[index] = scriptInformation[scripts[cnt]].scriptTag; + + if (strength && strength[cnt] == BIDI_STRONG) + str = strength[cnt]; + else if (strength) + str = strength[0]; + + cnt = 0; + + if (levels) + { + if (strength[cnt] == BIDI_STRONG) + layoutRTL = (odd(levels[cnt]))?1:0; + else + layoutRTL = (psState->uBidiLevel || odd(levels[cnt]))?1:0; + pItems[index].a.fRTL = odd(levels[cnt]); + pItems[index].a.fLayoutRTL = layoutRTL; + pItems[index].a.s.uBidiLevel = levels[cnt]; + } + else if (!pItems[index].a.s.uBidiLevel) + { + layoutRTL = (odd(baselevel))?1:0; + pItems[index].a.s.uBidiLevel = baselevel; + pItems[index].a.fLayoutRTL = odd(baselevel); + pItems[index].a.fRTL = odd(baselevel); + } + + TRACE("New_Level=%i New_Strength=%i New_Script=%d, eScript=%d index=%d cnt=%d iCharPos=%d\n", + levels?levels[cnt]:-1, str, New_Script, pItems[index].a.eScript, index, cnt, + pItems[index].iCharPos); + + for (cnt=1; cnt < cInChars; cnt++) + { + if(pwcInChars[cnt] != Numeric_space) + New_Script = scripts[cnt]; + else if (levels) + { + int j = 1; + while (cnt + j < cInChars - 1 && pwcInChars[cnt+j] == Numeric_space && levels[cnt] == levels[cnt+j]) + j++; + if (cnt + j < cInChars && levels[cnt] == levels[cnt+j]) + New_Script = scripts[cnt+j]; + else + New_Script = scripts[cnt]; + } + + new_run = FALSE; + /* merge space strengths*/ + if (strength && strength[cnt] == BIDI_STRONG && str != BIDI_STRONG && New_Script == pItems[index].a.eScript) + str = BIDI_STRONG; + + if (strength && strength[cnt] == BIDI_NEUTRAL && str == BIDI_STRONG && pwcInChars[cnt] != Numeric_space && New_Script == pItems[index].a.eScript) + str = BIDI_NEUTRAL; + + /* changes in level */ + if (levels && (levels[cnt] != pItems[index].a.s.uBidiLevel)) + { + TRACE("Level break(%i/%i)\n",pItems[index].a.s.uBidiLevel,levels[cnt]); + new_run = TRUE; + } + /* changes in strength */ + else if (strength && pwcInChars[cnt] != Numeric_space && str != strength[cnt]) + { + TRACE("Strength break (%i/%i)\n",str,strength[cnt]); + new_run = TRUE; + } + /* changes in script */ + else if (((pwcInChars[cnt] != Numeric_space) && (New_Script != -1) && (New_Script != pItems[index].a.eScript)) || (New_Script == Script_Control)) + { + TRACE("Script break(%i/%i)\n",pItems[index].a.eScript,New_Script); + new_run = TRUE; + } + + if (!new_run && strength && str == BIDI_STRONG) + { + layoutRTL = odd(levels[cnt])?1:0; + pItems[index].a.fLayoutRTL = layoutRTL; + } + + if (new_run) + { + TRACE("New_Level = %i, New_Strength = %i, New_Script=%d, eScript=%d\n", levels?levels[cnt]:-1, strength?strength[cnt]:str, New_Script, pItems[index].a.eScript); + + index++; + if (index+1 > cMaxItems) + return E_OUTOFMEMORY; + + if (strength) + str = strength[cnt]; + + pItems[index].iCharPos = cnt; + memset(&pItems[index].a, 0, sizeof(SCRIPT_ANALYSIS)); + + pItems[index].a = scriptInformation[New_Script].a; + pScriptTags[index] = scriptInformation[New_Script].scriptTag; + if (levels) + { + if (levels[cnt] == 0) + layoutRTL = 0; + else + layoutRTL = (layoutRTL || odd(levels[cnt]))?1:0; + pItems[index].a.fRTL = odd(levels[cnt]); + pItems[index].a.fLayoutRTL = layoutRTL; + pItems[index].a.s.uBidiLevel = levels[cnt]; + } + else if (!pItems[index].a.s.uBidiLevel) + { + pItems[index].a.s.uBidiLevel = baselevel; + pItems[index].a.fLayoutRTL = layoutRTL; + pItems[index].a.fRTL = odd(baselevel); + } + + TRACE("index=%d cnt=%d iCharPos=%d\n", index, cnt, pItems[index].iCharPos); + } + } + + /* While not strictly necessary according to the spec, make sure the n+1 + * item is set up to prevent random behaviour if the caller erroneously + * checks the n+1 structure */ + index++; + memset(&pItems[index].a, 0, sizeof(SCRIPT_ANALYSIS)); + + TRACE("index=%d cnt=%d iCharPos=%d\n", index, cnt, pItems[index].iCharPos); + + /* Set one SCRIPT_STATE item being returned */ + if (index + 1 > cMaxItems) return E_OUTOFMEMORY; + if (pcItems) *pcItems = index; + + /* Set SCRIPT_ITEM */ + pItems[index].iCharPos = cnt; /* the last item contains the ptr to the lastchar */ + heap_free(levels); + heap_free(strength); + heap_free(scripts); + return S_OK; +} + /*********************************************************************** * ScriptItemize (USP10.@) * @@ -506,184 +1209,132 @@ HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItem const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState, SCRIPT_ITEM *pItems, int *pcItems) { + OPENTYPE_TAG *discarded_tags; + HRESULT res; -#define Numeric_start 0x0030 -#define Numeric_stop 0x0039 -#define Numeric_space 0x0020 -#define Arabic_start 0x0600 -#define Arabic_stop 0x06ff -#define Hebrew_start 0x0590 -#define Hebrew_stop 0x05ff -#define Syriac_start 0x0700 -#define Syriac_stop 0x074f -#define Latin_start 0x0001 -#define Latin_stop 0x024f + discarded_tags = heap_alloc(cMaxItems * sizeof(OPENTYPE_TAG)); + if (!discarded_tags) + return E_OUTOFMEMORY; + res = ScriptItemizeOpenType(pwcInChars, cInChars, cMaxItems, psControl, psState, pItems, discarded_tags, pcItems); + heap_free(discarded_tags); + return res; +} - int cnt = 0, index = 0; - int New_Script = SCRIPT_UNDEFINED; - WORD *levels = NULL; - WORD baselevel = 0; +static inline int getGivenTabWidth(ScriptCache *psc, SCRIPT_TABDEF *pTabdef, int charPos, int current_x) +{ + int defWidth; + int cTabStops=0; + INT *lpTabPos = NULL; + INT nTabOrg = 0; + INT x = 0; - TRACE("%s,%d,%d,%p,%p,%p,%p\n", debugstr_wn(pwcInChars, cInChars), cInChars, cMaxItems, - psControl, psState, pItems, pcItems); + if (pTabdef) + lpTabPos = pTabdef->pTabStops; - if (!pwcInChars || !cInChars || !pItems || cMaxItems < 2) - return E_INVALIDARG; - - if (psState && psControl) + if (pTabdef && pTabdef->iTabOrigin) { - int i; - levels = heap_alloc_zero(cInChars * sizeof(WORD)); - if (!levels) - return E_OUTOFMEMORY; + if (pTabdef->iScale) + nTabOrg = (pTabdef->iTabOrigin * pTabdef->iScale)/4; + else + nTabOrg = pTabdef->iTabOrigin * psc->tm.tmAveCharWidth; + } - BIDI_DetermineLevels(pwcInChars, cInChars, psState, psControl, levels); - baselevel = levels[0]; - for (i = 0; i < cInChars; i++) - if (levels[i]!=levels[0]) + if (pTabdef) + cTabStops = pTabdef->cTabStops; + + if (cTabStops == 1) + { + if (pTabdef->iScale) + defWidth = ((pTabdef->pTabStops[0])*pTabdef->iScale) / 4; + else + defWidth = (pTabdef->pTabStops[0])*psc->tm.tmAveCharWidth; + cTabStops = 0; + } + else + defWidth = 8 * psc->tm.tmAveCharWidth; + + for (; cTabStops>0 ; lpTabPos++, cTabStops--) + { + int position = *lpTabPos; + if (position < 0) + position = -1 * position; + if (pTabdef->iScale) + position = (position * pTabdef->iScale) / 4; + else + position = position * psc->tm.tmAveCharWidth; + + if( nTabOrg + position > current_x) + { + if( *lpTabPos >= 0) + { + /* a left aligned tab */ + x = (nTabOrg + *lpTabPos) - current_x; break; - if (i >= cInChars) - { - heap_free(levels); - levels = NULL; - } - } - - pItems[index].iCharPos = 0; - memset(&pItems[index].a, 0, sizeof(SCRIPT_ANALYSIS)); - - if (pwcInChars[cnt] == '\r') - pItems[index].a.eScript = Script_CR; - else - if (pwcInChars[cnt] == '\n') - pItems[index].a.eScript = Script_LF; - else - if (pwcInChars[cnt] >= Numeric_start && pwcInChars[cnt] <= Numeric_stop) - pItems[index].a.eScript = Script_Numeric; - else - if (pwcInChars[cnt] >= Arabic_start && pwcInChars[cnt] <= Arabic_stop) - pItems[index].a.eScript = Script_Arabic; - else - if (pwcInChars[cnt] >= Hebrew_start && pwcInChars[cnt] <= Hebrew_stop) - pItems[index].a.eScript = Script_Hebrew; - else - if (pwcInChars[cnt] >= Syriac_start && pwcInChars[cnt] <= Syriac_stop) - pItems[index].a.eScript = Script_Syriac; - else - if (pwcInChars[cnt] >= Latin_start && pwcInChars[cnt] <= Latin_stop) - pItems[index].a.eScript = Script_Latin; - - if (levels) - { - pItems[index].a.fRTL = odd(levels[cnt]); - pItems[index].a.fLayoutRTL = odd(levels[cnt]); - pItems[index].a.s.uBidiLevel = levels[cnt]; - } - else if ((pItems[index].a.eScript == Script_Arabic) || - (pItems[index].a.eScript == Script_Hebrew) || - (pItems[index].a.eScript == Script_Syriac)) - { - pItems[index].a.s.uBidiLevel = 1; - pItems[index].a.fRTL = 1; - pItems[index].a.fLayoutRTL = 1; - } - else - { - pItems[index].a.s.uBidiLevel = baselevel; - pItems[index].a.fLayoutRTL = odd(baselevel); - pItems[index].a.fRTL = odd(baselevel); - } - - TRACE("New_Level=%i New_Script=%d, eScript=%d index=%d cnt=%d iCharPos=%d\n", - levels?levels[cnt]:-1, New_Script, pItems[index].a.eScript, index, cnt, - pItems[index].iCharPos); - - for (cnt=1; cnt < cInChars; cnt++) - { - if (levels && (levels[cnt] == pItems[index].a.s.uBidiLevel)) - continue; - - if (pwcInChars[cnt] == '\r') - New_Script = Script_CR; - else - if (pwcInChars[cnt] == '\n') - New_Script = Script_LF; - else - if ((pwcInChars[cnt] >= Numeric_start && pwcInChars[cnt] <= Numeric_stop) - || (New_Script == Script_Numeric && pwcInChars[cnt] == Numeric_space)) - New_Script = Script_Numeric; - else - if ((pwcInChars[cnt] >= Arabic_start && pwcInChars[cnt] <= Arabic_stop) - || (New_Script == Script_Arabic && pwcInChars[cnt] == Numeric_space)) - New_Script = Script_Arabic; - else - if ((pwcInChars[cnt] >= Hebrew_start && pwcInChars[cnt] <= Hebrew_stop) - || (New_Script == Script_Hebrew && pwcInChars[cnt] == Numeric_space)) - New_Script = Script_Hebrew; - else - if ((pwcInChars[cnt] >= Syriac_start && pwcInChars[cnt] <= Syriac_stop) - || (New_Script == Script_Syriac && pwcInChars[cnt] == Numeric_space)) - New_Script = Script_Syriac; - else - if ((pwcInChars[cnt] >= Latin_start && pwcInChars[cnt] <= Latin_stop) - || (New_Script == Script_Latin && pwcInChars[cnt] == Numeric_space)) - New_Script = Script_Latin; - else - New_Script = SCRIPT_UNDEFINED; - - if ((levels && (levels[cnt] != pItems[index].a.s.uBidiLevel)) || New_Script != pItems[index].a.eScript) - { - TRACE("New_Level = %i, New_Script=%d, eScript=%d ", levels?levels[cnt]:-1, New_Script, pItems[index].a.eScript); - index++; - if (index+1 > cMaxItems) - return E_OUTOFMEMORY; - - pItems[index].iCharPos = cnt; - memset(&pItems[index].a, 0, sizeof(SCRIPT_ANALYSIS)); - - if (levels) - { - pItems[index].a.fRTL = odd(levels[cnt]); - pItems[index].a.fLayoutRTL = odd(levels[cnt]); - pItems[index].a.s.uBidiLevel = levels[cnt]; - } - else if ((New_Script == Script_Arabic) || - (New_Script == Script_Hebrew) || - (New_Script == Script_Syriac)) - { - pItems[index].a.s.uBidiLevel = 1; - pItems[index].a.fRTL = 1; - pItems[index].a.fLayoutRTL = 1; } else { - pItems[index].a.s.uBidiLevel = baselevel; - pItems[index].a.fLayoutRTL = odd(baselevel); - pItems[index].a.fRTL = odd(baselevel); + FIXME("Negative tabstop\n"); + break; } - - pItems[index].a.eScript = New_Script; - - TRACE("index=%d cnt=%d iCharPos=%d\n", index, cnt, pItems[index].iCharPos); } } + if ((!cTabStops) && (defWidth > 0)) + x =((((current_x - nTabOrg) / defWidth)+1) * defWidth) - current_x; + else if ((!cTabStops) && (defWidth < 0)) + FIXME("TODO: Negative defWidth\n"); - /* While not strictly necessary according to the spec, make sure the n+1 - * item is set up to prevent random behaviour if the caller erroneously - * checks the n+1 structure */ - index++; - memset(&pItems[index].a, 0, sizeof(SCRIPT_ANALYSIS)); + return x; +} - TRACE("index=%d cnt=%d iCharPos=%d\n", index, cnt, pItems[index].iCharPos); +/*********************************************************************** + * Helper function for ScriptStringAnalyse + */ +static BOOL requires_fallback(HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, + const WCHAR *pwcInChars, int cChars ) +{ + /* FIXME: When to properly fallback is still a bit of a mystery */ + WORD *glyphs; - /* Set one SCRIPT_STATE item being returned */ - if (index + 1 > cMaxItems) return E_OUTOFMEMORY; - if (pcItems) *pcItems = index; + if (psa->fNoGlyphIndex) + return FALSE; - /* Set SCRIPT_ITEM */ - pItems[index].iCharPos = cnt; /* the last item contains the ptr to the lastchar */ - heap_free(levels); - return S_OK; + if (init_script_cache(hdc, psc) != S_OK) + return FALSE; + + if (SHAPE_CheckFontForRequiredFeatures(hdc, (ScriptCache *)*psc, psa) != S_OK) + return TRUE; + + glyphs = heap_alloc(sizeof(WORD) * cChars); + if (!glyphs) + return FALSE; + if (ScriptGetCMap(hdc, psc, pwcInChars, cChars, 0, glyphs) != S_OK) + { + heap_free(glyphs); + return TRUE; + } + heap_free(glyphs); + + return FALSE; +} + +static void find_fallback_font(DWORD scriptid, LPWSTR FaceName) +{ + HKEY hkey; + + if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Uniscribe\\Fallback", &hkey)) + { + static const WCHAR szFmt[] = {'%','x',0}; + WCHAR value[10]; + DWORD count = LF_FACESIZE * sizeof(WCHAR); + DWORD type; + + sprintfW(value, szFmt, scriptInformation[scriptid].scriptTag); + if (RegQueryValueExW(hkey, value, 0, &type, (LPBYTE)FaceName, &count)) + lstrcpyW(FaceName,scriptInformation[scriptid].fallbackFont); + RegCloseKey(hkey); + } + else + lstrcpyW(FaceName,scriptInformation[scriptid].fallbackFont); } /*********************************************************************** @@ -699,7 +1350,11 @@ HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString, { HRESULT hr = E_OUTOFMEMORY; StringAnalysis *analysis = NULL; + SCRIPT_CONTROL sControl; + SCRIPT_STATE sState; int i, num_items = 255; + BYTE *BidiLevel; + WCHAR *iString = NULL; TRACE("(%p,%p,%d,%d,%d,0x%x,%d,%p,%p,%p,%p,%p,%p)\n", hdc, pString, cString, cGlyphs, iCharset, dwFlags, iReqWidth, @@ -719,8 +1374,32 @@ HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString, /* FIXME: handle clipping */ analysis->clip_len = cString; analysis->hdc = hdc; + analysis->dwFlags = dwFlags; - hr = ScriptItemize(pString, cString, num_items, psControl, psState, analysis->pItem, + if (psState) + sState = *psState; + else + memset(&sState, 0, sizeof(SCRIPT_STATE)); + + if (psControl) + sControl = *psControl; + else + memset(&sControl, 0, sizeof(SCRIPT_CONTROL)); + + if (dwFlags & SSA_PASSWORD) + { + iString = heap_alloc(sizeof(WCHAR)*cString); + if (!iString) + { + hr = E_OUTOFMEMORY; + goto error; + } + for (i = 0; i < cString; i++) + iString[i] = *((const WCHAR *)pString); + pString = iString; + } + + hr = ScriptItemize(pString, cString, num_items, &sControl, &sState, analysis->pItem, &analysis->numItems); while (hr == E_OUTOFMEMORY) @@ -737,56 +1416,266 @@ HRESULT WINAPI ScriptStringAnalyse(HDC hdc, const void *pString, int cString, } if (hr != S_OK) goto error; - if ((analysis->logattrs = heap_alloc(sizeof(SCRIPT_LOGATTR) * cString))) - ScriptBreak(pString, cString, (SCRIPT_STRING_ANALYSIS)analysis, analysis->logattrs); - else - goto error; + /* set back to out of memory for default goto error behaviour */ + hr = E_OUTOFMEMORY; - if (!(analysis->glyphs = heap_alloc_zero(sizeof(StringGlyphs) * analysis->numItems))) - goto error; - - for (i = 0; i < analysis->numItems; i++) + if (dwFlags & SSA_BREAK) { - SCRIPT_CACHE *sc = (SCRIPT_CACHE *)&analysis->sc; - int cChar = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos; - int numGlyphs = 1.5 * cChar + 16; - WORD *glyphs = heap_alloc_zero(sizeof(WORD) * numGlyphs); - WORD *pwLogClust = heap_alloc_zero(sizeof(WORD) * cChar); - int *piAdvance = heap_alloc_zero(sizeof(int) * numGlyphs); - SCRIPT_VISATTR *psva = heap_alloc_zero(sizeof(SCRIPT_VISATTR) * cChar); - GOFFSET *pGoffset = heap_alloc_zero(sizeof(GOFFSET) * numGlyphs); - ABC *abc = heap_alloc_zero(sizeof(ABC)); - int numGlyphsReturned; - - /* FIXME: non unicode strings */ - const WCHAR* pStr = (const WCHAR*)pString; - hr = ScriptShape(hdc, sc, &pStr[analysis->pItem[i].iCharPos], - cChar, numGlyphs, &analysis->pItem[i].a, - glyphs, pwLogClust, psva, &numGlyphsReturned); - hr = ScriptPlace(hdc, sc, glyphs, numGlyphsReturned, psva, &analysis->pItem[i].a, - piAdvance, pGoffset, abc); - - analysis->glyphs[i].numGlyphs = numGlyphsReturned; - analysis->glyphs[i].glyphs = glyphs; - analysis->glyphs[i].pwLogClust = pwLogClust; - analysis->glyphs[i].piAdvance = piAdvance; - analysis->glyphs[i].psva = psva; - analysis->glyphs[i].pGoffset = pGoffset; - analysis->glyphs[i].abc = abc; + if ((analysis->logattrs = heap_alloc(sizeof(SCRIPT_LOGATTR) * cString))) + { + for (i = 0; i < analysis->numItems; i++) + ScriptBreak(&((LPWSTR)pString)[analysis->pItem[i].iCharPos], analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos, &analysis->pItem[i].a, &analysis->logattrs[analysis->pItem[i].iCharPos]); + } + else + goto error; } + if (!(analysis->logical2visual = heap_alloc_zero(sizeof(int) * analysis->numItems))) + goto error; + if (!(BidiLevel = heap_alloc_zero(analysis->numItems))) + goto error; + + if (dwFlags & SSA_GLYPHS) + { + int tab_x = 0; + if (!(analysis->glyphs = heap_alloc_zero(sizeof(StringGlyphs) * analysis->numItems))) + goto error; + + for (i = 0; i < analysis->numItems; i++) + { + SCRIPT_CACHE *sc = (SCRIPT_CACHE*)&analysis->glyphs[i].sc; + int cChar = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos; + int numGlyphs = 1.5 * cChar + 16; + WORD *glyphs = heap_alloc_zero(sizeof(WORD) * numGlyphs); + WORD *pwLogClust = heap_alloc_zero(sizeof(WORD) * cChar); + int *piAdvance = heap_alloc_zero(sizeof(int) * numGlyphs); + SCRIPT_VISATTR *psva = heap_alloc_zero(sizeof(SCRIPT_VISATTR) * numGlyphs); + GOFFSET *pGoffset = heap_alloc_zero(sizeof(GOFFSET) * numGlyphs); + ABC *abc = heap_alloc_zero(sizeof(ABC)); + int numGlyphsReturned; + HFONT originalFont = 0x0; + + /* FIXME: non unicode strings */ + const WCHAR* pStr = (const WCHAR*)pString; + analysis->glyphs[i].fallbackFont = NULL; + + if (!glyphs || !pwLogClust || !piAdvance || !psva || !pGoffset || !abc) + { + heap_free (glyphs); + heap_free (pwLogClust); + heap_free (piAdvance); + heap_free (psva); + heap_free (pGoffset); + heap_free (abc); + hr = E_OUTOFMEMORY; + goto error; + } + + if ((dwFlags & SSA_FALLBACK) && requires_fallback(hdc, sc, &analysis->pItem[i].a, &pStr[analysis->pItem[i].iCharPos], cChar)) + { + LOGFONTW lf; + GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), & lf); + lf.lfCharSet = scriptInformation[analysis->pItem[i].a.eScript].props.bCharSet; + find_fallback_font(analysis->pItem[i].a.eScript, lf.lfFaceName); + analysis->glyphs[i].fallbackFont = CreateFontIndirectW(&lf); + if (analysis->glyphs[i].fallbackFont) + { + ScriptFreeCache(sc); + originalFont = SelectObject(hdc, analysis->glyphs[i].fallbackFont); + } + } + + hr = ScriptShape(hdc, sc, &pStr[analysis->pItem[i].iCharPos], + cChar, numGlyphs, &analysis->pItem[i].a, + glyphs, pwLogClust, psva, &numGlyphsReturned); + hr = ScriptPlace(hdc, sc, glyphs, numGlyphsReturned, psva, &analysis->pItem[i].a, + piAdvance, pGoffset, abc); + if (originalFont) + SelectObject(hdc,originalFont); + + if (dwFlags & SSA_TAB) + { + int tabi = 0; + for (tabi = 0; tabi < cChar; tabi++) + { + if (pStr[analysis->pItem[i].iCharPos+tabi] == 0x0009) + piAdvance[tabi] = getGivenTabWidth(analysis->glyphs[i].sc, pTabdef, analysis->pItem[i].iCharPos+tabi, tab_x); + tab_x+=piAdvance[tabi]; + } + } + + analysis->glyphs[i].numGlyphs = numGlyphsReturned; + analysis->glyphs[i].glyphs = glyphs; + analysis->glyphs[i].pwLogClust = pwLogClust; + analysis->glyphs[i].piAdvance = piAdvance; + analysis->glyphs[i].psva = psva; + analysis->glyphs[i].pGoffset = pGoffset; + analysis->glyphs[i].abc = abc; + analysis->glyphs[i].iMaxPosX= -1; + + BidiLevel[i] = analysis->pItem[i].a.s.uBidiLevel; + } + } + else + { + for (i = 0; i < analysis->numItems; i++) + BidiLevel[i] = analysis->pItem[i].a.s.uBidiLevel; + } + + ScriptLayout(analysis->numItems, BidiLevel, NULL, analysis->logical2visual); + heap_free(BidiLevel); + *pssa = analysis; + heap_free(iString); return S_OK; error: + heap_free(iString); heap_free(analysis->glyphs); heap_free(analysis->logattrs); heap_free(analysis->pItem); - heap_free(analysis->sc); + heap_free(analysis->logical2visual); heap_free(analysis); return hr; } +static inline BOOL does_glyph_start_cluster(const SCRIPT_VISATTR *pva, const WORD *pwLogClust, int cChars, int glyph, int direction) +{ + int i; + + if (pva[glyph].fClusterStart) + return TRUE; + for (i = 0; i < cChars; i++) + if (pwLogClust[i] == glyph) break; + if (i != cChars) + return TRUE; + + return FALSE; +} + + +static HRESULT SS_ItemOut( SCRIPT_STRING_ANALYSIS ssa, + int iX, + int iY, + int iItem, + int cStart, + int cEnd, + UINT uOptions, + const RECT *prc, + BOOL fSelected, + BOOL fDisabled) +{ + StringAnalysis *analysis; + int off_x = 0; + HRESULT hr; + COLORREF BkColor = 0x0; + COLORREF TextColor = 0x0; + INT BkMode = 0; + INT runStart, runEnd; + INT iGlyph, cGlyphs; + HFONT oldFont = 0x0; + + TRACE("(%p,%d,%d,%d,%d,%d, 0x%1x, %d, %d)\n", + ssa, iX, iY, iItem, cStart, cEnd, uOptions, fSelected, fDisabled); + + if (!(analysis = ssa)) return E_INVALIDARG; + + if ((cStart >= 0 && analysis->pItem[iItem+1].iCharPos <= cStart) || + (cEnd >= 0 && analysis->pItem[iItem].iCharPos >= cEnd)) + return S_OK; + + if (fSelected) + { + BkMode = GetBkMode(analysis->hdc); + SetBkMode( analysis->hdc, OPAQUE); + BkColor = GetBkColor(analysis->hdc); + SetBkColor(analysis->hdc, GetSysColor(COLOR_HIGHLIGHT)); + if (!fDisabled) + { + TextColor = GetTextColor(analysis->hdc); + SetTextColor(analysis->hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + } + } + if (analysis->glyphs[iItem].fallbackFont) + oldFont = SelectObject(analysis->hdc, analysis->glyphs[iItem].fallbackFont); + + if (cStart >= 0 && analysis->pItem[iItem+1].iCharPos > cStart && analysis->pItem[iItem].iCharPos <= cStart) + runStart = cStart - analysis->pItem[iItem].iCharPos; + else + runStart = 0; + if (cEnd >= 0 && analysis->pItem[iItem+1].iCharPos > cEnd && analysis->pItem[iItem].iCharPos <= cEnd) + runEnd = (cEnd-1) - analysis->pItem[iItem].iCharPos; + else + runEnd = (analysis->pItem[iItem+1].iCharPos - analysis->pItem[iItem].iCharPos) - 1; + + if (analysis->pItem[iItem].a.fRTL) + { + if (cEnd >= 0 && cEnd < analysis->pItem[iItem+1].iCharPos) + ScriptStringCPtoX(ssa, cEnd, FALSE, &off_x); + else + ScriptStringCPtoX(ssa, analysis->pItem[iItem+1].iCharPos-1, TRUE, &off_x); + } + else + { + if (cStart >=0 && runStart) + ScriptStringCPtoX(ssa, cStart, FALSE, &off_x); + else + ScriptStringCPtoX(ssa, analysis->pItem[iItem].iCharPos, FALSE, &off_x); + } + + if (analysis->pItem[iItem].a.fRTL) + iGlyph = analysis->glyphs[iItem].pwLogClust[runEnd]; + else + iGlyph = analysis->glyphs[iItem].pwLogClust[runStart]; + + if (analysis->pItem[iItem].a.fRTL) + cGlyphs = analysis->glyphs[iItem].pwLogClust[runStart] - iGlyph; + else + cGlyphs = analysis->glyphs[iItem].pwLogClust[runEnd] - iGlyph; + + cGlyphs++; + + if (cEnd < 0 || scriptInformation[analysis->pItem[iItem].a.eScript].props.fNeedsCaretInfo) + { + INT direction; + INT clust_glyph; + + clust_glyph = iGlyph + cGlyphs; + if (analysis->pItem[iItem].a.fRTL) + direction = -1; + else + direction = 1; + + while(clust_glyph < analysis->glyphs[iItem].numGlyphs && + !does_glyph_start_cluster(analysis->glyphs[iItem].psva, analysis->glyphs[iItem].pwLogClust, (analysis->pItem[iItem+1].iCharPos - analysis->pItem[iItem].iCharPos), clust_glyph, direction)) + { + cGlyphs++; + clust_glyph++; + } + } + + hr = ScriptTextOut(analysis->hdc, + (SCRIPT_CACHE *)&analysis->glyphs[iItem].sc, iX + off_x, + iY, uOptions, prc, &analysis->pItem[iItem].a, NULL, 0, + &analysis->glyphs[iItem].glyphs[iGlyph], cGlyphs, + &analysis->glyphs[iItem].piAdvance[iGlyph], NULL, + &analysis->glyphs[iItem].pGoffset[iGlyph]); + + TRACE("ScriptTextOut hr=%08x\n", hr); + + if (fSelected) + { + SetBkColor(analysis->hdc, BkColor); + SetBkMode( analysis->hdc, BkMode); + if (!fDisabled) + SetTextColor(analysis->hdc, TextColor); + } + if (analysis->glyphs[iItem].fallbackFont) + SelectObject(analysis->hdc, oldFont); + + return hr; +} + /*********************************************************************** * ScriptStringOut (USP10.@) * @@ -818,61 +1707,35 @@ HRESULT WINAPI ScriptStringOut(SCRIPT_STRING_ANALYSIS ssa, BOOL fDisabled) { StringAnalysis *analysis; - WORD *glyphs; - int item, cnt, x; + int item; HRESULT hr; TRACE("(%p,%d,%d,0x%1x,%p,%d,%d,%d)\n", ssa, iX, iY, uOptions, prc, iMinSel, iMaxSel, fDisabled); if (!(analysis = ssa)) return E_INVALIDARG; + if (!(analysis->dwFlags & SSA_GLYPHS)) return E_INVALIDARG; - /* - * Get storage for the output buffer for the consolidated strings - */ - cnt = 0; for (item = 0; item < analysis->numItems; item++) { - cnt += analysis->glyphs[item].numGlyphs; + hr = SS_ItemOut( ssa, iX, iY, analysis->logical2visual[item], -1, -1, uOptions, prc, FALSE, fDisabled); + if (FAILED(hr)) + return hr; } - if (!(glyphs = heap_alloc(sizeof(WCHAR) * cnt))) return E_OUTOFMEMORY; - /* - * ScriptStringOut only processes glyphs hence set ETO_GLYPH_INDEX - */ - uOptions |= ETO_GLYPH_INDEX; - analysis->pItem[0].a.fNoGlyphIndex = FALSE; /* say that we have glyphs */ - - /* - * Copy the string items into the output buffer - */ - - TRACE("numItems %d\n", analysis->numItems); - - cnt = 0; - for (item = 0; item < analysis->numItems; item++) + if (iMinSel < iMaxSel && (iMinSel > 0 || iMaxSel > 0)) { - memcpy(&glyphs[cnt], analysis->glyphs[item].glyphs, - sizeof(WCHAR) * analysis->glyphs[item].numGlyphs); - - TRACE("Item %d, Glyphs %d ", item, analysis->glyphs[item].numGlyphs); - for (x = cnt; x < analysis->glyphs[item].numGlyphs + cnt; x ++) - TRACE("%04x", glyphs[x]); - TRACE("\n"); - - cnt += analysis->glyphs[item].numGlyphs; /* point to the end of the copied text */ + if (iMaxSel > 0 && iMinSel < 0) + iMinSel = 0; + for (item = 0; item < analysis->numItems; item++) + { + hr = SS_ItemOut( ssa, iX, iY, analysis->logical2visual[item], iMinSel, iMaxSel, uOptions, prc, TRUE, fDisabled); + if (FAILED(hr)) + return hr; + } } - hr = ScriptTextOut(analysis->hdc, (SCRIPT_CACHE *)&analysis->sc, iX, iY, - uOptions, prc, &analysis->pItem->a, NULL, 0, glyphs, cnt, - analysis->glyphs->piAdvance, NULL, analysis->glyphs->pGoffset); - TRACE("ScriptTextOut hr=%08x\n", hr); - - /* - * Free the output buffer and script cache - */ - heap_free(glyphs); - return hr; + return S_OK; } /*********************************************************************** @@ -881,14 +1744,14 @@ HRESULT WINAPI ScriptStringOut(SCRIPT_STRING_ANALYSIS ssa, */ HRESULT WINAPI ScriptStringCPtoX(SCRIPT_STRING_ANALYSIS ssa, int icp, BOOL fTrailing, int* pX) { - int i, j; + int item; int runningX = 0; - int runningCp = 0; StringAnalysis* analysis = ssa; TRACE("(%p), %d, %d, (%p)\n", ssa, icp, fTrailing, pX); if (!ssa || !pX) return S_FALSE; + if (!(analysis->dwFlags & SSA_GLYPHS)) return S_FALSE; /* icp out of range */ if(icp < 0) @@ -897,23 +1760,40 @@ HRESULT WINAPI ScriptStringCPtoX(SCRIPT_STRING_ANALYSIS ssa, int icp, BOOL fTrai return E_INVALIDARG; } - for(i=0; inumItems; i++) + for(item=0; itemnumItems; item++) { - for(j=0; jglyphs[i].numGlyphs; j++) + int CP, i; + int offset; + + i = analysis->logical2visual[item]; + CP = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos; + /* initialize max extents for uninitialized runs */ + if (analysis->glyphs[i].iMaxPosX == -1) { - if(runningCp == icp && fTrailing == FALSE) - { - *pX = runningX; - return S_OK; - } - runningX += analysis->glyphs[i].piAdvance[j]; - if(runningCp == icp && fTrailing == TRUE) - { - *pX = runningX; - return S_OK; - } - runningCp++; + if (analysis->pItem[i].a.fRTL) + ScriptCPtoX(0, FALSE, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust, + analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance, + &analysis->pItem[i].a, &analysis->glyphs[i].iMaxPosX); + else + ScriptCPtoX(CP, TRUE, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust, + analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance, + &analysis->pItem[i].a, &analysis->glyphs[i].iMaxPosX); } + + if (icp >= analysis->pItem[i+1].iCharPos || icp < analysis->pItem[i].iCharPos) + { + runningX += analysis->glyphs[i].iMaxPosX; + continue; + } + + icp -= analysis->pItem[i].iCharPos; + ScriptCPtoX(icp, fTrailing, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust, + analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance, + &analysis->pItem[i].a, &offset); + runningX += offset; + + *pX = runningX; + return S_OK; } /* icp out of range */ @@ -925,44 +1805,66 @@ HRESULT WINAPI ScriptStringCPtoX(SCRIPT_STRING_ANALYSIS ssa, int icp, BOOL fTrai * ScriptStringXtoCP (USP10.@) * */ -HRESULT WINAPI ScriptStringXtoCP(SCRIPT_STRING_ANALYSIS ssa, int iX, int* piCh, int* piTrailing) +HRESULT WINAPI ScriptStringXtoCP(SCRIPT_STRING_ANALYSIS ssa, int iX, int* piCh, int* piTrailing) { StringAnalysis* analysis = ssa; - int i; - int j; - int runningX = 0; - int runningCp = 0; - int width; + int item; TRACE("(%p), %d, (%p), (%p)\n", ssa, iX, piCh, piTrailing); if (!ssa || !piCh || !piTrailing) return S_FALSE; + if (!(analysis->dwFlags & SSA_GLYPHS)) return S_FALSE; /* out of range */ if(iX < 0) { - *piCh = -1; - *piTrailing = TRUE; + if (analysis->pItem[0].a.fRTL) + { + *piCh = 1; + *piTrailing = FALSE; + } + else + { + *piCh = -1; + *piTrailing = TRUE; + } return S_OK; } - for(i=0; inumItems; i++) + for(item=0; itemnumItems; item++) { - for(j=0; jglyphs[i].numGlyphs; j++) + int i; + int CP; + + for (i = 0; i < analysis->numItems && analysis->logical2visual[i] != item; i++) + /* nothing */; + + CP = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos; + /* initialize max extents for uninitialized runs */ + if (analysis->glyphs[i].iMaxPosX == -1) { - width = analysis->glyphs[i].piAdvance[j]; - if(iX < (runningX + width)) - { - *piCh = runningCp; - if((iX - runningX) > width/2) - *piTrailing = TRUE; - else - *piTrailing = FALSE; - return S_OK; - } - runningX += width; - runningCp++; + if (analysis->pItem[i].a.fRTL) + ScriptCPtoX(0, FALSE, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust, + analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance, + &analysis->pItem[i].a, &analysis->glyphs[i].iMaxPosX); + else + ScriptCPtoX(CP, TRUE, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust, + analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance, + &analysis->pItem[i].a, &analysis->glyphs[i].iMaxPosX); } + + if (iX > analysis->glyphs[i].iMaxPosX) + { + iX -= analysis->glyphs[i].iMaxPosX; + continue; + } + + ScriptXtoCP(iX, CP, analysis->glyphs[i].numGlyphs, analysis->glyphs[i].pwLogClust, + analysis->glyphs[i].psva, analysis->glyphs[i].piAdvance, + &analysis->pItem[i].a, piCh, piTrailing); + *piCh += analysis->pItem[i].iCharPos; + + return S_OK; } /* out of range */ @@ -996,29 +1898,89 @@ HRESULT WINAPI ScriptStringFree(SCRIPT_STRING_ANALYSIS *pssa) if (!pssa || !(analysis = *pssa)) return E_INVALIDARG; invalid = analysis->invalid; - ScriptFreeCache((SCRIPT_CACHE *)&analysis->sc); - for (i = 0; i < analysis->numItems; i++) + if (analysis->glyphs) { - heap_free(analysis->glyphs[i].glyphs); - heap_free(analysis->glyphs[i].pwLogClust); - heap_free(analysis->glyphs[i].piAdvance); - heap_free(analysis->glyphs[i].psva); - heap_free(analysis->glyphs[i].pGoffset); - heap_free(analysis->glyphs[i].abc); + for (i = 0; i < analysis->numItems; i++) + { + heap_free(analysis->glyphs[i].glyphs); + heap_free(analysis->glyphs[i].pwLogClust); + heap_free(analysis->glyphs[i].piAdvance); + heap_free(analysis->glyphs[i].psva); + heap_free(analysis->glyphs[i].pGoffset); + heap_free(analysis->glyphs[i].abc); + if (analysis->glyphs[i].fallbackFont) + DeleteObject(analysis->glyphs[i].fallbackFont); + ScriptFreeCache((SCRIPT_CACHE *)&analysis->glyphs[i].sc); + heap_free(analysis->glyphs[i].sc); + } + heap_free(analysis->glyphs); } - heap_free(analysis->glyphs); heap_free(analysis->pItem); heap_free(analysis->logattrs); heap_free(analysis->sz); - heap_free(analysis->sc); + heap_free(analysis->logical2visual); heap_free(analysis); if (invalid) return E_INVALIDARG; return S_OK; } +static inline int get_cluster_size(const WORD *pwLogClust, int cChars, int item, + int direction, int* iCluster, int *check_out) +{ + int clust_size = 1; + int check; + WORD clust = pwLogClust[item]; + + for (check = item+direction; check < cChars && check >= 0; check+=direction) + { + if (pwLogClust[check] == clust) + { + clust_size ++; + if (iCluster && *iCluster == -1) + *iCluster = item; + } + else break; + } + + if (check_out) + *check_out = check; + + return clust_size; +} + +static inline int get_glyph_cluster_advance(const int* piAdvance, const SCRIPT_VISATTR *pva, const WORD *pwLogClust, int cGlyphs, int cChars, int glyph, int direction) +{ + int advance; + int log_clust_max = 0; + int i; + + advance = piAdvance[glyph]; + + for (i = 0; i < cChars; i++) + { + if (pwLogClust[i] > log_clust_max) + log_clust_max = pwLogClust[i]; + } + + if (glyph > log_clust_max) + return advance; + + for (glyph+=direction; glyph < cGlyphs && glyph >= 0; glyph +=direction) + { + + if (does_glyph_start_cluster(pva, pwLogClust, cChars, glyph, direction)) + break; + if (glyph > log_clust_max) + break; + advance += piAdvance[glyph]; + } + + return advance; +} + /*********************************************************************** * ScriptCPtoX (USP10.@) * @@ -1033,19 +1995,100 @@ HRESULT WINAPI ScriptCPtoX(int iCP, const SCRIPT_ANALYSIS *psa, int *piX) { - int item; - int iPosX; - float fMaxPosX = 0; + int item; + float iPosX; + int iSpecial = -1; + int iCluster = -1; + int clust_size = 1; + float special_size = 0.0; + int iMaxPos = 0; + int advance = 0; + BOOL rtl = FALSE; + TRACE("(%d,%d,%d,%d,%p,%p,%p,%p,%p)\n", iCP, fTrailing, cChars, cGlyphs, pwLogClust, psva, piAdvance, psa, piX); - for (item=0; item < cGlyphs; item++) /* total piAdvance */ - fMaxPosX += piAdvance[item]; - iPosX = (fMaxPosX/cGlyphs)*(iCP+fTrailing); - if (iPosX > fMaxPosX) - iPosX = fMaxPosX; - *piX = iPosX; /* Return something in range */ + if (psa->fRTL && ! psa->fLogicalOrder) + rtl = TRUE; + + if (fTrailing) + iCP++; + + if (rtl) + { + int max_clust = pwLogClust[0]; + + for (item=0; item < cGlyphs; item++) + if (pwLogClust[item] > max_clust) + { + ERR("We do not handle non reversed clusters properly\n"); + break; + } + + iMaxPos = 0; + for (item = max_clust; item >=0; item --) + iMaxPos += piAdvance[item]; + } + + iPosX = 0.0; + for (item=0; item < iCP && item < cChars; item++) + { + if (iSpecial == -1 && (iCluster == -1 || (iCluster != -1 && iCluster+clust_size <= item))) + { + int check; + int clust = pwLogClust[item]; + + iCluster = -1; + clust_size = get_cluster_size(pwLogClust, cChars, item, 1, &iCluster, + &check); + + advance = get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, clust, 1); + + if (check >= cChars && !iMaxPos) + { + for (check = clust; check < cChars; check++) + special_size += get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, check, 1); + iSpecial = item; + special_size /= (cChars - item); + iPosX += special_size; + } + else + { + if (scriptInformation[psa->eScript].props.fNeedsCaretInfo) + { + clust_size --; + if (clust_size == 0) + iPosX += advance; + } + else + iPosX += advance / (float)clust_size; + } + } + else if (iSpecial != -1) + iPosX += special_size; + else /* (iCluster != -1) */ + { + int adv = get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, pwLogClust[iCluster], 1); + if (scriptInformation[psa->eScript].props.fNeedsCaretInfo) + { + clust_size --; + if (clust_size == 0) + iPosX += adv; + } + else + iPosX += adv / (float)clust_size; + } + } + + if (iMaxPos > 0) + { + iPosX = iMaxPos - iPosX; + if (iPosX < 0) + iPosX = 0; + } + + *piX = iPosX; TRACE("*piX=%d\n", *piX); return S_OK; } @@ -1065,40 +2108,147 @@ HRESULT WINAPI ScriptXtoCP(int iX, int *piTrailing) { int item; - int iPosX; - float fMaxPosX = 1; - float fAvePosX; + float iPosX; + float iLastPosX; + int iSpecial = -1; + int iCluster = -1; + int clust_size = 1; + int cjump = 0; + int advance; + float special_size = 0.0; + int direction = 1; + TRACE("(%d,%d,%d,%p,%p,%p,%p,%p,%p)\n", iX, cChars, cGlyphs, pwLogClust, psva, piAdvance, psa, piCP, piTrailing); - if (iX < 0) /* iX is before start of run */ + + if (psa->fRTL && ! psa->fLogicalOrder) + direction = -1; + + if (direction<0) + { + int max_clust = pwLogClust[0]; + + if (iX < 0) + { + *piCP = cChars; + *piTrailing = 0; + return S_OK; + } + + for (item=0; item < cChars; item++) + if (pwLogClust[item] > max_clust) + { + ERR("We do not handle non reversed clusters properly\n"); + break; + } + } + + if (iX < 0) { *piCP = -1; - *piTrailing = TRUE; + *piTrailing = 1; return S_OK; } - for (item=0; item < cGlyphs; item++) /* total piAdvance */ - fMaxPosX += piAdvance[item]; - - if (iX >= fMaxPosX) /* iX too large */ - { - *piCP = cChars; - *piTrailing = FALSE; - return S_OK; - } - - fAvePosX = fMaxPosX / cGlyphs; - iPosX = fAvePosX; - for (item = 1; item < cGlyphs && iPosX < iX; item++) - iPosX += fAvePosX; - if (iPosX - iX > fAvePosX/2) - *piTrailing = 0; + iPosX = iLastPosX = 0; + if (direction > 0) + item = 0; else - *piTrailing = 1; /* yep we are over halfway */ + item = cChars - 1; + for (; iPosX <= iX && item < cChars && item >= 0; item+=direction) + { + iLastPosX = iPosX; + if (iSpecial == -1 && + (iCluster == -1 || + (iCluster != -1 && + ((direction > 0 && iCluster+clust_size <= item) || + (direction < 0 && iCluster-clust_size >= item)) + ) + ) + ) + { + int check; + int clust = pwLogClust[item]; - *piCP = item -1; /* Return character position */ - TRACE("*piCP=%d iPposX=%d\n", *piCP, iPosX); + iCluster = -1; + cjump = 0; + clust_size = get_cluster_size(pwLogClust, cChars, item, direction, + &iCluster, &check); + advance = get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, clust, direction); + + if (check >= cChars && direction > 0) + { + for (check = clust; check < cChars; check++) + special_size += get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, check, direction); + iSpecial = item; + special_size /= (cChars - item); + iPosX += special_size; + } + else + { + if (scriptInformation[psa->eScript].props.fNeedsCaretInfo) + { + if (!cjump) + iPosX += advance; + cjump++; + } + else + iPosX += advance / (float)clust_size; + } + } + else if (iSpecial != -1) + iPosX += special_size; + else /* (iCluster != -1) */ + { + int adv = get_glyph_cluster_advance(piAdvance, psva, pwLogClust, cGlyphs, cChars, pwLogClust[iCluster], direction); + if (scriptInformation[psa->eScript].props.fNeedsCaretInfo) + { + if (!cjump) + iPosX += adv; + cjump++; + } + else + iPosX += adv / (float)clust_size; + } + } + + if (direction > 0) + { + if (iPosX > iX) + item--; + if (item < cChars && ((iPosX - iLastPosX) / 2.0) + iX >= iPosX) + { + if (scriptInformation[psa->eScript].props.fNeedsCaretInfo && clust_size > 1) + item+=(clust_size-1); + *piTrailing = 1; + } + else + *piTrailing = 0; + } + else + { + if (iX == iLastPosX) + item++; + if (iX >= iLastPosX && iX <= iPosX) + item++; + + if (iLastPosX == iX) + *piTrailing = 0; + else if (item < 0 || ((iLastPosX - iPosX) / 2.0) + iX <= iLastPosX) + { + if (scriptInformation[psa->eScript].props.fNeedsCaretInfo && clust_size > 1) + item-=(clust_size-1); + *piTrailing = 1; + } + else + *piTrailing = 0; + } + + *piCP = item; + + TRACE("*piCP=%d\n", *piCP); + TRACE("*piTrailing=%d\n", *piTrailing); return S_OK; } @@ -1118,186 +2268,18 @@ HRESULT WINAPI ScriptXtoCP(int iX, */ HRESULT WINAPI ScriptBreak(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la) { - int i; - TRACE("(%s, %d, %p, %p)\n", debugstr_wn(chars, count), count, sa, la); if (!la) return S_FALSE; - for (i = 0; i < count; i++) - { - memset(&la[i], 0, sizeof(SCRIPT_LOGATTR)); + BREAK_line(chars, count, sa, la); - /* FIXME: set the other flags */ - la[i].fWhiteSpace = (chars[i] == ' '); - la[i].fCharStop = 1; - - if (i > 0 && la[i - 1].fWhiteSpace) - { - la[i].fSoftBreak = 1; - la[i].fWordStop = 1; - } - } return S_OK; } -static const struct -{ - WCHAR start; - WCHAR end; - DWORD flag; -} -complex_ranges[] = -{ - { 0, 0x0b, SIC_COMPLEX }, - { 0x0c, 0x0c, SIC_NEUTRAL }, - { 0x0d, 0x1f, SIC_COMPLEX }, - { 0x20, 0x2f, SIC_NEUTRAL }, - { 0x30, 0x39, SIC_ASCIIDIGIT }, - { 0x3a, 0x40, SIC_NEUTRAL }, - { 0x5b, 0x60, SIC_NEUTRAL }, - { 0x7b, 0x7e, SIC_NEUTRAL }, - { 0x7f, 0x9f, SIC_COMPLEX }, - { 0xa0, 0xa5, SIC_NEUTRAL }, - { 0xa7, 0xa8, SIC_NEUTRAL }, - { 0xab, 0xab, SIC_NEUTRAL }, - { 0xad, 0xad, SIC_NEUTRAL }, - { 0xaf, 0xaf, SIC_NEUTRAL }, - { 0xb0, 0xb1, SIC_NEUTRAL }, - { 0xb4, 0xb4, SIC_NEUTRAL }, - { 0xb6, 0xb8, SIC_NEUTRAL }, - { 0xbb, 0xbf, SIC_NEUTRAL }, - { 0xd7, 0xd7, SIC_NEUTRAL }, - { 0xf7, 0xf7, SIC_NEUTRAL }, - { 0x2b9, 0x2ba, SIC_NEUTRAL }, - { 0x2c2, 0x2cf, SIC_NEUTRAL }, - { 0x2d2, 0x2df, SIC_NEUTRAL }, - { 0x2e5, 0x2e9, SIC_COMPLEX }, - { 0x2ea, 0x2ed, SIC_NEUTRAL }, - { 0x300, 0x362, SIC_COMPLEX }, - { 0x530, 0x60b, SIC_COMPLEX }, - { 0x60c, 0x60d, SIC_NEUTRAL }, - { 0x60e, 0x669, SIC_COMPLEX }, - { 0x66a, 0x66a, SIC_NEUTRAL }, - { 0x66b, 0x6e8, SIC_COMPLEX }, - { 0x6e9, 0x6e9, SIC_NEUTRAL }, - { 0x6ea, 0x7bf, SIC_COMPLEX }, - { 0x900, 0x1360, SIC_COMPLEX }, - { 0x137d, 0x137f, SIC_COMPLEX }, - { 0x1680, 0x1680, SIC_NEUTRAL }, - { 0x1780, 0x18af, SIC_COMPLEX }, - { 0x2000, 0x200a, SIC_NEUTRAL }, - { 0x200b, 0x200f, SIC_COMPLEX }, - { 0x2010, 0x2016, SIC_NEUTRAL }, - { 0x2018, 0x2022, SIC_NEUTRAL }, - { 0x2024, 0x2028, SIC_NEUTRAL }, - { 0x2029, 0x202e, SIC_COMPLEX }, - { 0x202f, 0x2037, SIC_NEUTRAL }, - { 0x2039, 0x203c, SIC_NEUTRAL }, - { 0x2044, 0x2046, SIC_NEUTRAL }, - { 0x206a, 0x206f, SIC_COMPLEX }, - { 0x207a, 0x207e, SIC_NEUTRAL }, - { 0x208a, 0x20aa, SIC_NEUTRAL }, - { 0x20ac, 0x20cf, SIC_NEUTRAL }, - { 0x20d0, 0x20ff, SIC_COMPLEX }, - { 0x2103, 0x2103, SIC_NEUTRAL }, - { 0x2105, 0x2105, SIC_NEUTRAL }, - { 0x2109, 0x2109, SIC_NEUTRAL }, - { 0x2116, 0x2116, SIC_NEUTRAL }, - { 0x2121, 0x2122, SIC_NEUTRAL }, - { 0x212e, 0x212e, SIC_NEUTRAL }, - { 0x2153, 0x2154, SIC_NEUTRAL }, - { 0x215b, 0x215e, SIC_NEUTRAL }, - { 0x2190, 0x2199, SIC_NEUTRAL }, - { 0x21b8, 0x21b9, SIC_NEUTRAL }, - { 0x21d2, 0x21d2, SIC_NEUTRAL }, - { 0x21d4, 0x21d4, SIC_NEUTRAL }, - { 0x21e7, 0x21e7, SIC_NEUTRAL }, - { 0x2200, 0x2200, SIC_NEUTRAL }, - { 0x2202, 0x2203, SIC_NEUTRAL }, - { 0x2207, 0x2208, SIC_NEUTRAL }, - { 0x220b, 0x220b, SIC_NEUTRAL }, - { 0x220f, 0x220f, SIC_NEUTRAL }, - { 0x2211, 0x2213, SIC_NEUTRAL }, - { 0x2215, 0x2215, SIC_NEUTRAL }, - { 0x221a, 0x221a, SIC_NEUTRAL }, - { 0x221d, 0x2220, SIC_NEUTRAL }, - { 0x2223, 0x2223, SIC_NEUTRAL }, - { 0x2225, 0x2225, SIC_NEUTRAL }, - { 0x2227, 0x222c, SIC_NEUTRAL }, - { 0x222e, 0x222e, SIC_NEUTRAL }, - { 0x2234, 0x2237, SIC_NEUTRAL }, - { 0x223c, 0x223d, SIC_NEUTRAL }, - { 0x2248, 0x2248, SIC_NEUTRAL }, - { 0x224c, 0x224c, SIC_NEUTRAL }, - { 0x2252, 0x2252, SIC_NEUTRAL }, - { 0x2260, 0x2261, SIC_NEUTRAL }, - { 0x2264, 0x2267, SIC_NEUTRAL }, - { 0x226a, 0x226b, SIC_NEUTRAL }, - { 0x226e, 0x226f, SIC_NEUTRAL }, - { 0x2282, 0x2283, SIC_NEUTRAL }, - { 0x2286, 0x2287, SIC_NEUTRAL }, - { 0x2295, 0x2295, SIC_NEUTRAL }, - { 0x2299, 0x2299, SIC_NEUTRAL }, - { 0x22a5, 0x22a5, SIC_NEUTRAL }, - { 0x22bf, 0x22bf, SIC_NEUTRAL }, - { 0x2312, 0x2312, SIC_NEUTRAL }, - { 0x24ea, 0x24ea, SIC_COMPLEX }, - { 0x2500, 0x254b, SIC_NEUTRAL }, - { 0x2550, 0x256d, SIC_NEUTRAL }, - { 0x256e, 0x2574, SIC_NEUTRAL }, - { 0x2581, 0x258f, SIC_NEUTRAL }, - { 0x2592, 0x2595, SIC_NEUTRAL }, - { 0x25a0, 0x25a1, SIC_NEUTRAL }, - { 0x25a3, 0x25a9, SIC_NEUTRAL }, - { 0x25b2, 0x25b3, SIC_NEUTRAL }, - { 0x25b6, 0x25b7, SIC_NEUTRAL }, - { 0x25bc, 0x25bd, SIC_NEUTRAL }, - { 0x25c0, 0x25c1, SIC_NEUTRAL }, - { 0x25c6, 0x25c8, SIC_NEUTRAL }, - { 0x25cb, 0x25cb, SIC_NEUTRAL }, - { 0x25ce, 0x25d1, SIC_NEUTRAL }, - { 0x25e2, 0x25e5, SIC_NEUTRAL }, - { 0x25ef, 0x25ef, SIC_NEUTRAL }, - { 0x2605, 0x2606, SIC_NEUTRAL }, - { 0x2609, 0x2609, SIC_NEUTRAL }, - { 0x260e, 0x260f, SIC_NEUTRAL }, - { 0x261c, 0x261c, SIC_NEUTRAL }, - { 0x261e, 0x261e, SIC_NEUTRAL }, - { 0x2640, 0x2640, SIC_NEUTRAL }, - { 0x2642, 0x2642, SIC_NEUTRAL }, - { 0x2660, 0x2661, SIC_NEUTRAL }, - { 0x2663, 0x2665, SIC_NEUTRAL }, - { 0x2667, 0x266a, SIC_NEUTRAL }, - { 0x266c, 0x266d, SIC_NEUTRAL }, - { 0x266f, 0x266f, SIC_NEUTRAL }, - { 0x273d, 0x273d, SIC_NEUTRAL }, - { 0x2e80, 0x312f, SIC_COMPLEX }, - { 0x3190, 0x31bf, SIC_COMPLEX }, - { 0x31f0, 0x31ff, SIC_COMPLEX }, - { 0x3220, 0x325f, SIC_COMPLEX }, - { 0x3280, 0xa4ff, SIC_COMPLEX }, - { 0xd800, 0xdfff, SIC_COMPLEX }, - { 0xe000, 0xf8ff, SIC_NEUTRAL }, - { 0xf900, 0xfaff, SIC_COMPLEX }, - { 0xfb13, 0xfb28, SIC_COMPLEX }, - { 0xfb29, 0xfb29, SIC_NEUTRAL }, - { 0xfb2a, 0xfb4f, SIC_COMPLEX }, - { 0xfd3e, 0xfd3f, SIC_NEUTRAL }, - { 0xfdd0, 0xfdef, SIC_COMPLEX }, - { 0xfe20, 0xfe6f, SIC_COMPLEX }, - { 0xfeff, 0xfeff, SIC_COMPLEX }, - { 0xff01, 0xff5e, SIC_COMPLEX }, - { 0xff61, 0xff9f, SIC_COMPLEX }, - { 0xffe0, 0xffe6, SIC_COMPLEX }, - { 0xffe8, 0xffee, SIC_COMPLEX }, - { 0xfff9, 0xfffb, SIC_COMPLEX }, - { 0xfffe, 0xfffe, SIC_COMPLEX } -}; - /*********************************************************************** * ScriptIsComplex (USP10.@) - * + * * Determine if a string is complex. * * PARAMS @@ -1309,28 +2291,165 @@ complex_ranges[] = * Success: S_OK * Failure: S_FALSE * - * NOTES - * Behaviour matches that of WinXP. */ HRESULT WINAPI ScriptIsComplex(const WCHAR *chars, int len, DWORD flag) { int i; - unsigned int j; TRACE("(%s,%d,0x%x)\n", debugstr_wn(chars, len), len, flag); for (i = 0; i < len; i++) { - for (j = 0; j < sizeof(complex_ranges)/sizeof(complex_ranges[0]); j++) - { - if (chars[i] >= complex_ranges[j].start && - chars[i] <= complex_ranges[j].end && - (flag & complex_ranges[j].flag)) return S_OK; - } + int script; + + if ((flag & SIC_ASCIIDIGIT) && chars[i] >= 0x30 && chars[i] <= 0x39) + return S_OK; + + script = get_char_script(chars[i]); + if ((scriptInformation[script].props.fComplex && (flag & SIC_COMPLEX))|| + (!scriptInformation[script].props.fComplex && (flag & SIC_NEUTRAL))) + return S_OK; } return S_FALSE; } +/*********************************************************************** + * ScriptShapeOpenType (USP10.@) + * + * Produce glyphs and visual attributes for a run. + * + * PARAMS + * hdc [I] Device context. + * psc [I/O] Opaque pointer to a script cache. + * psa [I/O] Script analysis. + * tagScript [I] The OpenType tag for the Script + * tagLangSys [I] The OpenType tag for the Language + * rcRangeChars[I] Array of Character counts in each range + * rpRangeProperties [I] Array of TEXTRANGE_PROPERTIES structures + * cRanges [I] Count of ranges + * pwcChars [I] Array of characters specifying the run. + * cChars [I] Number of characters in pwcChars. + * cMaxGlyphs [I] Length of pwOutGlyphs. + * pwLogClust [O] Array of logical cluster info. + * pCharProps [O] Array of character property values + * pwOutGlyphs [O] Array of glyphs. + * pOutGlyphProps [O] Array of attributes for the retrieved glyphs + * pcGlyphs [O] Number of glyphs returned. + * + * RETURNS + * Success: S_OK + * Failure: Non-zero HRESULT value. + */ +HRESULT WINAPI ScriptShapeOpenType( HDC hdc, SCRIPT_CACHE *psc, + SCRIPT_ANALYSIS *psa, OPENTYPE_TAG tagScript, + OPENTYPE_TAG tagLangSys, int *rcRangeChars, + TEXTRANGE_PROPERTIES **rpRangeProperties, + int cRanges, const WCHAR *pwcChars, int cChars, + int cMaxGlyphs, WORD *pwLogClust, + SCRIPT_CHARPROP *pCharProps, WORD *pwOutGlyphs, + SCRIPT_GLYPHPROP *pOutGlyphProps, int *pcGlyphs) +{ + HRESULT hr; + unsigned int i; + BOOL rtl; + + TRACE("(%p, %p, %p, %s, %s, %p, %p, %d, %s, %d, %d, %p, %p, %p, %p, %p )\n", + hdc, psc, psa, + debugstr_an((char*)&tagScript,4), debugstr_an((char*)&tagLangSys,4), + rcRangeChars, rpRangeProperties, cRanges, debugstr_wn(pwcChars, cChars), + cChars, cMaxGlyphs, pwLogClust, pCharProps, pwOutGlyphs, pOutGlyphProps, pcGlyphs); + + if (psa) TRACE("psa values: %d, %d, %d, %d, %d, %d, %d\n", psa->eScript, psa->fRTL, psa->fLayoutRTL, + psa->fLinkBefore, psa->fLinkAfter, psa->fLogicalOrder, psa->fNoGlyphIndex); + + if (!pOutGlyphProps || !pcGlyphs || !pCharProps) return E_INVALIDARG; + if (cChars > cMaxGlyphs) return E_OUTOFMEMORY; + + if (cRanges) + FIXME("Ranges not supported yet\n"); + + rtl = (psa && !psa->fLogicalOrder && psa->fRTL); + + *pcGlyphs = cChars; + if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr; + if (!pwLogClust) return E_FAIL; + + ((ScriptCache *)*psc)->userScript = tagScript; + ((ScriptCache *)*psc)->userLang = tagLangSys; + + /* set fNoGlyphIndex non truetype/opentype fonts */ + if (!psa->fNoGlyphIndex && !((ScriptCache *)*psc)->sfnt) + psa->fNoGlyphIndex = TRUE; + + /* Initialize a SCRIPT_VISATTR and LogClust for each char in this run */ + for (i = 0; i < cChars; i++) + { + int idx = i; + if (rtl) idx = cChars - 1 - i; + /* FIXME: set to better values */ + pOutGlyphProps[i].sva.uJustification = (pwcChars[idx] == ' ') ? SCRIPT_JUSTIFY_BLANK : SCRIPT_JUSTIFY_CHARACTER; + pOutGlyphProps[i].sva.fClusterStart = 1; + pOutGlyphProps[i].sva.fDiacritic = 0; + pOutGlyphProps[i].sva.fZeroWidth = 0; + pOutGlyphProps[i].sva.fReserved = 0; + pOutGlyphProps[i].sva.fShapeReserved = 0; + + /* FIXME: have the shaping engine set this */ + pCharProps[i].fCanGlyphAlone = 0; + + pwLogClust[i] = idx; + } + + if (psa && !psa->fNoGlyphIndex) + { + WCHAR *rChars; + if ((hr = SHAPE_CheckFontForRequiredFeatures(hdc, (ScriptCache *)*psc, psa)) != S_OK) return hr; + + rChars = heap_alloc(sizeof(WCHAR) * cChars); + if (!rChars) return E_OUTOFMEMORY; + for (i = 0; i < cChars; i++) + { + int idx = i; + WCHAR chInput; + if (rtl) idx = cChars - 1 - i; + if (psa->fRTL) + chInput = mirror_char(pwcChars[idx]); + else + chInput = pwcChars[idx]; + /* special case for tabs */ + if (chInput == 0x0009) + chInput = 0x0020; + if (!(pwOutGlyphs[i] = get_cache_glyph(psc, chInput))) + { + WORD glyph; + if (!hdc) return E_PENDING; + if (GetGlyphIndicesW(hdc, &chInput, 1, &glyph, 0) == GDI_ERROR) return S_FALSE; + pwOutGlyphs[i] = set_cache_glyph(psc, chInput, glyph); + } + rChars[i] = chInput; + } + + SHAPE_ContextualShaping(hdc, (ScriptCache *)*psc, psa, rChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs, pwLogClust); + SHAPE_ApplyDefaultOpentypeFeatures(hdc, (ScriptCache *)*psc, psa, pwOutGlyphs, pcGlyphs, cMaxGlyphs, cChars, pwLogClust); + SHAPE_CharGlyphProp(hdc, (ScriptCache *)*psc, psa, pwcChars, cChars, pwOutGlyphs, *pcGlyphs, pwLogClust, pCharProps, pOutGlyphProps); + heap_free(rChars); + } + else + { + TRACE("no glyph translation\n"); + for (i = 0; i < cChars; i++) + { + int idx = i; + /* No mirroring done here */ + if (rtl) idx = cChars - 1 - i; + pwOutGlyphs[i] = pwcChars[idx]; + } + } + + return S_OK; +} + + /*********************************************************************** * ScriptShape (USP10.@) * @@ -1352,96 +2471,59 @@ HRESULT WINAPI ScriptIsComplex(const WCHAR *chars, int len, DWORD flag) * Success: S_OK * Failure: Non-zero HRESULT value. */ -HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars, +HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars, int cChars, int cMaxGlyphs, SCRIPT_ANALYSIS *psa, WORD *pwOutGlyphs, WORD *pwLogClust, SCRIPT_VISATTR *psva, int *pcGlyphs) { HRESULT hr; - unsigned int i; - BOOL rtl; - - TRACE("(%p, %p, %s, %d, %d, %p, %p, %p, %p, %p)\n", hdc, psc, debugstr_wn(pwcChars, cChars), - cChars, cMaxGlyphs, psa, pwOutGlyphs, pwLogClust, psva, pcGlyphs); - - if (psa) TRACE("psa values: %d, %d, %d, %d, %d, %d, %d\n", psa->eScript, psa->fRTL, psa->fLayoutRTL, - psa->fLinkBefore, psa->fLinkAfter, psa->fLogicalOrder, psa->fNoGlyphIndex); + int i; + SCRIPT_CHARPROP *charProps; + SCRIPT_GLYPHPROP *glyphProps; if (!psva || !pcGlyphs) return E_INVALIDARG; if (cChars > cMaxGlyphs) return E_OUTOFMEMORY; - rtl = (!psa->fLogicalOrder && psa->fRTL); - *pcGlyphs = cChars; - if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr; - if (!pwLogClust) return E_FAIL; + charProps = heap_alloc_zero(sizeof(SCRIPT_CHARPROP)*cChars); + if (!charProps) return E_OUTOFMEMORY; + glyphProps = heap_alloc_zero(sizeof(SCRIPT_GLYPHPROP)*cMaxGlyphs); + if (!glyphProps) return E_OUTOFMEMORY; - if ((get_cache_pitch_family(psc) & TMPF_TRUETYPE) && !psa->fNoGlyphIndex) + hr = ScriptShapeOpenType(hdc, psc, psa, scriptInformation[psa->eScript].scriptTag, 0, NULL, NULL, 0, pwcChars, cChars, cMaxGlyphs, pwLogClust, charProps, pwOutGlyphs, glyphProps, pcGlyphs); + + if (SUCCEEDED(hr)) { - WCHAR *rChars = heap_alloc(sizeof(WCHAR) * cChars); - if (!rChars) return E_OUTOFMEMORY; - for (i = 0; i < cChars; i++) - { - int idx = i; - WCHAR chInput; - if (rtl) idx = cChars - 1 - i; - if (psa->fRTL) - chInput = mirror_char(pwcChars[idx]); - else - chInput = pwcChars[idx]; - if (!(pwOutGlyphs[i] = get_cache_glyph(psc, chInput))) - { - WORD glyph; - if (!hdc) return E_PENDING; - if (GetGlyphIndicesW(hdc, &chInput, 1, &glyph, 0) == GDI_ERROR) return S_FALSE; - pwOutGlyphs[i] = set_cache_glyph(psc, chInput, glyph); - } - rChars[i] = chInput; - } - SHAPE_ShapeArabicGlyphs(hdc, (ScriptCache *)*psc, psa, rChars, cChars, pwOutGlyphs, pcGlyphs, cMaxGlyphs); - heap_free(rChars); - } - else - { - TRACE("no glyph translation\n"); - for (i = 0; i < cChars; i++) - { - int idx = i; - /* No mirroring done here */ - if (rtl) idx = cChars - 1 - i; - pwOutGlyphs[i] = pwcChars[idx]; - } + for (i = 0; i < *pcGlyphs; i++) + psva[i] = glyphProps[i].sva; } - /* set up a valid SCRIPT_VISATTR and LogClust for each char in this run */ - for (i = 0; i < cChars; i++) - { - int idx = i; - if (rtl) idx = cChars - 1 - i; - /* FIXME: set to better values */ - psva[i].uJustification = (pwcChars[idx] == ' ') ? SCRIPT_JUSTIFY_BLANK : SCRIPT_JUSTIFY_CHARACTER; - psva[i].fClusterStart = 1; - psva[i].fDiacritic = 0; - psva[i].fZeroWidth = 0; - psva[i].fReserved = 0; - psva[i].fShapeReserved = 0; + heap_free(charProps); + heap_free(glyphProps); - pwLogClust[i] = idx; - } - return S_OK; + return hr; } /*********************************************************************** - * ScriptPlace (USP10.@) + * ScriptPlaceOpenType (USP10.@) * * Produce advance widths for a run. * * PARAMS * hdc [I] Device context. * psc [I/O] Opaque pointer to a script cache. - * pwGlyphs [I] Array of glyphs. - * cGlyphs [I] Number of glyphs in pwGlyphs. - * psva [I] Array of visual attributes. * psa [I/O] String analysis. + * tagScript [I] The OpenType tag for the Script + * tagLangSys [I] The OpenType tag for the Language + * rcRangeChars[I] Array of Character counts in each range + * rpRangeProperties [I] Array of TEXTRANGE_PROPERTIES structures + * cRanges [I] Count of ranges + * pwcChars [I] Array of characters specifying the run. + * pwLogClust [I] Array of logical cluster info + * pCharProps [I] Array of character property values + * cChars [I] Number of characters in pwcChars. + * pwGlyphs [I] Array of glyphs. + * pGlyphProps [I] Array of attributes for the retrieved glyphs + * cGlyphs [I] Count of Glyphs * piAdvance [O] Array of advance widths. * pGoffset [O] Glyph offsets. * pABC [O] Combined ABC width. @@ -1450,20 +2532,37 @@ HRESULT WINAPI ScriptShape(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcChars, * Success: S_OK * Failure: Non-zero HRESULT value. */ -HRESULT WINAPI ScriptPlace(HDC hdc, SCRIPT_CACHE *psc, const WORD *pwGlyphs, - int cGlyphs, const SCRIPT_VISATTR *psva, - SCRIPT_ANALYSIS *psa, int *piAdvance, GOFFSET *pGoffset, ABC *pABC ) + +HRESULT WINAPI ScriptPlaceOpenType( HDC hdc, SCRIPT_CACHE *psc, SCRIPT_ANALYSIS *psa, + OPENTYPE_TAG tagScript, OPENTYPE_TAG tagLangSys, + int *rcRangeChars, TEXTRANGE_PROPERTIES **rpRangeProperties, + int cRanges, const WCHAR *pwcChars, WORD *pwLogClust, + SCRIPT_CHARPROP *pCharProps, int cChars, + const WORD *pwGlyphs, const SCRIPT_GLYPHPROP *pGlyphProps, + int cGlyphs, int *piAdvance, + GOFFSET *pGoffset, ABC *pABC +) { HRESULT hr; int i; - TRACE("(%p, %p, %p, %d, %p, %p, %p, %p, %p)\n", hdc, psc, pwGlyphs, cGlyphs, psva, psa, - piAdvance, pGoffset, pABC); + TRACE("(%p, %p, %p, %s, %s, %p, %p, %d, %s, %p, %p, %d, %p, %p, %d, %p %p %p)\n", + hdc, psc, psa, + debugstr_an((char*)&tagScript,4), debugstr_an((char*)&tagLangSys,4), + rcRangeChars, rpRangeProperties, cRanges, debugstr_wn(pwcChars, cChars), + pwLogClust, pCharProps, cChars, pwGlyphs, pGlyphProps, cGlyphs, piAdvance, + pGoffset, pABC); - if (!psva) return E_INVALIDARG; + if (!pGlyphProps) return E_INVALIDARG; if ((hr = init_script_cache(hdc, psc)) != S_OK) return hr; if (!pGoffset) return E_FAIL; + if (cRanges) + FIXME("Ranges not supported yet\n"); + + ((ScriptCache *)*psc)->userScript = tagScript; + ((ScriptCache *)*psc)->userLang = tagLangSys; + if (pABC) memset(pABC, 0, sizeof(ABC)); for (i = 0; i < cGlyphs; i++) { @@ -1499,6 +2598,53 @@ HRESULT WINAPI ScriptPlace(HDC hdc, SCRIPT_CACHE *psc, const WORD *pwGlyphs, return S_OK; } +/*********************************************************************** + * ScriptPlace (USP10.@) + * + * Produce advance widths for a run. + * + * PARAMS + * hdc [I] Device context. + * psc [I/O] Opaque pointer to a script cache. + * pwGlyphs [I] Array of glyphs. + * cGlyphs [I] Number of glyphs in pwGlyphs. + * psva [I] Array of visual attributes. + * psa [I/O] String analysis. + * piAdvance [O] Array of advance widths. + * pGoffset [O] Glyph offsets. + * pABC [O] Combined ABC width. + * + * RETURNS + * Success: S_OK + * Failure: Non-zero HRESULT value. + */ +HRESULT WINAPI ScriptPlace(HDC hdc, SCRIPT_CACHE *psc, const WORD *pwGlyphs, + int cGlyphs, const SCRIPT_VISATTR *psva, + SCRIPT_ANALYSIS *psa, int *piAdvance, GOFFSET *pGoffset, ABC *pABC ) +{ + HRESULT hr; + SCRIPT_GLYPHPROP *glyphProps; + int i; + + TRACE("(%p, %p, %p, %d, %p, %p, %p, %p, %p)\n", hdc, psc, pwGlyphs, cGlyphs, psva, psa, + piAdvance, pGoffset, pABC); + + if (!psva) return E_INVALIDARG; + if (!pGoffset) return E_FAIL; + + glyphProps = heap_alloc(sizeof(SCRIPT_GLYPHPROP)*cGlyphs); + if (!glyphProps) return E_OUTOFMEMORY; + + for (i = 0; i < cGlyphs; i++) + glyphProps[i].sva = psva[i]; + + hr = ScriptPlaceOpenType(hdc, psc, psa, scriptInformation[psa->eScript].scriptTag, 0, NULL, NULL, 0, NULL, NULL, NULL, 0, pwGlyphs, glyphProps, cGlyphs, piAdvance, pGoffset, pABC); + + heap_free(glyphProps); + + return hr; +} + /*********************************************************************** * ScriptGetCMap (USP10.@) * @@ -1769,13 +2915,30 @@ HRESULT WINAPI ScriptStringGetLogicalWidths(SCRIPT_STRING_ANALYSIS ssa, int *piD TRACE("%p, %p\n", ssa, piDx); if (!analysis) return S_FALSE; + if (!(analysis->dwFlags & SSA_GLYPHS)) return S_FALSE; for (i = 0; i < analysis->numItems; i++) { - for (j = 0; j < analysis->glyphs[i].numGlyphs; j++) + int cChar = analysis->pItem[i+1].iCharPos - analysis->pItem[i].iCharPos; + int direction = 1; + + if (analysis->pItem[i].a.fRTL && ! analysis->pItem[i].a.fLogicalOrder) + direction = -1; + + for (j = 0; j < cChar; j++) { - piDx[next] = analysis->glyphs[i].piAdvance[j]; - next++; + int k; + int glyph = analysis->glyphs[i].pwLogClust[j]; + int clust_size = get_cluster_size(analysis->glyphs[i].pwLogClust, + cChar, j, direction, NULL, NULL); + int advance = get_glyph_cluster_advance(analysis->glyphs[i].piAdvance, analysis->glyphs[i].psva, analysis->glyphs[i].pwLogClust, analysis->glyphs[i].numGlyphs, cChar, glyph, direction); + + for (k = 0; k < clust_size; k++) + { + piDx[next] = advance / clust_size; + next++; + if (k) j++; + } } } return S_OK; @@ -1824,16 +2987,21 @@ const SIZE * WINAPI ScriptString_pSize(SCRIPT_STRING_ANALYSIS ssa) TRACE("(%p)\n", ssa); if (!analysis) return NULL; + if (!(analysis->dwFlags & SSA_GLYPHS)) return NULL; if (!analysis->sz) { if (!(analysis->sz = heap_alloc(sizeof(SIZE)))) return NULL; - analysis->sz->cy = analysis->sc->tm.tmHeight; + analysis->sz->cy = analysis->glyphs[0].sc->tm.tmHeight; analysis->sz->cx = 0; for (i = 0; i < analysis->numItems; i++) + { + if (analysis->glyphs[i].sc->tm.tmHeight > analysis->sz->cy) + analysis->sz->cy = analysis->glyphs[i].sc->tm.tmHeight; for (j = 0; j < analysis->glyphs[i].numGlyphs; j++) analysis->sz->cx += analysis->glyphs[i].piAdvance[j]; + } } return analysis->sz; } @@ -1857,6 +3025,7 @@ const SCRIPT_LOGATTR * WINAPI ScriptString_pLogAttr(SCRIPT_STRING_ANALYSIS ssa) TRACE("(%p)\n", ssa); if (!analysis) return NULL; + if (!(analysis->dwFlags & SSA_BREAK)) return NULL; return analysis->logattrs; } @@ -1904,6 +3073,7 @@ HRESULT WINAPI ScriptStringGetOrder(SCRIPT_STRING_ANALYSIS ssa, UINT *order) TRACE("(%p)\n", ssa); if (!analysis) return S_FALSE; + if (!(analysis->dwFlags & SSA_GLYPHS)) return S_FALSE; /* FIXME: handle RTL scripts */ for (i = 0, k = 0; i < analysis->numItems; i++) @@ -1989,3 +3159,9 @@ HRESULT WINAPI ScriptJustify(const SCRIPT_VISATTR *sva, const int *advance, for (i = 0; i < num_glyphs; i++) justify[i] = advance[i]; return S_OK; } + +BOOL gbLpkPresent = FALSE; +VOID WINAPI LpkPresent() +{ + gbLpkPresent = TRUE; /* Turn it on this way! Wine is out of control! */ +} diff --git a/reactos/dll/win32/usp10/usp10.rbuild b/reactos/dll/win32/usp10/usp10.rbuild index eda28014bbc..9c477d1ecd8 100644 --- a/reactos/dll/win32/usp10/usp10.rbuild +++ b/reactos/dll/win32/usp10/usp10.rbuild @@ -7,11 +7,17 @@ include/reactos/wine bidi.c + breaking.c usp10.c + indic.c + linebreak.c + indicsyllable.c mirror.c shape.c shaping.c wine + advapi32 + user32 gdi32 ntdll msvcrt diff --git a/reactos/dll/win32/usp10/usp10.spec b/reactos/dll/win32/usp10/usp10.spec index 5e358707c41..99b3e2bda9f 100644 --- a/reactos/dll/win32/usp10/usp10.spec +++ b/reactos/dll/win32/usp10/usp10.spec @@ -1,4 +1,4 @@ -@ stub LpkPresent +@ stdcall LpkPresent() @ stdcall ScriptApplyDigitSubstitution(ptr ptr ptr) @ stdcall ScriptApplyLogicalWidth(ptr long long ptr ptr ptr ptr ptr ptr) @ stdcall ScriptBreak(ptr long ptr ptr) @@ -6,17 +6,25 @@ @ stdcall ScriptCacheGetHeight(ptr ptr ptr) @ stdcall ScriptFreeCache(ptr) @ stdcall ScriptGetCMap(ptr ptr ptr long long ptr) +@ stub ScriptGetFontAlternateGlyphs +@ stub ScriptGetFontFeatureTags +@ stub ScriptGetFontLanguageTags @ stdcall ScriptGetFontProperties(long ptr ptr) +@ stub ScriptGetFontScriptTags @ stdcall ScriptGetGlyphABCWidth(ptr ptr long ptr) @ stdcall ScriptGetLogicalWidths(ptr long long ptr ptr ptr ptr) @ stdcall ScriptGetProperties(ptr long) @ stdcall ScriptIsComplex(wstr long long) @ stdcall ScriptItemize(wstr long long ptr ptr ptr ptr) +@ stdcall ScriptItemizeOpenType(wstr long long ptr ptr ptr ptr ptr) @ stdcall ScriptJustify(ptr ptr long long long ptr) @ stdcall ScriptLayout(long ptr ptr ptr) @ stdcall ScriptPlace(ptr ptr ptr long ptr ptr ptr ptr ptr) +@ stdcall ScriptPlaceOpenType(ptr ptr ptr long long ptr ptr long wstr ptr ptr long ptr ptr long ptr ptr ptr) +@ stub ScriptPositionSingleGlyph @ stdcall ScriptRecordDigitSubstitution(ptr ptr) @ stdcall ScriptShape(ptr ptr ptr long long ptr ptr ptr ptr ptr) +@ stdcall ScriptShapeOpenType(ptr ptr ptr long long ptr ptr long wstr long long ptr ptr ptr ptr ptr) @ stdcall ScriptStringAnalyse(ptr ptr long long long long long ptr ptr ptr ptr ptr ptr) @ stdcall ScriptStringCPtoX(ptr long long ptr) @ stdcall ScriptStringFree(ptr) @@ -28,6 +36,7 @@ @ stdcall ScriptString_pLogAttr(ptr) @ stdcall ScriptString_pSize(ptr) @ stdcall ScriptString_pcOutChars(ptr) +@ stub ScriptSubstituteSingleGlyph @ stdcall ScriptTextOut(ptr ptr long long long ptr ptr ptr long ptr long ptr ptr ptr) @ stdcall ScriptXtoCP(long long long ptr ptr ptr ptr ptr ptr) @ stub UspAllocCache diff --git a/reactos/dll/win32/usp10/usp10_internal.h b/reactos/dll/win32/usp10/usp10_internal.h index 56226eec5f0..6f5d3d14d86 100644 --- a/reactos/dll/win32/usp10/usp10_internal.h +++ b/reactos/dll/win32/usp10/usp10_internal.h @@ -18,33 +18,132 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * */ +#define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \ + ( ( (ULONG)_x4 << 24 ) | \ + ( (ULONG)_x3 << 16 ) | \ + ( (ULONG)_x2 << 8 ) | \ + (ULONG)_x1 ) + -#define Script_Syriac 8 -#define Script_Hebrew 7 -#define Script_Arabic 6 #define Script_Latin 1 -#define Script_Numeric 5 -#define Script_CR 22 -#define Script_LF 23 +#define Script_CR 2 +#define Script_Numeric 3 +#define Script_Control 4 +#define Script_Punctuation 5 +#define Script_Arabic 6 +#define Script_Arabic_Numeric 7 +#define Script_Hebrew 8 +#define Script_Syriac 9 +#define Script_Persian 10 +#define Script_Thaana 11 +#define Script_Greek 12 +#define Script_Cyrillic 13 +#define Script_Armenian 14 +#define Script_Georgian 15 +/* Unicode Chapter 10 */ +#define Script_Sinhala 16 +#define Script_Tibetan 17 +#define Script_Tibetan_Numeric 18 +#define Script_Phags_pa 19 +/* Unicode Chapter 11 */ +#define Script_Thai 20 +#define Script_Thai_Numeric 21 +#define Script_Lao 22 +#define Script_Lao_Numeric 23 +/* Unicode Chapter 9 */ +#define Script_Devanagari 24 +#define Script_Devanagari_Numeric 25 +#define Script_Bengali 26 +#define Script_Bengali_Numeric 27 +#define Script_Bengali_Currency 28 +#define Script_Gurmukhi 29 +#define Script_Gurmukhi_Numeric 30 +#define Script_Gujarati 31 +#define Script_Gujarati_Numeric 32 +#define Script_Gujarati_Currency 33 +#define Script_Oriya 34 +#define Script_Oriya_Numeric 35 +#define Script_Tamil 36 +#define Script_Tamil_Numeric 37 +#define Script_Telugu 38 +#define Script_Telugu_Numeric 39 +#define Script_Kannada 40 +#define Script_Kannada_Numeric 41 +#define Script_Malayalam 42 +#define Script_Malayalam_Numeric 43 +/* More supplemental */ +#define Script_Diacritical 44 +#define Script_Punctuation2 45 +#define Script_Numeric2 46 #define GLYPH_BLOCK_SHIFT 8 #define GLYPH_BLOCK_SIZE (1UL << GLYPH_BLOCK_SHIFT) #define GLYPH_BLOCK_MASK (GLYPH_BLOCK_SIZE - 1) #define GLYPH_MAX 65536 +typedef struct { + char tag[5]; + char script[5]; + LPCVOID feature; +} LoadedFeature; + typedef struct { LOGFONTW lf; TEXTMETRICW tm; + BOOL sfnt; WORD *glyphs[GLYPH_MAX / GLYPH_BLOCK_SIZE]; ABC *widths[GLYPH_MAX / GLYPH_BLOCK_SIZE]; - LPVOID *GSUB_Table; + LPVOID GSUB_Table; + LPVOID GDEF_Table; + INT feature_count; + LoadedFeature *features; + + OPENTYPE_TAG userScript; + OPENTYPE_TAG userLang; } ScriptCache; +typedef struct { + INT start; + INT base; + INT ralf; + INT blwf; + INT pref; + INT end; +} IndicSyllable; + +enum {lex_Halant, lex_Composed_Vowel, lex_Matra_post, lex_Matra_pre, lex_Matra_above, lex_Matra_below, lex_ZWJ, lex_ZWNJ, lex_NBSP, lex_Modifier, lex_Vowel, lex_Consonant, lex_Generic, lex_Ra, lex_Vedic, lex_Anudatta, lex_Nukta}; + +static inline BOOL is_consonant( int type ) +{ + return (type == lex_Ra || type == lex_Consonant); +} + +static inline WCHAR get_table_entry( const unsigned short *table, WCHAR ch ) +{ + return table[table[table[ch >> 8] + ((ch >> 4) & 0x0f)] + (ch & 0xf)]; +} + +typedef int (*lexical_function)(WCHAR c); +typedef void (*reorder_function)(LPWSTR pwChar, IndicSyllable *syllable, lexical_function lex); + #define odd(x) ((x) & 1) +#define BIDI_STRONG 1 +#define BIDI_WEAK 2 +#define BIDI_NEUTRAL 0 BOOL BIDI_DetermineLevels( LPCWSTR lpString, INT uCount, const SCRIPT_STATE *s, - const SCRIPT_CONTROL *c, WORD *lpOutLevels ); + const SCRIPT_CONTROL *c, WORD *lpOutLevels ) DECLSPEC_HIDDEN; +BOOL BIDI_GetStrengths(LPCWSTR lpString, INT uCount, const SCRIPT_CONTROL *c, + WORD* lpStrength) DECLSPEC_HIDDEN; +INT BIDI_ReorderV2lLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse) DECLSPEC_HIDDEN; +INT BIDI_ReorderL2vLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse) DECLSPEC_HIDDEN; +void SHAPE_ContextualShaping(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, WORD *pwLogClust) DECLSPEC_HIDDEN; +void SHAPE_ApplyDefaultOpentypeFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs, INT cChars, WORD *pwLogClust) DECLSPEC_HIDDEN; +HRESULT SHAPE_CheckFontForRequiredFeatures(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa) DECLSPEC_HIDDEN; +void SHAPE_CharGlyphProp(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, const WCHAR* pwcChars, const INT cChars, const WORD* pwGlyphs, const INT cGlyphs, WORD *pwLogClust, SCRIPT_CHARPROP *pCharProp, SCRIPT_GLYPHPROP *pGlyphProp) DECLSPEC_HIDDEN; +INT SHAPE_does_GSUB_feature_apply_to_chars(HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, const WCHAR *chars, INT write_dir, INT count, const char* feature) DECLSPEC_HIDDEN; -INT BIDI_ReorderV2lLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse); -INT BIDI_ReorderL2vLevel(int level, int *pIndexs, const BYTE* plevel, int cch, BOOL fReverse); -void SHAPE_ShapeArabicGlyphs(HDC hdc, ScriptCache *psc, SCRIPT_ANALYSIS *psa, WCHAR* pwcChars, INT cChars, WORD* pwOutGlyphs, INT* pcGlyphs, INT cMaxGlyphs); +void Indic_ReorderCharacters( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPWSTR input, int cChars, IndicSyllable **syllables, int *syllable_count, lexical_function lexical_f, reorder_function reorder_f, BOOL modern) DECLSPEC_HIDDEN; +void Indic_ParseSyllables( HDC hdc, SCRIPT_ANALYSIS *psa, ScriptCache* psc, LPCWSTR input, const int cChar, IndicSyllable **syllables, int *syllable_count, lexical_function lex, BOOL modern); + +void BREAK_line(const WCHAR *chars, int count, const SCRIPT_ANALYSIS *sa, SCRIPT_LOGATTR *la) DECLSPEC_HIDDEN; diff --git a/reactos/dll/win32/usp10/usp10_ros.diff b/reactos/dll/win32/usp10/usp10_ros.diff index 1f2c479ee7a..83bd411eeb1 100644 --- a/reactos/dll/win32/usp10/usp10_ros.diff +++ b/reactos/dll/win32/usp10/usp10_ros.diff @@ -1,20 +1,20 @@ Index: usp10.c =================================================================== ---- usp10.c (revision 44689) -+++ usp10.c (working copy) -@@ -1841,3 +1841,9 @@ - for (i = 0; i < num_glyphs; i++) justify[i] = advance[i]; - return S_OK; - } -+ -+BOOL gbLpkPresent = FALSE; -+VOID WINAPI LpkPresent() -+{ -+ gbLpkPresent = TRUE; /* Turn it on this way! Wine is out of control! */ -+} +--- usp10.c (revision 54504) ++++ usp10.c (working copy) +@@ -1989,3 +3159,9 @@ + for (i = 0; i < num_glyphs; i++) justify[i] = advance[i]; + return S_OK; + } ++ ++BOOL gbLpkPresent = FALSE; ++VOID WINAPI LpkPresent() ++{ ++ gbLpkPresent = TRUE; /* Turn it on this way! Wine is out of control! */ ++} Index: usp10.spec =================================================================== ---- usp10.spec (revision 44689) +--- usp10.spec (revision 54504) +++ usp10.spec (working copy) @@ -1,4 +1,4 @@ -@ stub LpkPresent diff --git a/reactos/include/psdk/usp10.h b/reactos/include/psdk/usp10.h index e101b6c696d..e84eeb73823 100644 --- a/reactos/include/psdk/usp10.h +++ b/reactos/include/psdk/usp10.h @@ -49,8 +49,8 @@ extern "C" { #define SSA_LPKANSIFALLBACK 0x08000000 #define SSA_PIDX 0x10000000 #define SSA_LAYOUTRTL 0x20000000 -#define SSA_DONTGLYPH 0x40000000 -#define SSA_NOKASHIDA 0x80000000 +#define SSA_DONTGLYPH 0x40000000 +#define SSA_NOKASHIDA 0x80000000 /** StringIsComplex */ #define SIC_COMPLEX 1 @@ -86,7 +86,7 @@ typedef enum tag_SCRIPT_JUSTIFY { SCRIPT_JUSTIFY_ARABIC_BA = 12, SCRIPT_JUSTIFY_ARABIC_BARA = 13, SCRIPT_JUSTIFY_ARABIC_SEEN = 14, - SCRIPT_JUSTIFY_RESERVED4 = 15, + SCRIPT_JUSTIFY_ARABIC_SEEN_M = 15, } SCRIPT_JUSTIFY; typedef struct tag_SCRIPT_CONTROL { @@ -99,14 +99,15 @@ typedef struct tag_SCRIPT_CONTROL { DWORD fNeutralOverride :1; DWORD fNumericOverride :1; DWORD fLegacyBidiClass :1; - DWORD fReserved :8; + DWORD fMergeNeutralItems :1; + DWORD fReserved :7; } SCRIPT_CONTROL; typedef struct { DWORD langid :16; DWORD fNumeric :1; - DWORD fComplex :1; - DWORD fNeedsWordBreaking :1; + DWORD fComplex :1; + DWORD fNeedsWordBreaking :1; DWORD fNeedsCaretInfo :1; DWORD bCharSet :8; DWORD fControl :1; @@ -192,7 +193,7 @@ typedef struct tag_SCRIPT_LOGATTR { } SCRIPT_LOGATTR; typedef void *SCRIPT_CACHE; -typedef void *SCRIPT_STRING_ANALYSIS; +typedef void *SCRIPT_STRING_ANALYSIS; #ifndef LSDEFS_DEFINED typedef struct tagGOFFSET { @@ -201,16 +202,42 @@ typedef struct tagGOFFSET { } GOFFSET; #endif +typedef ULONG OPENTYPE_TAG; + +typedef struct tagOPENTYPE_FEATURE_RECORD +{ + OPENTYPE_TAG tagFeature; + LONG lParameter; +} OPENTYPE_FEATURE_RECORD; + +typedef struct tagSCRIPT_GLYPHPROP +{ + SCRIPT_VISATTR sva; + WORD reserved; +} SCRIPT_GLYPHPROP; + +typedef struct tagSCRIPT_CHARPROP +{ + WORD fCanGlyphAlone :1; + WORD reserved :15; +} SCRIPT_CHARPROP; + +typedef struct tagTEXTRANGE_PROPERTIES +{ + OPENTYPE_FEATURE_RECORD *potfRecords; + INT cotfRecords; +} TEXTRANGE_PROPERTIES; + /* Function Declarations */ -HRESULT WINAPI ScriptApplyDigitSubstitution(const SCRIPT_DIGITSUBSTITUTE* psds, +HRESULT WINAPI ScriptApplyDigitSubstitution(const SCRIPT_DIGITSUBSTITUTE* psds, SCRIPT_CONTROL* psc, SCRIPT_STATE* pss); HRESULT WINAPI ScriptApplyLogicalWidth(const int *piDx, int cChars, int cGlyphs, const WORD *pwLogClust, const SCRIPT_VISATTR *psva, const int *piAdvance, const SCRIPT_ANALYSIS *psa, ABC *pABC, int *piJustify); HRESULT WINAPI ScriptRecordDigitSubstitution(LCID Locale, SCRIPT_DIGITSUBSTITUTE *psds); -HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItems, - const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState, +HRESULT WINAPI ScriptItemize(const WCHAR *pwcInChars, int cInChars, int cMaxItems, + const SCRIPT_CONTROL *psControl, const SCRIPT_STATE *psState, SCRIPT_ITEM *pItems, int *pcItems); HRESULT WINAPI ScriptGetCMap(HDC hdc, SCRIPT_CACHE *psc, const WCHAR *pwcInChars, int cChars, DWORD dwFlags, WORD *pwOutGlyphs); @@ -220,9 +247,9 @@ HRESULT WINAPI ScriptGetLogicalWidths(const SCRIPT_ANALYSIS *psa, int cChars, in const int *piGlyphWidth, const WORD *pwLogClust, const SCRIPT_VISATTR *psva, int *piDx); HRESULT WINAPI ScriptGetProperties(const SCRIPT_PROPERTIES ***ppSp, int *piNumScripts); -HRESULT WINAPI ScriptStringAnalyse(HDC hdc, - const void *pString, - int cString, +HRESULT WINAPI ScriptStringAnalyse(HDC hdc, + const void *pString, + int cString, int cGlyphs, int iCharset, DWORD dwFlags, diff --git a/reactos/include/psdk/winnt.h b/reactos/include/psdk/winnt.h index c9ba6680005..1e669ab3b73 100644 --- a/reactos/include/psdk/winnt.h +++ b/reactos/include/psdk/winnt.h @@ -916,6 +916,7 @@ typedef enum { #define LANG_ORIYA 0x48 #define LANG_PASHTO 0x63 #define LANG_FARSI 0x29 +#define LANG_PERSIAN 0x29 #define LANG_POLISH 0x15 #define LANG_PORTUGUESE 0x16 #define LANG_PUNJABI 0x46