예제 #1
0
/*
 * convert to the correct display level of THAI vowels and marks.
 */
static HB_Bool HB_ThaiConvertStringToGlyphIndices (HB_ShaperItem *item)
{
    char s[128];
    char *cstr = s;
    const HB_UChar16 *string = item->string + item->item.pos;
    const hb_uint32 len = item->item.length;
    unsigned short *logClusters = item->log_clusters;
    hb_uint32 i = 0, slen = 0;

    if (!init_libthai())
        return HB_BasicShape (item);

    if (len >= 128)
        cstr = (char *)malloc(len*sizeof(char) + 1);

    if (!cstr)
        return HB_BasicShape (item);

    to_tis620(string, len, cstr);

    /* Get font type */
    static ThaiFontType font_type;
    static HB_Font itemFont;
    if (itemFont != item->font) {
        font_type = getThaiFontType (item);
        itemFont = item->font;
    }

    /* allocate temporary glyphs buffers */
    HB_STACKARRAY (HB_UChar16, glyphString, (item->item.length * 2));

    while (i < item->item.length) {
        struct thcell_t tis_cell;
        unsigned char rglyphs[4];
        int cell_length;
        int lgn = 0;
        HB_Bool haveSaraAm = false;

        cell_length = th_next_cell ((const unsigned char *)cstr + i, len - i, &tis_cell, true); /* !item->fixedPitch); */
        haveSaraAm  = (cstr[i + cell_length - 1] == (char)0xd3);

        /* set shaper item's log_clusters */
        logClusters[i] = slen;
        for (int j = 1; j < cell_length; j++) {
            logClusters[i + j] = logClusters[i];
        }

        /* Find Logical Glyphs by font type */
        switch (font_type) {
        case TIS:
            lgn = th_render_cell_tis (tis_cell, rglyphs, sizeof(rglyphs) / sizeof(rglyphs[0]), true);
            break;
        case WIN:
            lgn = th_render_cell_mac (tis_cell, rglyphs, sizeof(rglyphs) / sizeof(rglyphs[0]), true);
            break;
        case MAC:
            lgn = th_render_cell_win (tis_cell, rglyphs, sizeof(rglyphs) / sizeof(rglyphs[0]), true);
            break;
        }

        /* Add glyphs to glyphs string and setting some attributes */
        for (int lgi = 0; lgi < lgn; lgi++) {
            if ( rglyphs[lgi] == 0xdd/*TH_BLANK_BASE_GLYPH*/ ) {
                glyphString[slen++] = C_DOTTED_CIRCLE;
            } else if ((unsigned char)cstr[i] == (unsigned char)~0) {
                // The only glyphs that should be passed to this function that cannot be mapped to
                // tis620 are the ones of type Inherited class.  Pass these glyphs untouched.
                glyphString[slen++] = string[i];
                if (string[i] == 0x200D || string[i] == 0x200C) {
                    // Check that we do not run out of bounds when setting item->attributes.  If we do
                    // run out of bounds then this function will return false, the necessary amount of
                    // memory is reallocated, and this function will then be called again.
                    if (slen <= item->num_glyphs)
                        item->attributes[slen-1].dontPrint = true; // Hide ZWJ and ZWNJ characters
                }
            } else {
                glyphString[slen++] = (HB_UChar16) thai_get_glyph_index (font_type, rglyphs[lgi]);
            }
        }

        /* Special case to handle U+0E33 (SARA AM, ำ): SARA AM is normally written at the end of a
         * word with a base character and an optional top character before it. For example, U+0E0B
         * (base), U+0E49 (top), U+0E33 (SARA AM). The sequence should be converted to 4 glyphs:
         * base, hilo (the little circle in the top left part of SARA AM, NIKHAHIT), top, then the
         * right part of SARA AM (SARA AA).
         *
         * The painting process finds out the starting glyph and ending glyph of a character
         * sequence by checking the logClusters array. In this case, logClusters array should
         * ideally be [ 0, 1, 3 ] so that glyphsStart = 0 and glyphsEnd = 3 (slen - 1) to paint out
         * all the glyphs generated.
         *
         * A special case in this special case is when we have no base character. When an isolated
         * SARA AM is processed (cell_length = 1), libthai will produce 3 glyphs: dotted circle
         * (indicates that the base is empty), NIKHAHIT then SARA AA. If logClusters[0] = 1, it will
         * paint from the second glyph in the glyphs array. So in this case logClusters[0] should
         * point to the first glyph it produces, aka. the dotted circle. */
        if (haveSaraAm) {
            logClusters[i + cell_length - 1] = cell_length == 1 ? slen - 3 : slen - 1;
            if (tis_cell.top != 0) {
                if (cell_length > 1) {
                    /* set the logClusters[top character] to slen - 2 as it points to the second to
                     * lastglyph (slen - 2) */
                    logClusters[i + cell_length - 2] = slen - 2;
                }
            }
            /* check for overflow */
            if (logClusters[i + cell_length - 1] > slen)
                logClusters[i + cell_length - 1] = 0;
        }

        i += cell_length;
    }
    glyphString[slen] = (HB_UChar16) '\0';

    /* for check, should reallocate space or not */
    HB_Bool spaceOK = (item->num_glyphs >= slen);

    /* Convert to Glyph indices */
    HB_Bool haveGlyphs = item->font->klass->convertStringToGlyphIndices (
                             item->font,
                             glyphString, slen,
                             item->glyphs, &item->num_glyphs,
                             item->shaperFlags);

    HB_FREE_STACKARRAY (glyphString);

    if (len >= 128)
        free(cstr);

    return (haveGlyphs && spaceOK);
}
예제 #2
0
/*
 * convert to the correct display level of THAI vowels and marks.
 */
static HB_Bool HB_ThaiConvertStringToGlyphIndices (HB_ShaperItem *item)
{
    char s[128];
    char *cstr = s;
    const HB_UChar16 *string = item->string + item->item.pos;
    const hb_uint32 len = item->item.length;
    unsigned short *logClusters = item->log_clusters;
    hb_uint32 i = 0, slen = 0;

    if (!init_libthai())
        return HB_BasicShape (item);

    if (len >= 128)
        cstr = (char *)malloc(len*sizeof(char) + 1);

    if (!cstr)
        return HB_BasicShape (item);

    to_tis620(string, len, cstr);

    /* Get font type */
    static ThaiFontType font_type;
    static HB_Font itemFont;
    if (itemFont != item->font) {
        font_type = getThaiFontType (item);
        itemFont = item->font;
    }

    /* allocate temporary glyphs buffers */
    HB_STACKARRAY (HB_UChar16, glyphString, (item->item.length * 2));

    while (i < item->item.length) {
        struct thcell_t tis_cell;
        unsigned char rglyphs[4];
        int cell_length;
        int lgn = 0;
        HB_Bool haveSaraAm = false;

        cell_length = th_next_cell ((const unsigned char *)cstr + i, len - i, &tis_cell, true); /* !item->fixedPitch); */
        haveSaraAm  = (cstr[i + cell_length - 1] == (char)0xd3);

        /* set shaper item's log_clusters */
        logClusters[i] = slen;
        for (int j = 1; j < cell_length; j++) {
            logClusters[i + j] = logClusters[i];
        }

        /* Find Logical Glyphs by font type */
        switch (font_type) {
            case TIS: lgn = th_render_cell_tis (tis_cell, rglyphs, sizeof(rglyphs) / sizeof(rglyphs[0]), true); break;
            case WIN: lgn = th_render_cell_mac (tis_cell, rglyphs, sizeof(rglyphs) / sizeof(rglyphs[0]), true); break;
            case MAC: lgn = th_render_cell_win (tis_cell, rglyphs, sizeof(rglyphs) / sizeof(rglyphs[0]), true); break;
        }

        /* Add glyphs to glyphs string and setting some attributes */
        for (int lgi = 0; lgi < lgn; lgi++) {
            if ( rglyphs[lgi] == 0xdd/*TH_BLANK_BASE_GLYPH*/ ) {
                //if ( !item->fixedPitch ) {
                    glyphString[slen++] = C_DOTTED_CIRCLE;
                    item->attributes[slen-1].dontPrint = true; // FIXME this will hide all dotted circle
                //}
            }
            else {
                glyphString[slen++] = (HB_UChar16) thai_get_glyph_index (font_type, rglyphs[lgi]);
            }
        }

        if (haveSaraAm) {
            logClusters[i + cell_length - 1] = slen - 1; // Set logClusters before NIKAHIT
            if (tis_cell.top != 0)
                logClusters[i + cell_length - 2] = slen - 2; // Set logClusters before NIKAHIT when tis_cell has top
            if (logClusters[i + cell_length - 1] > slen)
                logClusters[i + cell_length - 1] = 0;
        }

        i += cell_length;
    }
    glyphString[slen] = (HB_UChar16) '\0';

    /* for check, should reallocate space or not */
    HB_Bool spaceOK = (item->num_glyphs >= slen);

    /* Convert to Glyph indices */
    HB_Bool haveGlyphs = item->font->klass->convertStringToGlyphIndices (
                                          item->font,
                                          glyphString, slen,
                                          item->glyphs, &item->num_glyphs,
                                          item->shaperFlags);

    HB_FREE_STACKARRAY (glyphString);

    if (len >= 128)
        free(cstr);

    return (haveGlyphs && spaceOK);
}