15469607a00d84a07dc638eda46a87fc90142d64breed@android.com/*
25469607a00d84a07dc638eda46a87fc90142d64breed@android.com * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
35469607a00d84a07dc638eda46a87fc90142d64breed@android.com *
45469607a00d84a07dc638eda46a87fc90142d64breed@android.com * This is part of HarfBuzz, an OpenType Layout engine library.
55469607a00d84a07dc638eda46a87fc90142d64breed@android.com *
65469607a00d84a07dc638eda46a87fc90142d64breed@android.com * Permission is hereby granted, without written agreement and without
75469607a00d84a07dc638eda46a87fc90142d64breed@android.com * license or royalty fees, to use, copy, modify, and distribute this
85469607a00d84a07dc638eda46a87fc90142d64breed@android.com * software and its documentation for any purpose, provided that the
95469607a00d84a07dc638eda46a87fc90142d64breed@android.com * above copyright notice and the following two paragraphs appear in
105469607a00d84a07dc638eda46a87fc90142d64breed@android.com * all copies of this software.
115469607a00d84a07dc638eda46a87fc90142d64breed@android.com *
125469607a00d84a07dc638eda46a87fc90142d64breed@android.com * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
135469607a00d84a07dc638eda46a87fc90142d64breed@android.com * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
145469607a00d84a07dc638eda46a87fc90142d64breed@android.com * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
155469607a00d84a07dc638eda46a87fc90142d64breed@android.com * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
165469607a00d84a07dc638eda46a87fc90142d64breed@android.com * DAMAGE.
175469607a00d84a07dc638eda46a87fc90142d64breed@android.com *
185469607a00d84a07dc638eda46a87fc90142d64breed@android.com * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
195469607a00d84a07dc638eda46a87fc90142d64breed@android.com * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
205469607a00d84a07dc638eda46a87fc90142d64breed@android.com * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
215469607a00d84a07dc638eda46a87fc90142d64breed@android.com * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
225469607a00d84a07dc638eda46a87fc90142d64breed@android.com * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
235469607a00d84a07dc638eda46a87fc90142d64breed@android.com */
245469607a00d84a07dc638eda46a87fc90142d64breed@android.com
255469607a00d84a07dc638eda46a87fc90142d64breed@android.com#include "harfbuzz-shaper.h"
265469607a00d84a07dc638eda46a87fc90142d64breed@android.com#include "harfbuzz-shaper-private.h"
275469607a00d84a07dc638eda46a87fc90142d64breed@android.com
285469607a00d84a07dc638eda46a87fc90142d64breed@android.com#include <assert.h>
295469607a00d84a07dc638eda46a87fc90142d64breed@android.com
305469607a00d84a07dc638eda46a87fc90142d64breed@android.com/*
315469607a00d84a07dc638eda46a87fc90142d64breed@android.com tibetan syllables are of the form:
325469607a00d84a07dc638eda46a87fc90142d64breed@android.com    head position consonant
335469607a00d84a07dc638eda46a87fc90142d64breed@android.com    first sub-joined consonant
345469607a00d84a07dc638eda46a87fc90142d64breed@android.com    ....intermediate sub-joined consonants (if any)
355469607a00d84a07dc638eda46a87fc90142d64breed@android.com    last sub-joined consonant
365469607a00d84a07dc638eda46a87fc90142d64breed@android.com    sub-joined vowel (a-chung U+0F71)
375469607a00d84a07dc638eda46a87fc90142d64breed@android.com    standard or compound vowel sign (or 'virama' for devanagari transliteration)
385469607a00d84a07dc638eda46a87fc90142d64breed@android.com*/
395469607a00d84a07dc638eda46a87fc90142d64breed@android.com
405469607a00d84a07dc638eda46a87fc90142d64breed@android.comtypedef enum {
415469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanOther,
425469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanHeadConsonant,
435469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanSubjoinedConsonant,
445469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanSubjoinedVowel,
455469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanVowel
465469607a00d84a07dc638eda46a87fc90142d64breed@android.com} TibetanForm;
475469607a00d84a07dc638eda46a87fc90142d64breed@android.com
485469607a00d84a07dc638eda46a87fc90142d64breed@android.com/* this table starts at U+0f40 */
495469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic const unsigned char tibetanForm[0x80] = {
505469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
515469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
525469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
535469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
545469607a00d84a07dc638eda46a87fc90142d64breed@android.com
555469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
565469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
575469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
585469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
595469607a00d84a07dc638eda46a87fc90142d64breed@android.com
605469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
615469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
625469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant, TibetanHeadConsonant,
635469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanOther, TibetanOther, TibetanOther, TibetanOther,
645469607a00d84a07dc638eda46a87fc90142d64breed@android.com
655469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanOther, TibetanVowel, TibetanVowel, TibetanVowel,
665469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel,
675469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel,
685469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel,
695469607a00d84a07dc638eda46a87fc90142d64breed@android.com
705469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel,
715469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanVowel, TibetanVowel, TibetanVowel, TibetanVowel,
725469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanOther, TibetanOther, TibetanOther, TibetanOther,
735469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanOther, TibetanOther, TibetanOther, TibetanOther,
745469607a00d84a07dc638eda46a87fc90142d64breed@android.com
755469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
765469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
775469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
785469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
795469607a00d84a07dc638eda46a87fc90142d64breed@android.com
805469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
815469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
825469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
835469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
845469607a00d84a07dc638eda46a87fc90142d64breed@android.com
855469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
865469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
875469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant, TibetanSubjoinedConsonant,
885469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanSubjoinedConsonant, TibetanOther, TibetanOther, TibetanOther
895469607a00d84a07dc638eda46a87fc90142d64breed@android.com};
905469607a00d84a07dc638eda46a87fc90142d64breed@android.com
915469607a00d84a07dc638eda46a87fc90142d64breed@android.com
925469607a00d84a07dc638eda46a87fc90142d64breed@android.com#define tibetan_form(c) \
935469607a00d84a07dc638eda46a87fc90142d64breed@android.com    (TibetanForm)tibetanForm[c - 0x0f40]
945469607a00d84a07dc638eda46a87fc90142d64breed@android.com
955469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic const HB_OpenTypeFeature tibetan_features[] = {
965469607a00d84a07dc638eda46a87fc90142d64breed@android.com    { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty },
975469607a00d84a07dc638eda46a87fc90142d64breed@android.com    { HB_MAKE_TAG('a', 'b', 'v', 's'), AboveSubstProperty },
985469607a00d84a07dc638eda46a87fc90142d64breed@android.com    { HB_MAKE_TAG('b', 'l', 'w', 's'), BelowSubstProperty },
995469607a00d84a07dc638eda46a87fc90142d64breed@android.com    { HB_MAKE_TAG('c', 'a', 'l', 't'), CaltProperty },
1005469607a00d84a07dc638eda46a87fc90142d64breed@android.com    {0, 0}
1015469607a00d84a07dc638eda46a87fc90142d64breed@android.com};
1025469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1035469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic HB_Bool tibetan_shape_syllable(HB_Bool openType, HB_ShaperItem *item, HB_Bool invalid)
1045469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
1055469607a00d84a07dc638eda46a87fc90142d64breed@android.com    hb_uint32 i;
1065469607a00d84a07dc638eda46a87fc90142d64breed@android.com    const HB_UChar16 *str = item->string + item->item.pos;
1075469607a00d84a07dc638eda46a87fc90142d64breed@android.com    int len = item->item.length;
1085469607a00d84a07dc638eda46a87fc90142d64breed@android.com#ifndef NO_OPENTYPE
1095469607a00d84a07dc638eda46a87fc90142d64breed@android.com    const int availableGlyphs = item->num_glyphs;
1105469607a00d84a07dc638eda46a87fc90142d64breed@android.com#endif
1115469607a00d84a07dc638eda46a87fc90142d64breed@android.com    HB_Bool haveGlyphs;
1125469607a00d84a07dc638eda46a87fc90142d64breed@android.com    HB_STACKARRAY(HB_UChar16, reordered, len + 4);
1135469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1145469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if (item->num_glyphs < item->item.length + 4) {
1155469607a00d84a07dc638eda46a87fc90142d64breed@android.com        item->num_glyphs = item->item.length + 4;
1165469607a00d84a07dc638eda46a87fc90142d64breed@android.com        return FALSE;
1175469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
1185469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1195469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if (invalid) {
1205469607a00d84a07dc638eda46a87fc90142d64breed@android.com        *reordered = 0x25cc;
1215469607a00d84a07dc638eda46a87fc90142d64breed@android.com        memcpy(reordered+1, str, len*sizeof(HB_UChar16));
1225469607a00d84a07dc638eda46a87fc90142d64breed@android.com        len++;
1235469607a00d84a07dc638eda46a87fc90142d64breed@android.com        str = reordered;
1245469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
1255469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1265469607a00d84a07dc638eda46a87fc90142d64breed@android.com    haveGlyphs = item->font->klass->convertStringToGlyphIndices(item->font,
1275469607a00d84a07dc638eda46a87fc90142d64breed@android.com                                                                str, len,
1285469607a00d84a07dc638eda46a87fc90142d64breed@android.com                                                                item->glyphs, &item->num_glyphs,
1295469607a00d84a07dc638eda46a87fc90142d64breed@android.com                                                                item->item.bidiLevel % 2);
1305469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1315469607a00d84a07dc638eda46a87fc90142d64breed@android.com    HB_FREE_STACKARRAY(reordered);
1325469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1335469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if (!haveGlyphs)
1345469607a00d84a07dc638eda46a87fc90142d64breed@android.com        return FALSE;
1355469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1365469607a00d84a07dc638eda46a87fc90142d64breed@android.com    for (i = 0; i < item->item.length; i++) {
1375469607a00d84a07dc638eda46a87fc90142d64breed@android.com        item->attributes[i].mark = FALSE;
1385469607a00d84a07dc638eda46a87fc90142d64breed@android.com        item->attributes[i].clusterStart = FALSE;
1395469607a00d84a07dc638eda46a87fc90142d64breed@android.com        item->attributes[i].justification = 0;
1405469607a00d84a07dc638eda46a87fc90142d64breed@android.com        item->attributes[i].zeroWidth = FALSE;
1415469607a00d84a07dc638eda46a87fc90142d64breed@android.com/*        IDEBUG("    %d: %4x", i, str[i]); */
1425469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
1435469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1445469607a00d84a07dc638eda46a87fc90142d64breed@android.com    /* now we have the syllable in the right order, and can start running it through open type. */
1455469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1465469607a00d84a07dc638eda46a87fc90142d64breed@android.com#ifndef NO_OPENTYPE
1475469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if (openType) {
1485469607a00d84a07dc638eda46a87fc90142d64breed@android.com        HB_OpenTypeShape(item, /*properties*/0);
1495469607a00d84a07dc638eda46a87fc90142d64breed@android.com        if (!HB_OpenTypePosition(item, availableGlyphs, /*doLogClusters*/FALSE))
1505469607a00d84a07dc638eda46a87fc90142d64breed@android.com            return FALSE;
1515469607a00d84a07dc638eda46a87fc90142d64breed@android.com    } else {
1525469607a00d84a07dc638eda46a87fc90142d64breed@android.com        HB_HeuristicPosition(item);
1535469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
1545469607a00d84a07dc638eda46a87fc90142d64breed@android.com#endif
1555469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1565469607a00d84a07dc638eda46a87fc90142d64breed@android.com    item->attributes[0].clusterStart = TRUE;
1575469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return TRUE;
1585469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
1595469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1605469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1615469607a00d84a07dc638eda46a87fc90142d64breed@android.comstatic int tibetan_nextSyllableBoundary(const HB_UChar16 *s, int start, int end, HB_Bool *invalid)
1625469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
1635469607a00d84a07dc638eda46a87fc90142d64breed@android.com    const HB_UChar16 *uc = s + start;
1645469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1655469607a00d84a07dc638eda46a87fc90142d64breed@android.com    int pos = 0;
1665469607a00d84a07dc638eda46a87fc90142d64breed@android.com    TibetanForm state = tibetan_form(*uc);
1675469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1685469607a00d84a07dc638eda46a87fc90142d64breed@android.com/*     qDebug("state[%d]=%d (uc=%4x)", pos, state, uc[pos]);*/
1695469607a00d84a07dc638eda46a87fc90142d64breed@android.com    pos++;
1705469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1715469607a00d84a07dc638eda46a87fc90142d64breed@android.com    if (state != TibetanHeadConsonant) {
1725469607a00d84a07dc638eda46a87fc90142d64breed@android.com        if (state != TibetanOther)
1735469607a00d84a07dc638eda46a87fc90142d64breed@android.com            *invalid = TRUE;
1745469607a00d84a07dc638eda46a87fc90142d64breed@android.com        goto finish;
1755469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
1765469607a00d84a07dc638eda46a87fc90142d64breed@android.com
1775469607a00d84a07dc638eda46a87fc90142d64breed@android.com    while (pos < end - start) {
1785469607a00d84a07dc638eda46a87fc90142d64breed@android.com        TibetanForm newState = tibetan_form(uc[pos]);
1795469607a00d84a07dc638eda46a87fc90142d64breed@android.com        switch(newState) {
1805469607a00d84a07dc638eda46a87fc90142d64breed@android.com        case TibetanSubjoinedConsonant:
1815469607a00d84a07dc638eda46a87fc90142d64breed@android.com        case TibetanSubjoinedVowel:
1825469607a00d84a07dc638eda46a87fc90142d64breed@android.com            if (state != TibetanHeadConsonant &&
1835469607a00d84a07dc638eda46a87fc90142d64breed@android.com                 state != TibetanSubjoinedConsonant)
1845469607a00d84a07dc638eda46a87fc90142d64breed@android.com                goto finish;
1855469607a00d84a07dc638eda46a87fc90142d64breed@android.com            state = newState;
1865469607a00d84a07dc638eda46a87fc90142d64breed@android.com            break;
1875469607a00d84a07dc638eda46a87fc90142d64breed@android.com        case TibetanVowel:
1885469607a00d84a07dc638eda46a87fc90142d64breed@android.com            if (state != TibetanHeadConsonant &&
1895469607a00d84a07dc638eda46a87fc90142d64breed@android.com                 state != TibetanSubjoinedConsonant &&
1905469607a00d84a07dc638eda46a87fc90142d64breed@android.com                 state != TibetanSubjoinedVowel)
1915469607a00d84a07dc638eda46a87fc90142d64breed@android.com                goto finish;
1925469607a00d84a07dc638eda46a87fc90142d64breed@android.com            break;
1935469607a00d84a07dc638eda46a87fc90142d64breed@android.com        case TibetanOther:
1945469607a00d84a07dc638eda46a87fc90142d64breed@android.com        case TibetanHeadConsonant:
1955469607a00d84a07dc638eda46a87fc90142d64breed@android.com            goto finish;
1965469607a00d84a07dc638eda46a87fc90142d64breed@android.com        }
1975469607a00d84a07dc638eda46a87fc90142d64breed@android.com        pos++;
1985469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
1995469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2005469607a00d84a07dc638eda46a87fc90142d64breed@android.comfinish:
2015469607a00d84a07dc638eda46a87fc90142d64breed@android.com    *invalid = FALSE;
2025469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return start+pos;
2035469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
2045469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2055469607a00d84a07dc638eda46a87fc90142d64breed@android.comHB_Bool HB_TibetanShape(HB_ShaperItem *item)
2065469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
2075469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2085469607a00d84a07dc638eda46a87fc90142d64breed@android.com    HB_Bool openType = FALSE;
2095469607a00d84a07dc638eda46a87fc90142d64breed@android.com    unsigned short *logClusters = item->log_clusters;
2105469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2115469607a00d84a07dc638eda46a87fc90142d64breed@android.com    HB_ShaperItem syllable = *item;
2125469607a00d84a07dc638eda46a87fc90142d64breed@android.com    int first_glyph = 0;
2135469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2145469607a00d84a07dc638eda46a87fc90142d64breed@android.com    int sstart = item->item.pos;
2155469607a00d84a07dc638eda46a87fc90142d64breed@android.com    int end = sstart + item->item.length;
2165469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2175469607a00d84a07dc638eda46a87fc90142d64breed@android.com    assert(item->item.script == HB_Script_Tibetan);
2185469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2195469607a00d84a07dc638eda46a87fc90142d64breed@android.com#ifndef QT_NO_OPENTYPE
2205469607a00d84a07dc638eda46a87fc90142d64breed@android.com    openType = HB_SelectScript(item, tibetan_features);
2215469607a00d84a07dc638eda46a87fc90142d64breed@android.com#endif
2225469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2235469607a00d84a07dc638eda46a87fc90142d64breed@android.com    while (sstart < end) {
2245469607a00d84a07dc638eda46a87fc90142d64breed@android.com        HB_Bool invalid;
2255469607a00d84a07dc638eda46a87fc90142d64breed@android.com        int i;
2265469607a00d84a07dc638eda46a87fc90142d64breed@android.com        int send = tibetan_nextSyllableBoundary(item->string, sstart, end, &invalid);
2275469607a00d84a07dc638eda46a87fc90142d64breed@android.com/*        IDEBUG("syllable from %d, length %d, invalid=%s", sstart, send-sstart,
2285469607a00d84a07dc638eda46a87fc90142d64breed@android.com                 invalid ? "TRUE" : "FALSE"); */
2295469607a00d84a07dc638eda46a87fc90142d64breed@android.com        syllable.item.pos = sstart;
2305469607a00d84a07dc638eda46a87fc90142d64breed@android.com        syllable.item.length = send-sstart;
2315469607a00d84a07dc638eda46a87fc90142d64breed@android.com        syllable.glyphs = item->glyphs + first_glyph;
2325469607a00d84a07dc638eda46a87fc90142d64breed@android.com        syllable.attributes = item->attributes + first_glyph;
2335469607a00d84a07dc638eda46a87fc90142d64breed@android.com        syllable.offsets = item->offsets + first_glyph;
2345469607a00d84a07dc638eda46a87fc90142d64breed@android.com        syllable.advances = item->advances + first_glyph;
2355469607a00d84a07dc638eda46a87fc90142d64breed@android.com        syllable.num_glyphs = item->num_glyphs - first_glyph;
2365469607a00d84a07dc638eda46a87fc90142d64breed@android.com        if (!tibetan_shape_syllable(openType, &syllable, invalid)) {
2375469607a00d84a07dc638eda46a87fc90142d64breed@android.com            item->num_glyphs += syllable.num_glyphs;
2385469607a00d84a07dc638eda46a87fc90142d64breed@android.com            return FALSE;
2395469607a00d84a07dc638eda46a87fc90142d64breed@android.com        }
2405469607a00d84a07dc638eda46a87fc90142d64breed@android.com        /* fix logcluster array */
2415469607a00d84a07dc638eda46a87fc90142d64breed@android.com        for (i = sstart; i < send; ++i)
2425469607a00d84a07dc638eda46a87fc90142d64breed@android.com            logClusters[i-item->item.pos] = first_glyph;
2435469607a00d84a07dc638eda46a87fc90142d64breed@android.com        sstart = send;
2445469607a00d84a07dc638eda46a87fc90142d64breed@android.com        first_glyph += syllable.num_glyphs;
2455469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
2465469607a00d84a07dc638eda46a87fc90142d64breed@android.com    item->num_glyphs = first_glyph;
2475469607a00d84a07dc638eda46a87fc90142d64breed@android.com    return TRUE;
2485469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
2495469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2505469607a00d84a07dc638eda46a87fc90142d64breed@android.comvoid HB_TibetanAttributes(HB_Script script, const HB_UChar16 *text, hb_uint32 from, hb_uint32 len, HB_CharAttributes *attributes)
2515469607a00d84a07dc638eda46a87fc90142d64breed@android.com{
2525469607a00d84a07dc638eda46a87fc90142d64breed@android.com    int end = from + len;
2535469607a00d84a07dc638eda46a87fc90142d64breed@android.com    const HB_UChar16 *uc = text + from;
2545469607a00d84a07dc638eda46a87fc90142d64breed@android.com    hb_uint32 i = 0;
2555469607a00d84a07dc638eda46a87fc90142d64breed@android.com    HB_UNUSED(script);
2565469607a00d84a07dc638eda46a87fc90142d64breed@android.com    attributes += from;
2575469607a00d84a07dc638eda46a87fc90142d64breed@android.com    while (i < len) {
2585469607a00d84a07dc638eda46a87fc90142d64breed@android.com        HB_Bool invalid;
2595469607a00d84a07dc638eda46a87fc90142d64breed@android.com        hb_uint32 boundary = tibetan_nextSyllableBoundary(text, from+i, end, &invalid) - from;
2605469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2615469607a00d84a07dc638eda46a87fc90142d64breed@android.com        attributes[i].charStop = TRUE;
2625469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2635469607a00d84a07dc638eda46a87fc90142d64breed@android.com        if (boundary > len-1) boundary = len;
2645469607a00d84a07dc638eda46a87fc90142d64breed@android.com        i++;
2655469607a00d84a07dc638eda46a87fc90142d64breed@android.com        while (i < boundary) {
2665469607a00d84a07dc638eda46a87fc90142d64breed@android.com            attributes[i].charStop = FALSE;
2675469607a00d84a07dc638eda46a87fc90142d64breed@android.com            ++uc;
2685469607a00d84a07dc638eda46a87fc90142d64breed@android.com            ++i;
2695469607a00d84a07dc638eda46a87fc90142d64breed@android.com        }
2705469607a00d84a07dc638eda46a87fc90142d64breed@android.com        assert(i == boundary);
2715469607a00d84a07dc638eda46a87fc90142d64breed@android.com    }
2725469607a00d84a07dc638eda46a87fc90142d64breed@android.com}
2735469607a00d84a07dc638eda46a87fc90142d64breed@android.com
2745469607a00d84a07dc638eda46a87fc90142d64breed@android.com
275