15569331642446be05292e3e1f8a51218827168cdclaireho/*
25569331642446be05292e3e1f8a51218827168cdclaireho * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
35569331642446be05292e3e1f8a51218827168cdclaireho *
45569331642446be05292e3e1f8a51218827168cdclaireho * This is part of HarfBuzz, an OpenType Layout engine library.
55569331642446be05292e3e1f8a51218827168cdclaireho *
65569331642446be05292e3e1f8a51218827168cdclaireho * Permission is hereby granted, without written agreement and without
75569331642446be05292e3e1f8a51218827168cdclaireho * license or royalty fees, to use, copy, modify, and distribute this
85569331642446be05292e3e1f8a51218827168cdclaireho * software and its documentation for any purpose, provided that the
95569331642446be05292e3e1f8a51218827168cdclaireho * above copyright notice and the following two paragraphs appear in
105569331642446be05292e3e1f8a51218827168cdclaireho * all copies of this software.
115569331642446be05292e3e1f8a51218827168cdclaireho *
125569331642446be05292e3e1f8a51218827168cdclaireho * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
135569331642446be05292e3e1f8a51218827168cdclaireho * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
145569331642446be05292e3e1f8a51218827168cdclaireho * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
155569331642446be05292e3e1f8a51218827168cdclaireho * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
165569331642446be05292e3e1f8a51218827168cdclaireho * DAMAGE.
175569331642446be05292e3e1f8a51218827168cdclaireho *
185569331642446be05292e3e1f8a51218827168cdclaireho * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
195569331642446be05292e3e1f8a51218827168cdclaireho * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
205569331642446be05292e3e1f8a51218827168cdclaireho * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
215569331642446be05292e3e1f8a51218827168cdclaireho * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
225569331642446be05292e3e1f8a51218827168cdclaireho * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
235569331642446be05292e3e1f8a51218827168cdclaireho */
245569331642446be05292e3e1f8a51218827168cdclaireho
255569331642446be05292e3e1f8a51218827168cdclaireho#include "harfbuzz-shaper.h"
265569331642446be05292e3e1f8a51218827168cdclaireho#include "harfbuzz-shaper-private.h"
275569331642446be05292e3e1f8a51218827168cdclaireho
285569331642446be05292e3e1f8a51218827168cdclaireho#include <assert.h>
295569331642446be05292e3e1f8a51218827168cdclaireho#include <stdio.h>
305569331642446be05292e3e1f8a51218827168cdclaireho
315569331642446be05292e3e1f8a51218827168cdclaireho#define FLAG(x) (1 << (x))
325569331642446be05292e3e1f8a51218827168cdclaireho
335569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Bool isLetter(HB_UChar16 ucs)
345569331642446be05292e3e1f8a51218827168cdclaireho{
355569331642446be05292e3e1f8a51218827168cdclaireho    const int test = FLAG(HB_Letter_Uppercase) |
365569331642446be05292e3e1f8a51218827168cdclaireho                     FLAG(HB_Letter_Lowercase) |
375569331642446be05292e3e1f8a51218827168cdclaireho                     FLAG(HB_Letter_Titlecase) |
385569331642446be05292e3e1f8a51218827168cdclaireho                     FLAG(HB_Letter_Modifier) |
395569331642446be05292e3e1f8a51218827168cdclaireho                     FLAG(HB_Letter_Other);
405569331642446be05292e3e1f8a51218827168cdclaireho    return FLAG(HB_GetUnicodeCharCategory(ucs)) & test;
415569331642446be05292e3e1f8a51218827168cdclaireho}
425569331642446be05292e3e1f8a51218827168cdclaireho
435569331642446be05292e3e1f8a51218827168cdclairehostatic HB_Bool isMark(HB_UChar16 ucs)
445569331642446be05292e3e1f8a51218827168cdclaireho{
455569331642446be05292e3e1f8a51218827168cdclaireho    const int test = FLAG(HB_Mark_NonSpacing) |
465569331642446be05292e3e1f8a51218827168cdclaireho                     FLAG(HB_Mark_SpacingCombining) |
475569331642446be05292e3e1f8a51218827168cdclaireho                     FLAG(HB_Mark_Enclosing);
485569331642446be05292e3e1f8a51218827168cdclaireho    return FLAG(HB_GetUnicodeCharCategory(ucs)) & test;
495569331642446be05292e3e1f8a51218827168cdclaireho}
505569331642446be05292e3e1f8a51218827168cdclaireho
515569331642446be05292e3e1f8a51218827168cdclairehoenum Form {
525569331642446be05292e3e1f8a51218827168cdclaireho    Invalid = 0x0,
535569331642446be05292e3e1f8a51218827168cdclaireho    UnknownForm = Invalid,
545569331642446be05292e3e1f8a51218827168cdclaireho    Consonant,
555569331642446be05292e3e1f8a51218827168cdclaireho    Nukta,
565569331642446be05292e3e1f8a51218827168cdclaireho    Halant,
575569331642446be05292e3e1f8a51218827168cdclaireho    Matra,
585569331642446be05292e3e1f8a51218827168cdclaireho    VowelMark,
595569331642446be05292e3e1f8a51218827168cdclaireho    StressMark,
605569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel,
615569331642446be05292e3e1f8a51218827168cdclaireho    LengthMark,
625569331642446be05292e3e1f8a51218827168cdclaireho    Control,
635569331642446be05292e3e1f8a51218827168cdclaireho    Other
645569331642446be05292e3e1f8a51218827168cdclaireho};
655569331642446be05292e3e1f8a51218827168cdclaireho
665569331642446be05292e3e1f8a51218827168cdclairehostatic const unsigned char indicForms[0xe00-0x900] = {
675569331642446be05292e3e1f8a51218827168cdclaireho    // Devangari
685569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, VowelMark, VowelMark, VowelMark,
695569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
705569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
715569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
725569331642446be05292e3e1f8a51218827168cdclaireho
735569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
745569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Consonant, Consonant, Consonant,
755569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
765569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
775569331642446be05292e3e1f8a51218827168cdclaireho
785569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
795569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
805569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
815569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
825569331642446be05292e3e1f8a51218827168cdclaireho
835569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
845569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
855569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, UnknownForm, UnknownForm,
865569331642446be05292e3e1f8a51218827168cdclaireho    Nukta, Other, Matra, Matra,
875569331642446be05292e3e1f8a51218827168cdclaireho
885569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Matra, Matra, Matra,
895569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Matra, Matra, Matra,
905569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Matra, Matra, Matra,
915569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Halant, UnknownForm, UnknownForm,
925569331642446be05292e3e1f8a51218827168cdclaireho
935569331642446be05292e3e1f8a51218827168cdclaireho    Other, StressMark, StressMark, StressMark,
945569331642446be05292e3e1f8a51218827168cdclaireho    StressMark, UnknownForm, UnknownForm, UnknownForm,
955569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
965569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
975569331642446be05292e3e1f8a51218827168cdclaireho
985569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, VowelMark, VowelMark,
995569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
1005569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
1015569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
1025569331642446be05292e3e1f8a51218827168cdclaireho
1035569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
1045569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
1055569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Consonant,
1065569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant /* ??? */, Consonant, Consonant,
1075569331642446be05292e3e1f8a51218827168cdclaireho
1085569331642446be05292e3e1f8a51218827168cdclaireho    // Bengali
1095569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, VowelMark, VowelMark, VowelMark,
1105569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
1115569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
1125569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Invalid, Invalid, IndependentVowel,
1135569331642446be05292e3e1f8a51218827168cdclaireho
1145569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Invalid, Invalid, IndependentVowel,
1155569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Consonant, Consonant, Consonant,
1165569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
1175569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
1185569331642446be05292e3e1f8a51218827168cdclaireho
1195569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
1205569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
1215569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Invalid, Consonant, Consonant,
1225569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
1235569331642446be05292e3e1f8a51218827168cdclaireho
1245569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Invalid, Consonant, Invalid,
1255569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Consonant, Consonant,
1265569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, UnknownForm, UnknownForm,
1275569331642446be05292e3e1f8a51218827168cdclaireho    Nukta, Other, Matra, Matra,
1285569331642446be05292e3e1f8a51218827168cdclaireho
1295569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Matra, Matra, Matra,
1305569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Invalid, Invalid, Matra,
1315569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Invalid, Invalid, Matra,
1325569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Halant, Consonant, UnknownForm,
1335569331642446be05292e3e1f8a51218827168cdclaireho
1345569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
1355569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, VowelMark,
1365569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
1375569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Invalid, Consonant,
1385569331642446be05292e3e1f8a51218827168cdclaireho
1395569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, VowelMark, VowelMark,
1405569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
1415569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
1425569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
1435569331642446be05292e3e1f8a51218827168cdclaireho
1445569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Other, Other,
1455569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
1465569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
1475569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
1485569331642446be05292e3e1f8a51218827168cdclaireho
1495569331642446be05292e3e1f8a51218827168cdclaireho    // Gurmukhi
1505569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, VowelMark, VowelMark, VowelMark,
1515569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
1525569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, IndependentVowel, Invalid,
1535569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, IndependentVowel,
1545569331642446be05292e3e1f8a51218827168cdclaireho
1555569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Invalid, Invalid, IndependentVowel,
1565569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Consonant, Consonant, Consonant,
1575569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
1585569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
1595569331642446be05292e3e1f8a51218827168cdclaireho
1605569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
1615569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
1625569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Invalid, Consonant, Consonant,
1635569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
1645569331642446be05292e3e1f8a51218827168cdclaireho
1655569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Invalid, Consonant, Consonant,
1665569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Consonant, Consonant, Invalid,
1675569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, UnknownForm, UnknownForm,
1685569331642446be05292e3e1f8a51218827168cdclaireho    Nukta, Other, Matra, Matra,
1695569331642446be05292e3e1f8a51218827168cdclaireho
1705569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Matra, Matra, Invalid,
1715569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Matra,
1725569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Invalid, Invalid, Matra,
1735569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Halant, UnknownForm, UnknownForm,
1745569331642446be05292e3e1f8a51218827168cdclaireho
1755569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
1765569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, UnknownForm, UnknownForm, UnknownForm,
1775569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Consonant, Consonant, Consonant,
1785569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Invalid, Consonant, Invalid,
1795569331642446be05292e3e1f8a51218827168cdclaireho
1805569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Invalid, Invalid,
1815569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
1825569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
1835569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
1845569331642446be05292e3e1f8a51218827168cdclaireho
1855569331642446be05292e3e1f8a51218827168cdclaireho    StressMark, StressMark, Consonant, Consonant,
1865569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
1875569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
1885569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
1895569331642446be05292e3e1f8a51218827168cdclaireho
1905569331642446be05292e3e1f8a51218827168cdclaireho    // Gujarati
1915569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, VowelMark, VowelMark, VowelMark,
1925569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
1935569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
1945569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, Invalid, IndependentVowel,
1955569331642446be05292e3e1f8a51218827168cdclaireho
1965569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, Invalid, IndependentVowel,
1975569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Consonant, Consonant, Consonant,
1985569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
1995569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
2005569331642446be05292e3e1f8a51218827168cdclaireho
2015569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
2025569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
2035569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Invalid, Consonant, Consonant,
2045569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
2055569331642446be05292e3e1f8a51218827168cdclaireho
2065569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Invalid, Consonant, Consonant,
2075569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Consonant, Consonant, Consonant,
2085569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, UnknownForm, UnknownForm,
2095569331642446be05292e3e1f8a51218827168cdclaireho    Nukta, Other, Matra, Matra,
2105569331642446be05292e3e1f8a51218827168cdclaireho
2115569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Matra, Matra, Matra,
2125569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Matra, Invalid, Matra,
2135569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Matra, Invalid, Matra,
2145569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Halant, UnknownForm, UnknownForm,
2155569331642446be05292e3e1f8a51218827168cdclaireho
2165569331642446be05292e3e1f8a51218827168cdclaireho    Other, UnknownForm, UnknownForm, UnknownForm,
2175569331642446be05292e3e1f8a51218827168cdclaireho    UnknownForm, UnknownForm, UnknownForm, UnknownForm,
2185569331642446be05292e3e1f8a51218827168cdclaireho    UnknownForm, UnknownForm, UnknownForm, UnknownForm,
2195569331642446be05292e3e1f8a51218827168cdclaireho    UnknownForm, UnknownForm, UnknownForm, UnknownForm,
2205569331642446be05292e3e1f8a51218827168cdclaireho
2215569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, VowelMark, VowelMark,
2225569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
2235569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
2245569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
2255569331642446be05292e3e1f8a51218827168cdclaireho
2265569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
2275569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
2285569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
2295569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
2305569331642446be05292e3e1f8a51218827168cdclaireho
2315569331642446be05292e3e1f8a51218827168cdclaireho    // Oriya
2325569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, VowelMark, VowelMark, VowelMark,
2335569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
2345569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
2355569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Invalid, Invalid, IndependentVowel,
2365569331642446be05292e3e1f8a51218827168cdclaireho
2375569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Invalid, Invalid, IndependentVowel,
2385569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Consonant, Consonant, Consonant,
2395569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
2405569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
2415569331642446be05292e3e1f8a51218827168cdclaireho
2425569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
2435569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
2445569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Invalid, Consonant, Consonant,
2455569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
2465569331642446be05292e3e1f8a51218827168cdclaireho
2475569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Invalid, Consonant, Consonant,
2485569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Consonant, Consonant, Consonant,
2495569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, UnknownForm, UnknownForm,
2505569331642446be05292e3e1f8a51218827168cdclaireho    Nukta, Other, Matra, Matra,
2515569331642446be05292e3e1f8a51218827168cdclaireho
2525569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Matra, Matra, Matra,
2535569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Matra,
2545569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Invalid, Invalid, Matra,
2555569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Halant, UnknownForm, UnknownForm,
2565569331642446be05292e3e1f8a51218827168cdclaireho
2575569331642446be05292e3e1f8a51218827168cdclaireho    Other, Invalid, Invalid, Invalid,
2585569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, UnknownForm, LengthMark, LengthMark,
2595569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
2605569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Invalid, Consonant,
2615569331642446be05292e3e1f8a51218827168cdclaireho
2625569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, Invalid, Invalid,
2635569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Other, Other,
2645569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
2655569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
2665569331642446be05292e3e1f8a51218827168cdclaireho
2675569331642446be05292e3e1f8a51218827168cdclaireho    Other, Consonant, Other, Other,
2685569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
2695569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
2705569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
2715569331642446be05292e3e1f8a51218827168cdclaireho
2725569331642446be05292e3e1f8a51218827168cdclaireho    //Tamil
2735569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, VowelMark, Other,
2745569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
2755569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, IndependentVowel, Invalid,
2765569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, IndependentVowel, IndependentVowel,
2775569331642446be05292e3e1f8a51218827168cdclaireho
2785569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Invalid, IndependentVowel, IndependentVowel,
2795569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Consonant, Invalid, Invalid,
2805569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Consonant, Consonant, Invalid,
2815569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Invalid, Consonant, Consonant,
2825569331642446be05292e3e1f8a51218827168cdclaireho
2835569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Consonant,
2845569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Invalid, Invalid, Invalid,
2855569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Invalid,
2865569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Consonant, Consonant,
2875569331642446be05292e3e1f8a51218827168cdclaireho
2885569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
2895569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
2905569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, UnknownForm, UnknownForm,
2915569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Matra, Matra,
2925569331642446be05292e3e1f8a51218827168cdclaireho
2935569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Matra, Matra, Invalid,
2945569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Matra, Matra,
2955569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Invalid, Matra, Matra,
2965569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Halant, Invalid, Invalid,
2975569331642446be05292e3e1f8a51218827168cdclaireho
2985569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
2995569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, LengthMark,
3005569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
3015569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
3025569331642446be05292e3e1f8a51218827168cdclaireho
3035569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
3045569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Other, Other,
3055569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3065569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3075569331642446be05292e3e1f8a51218827168cdclaireho
3085569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3095569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3105569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3115569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3125569331642446be05292e3e1f8a51218827168cdclaireho
3135569331642446be05292e3e1f8a51218827168cdclaireho    // Telugu
3145569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, VowelMark, VowelMark, VowelMark,
3155569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
3165569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
3175569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Invalid, IndependentVowel, IndependentVowel,
3185569331642446be05292e3e1f8a51218827168cdclaireho
3195569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Invalid, IndependentVowel, IndependentVowel,
3205569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Consonant, Consonant, Consonant,
3215569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
3225569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
3235569331642446be05292e3e1f8a51218827168cdclaireho
3245569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
3255569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
3265569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Invalid, Consonant, Consonant,
3275569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
3285569331642446be05292e3e1f8a51218827168cdclaireho
3295569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
3305569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Consonant, Consonant, Consonant,
3315569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, UnknownForm, UnknownForm,
3325569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Matra, Matra,
3335569331642446be05292e3e1f8a51218827168cdclaireho
3345569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Matra, Matra, Matra,
3355569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Invalid, Matra, Matra,
3365569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Invalid, Matra, Matra,
3375569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Halant, Invalid, Invalid,
3385569331642446be05292e3e1f8a51218827168cdclaireho
3395569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
3405569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, LengthMark, Matra, Invalid,
3415569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
3425569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
3435569331642446be05292e3e1f8a51218827168cdclaireho
3445569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, Invalid, Invalid,
3455569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Other, Other,
3465569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3475569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3485569331642446be05292e3e1f8a51218827168cdclaireho
3495569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3505569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3515569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3525569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3535569331642446be05292e3e1f8a51218827168cdclaireho
3545569331642446be05292e3e1f8a51218827168cdclaireho    // Kannada
3555569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, VowelMark, VowelMark,
3565569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
3575569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
3585569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Invalid, IndependentVowel, IndependentVowel,
3595569331642446be05292e3e1f8a51218827168cdclaireho
3605569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Invalid, IndependentVowel, IndependentVowel,
3615569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Consonant, Consonant, Consonant,
3625569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
3635569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
3645569331642446be05292e3e1f8a51218827168cdclaireho
3655569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
3665569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
3675569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Invalid, Consonant, Consonant,
3685569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
3695569331642446be05292e3e1f8a51218827168cdclaireho
3705569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
3715569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Consonant, Consonant, Consonant,
3725569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, UnknownForm, UnknownForm,
3735569331642446be05292e3e1f8a51218827168cdclaireho    Nukta, Other, Matra, Matra,
3745569331642446be05292e3e1f8a51218827168cdclaireho
3755569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Matra, Matra, Matra,
3765569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Invalid, Matra, Matra,
3775569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Invalid, Matra, Matra,
3785569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Halant, Invalid, Invalid,
3795569331642446be05292e3e1f8a51218827168cdclaireho
3805569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
3815569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, LengthMark, LengthMark, Invalid,
3825569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
3835569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Consonant, Invalid,
3845569331642446be05292e3e1f8a51218827168cdclaireho
3855569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, VowelMark, VowelMark,
3865569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Other, Other,
3875569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3885569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3895569331642446be05292e3e1f8a51218827168cdclaireho
3905569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3915569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3925569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3935569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
3945569331642446be05292e3e1f8a51218827168cdclaireho
3955569331642446be05292e3e1f8a51218827168cdclaireho    // Malayalam
3965569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, VowelMark, VowelMark,
3975569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
3985569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
3995569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Invalid, IndependentVowel, IndependentVowel,
4005569331642446be05292e3e1f8a51218827168cdclaireho
4015569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Invalid, IndependentVowel, IndependentVowel,
4025569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, Consonant, Consonant, Consonant,
4035569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
4045569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
4055569331642446be05292e3e1f8a51218827168cdclaireho
4065569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
4075569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
4085569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Invalid, Consonant, Consonant,
4095569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
4105569331642446be05292e3e1f8a51218827168cdclaireho
4115569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
4125569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
4135569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, UnknownForm, UnknownForm,
4145569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Matra, Matra,
4155569331642446be05292e3e1f8a51218827168cdclaireho
4165569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Matra, Matra, Matra,
4175569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Matra, Matra,
4185569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Invalid, Matra, Matra,
4195569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Halant, Invalid, Invalid,
4205569331642446be05292e3e1f8a51218827168cdclaireho
4215569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
4225569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Matra,
4235569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
4245569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
4255569331642446be05292e3e1f8a51218827168cdclaireho
4265569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, Invalid, Invalid,
4275569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Other, Other,
4285569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
4295569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
4305569331642446be05292e3e1f8a51218827168cdclaireho
4315569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
4325569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
4335569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
4345569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
4355569331642446be05292e3e1f8a51218827168cdclaireho
4365569331642446be05292e3e1f8a51218827168cdclaireho    // Sinhala
4375569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, VowelMark, VowelMark,
4385569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, IndependentVowel, IndependentVowel, IndependentVowel,
4395569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
4405569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
4415569331642446be05292e3e1f8a51218827168cdclaireho
4425569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, IndependentVowel, IndependentVowel,
4435569331642446be05292e3e1f8a51218827168cdclaireho    IndependentVowel, IndependentVowel, IndependentVowel, Invalid,
4445569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Consonant, Consonant,
4455569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
4465569331642446be05292e3e1f8a51218827168cdclaireho
4475569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
4485569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
4495569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
4505569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
4515569331642446be05292e3e1f8a51218827168cdclaireho
4525569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Invalid, Consonant,
4535569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
4545569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
4555569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Consonant, Invalid, Invalid,
4565569331642446be05292e3e1f8a51218827168cdclaireho
4575569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Consonant,
4585569331642446be05292e3e1f8a51218827168cdclaireho    Consonant, Consonant, Consonant, Invalid,
4595569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Halant, Invalid,
4605569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Matra,
4615569331642446be05292e3e1f8a51218827168cdclaireho
4625569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Matra, Matra, Matra,
4635569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Invalid, Matra, Invalid,
4645569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Matra, Matra, Matra,
4655569331642446be05292e3e1f8a51218827168cdclaireho    Matra, Matra, Matra, Matra,
4665569331642446be05292e3e1f8a51218827168cdclaireho
4675569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
4685569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
4695569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
4705569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Invalid, Invalid,
4715569331642446be05292e3e1f8a51218827168cdclaireho
4725569331642446be05292e3e1f8a51218827168cdclaireho    Invalid, Invalid, Matra, Matra,
4735569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
4745569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
4755569331642446be05292e3e1f8a51218827168cdclaireho    Other, Other, Other, Other,
4765569331642446be05292e3e1f8a51218827168cdclaireho};
4775569331642446be05292e3e1f8a51218827168cdclaireho
4785569331642446be05292e3e1f8a51218827168cdclairehoenum Position {
4795569331642446be05292e3e1f8a51218827168cdclaireho    None,
4805569331642446be05292e3e1f8a51218827168cdclaireho    Pre,
4815569331642446be05292e3e1f8a51218827168cdclaireho    Above,
4825569331642446be05292e3e1f8a51218827168cdclaireho    Below,
4835569331642446be05292e3e1f8a51218827168cdclaireho    Post,
4845569331642446be05292e3e1f8a51218827168cdclaireho    Split,
4855569331642446be05292e3e1f8a51218827168cdclaireho    Base,
4865569331642446be05292e3e1f8a51218827168cdclaireho    Reph,
4875569331642446be05292e3e1f8a51218827168cdclaireho    Vattu,
4885569331642446be05292e3e1f8a51218827168cdclaireho    Inherit
4895569331642446be05292e3e1f8a51218827168cdclaireho};
4905569331642446be05292e3e1f8a51218827168cdclaireho
4915569331642446be05292e3e1f8a51218827168cdclairehostatic const unsigned char indicPosition[0xe00-0x900] = {
4925569331642446be05292e3e1f8a51218827168cdclaireho    // Devanagari
4935569331642446be05292e3e1f8a51218827168cdclaireho    None, Above, Above, Post,
4945569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
4955569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
4965569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
4975569331642446be05292e3e1f8a51218827168cdclaireho
4985569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
4995569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5005569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5015569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5025569331642446be05292e3e1f8a51218827168cdclaireho
5035569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5045569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5055569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5065569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5075569331642446be05292e3e1f8a51218827168cdclaireho
5085569331642446be05292e3e1f8a51218827168cdclaireho    Below, None, None, None,
5095569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5105569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5115569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Post, Pre,
5125569331642446be05292e3e1f8a51218827168cdclaireho
5135569331642446be05292e3e1f8a51218827168cdclaireho    Post, Below, Below, Below,
5145569331642446be05292e3e1f8a51218827168cdclaireho    Below, Above, Above, Above,
5155569331642446be05292e3e1f8a51218827168cdclaireho    Above, Post, Post, Post,
5165569331642446be05292e3e1f8a51218827168cdclaireho    Post, None, None, None,
5175569331642446be05292e3e1f8a51218827168cdclaireho
5185569331642446be05292e3e1f8a51218827168cdclaireho    None, Above, Below, Above,
5195569331642446be05292e3e1f8a51218827168cdclaireho    Above, None, None, None,
5205569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5215569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5225569331642446be05292e3e1f8a51218827168cdclaireho
5235569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Below, Below,
5245569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5255569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5265569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5275569331642446be05292e3e1f8a51218827168cdclaireho
5285569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5295569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5305569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5315569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5325569331642446be05292e3e1f8a51218827168cdclaireho
5335569331642446be05292e3e1f8a51218827168cdclaireho    // Bengali
5345569331642446be05292e3e1f8a51218827168cdclaireho    None, Above, Post, Post,
5355569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5365569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5375569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5385569331642446be05292e3e1f8a51218827168cdclaireho
5395569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5405569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5415569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5425569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5435569331642446be05292e3e1f8a51218827168cdclaireho
5445569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5455569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5465569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5475569331642446be05292e3e1f8a51218827168cdclaireho    Below, None, None, Post,
5485569331642446be05292e3e1f8a51218827168cdclaireho
5495569331642446be05292e3e1f8a51218827168cdclaireho    Below, None, None, None,
5505569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5515569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5525569331642446be05292e3e1f8a51218827168cdclaireho    Below, None, Post, Pre,
5535569331642446be05292e3e1f8a51218827168cdclaireho
5545569331642446be05292e3e1f8a51218827168cdclaireho    Post, Below, Below, Below,
5555569331642446be05292e3e1f8a51218827168cdclaireho    Below, None, None, Pre,
5565569331642446be05292e3e1f8a51218827168cdclaireho    Pre, None, None, Split,
5575569331642446be05292e3e1f8a51218827168cdclaireho    Split, Below, None, None,
5585569331642446be05292e3e1f8a51218827168cdclaireho
5595569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5605569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, Post,
5615569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5625569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5635569331642446be05292e3e1f8a51218827168cdclaireho
5645569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Below, Below,
5655569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5665569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5675569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5685569331642446be05292e3e1f8a51218827168cdclaireho
5695569331642446be05292e3e1f8a51218827168cdclaireho    Below, None, None, None,
5705569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5715569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5725569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5735569331642446be05292e3e1f8a51218827168cdclaireho
5745569331642446be05292e3e1f8a51218827168cdclaireho    // Gurmukhi
5755569331642446be05292e3e1f8a51218827168cdclaireho    None, Above, Above, Post,
5765569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5775569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5785569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5795569331642446be05292e3e1f8a51218827168cdclaireho
5805569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5815569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5825569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5835569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5845569331642446be05292e3e1f8a51218827168cdclaireho
5855569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5865569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5875569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
5885569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, Post,
5895569331642446be05292e3e1f8a51218827168cdclaireho
5905569331642446be05292e3e1f8a51218827168cdclaireho    Below, None, None, None,
5915569331642446be05292e3e1f8a51218827168cdclaireho    None, Below, None, None,
5925569331642446be05292e3e1f8a51218827168cdclaireho    None, Below, None, None,
5935569331642446be05292e3e1f8a51218827168cdclaireho    Below, None, Post, Pre,
5945569331642446be05292e3e1f8a51218827168cdclaireho
5955569331642446be05292e3e1f8a51218827168cdclaireho    Post, Below, Below, None,
5965569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, Above,
5975569331642446be05292e3e1f8a51218827168cdclaireho    Above, None, None, Above,
5985569331642446be05292e3e1f8a51218827168cdclaireho    Above, None, None, None,
5995569331642446be05292e3e1f8a51218827168cdclaireho
6005569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6015569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6025569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6035569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6045569331642446be05292e3e1f8a51218827168cdclaireho
6055569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6065569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6075569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6085569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6095569331642446be05292e3e1f8a51218827168cdclaireho
6105569331642446be05292e3e1f8a51218827168cdclaireho    Above, Above, None, None,
6115569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6125569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6135569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6145569331642446be05292e3e1f8a51218827168cdclaireho
6155569331642446be05292e3e1f8a51218827168cdclaireho    // Gujarati
6165569331642446be05292e3e1f8a51218827168cdclaireho    None, Above, Above, Post,
6175569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6185569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6195569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6205569331642446be05292e3e1f8a51218827168cdclaireho
6215569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6225569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6235569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6245569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6255569331642446be05292e3e1f8a51218827168cdclaireho
6265569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6275569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6285569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6295569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6305569331642446be05292e3e1f8a51218827168cdclaireho
6315569331642446be05292e3e1f8a51218827168cdclaireho    Below, None, None, None,
6325569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6335569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6345569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Post, Pre,
6355569331642446be05292e3e1f8a51218827168cdclaireho
6365569331642446be05292e3e1f8a51218827168cdclaireho    Post, Below, Below, Below,
6375569331642446be05292e3e1f8a51218827168cdclaireho    Below, Above, None, Above,
6385569331642446be05292e3e1f8a51218827168cdclaireho    Above, Post, None, Post,
6395569331642446be05292e3e1f8a51218827168cdclaireho    Post, None, None, None,
6405569331642446be05292e3e1f8a51218827168cdclaireho
6415569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6425569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6435569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6445569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6455569331642446be05292e3e1f8a51218827168cdclaireho
6465569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Below, Below,
6475569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6485569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6495569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6505569331642446be05292e3e1f8a51218827168cdclaireho
6515569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6525569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6535569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6545569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6555569331642446be05292e3e1f8a51218827168cdclaireho
6565569331642446be05292e3e1f8a51218827168cdclaireho    // Oriya
6575569331642446be05292e3e1f8a51218827168cdclaireho    None, Above, Post, Post,
6585569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6595569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6605569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6615569331642446be05292e3e1f8a51218827168cdclaireho
6625569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6635569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6645569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6655569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6665569331642446be05292e3e1f8a51218827168cdclaireho
6675569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6685569331642446be05292e3e1f8a51218827168cdclaireho    Below, None, None, None,
6695569331642446be05292e3e1f8a51218827168cdclaireho    Below, None, None, None,
6705569331642446be05292e3e1f8a51218827168cdclaireho    Below, Below, Below, Post,
6715569331642446be05292e3e1f8a51218827168cdclaireho
6725569331642446be05292e3e1f8a51218827168cdclaireho    Below, None, Below, Below,
6735569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6745569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6755569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Post, Above,
6765569331642446be05292e3e1f8a51218827168cdclaireho
6775569331642446be05292e3e1f8a51218827168cdclaireho    Post, Below, Below, Below,
6785569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, Pre,
6795569331642446be05292e3e1f8a51218827168cdclaireho    Split, None, None, Split,
6805569331642446be05292e3e1f8a51218827168cdclaireho    Split, None, None, None,
6815569331642446be05292e3e1f8a51218827168cdclaireho
6825569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6835569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Above, Post,
6845569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6855569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, Post,
6865569331642446be05292e3e1f8a51218827168cdclaireho
6875569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6885569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6895569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6905569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6915569331642446be05292e3e1f8a51218827168cdclaireho
6925569331642446be05292e3e1f8a51218827168cdclaireho    None, Below, None, None,
6935569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6945569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6955569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
6965569331642446be05292e3e1f8a51218827168cdclaireho
6975569331642446be05292e3e1f8a51218827168cdclaireho    // Tamil
6985569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Above, None,
6995569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7005569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7015569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7025569331642446be05292e3e1f8a51218827168cdclaireho
7035569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7045569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7055569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7065569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7075569331642446be05292e3e1f8a51218827168cdclaireho
7085569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7095569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7105569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7115569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7125569331642446be05292e3e1f8a51218827168cdclaireho
7135569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7145569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7155569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7165569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Post, Post,
7175569331642446be05292e3e1f8a51218827168cdclaireho
7185569331642446be05292e3e1f8a51218827168cdclaireho    Above, Below, Below, None,
7195569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Pre, Pre,
7205569331642446be05292e3e1f8a51218827168cdclaireho    Pre, None, Split, Split,
7215569331642446be05292e3e1f8a51218827168cdclaireho    Split, Halant, None, None,
7225569331642446be05292e3e1f8a51218827168cdclaireho
7235569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7245569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, Post,
7255569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7265569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7275569331642446be05292e3e1f8a51218827168cdclaireho
7285569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7295569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7305569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7315569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7325569331642446be05292e3e1f8a51218827168cdclaireho
7335569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7345569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7355569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7365569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7375569331642446be05292e3e1f8a51218827168cdclaireho
7385569331642446be05292e3e1f8a51218827168cdclaireho    // Telugu
7395569331642446be05292e3e1f8a51218827168cdclaireho    None, Post, Post, Post,
7405569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7415569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7425569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7435569331642446be05292e3e1f8a51218827168cdclaireho
7445569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7455569331642446be05292e3e1f8a51218827168cdclaireho    None, Below, Below, Below,
7465569331642446be05292e3e1f8a51218827168cdclaireho    Below, Below, Below, Below,
7475569331642446be05292e3e1f8a51218827168cdclaireho    Below, Below, Below, Below,
7485569331642446be05292e3e1f8a51218827168cdclaireho
7495569331642446be05292e3e1f8a51218827168cdclaireho    Below, Below, Below, Below,
7505569331642446be05292e3e1f8a51218827168cdclaireho    Below, Below, Below, Below,
7515569331642446be05292e3e1f8a51218827168cdclaireho    Below, None, Below, Below,
7525569331642446be05292e3e1f8a51218827168cdclaireho    Below, Below, Below, Below,
7535569331642446be05292e3e1f8a51218827168cdclaireho
7545569331642446be05292e3e1f8a51218827168cdclaireho    Below, None, Below, Below,
7555569331642446be05292e3e1f8a51218827168cdclaireho    None, Below, Below, Below,
7565569331642446be05292e3e1f8a51218827168cdclaireho    Below, Below, None, None,
7575569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Post, Above,
7585569331642446be05292e3e1f8a51218827168cdclaireho
7595569331642446be05292e3e1f8a51218827168cdclaireho    Above, Post, Post, Post,
7605569331642446be05292e3e1f8a51218827168cdclaireho    Post, None, Above, Above,
7615569331642446be05292e3e1f8a51218827168cdclaireho    Split, None, Post, Above,
7625569331642446be05292e3e1f8a51218827168cdclaireho    Above, Halant, None, None,
7635569331642446be05292e3e1f8a51218827168cdclaireho
7645569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7655569331642446be05292e3e1f8a51218827168cdclaireho    None, Above, Below, None,
7665569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7675569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7685569331642446be05292e3e1f8a51218827168cdclaireho
7695569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7705569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7715569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7725569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7735569331642446be05292e3e1f8a51218827168cdclaireho
7745569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7755569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7765569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7775569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7785569331642446be05292e3e1f8a51218827168cdclaireho
7795569331642446be05292e3e1f8a51218827168cdclaireho    // Kannada
7805569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Post, Post,
7815569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7825569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7835569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7845569331642446be05292e3e1f8a51218827168cdclaireho
7855569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
7865569331642446be05292e3e1f8a51218827168cdclaireho    None, Below, Below, Below,
7875569331642446be05292e3e1f8a51218827168cdclaireho    Below, Below, Below, Below,
7885569331642446be05292e3e1f8a51218827168cdclaireho    Below, Below, Below, Below,
7895569331642446be05292e3e1f8a51218827168cdclaireho
7905569331642446be05292e3e1f8a51218827168cdclaireho    Below, Below, Below, Below,
7915569331642446be05292e3e1f8a51218827168cdclaireho    Below, Below, Below, Below,
7925569331642446be05292e3e1f8a51218827168cdclaireho    Below, Below, Below, Below,
7935569331642446be05292e3e1f8a51218827168cdclaireho    Below, Below, Below, Below,
7945569331642446be05292e3e1f8a51218827168cdclaireho
7955569331642446be05292e3e1f8a51218827168cdclaireho    Below, None, Below, Below,
7965569331642446be05292e3e1f8a51218827168cdclaireho    None, Below, Below, Below,
7975569331642446be05292e3e1f8a51218827168cdclaireho    Below, Below, None, None,
7985569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Post, Above,
7995569331642446be05292e3e1f8a51218827168cdclaireho
8005569331642446be05292e3e1f8a51218827168cdclaireho    Split, Post, Post, Post,
8015569331642446be05292e3e1f8a51218827168cdclaireho    Post, None, Above, Split,
8025569331642446be05292e3e1f8a51218827168cdclaireho    Split, None, Split, Split,
8035569331642446be05292e3e1f8a51218827168cdclaireho    Above, Halant, None, None,
8045569331642446be05292e3e1f8a51218827168cdclaireho
8055569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8065569331642446be05292e3e1f8a51218827168cdclaireho    None, Post, Post, None,
8075569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8085569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Below, None,
8095569331642446be05292e3e1f8a51218827168cdclaireho
8105569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Below, Below,
8115569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8125569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8135569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8145569331642446be05292e3e1f8a51218827168cdclaireho
8155569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8165569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8175569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8185569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8195569331642446be05292e3e1f8a51218827168cdclaireho
8205569331642446be05292e3e1f8a51218827168cdclaireho    // Malayalam
8215569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Post, Post,
8225569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8235569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8245569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8255569331642446be05292e3e1f8a51218827168cdclaireho
8265569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8275569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8285569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8295569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8305569331642446be05292e3e1f8a51218827168cdclaireho
8315569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8325569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8335569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8345569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, Post,
8355569331642446be05292e3e1f8a51218827168cdclaireho
8365569331642446be05292e3e1f8a51218827168cdclaireho    Post, None, Below, None,
8375569331642446be05292e3e1f8a51218827168cdclaireho    None, Post, None, None,
8385569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8395569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Post, Post,
8405569331642446be05292e3e1f8a51218827168cdclaireho
8415569331642446be05292e3e1f8a51218827168cdclaireho    Post, Post, Post, Post,
8425569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Pre, Pre,
8435569331642446be05292e3e1f8a51218827168cdclaireho    Pre, None, Split, Split,
8445569331642446be05292e3e1f8a51218827168cdclaireho    Split, Halant, None, None,
8455569331642446be05292e3e1f8a51218827168cdclaireho
8465569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8475569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, Post,
8485569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8495569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8505569331642446be05292e3e1f8a51218827168cdclaireho
8515569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8525569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8535569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8545569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8555569331642446be05292e3e1f8a51218827168cdclaireho
8565569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8575569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8585569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8595569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8605569331642446be05292e3e1f8a51218827168cdclaireho
8615569331642446be05292e3e1f8a51218827168cdclaireho    // Sinhala
8625569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Post, Post,
8635569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8645569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8655569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8665569331642446be05292e3e1f8a51218827168cdclaireho
8675569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8685569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8695569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8705569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8715569331642446be05292e3e1f8a51218827168cdclaireho
8725569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8735569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8745569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8755569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8765569331642446be05292e3e1f8a51218827168cdclaireho
8775569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8785569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8795569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8805569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8815569331642446be05292e3e1f8a51218827168cdclaireho
8825569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8835569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8845569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8855569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, Post,
8865569331642446be05292e3e1f8a51218827168cdclaireho
8875569331642446be05292e3e1f8a51218827168cdclaireho    Post, Post, Above, Above,
8885569331642446be05292e3e1f8a51218827168cdclaireho    Below, None, Below, None,
8895569331642446be05292e3e1f8a51218827168cdclaireho    Post, Pre, Split, Pre,
8905569331642446be05292e3e1f8a51218827168cdclaireho    Split, Split, Split, Post,
8915569331642446be05292e3e1f8a51218827168cdclaireho
8925569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8935569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8945569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8955569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8965569331642446be05292e3e1f8a51218827168cdclaireho
8975569331642446be05292e3e1f8a51218827168cdclaireho    None, None, Post, Post,
8985569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
8995569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None,
9005569331642446be05292e3e1f8a51218827168cdclaireho    None, None, None, None
9015569331642446be05292e3e1f8a51218827168cdclaireho};
9025569331642446be05292e3e1f8a51218827168cdclaireho
9035569331642446be05292e3e1f8a51218827168cdclairehostatic inline Form form(unsigned short uc) {
9045569331642446be05292e3e1f8a51218827168cdclaireho    if (uc < 0x900 || uc > 0xdff) {
9055569331642446be05292e3e1f8a51218827168cdclaireho        if (uc == 0x25cc)
9065569331642446be05292e3e1f8a51218827168cdclaireho            return Consonant;
9075569331642446be05292e3e1f8a51218827168cdclaireho        if (uc == 0x200c || uc == 0x200d)
9085569331642446be05292e3e1f8a51218827168cdclaireho            return Control;
9095569331642446be05292e3e1f8a51218827168cdclaireho        return Other;
9105569331642446be05292e3e1f8a51218827168cdclaireho    }
9115569331642446be05292e3e1f8a51218827168cdclaireho    return (Form)indicForms[uc-0x900];
9125569331642446be05292e3e1f8a51218827168cdclaireho}
9135569331642446be05292e3e1f8a51218827168cdclaireho
9145569331642446be05292e3e1f8a51218827168cdclairehostatic inline Position indic_position(unsigned short uc) {
9155569331642446be05292e3e1f8a51218827168cdclaireho    if (uc < 0x900 || uc > 0xdff)
9165569331642446be05292e3e1f8a51218827168cdclaireho        return None;
9175569331642446be05292e3e1f8a51218827168cdclaireho    return (Position) indicPosition[uc-0x900];
9185569331642446be05292e3e1f8a51218827168cdclaireho}
9195569331642446be05292e3e1f8a51218827168cdclaireho
9205569331642446be05292e3e1f8a51218827168cdclaireho
9215569331642446be05292e3e1f8a51218827168cdclairehoenum IndicScriptProperties {
9225569331642446be05292e3e1f8a51218827168cdclaireho    HasReph = 0x01,
9235569331642446be05292e3e1f8a51218827168cdclaireho    HasSplit = 0x02
9245569331642446be05292e3e1f8a51218827168cdclaireho};
9255569331642446be05292e3e1f8a51218827168cdclaireho
9265569331642446be05292e3e1f8a51218827168cdclairehoconst hb_uint8 scriptProperties[10] = {
9275569331642446be05292e3e1f8a51218827168cdclaireho    // Devanagari,
9285569331642446be05292e3e1f8a51218827168cdclaireho    HasReph,
9295569331642446be05292e3e1f8a51218827168cdclaireho    // Bengali,
9305569331642446be05292e3e1f8a51218827168cdclaireho    HasReph|HasSplit,
9315569331642446be05292e3e1f8a51218827168cdclaireho    // Gurmukhi,
9325569331642446be05292e3e1f8a51218827168cdclaireho    0,
9335569331642446be05292e3e1f8a51218827168cdclaireho    // Gujarati,
9345569331642446be05292e3e1f8a51218827168cdclaireho    HasReph,
9355569331642446be05292e3e1f8a51218827168cdclaireho    // Oriya,
9365569331642446be05292e3e1f8a51218827168cdclaireho    HasReph|HasSplit,
9375569331642446be05292e3e1f8a51218827168cdclaireho    // Tamil,
9385569331642446be05292e3e1f8a51218827168cdclaireho    HasSplit,
9395569331642446be05292e3e1f8a51218827168cdclaireho    // Telugu,
9405569331642446be05292e3e1f8a51218827168cdclaireho    HasSplit,
9415569331642446be05292e3e1f8a51218827168cdclaireho    // Kannada,
9425569331642446be05292e3e1f8a51218827168cdclaireho    HasSplit|HasReph,
9435569331642446be05292e3e1f8a51218827168cdclaireho    // Malayalam,
9445569331642446be05292e3e1f8a51218827168cdclaireho    HasSplit,
9455569331642446be05292e3e1f8a51218827168cdclaireho    // Sinhala,
9465569331642446be05292e3e1f8a51218827168cdclaireho    HasSplit
9475569331642446be05292e3e1f8a51218827168cdclaireho};
9485569331642446be05292e3e1f8a51218827168cdclaireho
9495569331642446be05292e3e1f8a51218827168cdclairehostruct IndicOrdering {
9505569331642446be05292e3e1f8a51218827168cdclaireho    Form form;
9515569331642446be05292e3e1f8a51218827168cdclaireho    Position position;
9525569331642446be05292e3e1f8a51218827168cdclaireho};
9535569331642446be05292e3e1f8a51218827168cdclaireho
9545569331642446be05292e3e1f8a51218827168cdclairehostatic const IndicOrdering devanagari_order [] = {
9555569331642446be05292e3e1f8a51218827168cdclaireho    { Consonant, Below },
9565569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Below },
9575569331642446be05292e3e1f8a51218827168cdclaireho    { VowelMark, Below },
9585569331642446be05292e3e1f8a51218827168cdclaireho    { StressMark, Below },
9595569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Above },
9605569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Post },
9615569331642446be05292e3e1f8a51218827168cdclaireho    { Consonant, Reph },
9625569331642446be05292e3e1f8a51218827168cdclaireho    { VowelMark, Above },
9635569331642446be05292e3e1f8a51218827168cdclaireho    { StressMark, Above },
9645569331642446be05292e3e1f8a51218827168cdclaireho    { VowelMark, Post },
9655569331642446be05292e3e1f8a51218827168cdclaireho    { (Form)0, None }
9665569331642446be05292e3e1f8a51218827168cdclaireho};
9675569331642446be05292e3e1f8a51218827168cdclaireho
9685569331642446be05292e3e1f8a51218827168cdclairehostatic const IndicOrdering bengali_order [] = {
9695569331642446be05292e3e1f8a51218827168cdclaireho    { Consonant, Below },
9705569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Below },
9715569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Above },
9725569331642446be05292e3e1f8a51218827168cdclaireho    { Consonant, Reph },
9735569331642446be05292e3e1f8a51218827168cdclaireho    { VowelMark, Above },
9745569331642446be05292e3e1f8a51218827168cdclaireho    { Consonant, Post },
9755569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Post },
9765569331642446be05292e3e1f8a51218827168cdclaireho    { VowelMark, Post },
9775569331642446be05292e3e1f8a51218827168cdclaireho    { (Form)0, None }
9785569331642446be05292e3e1f8a51218827168cdclaireho};
9795569331642446be05292e3e1f8a51218827168cdclaireho
9805569331642446be05292e3e1f8a51218827168cdclairehostatic const IndicOrdering gurmukhi_order [] = {
9815569331642446be05292e3e1f8a51218827168cdclaireho    { Consonant, Below },
9825569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Below },
9835569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Above },
9845569331642446be05292e3e1f8a51218827168cdclaireho    { Consonant, Post },
9855569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Post },
9865569331642446be05292e3e1f8a51218827168cdclaireho    { VowelMark, Above },
9875569331642446be05292e3e1f8a51218827168cdclaireho    { (Form)0, None }
9885569331642446be05292e3e1f8a51218827168cdclaireho};
9895569331642446be05292e3e1f8a51218827168cdclaireho
9905569331642446be05292e3e1f8a51218827168cdclairehostatic const IndicOrdering tamil_order [] = {
9915569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Above },
9925569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Post },
9935569331642446be05292e3e1f8a51218827168cdclaireho    { VowelMark, Post },
9945569331642446be05292e3e1f8a51218827168cdclaireho    { (Form)0, None }
9955569331642446be05292e3e1f8a51218827168cdclaireho};
9965569331642446be05292e3e1f8a51218827168cdclaireho
9975569331642446be05292e3e1f8a51218827168cdclairehostatic const IndicOrdering telugu_order [] = {
9985569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Above },
9995569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Below },
10005569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Post },
10015569331642446be05292e3e1f8a51218827168cdclaireho    { Consonant, Below },
10025569331642446be05292e3e1f8a51218827168cdclaireho    { Consonant, Post },
10035569331642446be05292e3e1f8a51218827168cdclaireho    { VowelMark, Post },
10045569331642446be05292e3e1f8a51218827168cdclaireho    { (Form)0, None }
10055569331642446be05292e3e1f8a51218827168cdclaireho};
10065569331642446be05292e3e1f8a51218827168cdclaireho
10075569331642446be05292e3e1f8a51218827168cdclairehostatic const IndicOrdering kannada_order [] = {
10085569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Above },
10095569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Post },
10105569331642446be05292e3e1f8a51218827168cdclaireho    { Consonant, Below },
10115569331642446be05292e3e1f8a51218827168cdclaireho    { Consonant, Post },
10125569331642446be05292e3e1f8a51218827168cdclaireho    { LengthMark, Post },
10135569331642446be05292e3e1f8a51218827168cdclaireho    { Consonant, Reph },
10145569331642446be05292e3e1f8a51218827168cdclaireho    { VowelMark, Post },
10155569331642446be05292e3e1f8a51218827168cdclaireho    { (Form)0, None }
10165569331642446be05292e3e1f8a51218827168cdclaireho};
10175569331642446be05292e3e1f8a51218827168cdclaireho
10185569331642446be05292e3e1f8a51218827168cdclairehostatic const IndicOrdering malayalam_order [] = {
10195569331642446be05292e3e1f8a51218827168cdclaireho    { Consonant, Below },
10205569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Below },
10215569331642446be05292e3e1f8a51218827168cdclaireho    { Consonant, Reph },
10225569331642446be05292e3e1f8a51218827168cdclaireho    { Consonant, Post },
10235569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Post },
10245569331642446be05292e3e1f8a51218827168cdclaireho    { VowelMark, Post },
10255569331642446be05292e3e1f8a51218827168cdclaireho    { (Form)0, None }
10265569331642446be05292e3e1f8a51218827168cdclaireho};
10275569331642446be05292e3e1f8a51218827168cdclaireho
10285569331642446be05292e3e1f8a51218827168cdclairehostatic const IndicOrdering sinhala_order [] = {
10295569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Below },
10305569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Above },
10315569331642446be05292e3e1f8a51218827168cdclaireho    { Matra, Post },
10325569331642446be05292e3e1f8a51218827168cdclaireho    { VowelMark, Post },
10335569331642446be05292e3e1f8a51218827168cdclaireho    { (Form)0, None }
10345569331642446be05292e3e1f8a51218827168cdclaireho};
10355569331642446be05292e3e1f8a51218827168cdclaireho
10365569331642446be05292e3e1f8a51218827168cdclairehostatic const IndicOrdering * const indic_order[] = {
10375569331642446be05292e3e1f8a51218827168cdclaireho    devanagari_order, // Devanagari
10385569331642446be05292e3e1f8a51218827168cdclaireho    bengali_order, // Bengali
10395569331642446be05292e3e1f8a51218827168cdclaireho    gurmukhi_order, // Gurmukhi
10405569331642446be05292e3e1f8a51218827168cdclaireho    devanagari_order, // Gujarati
10415569331642446be05292e3e1f8a51218827168cdclaireho    bengali_order, // Oriya
10425569331642446be05292e3e1f8a51218827168cdclaireho    tamil_order, // Tamil
10435569331642446be05292e3e1f8a51218827168cdclaireho    telugu_order, // Telugu
10445569331642446be05292e3e1f8a51218827168cdclaireho    kannada_order, // Kannada
10455569331642446be05292e3e1f8a51218827168cdclaireho    malayalam_order, // Malayalam
10465569331642446be05292e3e1f8a51218827168cdclaireho    sinhala_order // Sinhala
10475569331642446be05292e3e1f8a51218827168cdclaireho};
10485569331642446be05292e3e1f8a51218827168cdclaireho
10495569331642446be05292e3e1f8a51218827168cdclaireho
10505569331642446be05292e3e1f8a51218827168cdclaireho
10515569331642446be05292e3e1f8a51218827168cdclaireho// vowel matras that have to be split into two parts.
10525569331642446be05292e3e1f8a51218827168cdclairehostatic const unsigned short split_matras[]  = {
10535569331642446be05292e3e1f8a51218827168cdclaireho    //  matra, split1, split2, split3
10545569331642446be05292e3e1f8a51218827168cdclaireho
10555569331642446be05292e3e1f8a51218827168cdclaireho    // bengalis
10565569331642446be05292e3e1f8a51218827168cdclaireho    0x9cb, 0x9c7, 0x9be, 0x0,
10575569331642446be05292e3e1f8a51218827168cdclaireho    0x9cc, 0x9c7, 0x9d7, 0x0,
10585569331642446be05292e3e1f8a51218827168cdclaireho    // oriya
10595569331642446be05292e3e1f8a51218827168cdclaireho    0xb48, 0xb47, 0xb56, 0x0,
10605569331642446be05292e3e1f8a51218827168cdclaireho    0xb4b, 0xb47, 0xb3e, 0x0,
10615569331642446be05292e3e1f8a51218827168cdclaireho    0xb4c, 0xb47, 0xb57, 0x0,
10625569331642446be05292e3e1f8a51218827168cdclaireho    // tamil
10635569331642446be05292e3e1f8a51218827168cdclaireho    0xbca, 0xbc6, 0xbbe, 0x0,
10645569331642446be05292e3e1f8a51218827168cdclaireho    0xbcb, 0xbc7, 0xbbe, 0x0,
10655569331642446be05292e3e1f8a51218827168cdclaireho    0xbcc, 0xbc6, 0xbd7, 0x0,
10665569331642446be05292e3e1f8a51218827168cdclaireho    // telugu
10675569331642446be05292e3e1f8a51218827168cdclaireho    0xc48, 0xc46, 0xc56, 0x0,
10685569331642446be05292e3e1f8a51218827168cdclaireho    // kannada
10695569331642446be05292e3e1f8a51218827168cdclaireho    0xcc0, 0xcbf, 0xcd5, 0x0,
10705569331642446be05292e3e1f8a51218827168cdclaireho    0xcc7, 0xcc6, 0xcd5, 0x0,
10715569331642446be05292e3e1f8a51218827168cdclaireho    0xcc8, 0xcc6, 0xcd6, 0x0,
10725569331642446be05292e3e1f8a51218827168cdclaireho    0xcca, 0xcc6, 0xcc2, 0x0,
10735569331642446be05292e3e1f8a51218827168cdclaireho    0xccb, 0xcc6, 0xcc2, 0xcd5,
10745569331642446be05292e3e1f8a51218827168cdclaireho    // malayalam
10755569331642446be05292e3e1f8a51218827168cdclaireho    0xd4a, 0xd46, 0xd3e, 0x0,
10765569331642446be05292e3e1f8a51218827168cdclaireho    0xd4b, 0xd47, 0xd3e, 0x0,
10775569331642446be05292e3e1f8a51218827168cdclaireho    0xd4c, 0xd46, 0xd57, 0x0,
10785569331642446be05292e3e1f8a51218827168cdclaireho    // sinhala
10795569331642446be05292e3e1f8a51218827168cdclaireho    0xdda, 0xdd9, 0xdca, 0x0,
10805569331642446be05292e3e1f8a51218827168cdclaireho    0xddc, 0xdd9, 0xdcf, 0x0,
10815569331642446be05292e3e1f8a51218827168cdclaireho    0xddd, 0xdd9, 0xdcf, 0xdca,
10825569331642446be05292e3e1f8a51218827168cdclaireho    0xdde, 0xdd9, 0xddf, 0x0,
10835569331642446be05292e3e1f8a51218827168cdclaireho    0xffff
10845569331642446be05292e3e1f8a51218827168cdclaireho};
10855569331642446be05292e3e1f8a51218827168cdclaireho
10865569331642446be05292e3e1f8a51218827168cdclairehostatic inline void splitMatra(unsigned short *reordered, int matra, int &len)
10875569331642446be05292e3e1f8a51218827168cdclaireho{
10885569331642446be05292e3e1f8a51218827168cdclaireho    unsigned short matra_uc = reordered[matra];
10895569331642446be05292e3e1f8a51218827168cdclaireho    //qDebug("matra=%d, reordered[matra]=%x", matra, reordered[matra]);
10905569331642446be05292e3e1f8a51218827168cdclaireho
10915569331642446be05292e3e1f8a51218827168cdclaireho    const unsigned short *split = split_matras;
10925569331642446be05292e3e1f8a51218827168cdclaireho    while (split[0] < matra_uc)
10935569331642446be05292e3e1f8a51218827168cdclaireho        split += 4;
10945569331642446be05292e3e1f8a51218827168cdclaireho
10955569331642446be05292e3e1f8a51218827168cdclaireho    assert(*split == matra_uc);
10965569331642446be05292e3e1f8a51218827168cdclaireho    ++split;
10975569331642446be05292e3e1f8a51218827168cdclaireho
10985569331642446be05292e3e1f8a51218827168cdclaireho    int added_chars = split[2] == 0x0 ? 1 : 2;
10995569331642446be05292e3e1f8a51218827168cdclaireho
11005569331642446be05292e3e1f8a51218827168cdclaireho    memmove(reordered + matra + added_chars, reordered + matra, (len-matra)*sizeof(unsigned short));
11015569331642446be05292e3e1f8a51218827168cdclaireho    reordered[matra] = split[0];
11025569331642446be05292e3e1f8a51218827168cdclaireho    reordered[matra+1] = split[1];
11035569331642446be05292e3e1f8a51218827168cdclaireho    if(added_chars == 2)
11045569331642446be05292e3e1f8a51218827168cdclaireho        reordered[matra+2] = split[2];
11055569331642446be05292e3e1f8a51218827168cdclaireho    len += added_chars;
11065569331642446be05292e3e1f8a51218827168cdclaireho}
11075569331642446be05292e3e1f8a51218827168cdclaireho
11085569331642446be05292e3e1f8a51218827168cdclaireho#ifndef NO_OPENTYPE
11095569331642446be05292e3e1f8a51218827168cdclairehostatic const HB_OpenTypeFeature indic_features[] = {
111057e6107a9d66a9a97b146def0ef38c010f954be6claireho    { HB_MAKE_TAG('l', 'o', 'c', 'a'), LocaProperty },
11115569331642446be05292e3e1f8a51218827168cdclaireho    { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },
11125569331642446be05292e3e1f8a51218827168cdclaireho    { HB_MAKE_TAG('i', 'n', 'i', 't'), InitProperty },
11135569331642446be05292e3e1f8a51218827168cdclaireho    { HB_MAKE_TAG('n', 'u', 'k', 't'), NuktaProperty },
11145569331642446be05292e3e1f8a51218827168cdclaireho    { HB_MAKE_TAG('a', 'k', 'h', 'n'), AkhantProperty },
11155569331642446be05292e3e1f8a51218827168cdclaireho    { HB_MAKE_TAG('r', 'p', 'h', 'f'), RephProperty },
11165569331642446be05292e3e1f8a51218827168cdclaireho    { HB_MAKE_TAG('b', 'l', 'w', 'f'), BelowFormProperty },
11175569331642446be05292e3e1f8a51218827168cdclaireho    { HB_MAKE_TAG('h', 'a', 'l', 'f'), HalfFormProperty },
11185569331642446be05292e3e1f8a51218827168cdclaireho    { HB_MAKE_TAG('p', 's', 't', 'f'), PostFormProperty },
111957e6107a9d66a9a97b146def0ef38c010f954be6claireho    { HB_MAKE_TAG('c', 'j', 'c', 't'), ConjunctFormProperty },
11205569331642446be05292e3e1f8a51218827168cdclaireho    { HB_MAKE_TAG('v', 'a', 't', 'u'), VattuProperty },
11215569331642446be05292e3e1f8a51218827168cdclaireho    { HB_MAKE_TAG('p', 'r', 'e', 's'), PreSubstProperty },
11225569331642446be05292e3e1f8a51218827168cdclaireho    { HB_MAKE_TAG('b', 'l', 'w', 's'), BelowSubstProperty },
11235569331642446be05292e3e1f8a51218827168cdclaireho    { HB_MAKE_TAG('a', 'b', 'v', 's'), AboveSubstProperty },
11245569331642446be05292e3e1f8a51218827168cdclaireho    { HB_MAKE_TAG('p', 's', 't', 's'), PostSubstProperty },
11255569331642446be05292e3e1f8a51218827168cdclaireho    { HB_MAKE_TAG('h', 'a', 'l', 'n'), HalantProperty },
112657e6107a9d66a9a97b146def0ef38c010f954be6claireho    { HB_MAKE_TAG('c', 'a', 'l', 't'), IndicCaltProperty },
11275569331642446be05292e3e1f8a51218827168cdclaireho    { 0, 0 }
11285569331642446be05292e3e1f8a51218827168cdclaireho};
11295569331642446be05292e3e1f8a51218827168cdclaireho#endif
11305569331642446be05292e3e1f8a51218827168cdclaireho
11315569331642446be05292e3e1f8a51218827168cdclaireho// #define INDIC_DEBUG
11325569331642446be05292e3e1f8a51218827168cdclaireho#ifdef INDIC_DEBUG
11335569331642446be05292e3e1f8a51218827168cdclaireho#define IDEBUG hb_debug
11345569331642446be05292e3e1f8a51218827168cdclaireho#include <stdarg.h>
11355569331642446be05292e3e1f8a51218827168cdclaireho
11365569331642446be05292e3e1f8a51218827168cdclairehostatic void hb_debug(const char *msg, ...)
11375569331642446be05292e3e1f8a51218827168cdclaireho{
11385569331642446be05292e3e1f8a51218827168cdclaireho    va_list ap;
11395569331642446be05292e3e1f8a51218827168cdclaireho    va_start(ap, msg); // use variable arg list
11405569331642446be05292e3e1f8a51218827168cdclaireho    vfprintf(stderr, msg, ap);
11415569331642446be05292e3e1f8a51218827168cdclaireho    va_end(ap);
11425569331642446be05292e3e1f8a51218827168cdclaireho    fprintf(stderr, "\n");
11435569331642446be05292e3e1f8a51218827168cdclaireho}
11445569331642446be05292e3e1f8a51218827168cdclaireho
11455569331642446be05292e3e1f8a51218827168cdclaireho#else
11465569331642446be05292e3e1f8a51218827168cdclaireho#define IDEBUG if(0) printf
11475569331642446be05292e3e1f8a51218827168cdclaireho#endif
11485569331642446be05292e3e1f8a51218827168cdclaireho
11495569331642446be05292e3e1f8a51218827168cdclaireho#if 0 //def INDIC_DEBUG
11505569331642446be05292e3e1f8a51218827168cdclairehostatic QString propertiesToString(int properties)
11515569331642446be05292e3e1f8a51218827168cdclaireho{
11525569331642446be05292e3e1f8a51218827168cdclaireho    QString res;
11535569331642446be05292e3e1f8a51218827168cdclaireho    properties = ~properties;
115457e6107a9d66a9a97b146def0ef38c010f954be6claireho    if (properties & LocaProperty)
115557e6107a9d66a9a97b146def0ef38c010f954be6claireho        res += "Loca ";
11565569331642446be05292e3e1f8a51218827168cdclaireho    if (properties & CcmpProperty)
11575569331642446be05292e3e1f8a51218827168cdclaireho        res += "Ccmp ";
11585569331642446be05292e3e1f8a51218827168cdclaireho    if (properties & InitProperty)
11595569331642446be05292e3e1f8a51218827168cdclaireho        res += "Init ";
11605569331642446be05292e3e1f8a51218827168cdclaireho    if (properties & NuktaProperty)
11615569331642446be05292e3e1f8a51218827168cdclaireho        res += "Nukta ";
11625569331642446be05292e3e1f8a51218827168cdclaireho    if (properties & AkhantProperty)
11635569331642446be05292e3e1f8a51218827168cdclaireho        res += "Akhant ";
11645569331642446be05292e3e1f8a51218827168cdclaireho    if (properties & RephProperty)
11655569331642446be05292e3e1f8a51218827168cdclaireho        res += "Reph ";
11665569331642446be05292e3e1f8a51218827168cdclaireho    if (properties & PreFormProperty)
11675569331642446be05292e3e1f8a51218827168cdclaireho        res += "PreForm ";
11685569331642446be05292e3e1f8a51218827168cdclaireho    if (properties & BelowFormProperty)
11695569331642446be05292e3e1f8a51218827168cdclaireho        res += "BelowForm ";
11705569331642446be05292e3e1f8a51218827168cdclaireho    if (properties & AboveFormProperty)
11715569331642446be05292e3e1f8a51218827168cdclaireho        res += "AboveForm ";
11725569331642446be05292e3e1f8a51218827168cdclaireho    if (properties & HalfFormProperty)
11735569331642446be05292e3e1f8a51218827168cdclaireho        res += "HalfForm ";
11745569331642446be05292e3e1f8a51218827168cdclaireho    if (properties & PostFormProperty)
11755569331642446be05292e3e1f8a51218827168cdclaireho        res += "PostForm ";
117657e6107a9d66a9a97b146def0ef38c010f954be6claireho    if (properties & ConjunctFormProperty)
117757e6107a9d66a9a97b146def0ef38c010f954be6claireho        res += "PostForm ";
11785569331642446be05292e3e1f8a51218827168cdclaireho    if (properties & VattuProperty)
11795569331642446be05292e3e1f8a51218827168cdclaireho        res += "Vattu ";
11805569331642446be05292e3e1f8a51218827168cdclaireho    if (properties & PreSubstProperty)
11815569331642446be05292e3e1f8a51218827168cdclaireho        res += "PreSubst ";
11825569331642446be05292e3e1f8a51218827168cdclaireho    if (properties & BelowSubstProperty)
11835569331642446be05292e3e1f8a51218827168cdclaireho        res += "BelowSubst ";
11845569331642446be05292e3e1f8a51218827168cdclaireho    if (properties & AboveSubstProperty)
11855569331642446be05292e3e1f8a51218827168cdclaireho        res += "AboveSubst ";
11865569331642446be05292e3e1f8a51218827168cdclaireho    if (properties & PostSubstProperty)
11875569331642446be05292e3e1f8a51218827168cdclaireho        res += "PostSubst ";
11885569331642446be05292e3e1f8a51218827168cdclaireho    if (properties & HalantProperty)
11895569331642446be05292e3e1f8a51218827168cdclaireho        res += "Halant ";
11905569331642446be05292e3e1f8a51218827168cdclaireho    if (properties & CligProperty)
11915569331642446be05292e3e1f8a51218827168cdclaireho        res += "Clig ";
119257e6107a9d66a9a97b146def0ef38c010f954be6claireho    if (properties & IndicCaltProperty)
119357e6107a9d66a9a97b146def0ef38c010f954be6claireho        res += "Calt ";
11945569331642446be05292e3e1f8a51218827168cdclaireho    return res;
11955569331642446be05292e3e1f8a51218827168cdclaireho}
11965569331642446be05292e3e1f8a51218827168cdclaireho#endif
11975569331642446be05292e3e1f8a51218827168cdclaireho
11985569331642446be05292e3e1f8a51218827168cdclairehostatic bool indic_shape_syllable(HB_Bool openType, HB_ShaperItem *item, bool invalid)
11995569331642446be05292e3e1f8a51218827168cdclaireho{
12005569331642446be05292e3e1f8a51218827168cdclaireho    HB_Script script = item->item.script;
12015569331642446be05292e3e1f8a51218827168cdclaireho    assert(script >= HB_Script_Devanagari && script <= HB_Script_Sinhala);
12025569331642446be05292e3e1f8a51218827168cdclaireho    const unsigned short script_base = 0x0900 + 0x80*(script-HB_Script_Devanagari);
12035569331642446be05292e3e1f8a51218827168cdclaireho    const unsigned short ra = script_base + 0x30;
12045569331642446be05292e3e1f8a51218827168cdclaireho    const unsigned short halant = script_base + 0x4d;
12055569331642446be05292e3e1f8a51218827168cdclaireho    const unsigned short nukta = script_base + 0x3c;
12065569331642446be05292e3e1f8a51218827168cdclaireho    bool control = false;
12075569331642446be05292e3e1f8a51218827168cdclaireho
12085569331642446be05292e3e1f8a51218827168cdclaireho    int len = (int)item->item.length;
12095569331642446be05292e3e1f8a51218827168cdclaireho    IDEBUG(">>>>> indic shape: from=%d, len=%d invalid=%d", item->item.pos, item->item.length, invalid);
12105569331642446be05292e3e1f8a51218827168cdclaireho
12115569331642446be05292e3e1f8a51218827168cdclaireho    if ((int)item->num_glyphs < len+4) {
12125569331642446be05292e3e1f8a51218827168cdclaireho        item->num_glyphs = len+4;
12135569331642446be05292e3e1f8a51218827168cdclaireho        return false;
12145569331642446be05292e3e1f8a51218827168cdclaireho    }
12155569331642446be05292e3e1f8a51218827168cdclaireho
12165569331642446be05292e3e1f8a51218827168cdclaireho    HB_STACKARRAY(HB_UChar16, reordered, len + 4);
12175569331642446be05292e3e1f8a51218827168cdclaireho    HB_STACKARRAY(hb_uint8, position, len + 4);
12185569331642446be05292e3e1f8a51218827168cdclaireho
12195569331642446be05292e3e1f8a51218827168cdclaireho    unsigned char properties = scriptProperties[script-HB_Script_Devanagari];
12205569331642446be05292e3e1f8a51218827168cdclaireho
12215569331642446be05292e3e1f8a51218827168cdclaireho    if (invalid) {
12225569331642446be05292e3e1f8a51218827168cdclaireho        *reordered = 0x25cc;
12235569331642446be05292e3e1f8a51218827168cdclaireho        memcpy(reordered+1, item->string + item->item.pos, len*sizeof(HB_UChar16));
12245569331642446be05292e3e1f8a51218827168cdclaireho        len++;
12255569331642446be05292e3e1f8a51218827168cdclaireho    } else {
12265569331642446be05292e3e1f8a51218827168cdclaireho        memcpy(reordered, item->string + item->item.pos, len*sizeof(HB_UChar16));
12275569331642446be05292e3e1f8a51218827168cdclaireho    }
12285569331642446be05292e3e1f8a51218827168cdclaireho    if (reordered[len-1] == 0x200c) // zero width non joiner
12295569331642446be05292e3e1f8a51218827168cdclaireho        len--;
12305569331642446be05292e3e1f8a51218827168cdclaireho
12315569331642446be05292e3e1f8a51218827168cdclaireho    int i;
12325569331642446be05292e3e1f8a51218827168cdclaireho    int base = 0;
12335569331642446be05292e3e1f8a51218827168cdclaireho    int reph = -1;
12345569331642446be05292e3e1f8a51218827168cdclaireho
12355569331642446be05292e3e1f8a51218827168cdclaireho#ifdef INDIC_DEBUG
12365569331642446be05292e3e1f8a51218827168cdclaireho    IDEBUG("original:");
12375569331642446be05292e3e1f8a51218827168cdclaireho    for (i = 0; i < len; i++) {
12385569331642446be05292e3e1f8a51218827168cdclaireho        IDEBUG("    %d: %4x", i, reordered[i]);
12395569331642446be05292e3e1f8a51218827168cdclaireho    }
12405569331642446be05292e3e1f8a51218827168cdclaireho#endif
12415569331642446be05292e3e1f8a51218827168cdclaireho
12425569331642446be05292e3e1f8a51218827168cdclaireho    if (len != 1) {
12435569331642446be05292e3e1f8a51218827168cdclaireho        HB_UChar16 *uc = reordered;
12445569331642446be05292e3e1f8a51218827168cdclaireho        bool beginsWithRa = false;
12455569331642446be05292e3e1f8a51218827168cdclaireho
12465569331642446be05292e3e1f8a51218827168cdclaireho        // Rule 1: find base consonant
12475569331642446be05292e3e1f8a51218827168cdclaireho        //
12485569331642446be05292e3e1f8a51218827168cdclaireho        // The shaping engine finds the base consonant of the
12495569331642446be05292e3e1f8a51218827168cdclaireho        // syllable, using the following algorithm: starting from the
12505569331642446be05292e3e1f8a51218827168cdclaireho        // end of the syllable, move backwards until a consonant is
12515569331642446be05292e3e1f8a51218827168cdclaireho        // found that does not have a below-base or post-base form
12525569331642446be05292e3e1f8a51218827168cdclaireho        // (post-base forms have to follow below-base forms), or
12535569331642446be05292e3e1f8a51218827168cdclaireho        // arrive at the first consonant. The consonant stopped at
12545569331642446be05292e3e1f8a51218827168cdclaireho        // will be the base.
12555569331642446be05292e3e1f8a51218827168cdclaireho        //
12565569331642446be05292e3e1f8a51218827168cdclaireho        //  * If the syllable starts with Ra + H (in a script that has
12575569331642446be05292e3e1f8a51218827168cdclaireho        //    'Reph'), Ra is excluded from candidates for base
12585569331642446be05292e3e1f8a51218827168cdclaireho        //    consonants.
12595569331642446be05292e3e1f8a51218827168cdclaireho        //
12605569331642446be05292e3e1f8a51218827168cdclaireho        // * In Kannada and Telugu, the base consonant cannot be
12615569331642446be05292e3e1f8a51218827168cdclaireho        //   farther than 3 consonants from the end of the syllable.
12625569331642446be05292e3e1f8a51218827168cdclaireho        // #### replace the HasReph property by testing if the feature exists in the font!
12635569331642446be05292e3e1f8a51218827168cdclaireho        if (form(*uc) == Consonant || (script == HB_Script_Bengali && form(*uc) == IndependentVowel)) {
12645569331642446be05292e3e1f8a51218827168cdclaireho            if ((properties & HasReph) && (len > 2) &&
12655569331642446be05292e3e1f8a51218827168cdclaireho                (*uc == ra || *uc == 0x9f0) && *(uc+1) == halant)
12665569331642446be05292e3e1f8a51218827168cdclaireho                beginsWithRa = true;
12675569331642446be05292e3e1f8a51218827168cdclaireho
12685569331642446be05292e3e1f8a51218827168cdclaireho            if (beginsWithRa && form(*(uc+2)) == Control)
12695569331642446be05292e3e1f8a51218827168cdclaireho                beginsWithRa = false;
12705569331642446be05292e3e1f8a51218827168cdclaireho
12715569331642446be05292e3e1f8a51218827168cdclaireho            base = (beginsWithRa ? 2 : 0);
12725569331642446be05292e3e1f8a51218827168cdclaireho            IDEBUG("    length = %d, beginsWithRa = %d, base=%d", len, beginsWithRa, base);
12735569331642446be05292e3e1f8a51218827168cdclaireho
12745569331642446be05292e3e1f8a51218827168cdclaireho            int lastConsonant = 0;
12755569331642446be05292e3e1f8a51218827168cdclaireho            int matra = -1;
12765569331642446be05292e3e1f8a51218827168cdclaireho            // we remember:
12775569331642446be05292e3e1f8a51218827168cdclaireho            // * the last consonant since we need it for rule 2
12785569331642446be05292e3e1f8a51218827168cdclaireho            // * the matras position for rule 3 and 4
12795569331642446be05292e3e1f8a51218827168cdclaireho
12805569331642446be05292e3e1f8a51218827168cdclaireho            // figure out possible base glyphs
12815569331642446be05292e3e1f8a51218827168cdclaireho            memset(position, 0, len);
12825569331642446be05292e3e1f8a51218827168cdclaireho            if (script == HB_Script_Devanagari || script == HB_Script_Gujarati) {
12835569331642446be05292e3e1f8a51218827168cdclaireho                bool vattu = false;
12845569331642446be05292e3e1f8a51218827168cdclaireho                for (i = base; i < len; ++i) {
12855569331642446be05292e3e1f8a51218827168cdclaireho                    position[i] = form(uc[i]);
12865569331642446be05292e3e1f8a51218827168cdclaireho                    if (position[i] == Consonant) {
12875569331642446be05292e3e1f8a51218827168cdclaireho                        lastConsonant = i;
12885569331642446be05292e3e1f8a51218827168cdclaireho                        vattu = (!vattu && uc[i] == ra);
12895569331642446be05292e3e1f8a51218827168cdclaireho                        if (vattu) {
12905569331642446be05292e3e1f8a51218827168cdclaireho                            IDEBUG("excluding vattu glyph at %d from base candidates", i);
12915569331642446be05292e3e1f8a51218827168cdclaireho                            position[i] = Vattu;
12925569331642446be05292e3e1f8a51218827168cdclaireho                        }
12935569331642446be05292e3e1f8a51218827168cdclaireho                    } else if (position[i] == Matra) {
12945569331642446be05292e3e1f8a51218827168cdclaireho                        matra = i;
12955569331642446be05292e3e1f8a51218827168cdclaireho                    }
12965569331642446be05292e3e1f8a51218827168cdclaireho                }
12975569331642446be05292e3e1f8a51218827168cdclaireho            } else {
12985569331642446be05292e3e1f8a51218827168cdclaireho                for (i = base; i < len; ++i) {
12995569331642446be05292e3e1f8a51218827168cdclaireho                    position[i] = form(uc[i]);
13005569331642446be05292e3e1f8a51218827168cdclaireho                    if (position[i] == Consonant)
13015569331642446be05292e3e1f8a51218827168cdclaireho                        lastConsonant = i;
13025569331642446be05292e3e1f8a51218827168cdclaireho                    else if (matra < 0 && position[i] == Matra)
13035569331642446be05292e3e1f8a51218827168cdclaireho                        matra = i;
13045569331642446be05292e3e1f8a51218827168cdclaireho                }
13055569331642446be05292e3e1f8a51218827168cdclaireho            }
13065569331642446be05292e3e1f8a51218827168cdclaireho            int skipped = 0;
13075569331642446be05292e3e1f8a51218827168cdclaireho            Position pos = Post;
130857e6107a9d66a9a97b146def0ef38c010f954be6claireho            for (i = len-1; i >= base; i--) {
13095569331642446be05292e3e1f8a51218827168cdclaireho                if (position[i] != Consonant && (position[i] != Control || script == HB_Script_Kannada))
13105569331642446be05292e3e1f8a51218827168cdclaireho                    continue;
13115569331642446be05292e3e1f8a51218827168cdclaireho
131257e6107a9d66a9a97b146def0ef38c010f954be6claireho                if (i < len-1 && position[i] == Control && position[i+1] == Consonant) {
131357e6107a9d66a9a97b146def0ef38c010f954be6claireho                    base = i+1;
131457e6107a9d66a9a97b146def0ef38c010f954be6claireho                    break;
131557e6107a9d66a9a97b146def0ef38c010f954be6claireho                }
131657e6107a9d66a9a97b146def0ef38c010f954be6claireho
13175569331642446be05292e3e1f8a51218827168cdclaireho                Position charPosition = indic_position(uc[i]);
13185569331642446be05292e3e1f8a51218827168cdclaireho                if (pos == Post && charPosition == Post) {
13195569331642446be05292e3e1f8a51218827168cdclaireho                    pos = Post;
13205569331642446be05292e3e1f8a51218827168cdclaireho                } else if ((pos == Post || pos == Below) && charPosition == Below) {
13215569331642446be05292e3e1f8a51218827168cdclaireho                    if (script == HB_Script_Devanagari || script == HB_Script_Gujarati)
13225569331642446be05292e3e1f8a51218827168cdclaireho                        base = i;
13235569331642446be05292e3e1f8a51218827168cdclaireho                    pos = Below;
13245569331642446be05292e3e1f8a51218827168cdclaireho                } else {
13255569331642446be05292e3e1f8a51218827168cdclaireho                    base = i;
13265569331642446be05292e3e1f8a51218827168cdclaireho                    break;
13275569331642446be05292e3e1f8a51218827168cdclaireho                }
13285569331642446be05292e3e1f8a51218827168cdclaireho                if (skipped == 2 && (script == HB_Script_Kannada || script == HB_Script_Telugu)) {
13295569331642446be05292e3e1f8a51218827168cdclaireho                    base = i;
13305569331642446be05292e3e1f8a51218827168cdclaireho                    break;
13315569331642446be05292e3e1f8a51218827168cdclaireho                }
13325569331642446be05292e3e1f8a51218827168cdclaireho                ++skipped;
13335569331642446be05292e3e1f8a51218827168cdclaireho            }
13345569331642446be05292e3e1f8a51218827168cdclaireho
13355569331642446be05292e3e1f8a51218827168cdclaireho            IDEBUG("    base consonant at %d skipped=%d, lastConsonant=%d", base, skipped, lastConsonant);
13365569331642446be05292e3e1f8a51218827168cdclaireho
13375569331642446be05292e3e1f8a51218827168cdclaireho            // Rule 2:
13385569331642446be05292e3e1f8a51218827168cdclaireho            //
13395569331642446be05292e3e1f8a51218827168cdclaireho            // If the base consonant is not the last one, Uniscribe
13405569331642446be05292e3e1f8a51218827168cdclaireho            // moves the halant from the base consonant to the last
13415569331642446be05292e3e1f8a51218827168cdclaireho            // one.
13425569331642446be05292e3e1f8a51218827168cdclaireho            if (lastConsonant > base) {
13435569331642446be05292e3e1f8a51218827168cdclaireho                int halantPos = 0;
13445569331642446be05292e3e1f8a51218827168cdclaireho                if (uc[base+1] == halant)
13455569331642446be05292e3e1f8a51218827168cdclaireho                    halantPos = base + 1;
13465569331642446be05292e3e1f8a51218827168cdclaireho                else if (uc[base+1] == nukta && uc[base+2] == halant)
13475569331642446be05292e3e1f8a51218827168cdclaireho                    halantPos = base + 2;
13485569331642446be05292e3e1f8a51218827168cdclaireho                if (halantPos > 0) {
13495569331642446be05292e3e1f8a51218827168cdclaireho                    IDEBUG("    moving halant from %d to %d!", base+1, lastConsonant);
13505569331642446be05292e3e1f8a51218827168cdclaireho                    for (i = halantPos; i < lastConsonant; i++)
13515569331642446be05292e3e1f8a51218827168cdclaireho                        uc[i] = uc[i+1];
13525569331642446be05292e3e1f8a51218827168cdclaireho                    uc[lastConsonant] = halant;
13535569331642446be05292e3e1f8a51218827168cdclaireho                }
13545569331642446be05292e3e1f8a51218827168cdclaireho            }
13555569331642446be05292e3e1f8a51218827168cdclaireho
13565569331642446be05292e3e1f8a51218827168cdclaireho            // Rule 3:
13575569331642446be05292e3e1f8a51218827168cdclaireho            //
13585569331642446be05292e3e1f8a51218827168cdclaireho            // If the syllable starts with Ra + H, Uniscribe moves
13595569331642446be05292e3e1f8a51218827168cdclaireho            // this combination so that it follows either:
13605569331642446be05292e3e1f8a51218827168cdclaireho
13615569331642446be05292e3e1f8a51218827168cdclaireho            // * the post-base 'matra' (if any) or the base consonant
13625569331642446be05292e3e1f8a51218827168cdclaireho            //   (in scripts that show similarity to Devanagari, i.e.,
13635569331642446be05292e3e1f8a51218827168cdclaireho            //   Devanagari, Gujarati, Bengali)
13645569331642446be05292e3e1f8a51218827168cdclaireho            // * the base consonant (other scripts)
13655569331642446be05292e3e1f8a51218827168cdclaireho            // * the end of the syllable (Kannada)
13665569331642446be05292e3e1f8a51218827168cdclaireho
13675569331642446be05292e3e1f8a51218827168cdclaireho            Position matra_position = None;
13685569331642446be05292e3e1f8a51218827168cdclaireho            if (matra > 0)
13695569331642446be05292e3e1f8a51218827168cdclaireho                matra_position = indic_position(uc[matra]);
13705569331642446be05292e3e1f8a51218827168cdclaireho            IDEBUG("    matra at %d with form %d, base=%d", matra, matra_position, base);
13715569331642446be05292e3e1f8a51218827168cdclaireho
13725569331642446be05292e3e1f8a51218827168cdclaireho            if (beginsWithRa && base != 0) {
13735569331642446be05292e3e1f8a51218827168cdclaireho                int toPos = base+1;
13745569331642446be05292e3e1f8a51218827168cdclaireho                if (toPos < len && uc[toPos] == nukta)
13755569331642446be05292e3e1f8a51218827168cdclaireho                    toPos++;
13765569331642446be05292e3e1f8a51218827168cdclaireho                if (toPos < len && uc[toPos] == halant)
13775569331642446be05292e3e1f8a51218827168cdclaireho                    toPos++;
13785569331642446be05292e3e1f8a51218827168cdclaireho                if (toPos < len && uc[toPos] == 0x200d)
13795569331642446be05292e3e1f8a51218827168cdclaireho                    toPos++;
13805569331642446be05292e3e1f8a51218827168cdclaireho                if (toPos < len-1 && uc[toPos] == ra && uc[toPos+1] == halant)
13815569331642446be05292e3e1f8a51218827168cdclaireho                    toPos += 2;
13825569331642446be05292e3e1f8a51218827168cdclaireho                if (script == HB_Script_Devanagari || script == HB_Script_Gujarati || script == HB_Script_Bengali) {
13835569331642446be05292e3e1f8a51218827168cdclaireho                    if (matra_position == Post || matra_position == Split) {
13845569331642446be05292e3e1f8a51218827168cdclaireho                        toPos = matra+1;
13855569331642446be05292e3e1f8a51218827168cdclaireho                        matra -= 2;
13865569331642446be05292e3e1f8a51218827168cdclaireho                    }
13875569331642446be05292e3e1f8a51218827168cdclaireho                } else if (script == HB_Script_Kannada) {
13885569331642446be05292e3e1f8a51218827168cdclaireho                    toPos = len;
13895569331642446be05292e3e1f8a51218827168cdclaireho                    matra -= 2;
13905569331642446be05292e3e1f8a51218827168cdclaireho                }
13915569331642446be05292e3e1f8a51218827168cdclaireho
13925569331642446be05292e3e1f8a51218827168cdclaireho                IDEBUG("moving leading ra+halant to position %d", toPos);
13935569331642446be05292e3e1f8a51218827168cdclaireho                for (i = 2; i < toPos; i++)
13945569331642446be05292e3e1f8a51218827168cdclaireho                    uc[i-2] = uc[i];
13955569331642446be05292e3e1f8a51218827168cdclaireho                uc[toPos-2] = ra;
13965569331642446be05292e3e1f8a51218827168cdclaireho                uc[toPos-1] = halant;
13975569331642446be05292e3e1f8a51218827168cdclaireho                base -= 2;
13985569331642446be05292e3e1f8a51218827168cdclaireho                if (properties & HasReph)
13995569331642446be05292e3e1f8a51218827168cdclaireho                    reph = toPos-2;
14005569331642446be05292e3e1f8a51218827168cdclaireho            }
14015569331642446be05292e3e1f8a51218827168cdclaireho
14025569331642446be05292e3e1f8a51218827168cdclaireho            // Rule 4:
14035569331642446be05292e3e1f8a51218827168cdclaireho
14045569331642446be05292e3e1f8a51218827168cdclaireho            // Uniscribe splits two- or three-part matras into their
14055569331642446be05292e3e1f8a51218827168cdclaireho            // parts. This splitting is a character-to-character
14065569331642446be05292e3e1f8a51218827168cdclaireho            // operation).
14075569331642446be05292e3e1f8a51218827168cdclaireho            //
14085569331642446be05292e3e1f8a51218827168cdclaireho            //      Uniscribe describes some moving operations for these
14095569331642446be05292e3e1f8a51218827168cdclaireho            //      matras here. For shaping however all pre matras need
14105569331642446be05292e3e1f8a51218827168cdclaireho            //      to be at the beginning of the syllable, so we just move
14115569331642446be05292e3e1f8a51218827168cdclaireho            //      them there now.
14125569331642446be05292e3e1f8a51218827168cdclaireho            if (matra_position == Split) {
14135569331642446be05292e3e1f8a51218827168cdclaireho                splitMatra(uc, matra, len);
14145569331642446be05292e3e1f8a51218827168cdclaireho                // Handle three-part matras (0xccb in Kannada)
14155569331642446be05292e3e1f8a51218827168cdclaireho                matra_position = indic_position(uc[matra]);
14165569331642446be05292e3e1f8a51218827168cdclaireho            }
14175569331642446be05292e3e1f8a51218827168cdclaireho
14185569331642446be05292e3e1f8a51218827168cdclaireho            if (matra_position == Pre) {
14195569331642446be05292e3e1f8a51218827168cdclaireho                unsigned short m = uc[matra];
14205569331642446be05292e3e1f8a51218827168cdclaireho                while (matra--)
14215569331642446be05292e3e1f8a51218827168cdclaireho                    uc[matra+1] = uc[matra];
14225569331642446be05292e3e1f8a51218827168cdclaireho                uc[0] = m;
14235569331642446be05292e3e1f8a51218827168cdclaireho                base++;
14245569331642446be05292e3e1f8a51218827168cdclaireho            }
14255569331642446be05292e3e1f8a51218827168cdclaireho        }
14265569331642446be05292e3e1f8a51218827168cdclaireho
14275569331642446be05292e3e1f8a51218827168cdclaireho        // Rule 5:
14285569331642446be05292e3e1f8a51218827168cdclaireho        //
14295569331642446be05292e3e1f8a51218827168cdclaireho        // Uniscribe classifies consonants and 'matra' parts as
14305569331642446be05292e3e1f8a51218827168cdclaireho        // pre-base, above-base (Reph), below-base or post-base. This
14315569331642446be05292e3e1f8a51218827168cdclaireho        // classification exists on the character code level and is
14325569331642446be05292e3e1f8a51218827168cdclaireho        // language-dependent, not font-dependent.
14335569331642446be05292e3e1f8a51218827168cdclaireho        for (i = 0; i < base; ++i)
14345569331642446be05292e3e1f8a51218827168cdclaireho            position[i] = Pre;
14355569331642446be05292e3e1f8a51218827168cdclaireho        position[base] = Base;
14365569331642446be05292e3e1f8a51218827168cdclaireho        for (i = base+1; i < len; ++i) {
14375569331642446be05292e3e1f8a51218827168cdclaireho            position[i] = indic_position(uc[i]);
14385569331642446be05292e3e1f8a51218827168cdclaireho            // #### replace by adjusting table
14395569331642446be05292e3e1f8a51218827168cdclaireho            if (uc[i] == nukta || uc[i] == halant)
14405569331642446be05292e3e1f8a51218827168cdclaireho                position[i] = Inherit;
14415569331642446be05292e3e1f8a51218827168cdclaireho        }
14425569331642446be05292e3e1f8a51218827168cdclaireho        if (reph > 0) {
14435569331642446be05292e3e1f8a51218827168cdclaireho            // recalculate reph, it might have changed.
14445569331642446be05292e3e1f8a51218827168cdclaireho            for (i = base+1; i < len; ++i)
14455569331642446be05292e3e1f8a51218827168cdclaireho                if (uc[i] == ra)
14465569331642446be05292e3e1f8a51218827168cdclaireho                    reph = i;
14475569331642446be05292e3e1f8a51218827168cdclaireho            position[reph] = Reph;
14485569331642446be05292e3e1f8a51218827168cdclaireho            position[reph+1] = Inherit;
14495569331642446be05292e3e1f8a51218827168cdclaireho        }
14505569331642446be05292e3e1f8a51218827168cdclaireho
14515569331642446be05292e3e1f8a51218827168cdclaireho        // all reordering happens now to the chars after the base
14525569331642446be05292e3e1f8a51218827168cdclaireho        int fixed = base+1;
14535569331642446be05292e3e1f8a51218827168cdclaireho        if (fixed < len && uc[fixed] == nukta)
14545569331642446be05292e3e1f8a51218827168cdclaireho            fixed++;
14555569331642446be05292e3e1f8a51218827168cdclaireho        if (fixed < len && uc[fixed] == halant)
14565569331642446be05292e3e1f8a51218827168cdclaireho            fixed++;
14575569331642446be05292e3e1f8a51218827168cdclaireho        if (fixed < len && uc[fixed] == 0x200d)
14585569331642446be05292e3e1f8a51218827168cdclaireho            fixed++;
14595569331642446be05292e3e1f8a51218827168cdclaireho
14605569331642446be05292e3e1f8a51218827168cdclaireho#ifdef INDIC_DEBUG
14615569331642446be05292e3e1f8a51218827168cdclaireho        for (i = fixed; i < len; ++i)
14625569331642446be05292e3e1f8a51218827168cdclaireho            IDEBUG("position[%d] = %d, form=%d uc=%x", i, position[i], form(uc[i]), uc[i]);
14635569331642446be05292e3e1f8a51218827168cdclaireho#endif
14645569331642446be05292e3e1f8a51218827168cdclaireho        // we continuosly position the matras and vowel marks and increase the fixed
14655569331642446be05292e3e1f8a51218827168cdclaireho        // until we reached the end.
14665569331642446be05292e3e1f8a51218827168cdclaireho        const IndicOrdering *finalOrder = indic_order[script-HB_Script_Devanagari];
14675569331642446be05292e3e1f8a51218827168cdclaireho
14685569331642446be05292e3e1f8a51218827168cdclaireho        IDEBUG("    reordering pass:");
14695569331642446be05292e3e1f8a51218827168cdclaireho        IDEBUG("        base=%d fixed=%d", base, fixed);
14705569331642446be05292e3e1f8a51218827168cdclaireho        int toMove = 0;
14715569331642446be05292e3e1f8a51218827168cdclaireho        while (finalOrder[toMove].form && fixed < len-1) {
14725569331642446be05292e3e1f8a51218827168cdclaireho            IDEBUG("        fixed = %d, toMove=%d, moving form %d with pos %d", fixed, toMove, finalOrder[toMove].form, finalOrder[toMove].position);
14735569331642446be05292e3e1f8a51218827168cdclaireho            for (i = fixed; i < len; i++) {
14745569331642446be05292e3e1f8a51218827168cdclaireho//                IDEBUG() << "           i=" << i << "uc=" << hex << uc[i] << "form=" << form(uc[i])
14755569331642446be05292e3e1f8a51218827168cdclaireho//                         << "position=" << position[i];
14765569331642446be05292e3e1f8a51218827168cdclaireho                if (form(uc[i]) == finalOrder[toMove].form &&
14775569331642446be05292e3e1f8a51218827168cdclaireho                     position[i] == finalOrder[toMove].position) {
14785569331642446be05292e3e1f8a51218827168cdclaireho                    // need to move this glyph
14795569331642446be05292e3e1f8a51218827168cdclaireho                    int to = fixed;
14805569331642446be05292e3e1f8a51218827168cdclaireho                    if (i < len-1 && position[i+1] == Inherit) {
14815569331642446be05292e3e1f8a51218827168cdclaireho                        IDEBUG("         moving two chars from %d to %d", i, to);
14825569331642446be05292e3e1f8a51218827168cdclaireho                        unsigned short ch = uc[i];
14835569331642446be05292e3e1f8a51218827168cdclaireho                        unsigned short ch2 = uc[i+1];
14845569331642446be05292e3e1f8a51218827168cdclaireho                        unsigned char pos = position[i];
14855569331642446be05292e3e1f8a51218827168cdclaireho                        for (int j = i+1; j > to+1; j--) {
14865569331642446be05292e3e1f8a51218827168cdclaireho                            uc[j] = uc[j-2];
14875569331642446be05292e3e1f8a51218827168cdclaireho                            position[j] = position[j-2];
14885569331642446be05292e3e1f8a51218827168cdclaireho                        }
14895569331642446be05292e3e1f8a51218827168cdclaireho                        uc[to] = ch;
14905569331642446be05292e3e1f8a51218827168cdclaireho                        uc[to+1] = ch2;
14915569331642446be05292e3e1f8a51218827168cdclaireho                        position[to] = pos;
14925569331642446be05292e3e1f8a51218827168cdclaireho                        position[to+1] = pos;
14935569331642446be05292e3e1f8a51218827168cdclaireho                        fixed += 2;
14945569331642446be05292e3e1f8a51218827168cdclaireho                    } else {
14955569331642446be05292e3e1f8a51218827168cdclaireho                        IDEBUG("         moving one char from %d to %d", i, to);
14965569331642446be05292e3e1f8a51218827168cdclaireho                        unsigned short ch = uc[i];
14975569331642446be05292e3e1f8a51218827168cdclaireho                        unsigned char pos = position[i];
14985569331642446be05292e3e1f8a51218827168cdclaireho                        for (int j = i; j > to; j--) {
14995569331642446be05292e3e1f8a51218827168cdclaireho                            uc[j] = uc[j-1];
15005569331642446be05292e3e1f8a51218827168cdclaireho                            position[j] = position[j-1];
15015569331642446be05292e3e1f8a51218827168cdclaireho                        }
15025569331642446be05292e3e1f8a51218827168cdclaireho                        uc[to] = ch;
15035569331642446be05292e3e1f8a51218827168cdclaireho                        position[to] = pos;
15045569331642446be05292e3e1f8a51218827168cdclaireho                        fixed++;
15055569331642446be05292e3e1f8a51218827168cdclaireho                    }
15065569331642446be05292e3e1f8a51218827168cdclaireho                }
15075569331642446be05292e3e1f8a51218827168cdclaireho            }
15085569331642446be05292e3e1f8a51218827168cdclaireho            toMove++;
15095569331642446be05292e3e1f8a51218827168cdclaireho        }
15105569331642446be05292e3e1f8a51218827168cdclaireho
15115569331642446be05292e3e1f8a51218827168cdclaireho    }
15125569331642446be05292e3e1f8a51218827168cdclaireho
15135569331642446be05292e3e1f8a51218827168cdclaireho    if (reph > 0) {
15145569331642446be05292e3e1f8a51218827168cdclaireho        // recalculate reph, it might have changed.
15155569331642446be05292e3e1f8a51218827168cdclaireho        for (i = base+1; i < len; ++i)
15165569331642446be05292e3e1f8a51218827168cdclaireho            if (reordered[i] == ra)
15175569331642446be05292e3e1f8a51218827168cdclaireho                reph = i;
15185569331642446be05292e3e1f8a51218827168cdclaireho    }
15195569331642446be05292e3e1f8a51218827168cdclaireho
15205569331642446be05292e3e1f8a51218827168cdclaireho#ifndef NO_OPENTYPE
15215569331642446be05292e3e1f8a51218827168cdclaireho    const int availableGlyphs = item->num_glyphs;
15225569331642446be05292e3e1f8a51218827168cdclaireho#endif
15235569331642446be05292e3e1f8a51218827168cdclaireho    if (!item->font->klass->convertStringToGlyphIndices(item->font,
15245569331642446be05292e3e1f8a51218827168cdclaireho                                                        reordered, len,
15255569331642446be05292e3e1f8a51218827168cdclaireho                                                        item->glyphs, &item->num_glyphs,
15265569331642446be05292e3e1f8a51218827168cdclaireho                                                        item->item.bidiLevel % 2))
15275569331642446be05292e3e1f8a51218827168cdclaireho        goto error;
15285569331642446be05292e3e1f8a51218827168cdclaireho
15295569331642446be05292e3e1f8a51218827168cdclaireho
15305569331642446be05292e3e1f8a51218827168cdclaireho    IDEBUG("  base=%d, reph=%d", base, reph);
15315569331642446be05292e3e1f8a51218827168cdclaireho    IDEBUG("reordered:");
15325569331642446be05292e3e1f8a51218827168cdclaireho    for (i = 0; i < len; i++) {
15335569331642446be05292e3e1f8a51218827168cdclaireho        item->attributes[i].mark = false;
15345569331642446be05292e3e1f8a51218827168cdclaireho        item->attributes[i].clusterStart = false;
15355569331642446be05292e3e1f8a51218827168cdclaireho        item->attributes[i].justification = 0;
15365569331642446be05292e3e1f8a51218827168cdclaireho        item->attributes[i].zeroWidth = false;
15375569331642446be05292e3e1f8a51218827168cdclaireho        IDEBUG("    %d: %4x", i, reordered[i]);
15385569331642446be05292e3e1f8a51218827168cdclaireho    }
15395569331642446be05292e3e1f8a51218827168cdclaireho
15405569331642446be05292e3e1f8a51218827168cdclaireho    // now we have the syllable in the right order, and can start running it through open type.
15415569331642446be05292e3e1f8a51218827168cdclaireho
15425569331642446be05292e3e1f8a51218827168cdclaireho    for (i = 0; i < len; ++i)
15435569331642446be05292e3e1f8a51218827168cdclaireho        control |= (form(reordered[i]) == Control);
15445569331642446be05292e3e1f8a51218827168cdclaireho
15455569331642446be05292e3e1f8a51218827168cdclaireho#ifndef NO_OPENTYPE
15465569331642446be05292e3e1f8a51218827168cdclaireho    if (openType) {
15475569331642446be05292e3e1f8a51218827168cdclaireho
15485569331642446be05292e3e1f8a51218827168cdclaireho        // we need to keep track of where the base glyph is for some
15495569331642446be05292e3e1f8a51218827168cdclaireho        // scripts and use the cluster feature for this.  This
15505569331642446be05292e3e1f8a51218827168cdclaireho        // also means we have to correct the logCluster output from
15515569331642446be05292e3e1f8a51218827168cdclaireho        // the open type engine manually afterwards.  for indic this
15525569331642446be05292e3e1f8a51218827168cdclaireho        // is rather simple, as all chars just point to the first
15535569331642446be05292e3e1f8a51218827168cdclaireho        // glyph in the syllable.
15545569331642446be05292e3e1f8a51218827168cdclaireho        HB_STACKARRAY(unsigned short, clusters, len);
15555569331642446be05292e3e1f8a51218827168cdclaireho        HB_STACKARRAY(unsigned int, properties, len);
15565569331642446be05292e3e1f8a51218827168cdclaireho
15575569331642446be05292e3e1f8a51218827168cdclaireho        for (i = 0; i < len; ++i)
15585569331642446be05292e3e1f8a51218827168cdclaireho            clusters[i] = i;
15595569331642446be05292e3e1f8a51218827168cdclaireho
15605569331642446be05292e3e1f8a51218827168cdclaireho        // features we should always apply
15615569331642446be05292e3e1f8a51218827168cdclaireho        for (i = 0; i < len; ++i)
156257e6107a9d66a9a97b146def0ef38c010f954be6claireho            properties[i] = ~(LocaProperty
156357e6107a9d66a9a97b146def0ef38c010f954be6claireho                              | CcmpProperty
15645569331642446be05292e3e1f8a51218827168cdclaireho                              | NuktaProperty
15655569331642446be05292e3e1f8a51218827168cdclaireho                              | VattuProperty
156657e6107a9d66a9a97b146def0ef38c010f954be6claireho                              | ConjunctFormProperty
15675569331642446be05292e3e1f8a51218827168cdclaireho                              | PreSubstProperty
15685569331642446be05292e3e1f8a51218827168cdclaireho                              | BelowSubstProperty
15695569331642446be05292e3e1f8a51218827168cdclaireho                              | AboveSubstProperty
15705569331642446be05292e3e1f8a51218827168cdclaireho                              | PostSubstProperty
15715569331642446be05292e3e1f8a51218827168cdclaireho                              | HalantProperty
157257e6107a9d66a9a97b146def0ef38c010f954be6claireho                              | IndicCaltProperty
15735569331642446be05292e3e1f8a51218827168cdclaireho                              | PositioningProperties);
15745569331642446be05292e3e1f8a51218827168cdclaireho
157557e6107a9d66a9a97b146def0ef38c010f954be6claireho        // Loca always applies
15765569331642446be05292e3e1f8a51218827168cdclaireho        // Ccmp always applies
15775569331642446be05292e3e1f8a51218827168cdclaireho        // Init
15785569331642446be05292e3e1f8a51218827168cdclaireho        if (item->item.pos == 0
15795569331642446be05292e3e1f8a51218827168cdclaireho            || !(isLetter(item->string[item->item.pos-1]) || isMark(item->string[item->item.pos-1])))
15805569331642446be05292e3e1f8a51218827168cdclaireho            properties[0] &= ~InitProperty;
15815569331642446be05292e3e1f8a51218827168cdclaireho
15825569331642446be05292e3e1f8a51218827168cdclaireho        // Nukta always applies
15835569331642446be05292e3e1f8a51218827168cdclaireho        // Akhant
15845569331642446be05292e3e1f8a51218827168cdclaireho        for (i = 0; i <= base; ++i)
15855569331642446be05292e3e1f8a51218827168cdclaireho            properties[i] &= ~AkhantProperty;
15865569331642446be05292e3e1f8a51218827168cdclaireho        // Reph
15875569331642446be05292e3e1f8a51218827168cdclaireho        if (reph >= 0) {
15885569331642446be05292e3e1f8a51218827168cdclaireho            properties[reph] &= ~RephProperty;
15895569331642446be05292e3e1f8a51218827168cdclaireho            properties[reph+1] &= ~RephProperty;
15905569331642446be05292e3e1f8a51218827168cdclaireho        }
15915569331642446be05292e3e1f8a51218827168cdclaireho        // BelowForm
15925569331642446be05292e3e1f8a51218827168cdclaireho        for (i = base+1; i < len; ++i)
15935569331642446be05292e3e1f8a51218827168cdclaireho            properties[i] &= ~BelowFormProperty;
15945569331642446be05292e3e1f8a51218827168cdclaireho
15955569331642446be05292e3e1f8a51218827168cdclaireho        if (script == HB_Script_Devanagari || script == HB_Script_Gujarati) {
15965569331642446be05292e3e1f8a51218827168cdclaireho            // vattu glyphs need this aswell
15975569331642446be05292e3e1f8a51218827168cdclaireho            bool vattu = false;
15985569331642446be05292e3e1f8a51218827168cdclaireho            for (i = base-2; i > 1; --i) {
15995569331642446be05292e3e1f8a51218827168cdclaireho                if (form(reordered[i]) == Consonant) {
16005569331642446be05292e3e1f8a51218827168cdclaireho                    vattu = (!vattu && reordered[i] == ra);
16015569331642446be05292e3e1f8a51218827168cdclaireho                    if (vattu) {
16025569331642446be05292e3e1f8a51218827168cdclaireho                        IDEBUG("forming vattu ligature at %d", i);
16035569331642446be05292e3e1f8a51218827168cdclaireho                        properties[i] &= ~BelowFormProperty;
16045569331642446be05292e3e1f8a51218827168cdclaireho                        properties[i+1] &= ~BelowFormProperty;
16055569331642446be05292e3e1f8a51218827168cdclaireho                    }
16065569331642446be05292e3e1f8a51218827168cdclaireho                }
16075569331642446be05292e3e1f8a51218827168cdclaireho            }
16085569331642446be05292e3e1f8a51218827168cdclaireho        }
16095569331642446be05292e3e1f8a51218827168cdclaireho        // HalfFormProperty
16105569331642446be05292e3e1f8a51218827168cdclaireho        for (i = 0; i < base; ++i)
16115569331642446be05292e3e1f8a51218827168cdclaireho            properties[i] &= ~HalfFormProperty;
16125569331642446be05292e3e1f8a51218827168cdclaireho        if (control) {
16135569331642446be05292e3e1f8a51218827168cdclaireho            for (i = 2; i < len; ++i) {
16145569331642446be05292e3e1f8a51218827168cdclaireho                if (reordered[i] == 0x200d /* ZWJ */) {
16155569331642446be05292e3e1f8a51218827168cdclaireho                    properties[i-1] &= ~HalfFormProperty;
16165569331642446be05292e3e1f8a51218827168cdclaireho                    properties[i-2] &= ~HalfFormProperty;
16175569331642446be05292e3e1f8a51218827168cdclaireho                } else if (reordered[i] == 0x200c /* ZWNJ */) {
16185569331642446be05292e3e1f8a51218827168cdclaireho                    properties[i-1] &= ~HalfFormProperty;
16195569331642446be05292e3e1f8a51218827168cdclaireho                    properties[i-2] &= ~HalfFormProperty;
16205569331642446be05292e3e1f8a51218827168cdclaireho                }
16215569331642446be05292e3e1f8a51218827168cdclaireho            }
16225569331642446be05292e3e1f8a51218827168cdclaireho        }
16235569331642446be05292e3e1f8a51218827168cdclaireho        // PostFormProperty
16245569331642446be05292e3e1f8a51218827168cdclaireho        for (i = base+1; i < len; ++i)
16255569331642446be05292e3e1f8a51218827168cdclaireho            properties[i] &= ~PostFormProperty;
16265569331642446be05292e3e1f8a51218827168cdclaireho        // vattu always applies
16275569331642446be05292e3e1f8a51218827168cdclaireho        // pres always applies
16285569331642446be05292e3e1f8a51218827168cdclaireho        // blws always applies
16295569331642446be05292e3e1f8a51218827168cdclaireho        // abvs always applies
16305569331642446be05292e3e1f8a51218827168cdclaireho        // psts always applies
16315569331642446be05292e3e1f8a51218827168cdclaireho        // halant always applies
163257e6107a9d66a9a97b146def0ef38c010f954be6claireho        // calt always applies
16335569331642446be05292e3e1f8a51218827168cdclaireho
16345569331642446be05292e3e1f8a51218827168cdclaireho#ifdef INDIC_DEBUG
16355569331642446be05292e3e1f8a51218827168cdclaireho//        {
16365569331642446be05292e3e1f8a51218827168cdclaireho//            IDEBUG("OT properties:");
16375569331642446be05292e3e1f8a51218827168cdclaireho//            for (int i = 0; i < len; ++i)
16385569331642446be05292e3e1f8a51218827168cdclaireho//                qDebug("    i: %s", ::propertiesToString(properties[i]).toLatin1().data());
16395569331642446be05292e3e1f8a51218827168cdclaireho//        }
16405569331642446be05292e3e1f8a51218827168cdclaireho#endif
16415569331642446be05292e3e1f8a51218827168cdclaireho
16425569331642446be05292e3e1f8a51218827168cdclaireho        // initialize
16435569331642446be05292e3e1f8a51218827168cdclaireho        item->log_clusters = clusters;
16445569331642446be05292e3e1f8a51218827168cdclaireho        HB_OpenTypeShape(item, properties);
16455569331642446be05292e3e1f8a51218827168cdclaireho
16465569331642446be05292e3e1f8a51218827168cdclaireho        int newLen = item->face->buffer->in_length;
16475569331642446be05292e3e1f8a51218827168cdclaireho        HB_GlyphItem otl_glyphs = item->face->buffer->in_string;
16485569331642446be05292e3e1f8a51218827168cdclaireho
16495569331642446be05292e3e1f8a51218827168cdclaireho        // move the left matra back to its correct position in malayalam and tamil
16505569331642446be05292e3e1f8a51218827168cdclaireho        if ((script == HB_Script_Malayalam || script == HB_Script_Tamil) && (form(reordered[0]) == Matra)) {
16515569331642446be05292e3e1f8a51218827168cdclaireho//             qDebug("reordering matra, len=%d", newLen);
16525569331642446be05292e3e1f8a51218827168cdclaireho            // need to find the base in the shaped string and move the matra there
16535569331642446be05292e3e1f8a51218827168cdclaireho            int basePos = 0;
16545569331642446be05292e3e1f8a51218827168cdclaireho            while (basePos < newLen && (int)otl_glyphs[basePos].cluster <= base)
16555569331642446be05292e3e1f8a51218827168cdclaireho                basePos++;
16565569331642446be05292e3e1f8a51218827168cdclaireho            --basePos;
16575569331642446be05292e3e1f8a51218827168cdclaireho            if (basePos < newLen && basePos > 1) {
16585569331642446be05292e3e1f8a51218827168cdclaireho//                 qDebug("moving prebase matra to position %d in syllable newlen=%d", basePos, newLen);
16595569331642446be05292e3e1f8a51218827168cdclaireho                HB_GlyphItemRec m = otl_glyphs[0];
16605569331642446be05292e3e1f8a51218827168cdclaireho                --basePos;
16615569331642446be05292e3e1f8a51218827168cdclaireho                for (i = 0; i < basePos; ++i)
16625569331642446be05292e3e1f8a51218827168cdclaireho                    otl_glyphs[i] = otl_glyphs[i+1];
16635569331642446be05292e3e1f8a51218827168cdclaireho                otl_glyphs[basePos] = m;
16645569331642446be05292e3e1f8a51218827168cdclaireho            }
16655569331642446be05292e3e1f8a51218827168cdclaireho        }
16665569331642446be05292e3e1f8a51218827168cdclaireho
16675569331642446be05292e3e1f8a51218827168cdclaireho        HB_Bool positioned = HB_OpenTypePosition(item, availableGlyphs, false);
16685569331642446be05292e3e1f8a51218827168cdclaireho
16695569331642446be05292e3e1f8a51218827168cdclaireho        HB_FREE_STACKARRAY(clusters);
16705569331642446be05292e3e1f8a51218827168cdclaireho        HB_FREE_STACKARRAY(properties);
16715569331642446be05292e3e1f8a51218827168cdclaireho
16725569331642446be05292e3e1f8a51218827168cdclaireho        if (!positioned)
16735569331642446be05292e3e1f8a51218827168cdclaireho            goto error;
16745569331642446be05292e3e1f8a51218827168cdclaireho
16755569331642446be05292e3e1f8a51218827168cdclaireho        if (control) {
16765569331642446be05292e3e1f8a51218827168cdclaireho            IDEBUG("found a control char in the syllable");
16775569331642446be05292e3e1f8a51218827168cdclaireho            hb_uint32 i = 0, j = 0;
16785569331642446be05292e3e1f8a51218827168cdclaireho            while (i < item->num_glyphs) {
16795569331642446be05292e3e1f8a51218827168cdclaireho                if (form(reordered[otl_glyphs[i].cluster]) == Control) {
16805569331642446be05292e3e1f8a51218827168cdclaireho                    ++i;
16815569331642446be05292e3e1f8a51218827168cdclaireho                    if (i >= item->num_glyphs)
16825569331642446be05292e3e1f8a51218827168cdclaireho                        break;
16835569331642446be05292e3e1f8a51218827168cdclaireho                }
16845569331642446be05292e3e1f8a51218827168cdclaireho                item->glyphs[j] = item->glyphs[i];
16855569331642446be05292e3e1f8a51218827168cdclaireho                item->attributes[j] = item->attributes[i];
16865569331642446be05292e3e1f8a51218827168cdclaireho                ++i;
16875569331642446be05292e3e1f8a51218827168cdclaireho                ++j;
16885569331642446be05292e3e1f8a51218827168cdclaireho            }
16895569331642446be05292e3e1f8a51218827168cdclaireho            item->num_glyphs = j;
16905569331642446be05292e3e1f8a51218827168cdclaireho        }
16915569331642446be05292e3e1f8a51218827168cdclaireho
16925569331642446be05292e3e1f8a51218827168cdclaireho    } else {
16935569331642446be05292e3e1f8a51218827168cdclaireho        HB_HeuristicPosition(item);
16945569331642446be05292e3e1f8a51218827168cdclaireho    }
16955569331642446be05292e3e1f8a51218827168cdclaireho#endif // NO_OPENTYPE
16965569331642446be05292e3e1f8a51218827168cdclaireho    item->attributes[0].clusterStart = true;
16975569331642446be05292e3e1f8a51218827168cdclaireho
16985569331642446be05292e3e1f8a51218827168cdclaireho    HB_FREE_STACKARRAY(reordered);
16995569331642446be05292e3e1f8a51218827168cdclaireho    HB_FREE_STACKARRAY(position);
17005569331642446be05292e3e1f8a51218827168cdclaireho
17015569331642446be05292e3e1f8a51218827168cdclaireho    IDEBUG("<<<<<<");
17025569331642446be05292e3e1f8a51218827168cdclaireho    return true;
17035569331642446be05292e3e1f8a51218827168cdclaireho
17045569331642446be05292e3e1f8a51218827168cdclairehoerror:
17055569331642446be05292e3e1f8a51218827168cdclaireho    HB_FREE_STACKARRAY(reordered);
17065569331642446be05292e3e1f8a51218827168cdclaireho    HB_FREE_STACKARRAY(position);
17075569331642446be05292e3e1f8a51218827168cdclaireho    return false;
17085569331642446be05292e3e1f8a51218827168cdclaireho}
17095569331642446be05292e3e1f8a51218827168cdclaireho
17105569331642446be05292e3e1f8a51218827168cdclaireho/* syllables are of the form:
17115569331642446be05292e3e1f8a51218827168cdclaireho
17125569331642446be05292e3e1f8a51218827168cdclaireho   (Consonant Nukta? Halant)* Consonant Matra? VowelMark? StressMark?
17135569331642446be05292e3e1f8a51218827168cdclaireho   (Consonant Nukta? Halant)* Consonant Halant
17145569331642446be05292e3e1f8a51218827168cdclaireho   IndependentVowel VowelMark? StressMark?
17155569331642446be05292e3e1f8a51218827168cdclaireho
17165569331642446be05292e3e1f8a51218827168cdclaireho   We return syllable boundaries on invalid combinations aswell
17175569331642446be05292e3e1f8a51218827168cdclaireho*/
17185569331642446be05292e3e1f8a51218827168cdclairehostatic int indic_nextSyllableBoundary(HB_Script script, const HB_UChar16 *s, int start, int end, bool *invalid)
17195569331642446be05292e3e1f8a51218827168cdclaireho{
17205569331642446be05292e3e1f8a51218827168cdclaireho    *invalid = false;
17215569331642446be05292e3e1f8a51218827168cdclaireho    IDEBUG("indic_nextSyllableBoundary: start=%d, end=%d", start, end);
17225569331642446be05292e3e1f8a51218827168cdclaireho    const HB_UChar16 *uc = s+start;
17235569331642446be05292e3e1f8a51218827168cdclaireho
17245569331642446be05292e3e1f8a51218827168cdclaireho    int pos = 0;
17255569331642446be05292e3e1f8a51218827168cdclaireho    Form state = form(uc[pos]);
17265569331642446be05292e3e1f8a51218827168cdclaireho    IDEBUG("state[%d]=%d (uc=%4x)", pos, state, uc[pos]);
17275569331642446be05292e3e1f8a51218827168cdclaireho    pos++;
17285569331642446be05292e3e1f8a51218827168cdclaireho
17295569331642446be05292e3e1f8a51218827168cdclaireho    if (state != Consonant && state != IndependentVowel) {
17305569331642446be05292e3e1f8a51218827168cdclaireho        if (state != Other)
17315569331642446be05292e3e1f8a51218827168cdclaireho            *invalid = true;
17325569331642446be05292e3e1f8a51218827168cdclaireho        goto finish;
17335569331642446be05292e3e1f8a51218827168cdclaireho    }
17345569331642446be05292e3e1f8a51218827168cdclaireho
17355569331642446be05292e3e1f8a51218827168cdclaireho    while (pos < end - start) {
17365569331642446be05292e3e1f8a51218827168cdclaireho        Form newState = form(uc[pos]);
17375569331642446be05292e3e1f8a51218827168cdclaireho        IDEBUG("state[%d]=%d (uc=%4x)", pos, newState, uc[pos]);
17385569331642446be05292e3e1f8a51218827168cdclaireho        switch(newState) {
17395569331642446be05292e3e1f8a51218827168cdclaireho        case Control:
17405569331642446be05292e3e1f8a51218827168cdclaireho            newState = state;
17415569331642446be05292e3e1f8a51218827168cdclaireho 	    if (state == Halant && uc[pos] == 0x200d /* ZWJ */)
17425569331642446be05292e3e1f8a51218827168cdclaireho  		break;
17435569331642446be05292e3e1f8a51218827168cdclaireho            // the control character should be the last char in the item
17445569331642446be05292e3e1f8a51218827168cdclaireho            ++pos;
17455569331642446be05292e3e1f8a51218827168cdclaireho            goto finish;
17465569331642446be05292e3e1f8a51218827168cdclaireho        case Consonant:
17475569331642446be05292e3e1f8a51218827168cdclaireho	    if (state == Halant && (script != HB_Script_Sinhala || uc[pos-1] == 0x200d /* ZWJ */))
17485569331642446be05292e3e1f8a51218827168cdclaireho                break;
17495569331642446be05292e3e1f8a51218827168cdclaireho            goto finish;
17505569331642446be05292e3e1f8a51218827168cdclaireho        case Halant:
17515569331642446be05292e3e1f8a51218827168cdclaireho            if (state == Nukta || state == Consonant)
17525569331642446be05292e3e1f8a51218827168cdclaireho                break;
17535569331642446be05292e3e1f8a51218827168cdclaireho            // Bengali has a special exception allowing the combination Vowel_A/E + Halant + Ya
17545569331642446be05292e3e1f8a51218827168cdclaireho            if (script == HB_Script_Bengali && pos == 1 &&
17555569331642446be05292e3e1f8a51218827168cdclaireho                 (uc[0] == 0x0985 || uc[0] == 0x098f))
17565569331642446be05292e3e1f8a51218827168cdclaireho                break;
17575569331642446be05292e3e1f8a51218827168cdclaireho            // Sinhala uses the Halant as a component of certain matras. Allow these, but keep the state on Matra.
17585569331642446be05292e3e1f8a51218827168cdclaireho            if (script == HB_Script_Sinhala && state == Matra) {
17595569331642446be05292e3e1f8a51218827168cdclaireho                ++pos;
17605569331642446be05292e3e1f8a51218827168cdclaireho                continue;
17615569331642446be05292e3e1f8a51218827168cdclaireho            }
17625569331642446be05292e3e1f8a51218827168cdclaireho            if (script == HB_Script_Malayalam && state == Matra && uc[pos-1] == 0x0d41) {
17635569331642446be05292e3e1f8a51218827168cdclaireho                ++pos;
17645569331642446be05292e3e1f8a51218827168cdclaireho                continue;
17655569331642446be05292e3e1f8a51218827168cdclaireho            }
17665569331642446be05292e3e1f8a51218827168cdclaireho            goto finish;
17675569331642446be05292e3e1f8a51218827168cdclaireho        case Nukta:
17685569331642446be05292e3e1f8a51218827168cdclaireho            if (state == Consonant)
17695569331642446be05292e3e1f8a51218827168cdclaireho                break;
17705569331642446be05292e3e1f8a51218827168cdclaireho            goto finish;
17715569331642446be05292e3e1f8a51218827168cdclaireho        case StressMark:
17725569331642446be05292e3e1f8a51218827168cdclaireho            if (state == VowelMark)
17735569331642446be05292e3e1f8a51218827168cdclaireho                break;
17745569331642446be05292e3e1f8a51218827168cdclaireho            // fall through
17755569331642446be05292e3e1f8a51218827168cdclaireho        case VowelMark:
17765569331642446be05292e3e1f8a51218827168cdclaireho            if (state == Matra || state == LengthMark || state == IndependentVowel)
17775569331642446be05292e3e1f8a51218827168cdclaireho                break;
17785569331642446be05292e3e1f8a51218827168cdclaireho            // fall through
17795569331642446be05292e3e1f8a51218827168cdclaireho        case Matra:
17805569331642446be05292e3e1f8a51218827168cdclaireho            if (state == Consonant || state == Nukta)
17815569331642446be05292e3e1f8a51218827168cdclaireho                break;
17825569331642446be05292e3e1f8a51218827168cdclaireho            if (state == Matra) {
17835569331642446be05292e3e1f8a51218827168cdclaireho                // ### needs proper testing for correct two/three part matras
17845569331642446be05292e3e1f8a51218827168cdclaireho                break;
17855569331642446be05292e3e1f8a51218827168cdclaireho            }
17865569331642446be05292e3e1f8a51218827168cdclaireho            // ### not sure if this is correct. If it is, does it apply only to Bengali or should
17875569331642446be05292e3e1f8a51218827168cdclaireho            // it work for all Indic languages?
17885569331642446be05292e3e1f8a51218827168cdclaireho            // the combination Independent_A + Vowel Sign AA is allowed.
17895569331642446be05292e3e1f8a51218827168cdclaireho            if (script == HB_Script_Bengali && uc[pos] == 0x9be && uc[pos-1] == 0x985)
17905569331642446be05292e3e1f8a51218827168cdclaireho                break;
17915569331642446be05292e3e1f8a51218827168cdclaireho            if (script == HB_Script_Tamil && state == Matra) {
17925569331642446be05292e3e1f8a51218827168cdclaireho                if (uc[pos-1] == 0x0bc6 &&
17935569331642446be05292e3e1f8a51218827168cdclaireho                     (uc[pos] == 0xbbe || uc[pos] == 0xbd7))
17945569331642446be05292e3e1f8a51218827168cdclaireho                    break;
17955569331642446be05292e3e1f8a51218827168cdclaireho                if (uc[pos-1] == 0x0bc7 && uc[pos] == 0xbbe)
17965569331642446be05292e3e1f8a51218827168cdclaireho                    break;
17975569331642446be05292e3e1f8a51218827168cdclaireho            }
17985569331642446be05292e3e1f8a51218827168cdclaireho            goto finish;
17995569331642446be05292e3e1f8a51218827168cdclaireho
18005569331642446be05292e3e1f8a51218827168cdclaireho        case LengthMark:
18015569331642446be05292e3e1f8a51218827168cdclaireho            if (state == Matra) {
18025569331642446be05292e3e1f8a51218827168cdclaireho                // ### needs proper testing for correct two/three part matras
18035569331642446be05292e3e1f8a51218827168cdclaireho                break;
18045569331642446be05292e3e1f8a51218827168cdclaireho            }
18055569331642446be05292e3e1f8a51218827168cdclaireho        case IndependentVowel:
18065569331642446be05292e3e1f8a51218827168cdclaireho        case Invalid:
18075569331642446be05292e3e1f8a51218827168cdclaireho        case Other:
18085569331642446be05292e3e1f8a51218827168cdclaireho            goto finish;
18095569331642446be05292e3e1f8a51218827168cdclaireho        }
18105569331642446be05292e3e1f8a51218827168cdclaireho        state = newState;
18115569331642446be05292e3e1f8a51218827168cdclaireho        pos++;
18125569331642446be05292e3e1f8a51218827168cdclaireho    }
18135569331642446be05292e3e1f8a51218827168cdclaireho finish:
18145569331642446be05292e3e1f8a51218827168cdclaireho    return pos+start;
18155569331642446be05292e3e1f8a51218827168cdclaireho}
18165569331642446be05292e3e1f8a51218827168cdclaireho
18175569331642446be05292e3e1f8a51218827168cdclairehoHB_Bool HB_IndicShape(HB_ShaperItem *item)
18185569331642446be05292e3e1f8a51218827168cdclaireho{
18195569331642446be05292e3e1f8a51218827168cdclaireho    assert(item->item.script >= HB_Script_Devanagari && item->item.script <= HB_Script_Sinhala);
18205569331642446be05292e3e1f8a51218827168cdclaireho
18215569331642446be05292e3e1f8a51218827168cdclaireho    HB_Bool openType = false;
18225569331642446be05292e3e1f8a51218827168cdclaireho#ifndef NO_OPENTYPE
18235569331642446be05292e3e1f8a51218827168cdclaireho    openType = HB_SelectScript(item, indic_features);
18245569331642446be05292e3e1f8a51218827168cdclaireho#endif
18255569331642446be05292e3e1f8a51218827168cdclaireho    unsigned short *logClusters = item->log_clusters;
18265569331642446be05292e3e1f8a51218827168cdclaireho
18275569331642446be05292e3e1f8a51218827168cdclaireho    HB_ShaperItem syllable = *item;
18285569331642446be05292e3e1f8a51218827168cdclaireho    int first_glyph = 0;
18295569331642446be05292e3e1f8a51218827168cdclaireho
18305569331642446be05292e3e1f8a51218827168cdclaireho    int sstart = item->item.pos;
18315569331642446be05292e3e1f8a51218827168cdclaireho    int end = sstart + item->item.length;
18325569331642446be05292e3e1f8a51218827168cdclaireho    IDEBUG("indic_shape: from %d length %d", item->item.pos, item->item.length);
18335569331642446be05292e3e1f8a51218827168cdclaireho    while (sstart < end) {
18345569331642446be05292e3e1f8a51218827168cdclaireho        bool invalid;
18355569331642446be05292e3e1f8a51218827168cdclaireho        int send = indic_nextSyllableBoundary(item->item.script, item->string, sstart, end, &invalid);
18365569331642446be05292e3e1f8a51218827168cdclaireho        IDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart,
18375569331642446be05292e3e1f8a51218827168cdclaireho               invalid ? "true" : "false");
18385569331642446be05292e3e1f8a51218827168cdclaireho        syllable.item.pos = sstart;
18395569331642446be05292e3e1f8a51218827168cdclaireho        syllable.item.length = send-sstart;
18405569331642446be05292e3e1f8a51218827168cdclaireho        syllable.glyphs = item->glyphs + first_glyph;
18415569331642446be05292e3e1f8a51218827168cdclaireho        syllable.attributes = item->attributes + first_glyph;
18425569331642446be05292e3e1f8a51218827168cdclaireho        syllable.offsets = item->offsets + first_glyph;
18435569331642446be05292e3e1f8a51218827168cdclaireho        syllable.advances = item->advances + first_glyph;
18445569331642446be05292e3e1f8a51218827168cdclaireho        syllable.num_glyphs = item->num_glyphs - first_glyph;
18455569331642446be05292e3e1f8a51218827168cdclaireho        if (!indic_shape_syllable(openType, &syllable, invalid)) {
18465569331642446be05292e3e1f8a51218827168cdclaireho            IDEBUG("syllable shaping failed, syllable requests %d glyphs", syllable.num_glyphs);
18475569331642446be05292e3e1f8a51218827168cdclaireho            item->num_glyphs += syllable.num_glyphs;
18485569331642446be05292e3e1f8a51218827168cdclaireho            return false;
18495569331642446be05292e3e1f8a51218827168cdclaireho        }
18505569331642446be05292e3e1f8a51218827168cdclaireho        // fix logcluster array
18515569331642446be05292e3e1f8a51218827168cdclaireho        IDEBUG("syllable:");
18525569331642446be05292e3e1f8a51218827168cdclaireho        hb_uint32 g;
18535569331642446be05292e3e1f8a51218827168cdclaireho        for (g = first_glyph; g < first_glyph + syllable.num_glyphs; ++g)
18545569331642446be05292e3e1f8a51218827168cdclaireho            IDEBUG("        %d -> glyph %x", g, item->glyphs[g]);
18555569331642446be05292e3e1f8a51218827168cdclaireho        IDEBUG("    logclusters:");
18565569331642446be05292e3e1f8a51218827168cdclaireho        int i;
18575569331642446be05292e3e1f8a51218827168cdclaireho        for (i = sstart; i < send; ++i) {
18585569331642446be05292e3e1f8a51218827168cdclaireho            IDEBUG("        %d -> glyph %d", i, first_glyph);
18595569331642446be05292e3e1f8a51218827168cdclaireho            logClusters[i-item->item.pos] = first_glyph;
18605569331642446be05292e3e1f8a51218827168cdclaireho        }
18615569331642446be05292e3e1f8a51218827168cdclaireho        sstart = send;
18625569331642446be05292e3e1f8a51218827168cdclaireho        first_glyph += syllable.num_glyphs;
18635569331642446be05292e3e1f8a51218827168cdclaireho    }
18645569331642446be05292e3e1f8a51218827168cdclaireho    item->num_glyphs = first_glyph;
18655569331642446be05292e3e1f8a51218827168cdclaireho    return true;
18665569331642446be05292e3e1f8a51218827168cdclaireho}
18675569331642446be05292e3e1f8a51218827168cdclaireho
18685569331642446be05292e3e1f8a51218827168cdclairehovoid HB_IndicAttributes(HB_Script script, const HB_UChar16 *text, hb_uint32 from, hb_uint32 len, HB_CharAttributes *attributes)
18695569331642446be05292e3e1f8a51218827168cdclaireho{
18705569331642446be05292e3e1f8a51218827168cdclaireho    int end = from + len;
18715569331642446be05292e3e1f8a51218827168cdclaireho    const HB_UChar16 *uc = text + from;
18725569331642446be05292e3e1f8a51218827168cdclaireho    attributes += from;
18735569331642446be05292e3e1f8a51218827168cdclaireho    hb_uint32 i = 0;
18745569331642446be05292e3e1f8a51218827168cdclaireho    while (i < len) {
18755569331642446be05292e3e1f8a51218827168cdclaireho        bool invalid;
18765569331642446be05292e3e1f8a51218827168cdclaireho        hb_uint32 boundary = indic_nextSyllableBoundary(script, text, from+i, end, &invalid) - from;
18775569331642446be05292e3e1f8a51218827168cdclaireho         attributes[i].charStop = true;
18785569331642446be05292e3e1f8a51218827168cdclaireho
18795569331642446be05292e3e1f8a51218827168cdclaireho        if (boundary > len-1) boundary = len;
18805569331642446be05292e3e1f8a51218827168cdclaireho        i++;
18815569331642446be05292e3e1f8a51218827168cdclaireho        while (i < boundary) {
18825569331642446be05292e3e1f8a51218827168cdclaireho            attributes[i].charStop = false;
18835569331642446be05292e3e1f8a51218827168cdclaireho            ++uc;
18845569331642446be05292e3e1f8a51218827168cdclaireho            ++i;
18855569331642446be05292e3e1f8a51218827168cdclaireho        }
18865569331642446be05292e3e1f8a51218827168cdclaireho        assert(i == boundary);
18875569331642446be05292e3e1f8a51218827168cdclaireho    }
18885569331642446be05292e3e1f8a51218827168cdclaireho
18895569331642446be05292e3e1f8a51218827168cdclaireho
18905569331642446be05292e3e1f8a51218827168cdclaireho}
18915569331642446be05292e3e1f8a51218827168cdclaireho
18925569331642446be05292e3e1f8a51218827168cdclaireho
1893