diff options
Diffstat (limited to 'tqtinterface/qt4/include/private/qt4_harfbuzz/src/harfbuzz-hangul.c')
| -rw-r--r-- | tqtinterface/qt4/include/private/qt4_harfbuzz/src/harfbuzz-hangul.c | 268 | 
1 files changed, 268 insertions, 0 deletions
| diff --git a/tqtinterface/qt4/include/private/qt4_harfbuzz/src/harfbuzz-hangul.c b/tqtinterface/qt4/include/private/qt4_harfbuzz/src/harfbuzz-hangul.c new file mode 100644 index 0000000..6f89ed6 --- /dev/null +++ b/tqtinterface/qt4/include/private/qt4_harfbuzz/src/harfbuzz-hangul.c @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * + * This is part of HarfBuzz, an OpenType Layout engine library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "harfbuzz-shaper.h" +#include "harfbuzz-shaper-private.h" + +#include <assert.h> + +/* +// Hangul is a syllable based script. Unicode reserves a large range +// for precomposed hangul, where syllables are already precomposed to +// their final glyph shape. In addition, a so called jamo range is +// defined, that can be used to express old Hangul. Modern hangul +// syllables can also be expressed as jamo, and should be composed +// into syllables. The operation is rather simple and mathematical. + +// Every hangul jamo is classified as being either a Leading consonant +// (L), and intermediat Vowel (V) or a trailing consonant (T). Modern +// hangul syllables (the ones in the precomposed area can be of type +// LV or LVT. +// +// Syllable breaks do _not_ occur between: +// +// L              L, V or precomposed +// V, LV          V, T +// LVT, T         T +// +// A standard syllable is of the form L+V+T*. The above rules allow +// nonstandard syllables L*V*T*. To transform them into standard +// syllables fill characters L_f and V_f can be inserted. +*/ + +enum { +    Hangul_SBase = 0xac00, +    Hangul_LBase = 0x1100, +    Hangul_VBase = 0x1161, +    Hangul_TBase = 0x11a7, +    Hangul_SCount = 11172, +    Hangul_LCount = 19, +    Hangul_VCount = 21, +    Hangul_TCount = 28, +    Hangul_NCount = 21*28 +}; + +#define hangul_isPrecomposed(uc) \ +    (uc >= Hangul_SBase && uc < Hangul_SBase + Hangul_SCount) + +#define hangul_isLV(uc) \ +    ((uc - Hangul_SBase) % Hangul_TCount == 0) + +typedef enum { +    L, +    V, +    T, +    LV, +    LVT, +    X +} HangulType; + +static HangulType hangul_type(unsigned short uc) { +    if (uc > Hangul_SBase && uc < Hangul_SBase + Hangul_SCount) +        return hangul_isLV(uc) ? LV : LVT; +    if (uc < Hangul_LBase || uc > 0x11ff) +        return X; +    if (uc < Hangul_VBase) +        return L; +    if (uc < Hangul_TBase) +        return V; +    return T; +} + +static int hangul_nextSyllableBoundary(const HB_UChar16 *s, int start, int end) +{ +    const HB_UChar16 *uc = s + start; + +    HangulType state = hangul_type(*uc); +    int pos = 1; + +    while (pos < end - start) { +        HangulType newState = hangul_type(uc[pos]); +        switch(newState) { +        case X: +            goto finish; +        case L: +        case V: +        case T: +            if (state > newState) +                goto finish; +            state = newState; +            break; +        case LV: +            if (state > L) +                goto finish; +            state = V; +            break; +        case LVT: +            if (state > L) +                goto finish; +            state = T; +        } +        ++pos; +    } + + finish: +    return start+pos; +} + +#ifndef NO_OPENTYPE +static const HB_OpenTypeFeature hangul_features [] = { +    { HB_MAKE_TAG('c', 'c', 'm', 'p'), CcmpProperty }, +    { HB_MAKE_TAG('l', 'j', 'm', 'o'), CcmpProperty }, +    { HB_MAKE_TAG('v', 'j', 'm', 'o'), CcmpProperty }, +    { HB_MAKE_TAG('t', 'j', 'm', 'o'), CcmpProperty }, +    { 0, 0 } +}; +#endif + +static HB_Bool hangul_shape_syllable(HB_ShaperItem *item, HB_Bool openType) +{ +    const HB_UChar16 *ch = item->string + item->item.pos; +    int len = item->item.length; +#ifndef NO_OPENTYPE +    const int availableGlyphs = item->num_glyphs; +#endif + +    int i; +    HB_UChar16 composed = 0; +    /* see if we can compose the syllable into a modern hangul */ +    if (item->item.length == 2) { +        int LIndex = ch[0] - Hangul_LBase; +        int VIndex = ch[1] - Hangul_VBase; +        if (LIndex >= 0 && LIndex < Hangul_LCount && +            VIndex >= 0 && VIndex < Hangul_VCount) +            composed = (LIndex * Hangul_VCount + VIndex) * Hangul_TCount + Hangul_SBase; +    } else if (item->item.length == 3) { +        int LIndex = ch[0] - Hangul_LBase; +        int VIndex = ch[1] - Hangul_VBase; +        int TIndex = ch[2] - Hangul_TBase; +        if (LIndex >= 0 && LIndex < Hangul_LCount && +            VIndex >= 0 && VIndex < Hangul_VCount && +            TIndex >= 0 && TIndex < Hangul_TCount) +            composed = (LIndex * Hangul_VCount + VIndex) * Hangul_TCount + TIndex + Hangul_SBase; +    } + + + +    /* if we have a modern hangul use the composed form */ +    if (composed) { +        ch = &composed; +        len = 1; +    } + +    if (!item->font->klass->convertStringToGlyphIndices(item->font, +                                                        ch, len, +                                                        item->glyphs, &item->num_glyphs, +                                                        item->item.bidiLevel % 2)) +        return FALSE; +    for (i = 0; i < len; i++) { +        item->attributes[i].mark = FALSE; +        item->attributes[i].clusterStart = FALSE; +        item->attributes[i].justification = 0; +        item->attributes[i].zeroWidth = FALSE; +        /*IDEBUG("    %d: %4x", i, ch[i].unicode()); */ +    } + +#ifndef NO_OPENTYPE +    if (!composed && openType) { +        HB_Bool positioned; + +        HB_STACKARRAY(unsigned short, logClusters, len); +        for (i = 0; i < len; ++i) +            logClusters[i] = i; +        item->log_clusters = logClusters; + +        HB_OpenTypeShape(item, /*properties*/0); + +        positioned = HB_OpenTypePosition(item, availableGlyphs, /*doLogClusters*/FALSE); + +        HB_FREE_STACKARRAY(logClusters); + +        if (!positioned) +            return FALSE; +    } else { +        HB_HeuristicPosition(item); +    } +#endif + +    item->attributes[0].clusterStart = TRUE; +    return TRUE; +} + +HB_Bool HB_HangulShape(HB_ShaperItem *item) +{ +    const HB_UChar16 *uc = item->string + item->item.pos; +    HB_Bool allPrecomposed = TRUE; +    int i; + +    assert(item->item.script == HB_Script_Hangul); + +    for (i = 0; i < (int)item->item.length; ++i) { +        if (!hangul_isPrecomposed(uc[i])) { +            allPrecomposed = FALSE; +            break; +        } +    } + +    if (!allPrecomposed) { +        HB_Bool openType = FALSE; +        unsigned short *logClusters = item->log_clusters; +        HB_ShaperItem syllable; +        int first_glyph = 0; +        int sstart = item->item.pos; +        int end = sstart + item->item.length; + +#ifndef NO_OPENTYPE +        openType = HB_SelectScript(item, hangul_features); +#endif +        syllable = *item; + +        while (sstart < end) { +            int send = hangul_nextSyllableBoundary(item->string, sstart, end); + +            syllable.item.pos = sstart; +            syllable.item.length = send-sstart; +            syllable.glyphs = item->glyphs + first_glyph; +            syllable.attributes = item->attributes + first_glyph; +            syllable.offsets = item->offsets + first_glyph; +            syllable.advances = item->advances + first_glyph; +            syllable.num_glyphs = item->num_glyphs - first_glyph; +            if (!hangul_shape_syllable(&syllable, openType)) { +                item->num_glyphs += syllable.num_glyphs; +                return FALSE; +            } +            /* fix logcluster array */ +            for (i = sstart; i < send; ++i) +                logClusters[i-item->item.pos] = first_glyph; +            sstart = send; +            first_glyph += syllable.num_glyphs; +        } +        item->num_glyphs = first_glyph; +        return TRUE; +    } + +    return HB_BasicShape(item); +} + + | 
