/* * 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); }
/* * 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); }