le_bool ThaiShaping::isLegalHere(LEUnicode ch, le_uint8 prevState) { le_uint8 charClass = getCharClass(ch); StateTransition transition = getTransition(prevState, charClass); switch (transition.action) { case tA: case tC: case tD: case tE: case tF: case tG: case tH: return TRUE; case tR: case tS: return FALSE; default: // FIXME: if we get here, there's an error // in the state table! return FALSE; } }
le_uint8 ThaiShaping::getNextState(LEUnicode ch, le_uint8 prevState, le_int32 inputIndex, le_uint8 glyphSet, LEUnicode errorChar, le_uint8 &charClass, LEUnicode *output, LEGlyphStorage &glyphStorage, le_int32 &outputIndex) { StateTransition transition; charClass = getCharClass(ch); transition = getTransition(prevState, charClass); return doTransition(transition, ch, inputIndex, glyphSet, errorChar, output, glyphStorage, outputIndex); }
le_int32 HangulOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success) { if (LE_FAILURE(success)) { return 0; } if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) { success = LE_ILLEGAL_ARGUMENT_ERROR; return 0; } le_int32 worstCase = count * 3; outChars = LE_NEW_ARRAY(LEUnicode, worstCase); if (outChars == NULL) { success = LE_MEMORY_ALLOCATION_ERROR; return 0; } glyphStorage.allocateGlyphArray(worstCase, rightToLeft, success); glyphStorage.allocateAuxData(success); if (LE_FAILURE(success)) { LE_DELETE_ARRAY(outChars); return 0; } le_int32 outCharCount = 0; le_int32 limit = offset + count; le_int32 i = offset; while (i < limit) { le_int32 state = 0; le_int32 inStart = i; le_int32 outStart = outCharCount; while( i < limit) { LEUnicode lead = 0; LEUnicode vowel = 0; LEUnicode trail = 0; int32_t chClass = getCharClass(chars[i], lead, vowel, trail); const StateTransition transition = stateTable[state][chClass]; if (chClass == CC_X) { /* Any character of type X will be stored as a trail jamo */ if ((transition.actionFlags & AF_T) != 0) { outChars[outCharCount] = trail; glyphStorage.setCharIndex(outCharCount, i-offset, success); glyphStorage.setAuxData(outCharCount++, nullFeatures, success); } } else { /* Any Hangul will be fully decomposed. Output the decomposed characters. */ if ((transition.actionFlags & AF_L) != 0) { outChars[outCharCount] = lead; glyphStorage.setCharIndex(outCharCount, i-offset, success); glyphStorage.setAuxData(outCharCount++, ljmoFeatures, success); } if ((transition.actionFlags & AF_V) != 0) { outChars[outCharCount] = vowel; glyphStorage.setCharIndex(outCharCount, i-offset, success); glyphStorage.setAuxData(outCharCount++, vjmoFeatures, success); } if ((transition.actionFlags & AF_T) != 0) { outChars[outCharCount] = trail; glyphStorage.setCharIndex(outCharCount, i-offset, success); glyphStorage.setAuxData(outCharCount++, tjmoFeatures, success); } } state = transition.newState; /* Negative next state means stop. */ if (state < 0) { break; } i += 1; } le_int32 inLength = i - inStart; le_int32 outLength = outCharCount - outStart; /* * See if the syllable can be composed into a single character. There are 5 * possible cases: * * Input Decomposed to Compose to * LV L, V LV * LVT L, V, T LVT * L, V L, V LV, DEL * LV, T L, V, T LVT, DEL * L, V, T L, V, T LVT, DEL, DEL */ if ((inLength >= 1 && inLength <= 3) && (outLength == 2 || outLength == 3)) { LEUnicode syllable = 0x0000; LEUnicode lead = outChars[outStart]; LEUnicode vowel = outChars[outStart + 1]; LEUnicode trail = outLength == 3? outChars[outStart + 2] : TJMO_FIRST; /* * If the composition consumes the whole decomposed syllable, * we can use it. */ if (compose(lead, vowel, trail, syllable) == outLength) { outCharCount = outStart; outChars[outCharCount] = syllable; glyphStorage.setCharIndex(outCharCount, inStart-offset, success); glyphStorage.setAuxData(outCharCount++, nullFeatures, success); /* * Replace the rest of the input characters with DEL. */ for(le_int32 d = inStart + 1; d < i; d += 1) { outChars[outCharCount] = 0xFFFF; glyphStorage.setCharIndex(outCharCount, d - offset, success); glyphStorage.setAuxData(outCharCount++, nullFeatures, success); } } } } glyphStorage.adoptGlyphCount(outCharCount); return outCharCount; }