sl@0: /* sl@0: * sl@0: * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved sl@0: * sl@0: */ sl@0: sl@0: #include "LETypes.h" sl@0: #include "OpenTypeTables.h" sl@0: #include "ArabicShaping.h" sl@0: #include "LEGlyphStorage.h" sl@0: sl@0: U_NAMESPACE_BEGIN sl@0: sl@0: enum { sl@0: _c_ = ArabicShaping::ST_NOSHAPE_DUAL, sl@0: _d_ = ArabicShaping::ST_DUAL, sl@0: _n_ = ArabicShaping::ST_NONE, sl@0: _r_ = ArabicShaping::ST_RIGHT, sl@0: _t_ = ArabicShaping::ST_TRANSPARENT, sl@0: _x_ = ArabicShaping::ST_NOSHAPE_NONE sl@0: }; sl@0: sl@0: const ArabicShaping::ShapeType ArabicShaping::shapeTypes[] = sl@0: { sl@0: _t_, _t_, _t_, _t_, _t_, _t_, _x_, _x_, _x_, _x_, _x_, _n_, _x_, _x_, _x_, _n_, // 0x610 - 0x61f sl@0: _x_, _n_, _r_, _r_, _r_, _r_, _d_, _r_, _d_, _r_, _d_, _d_, _d_, _d_, _d_, _r_, // 0x620 - 0x62f sl@0: _r_, _r_, _r_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _x_, _x_, _x_, _x_, _x_, // 0x630 - 0x63f sl@0: _c_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _r_, _d_, _d_, _t_, _t_, _t_, _t_, _t_, // 0x640 - 0x64f sl@0: _t_, _t_, _t_, _t_, _t_, _t_, _t_, _t_, _t_, _x_, _x_, _x_, _x_, _x_, _x_, _x_, // 0x650 - 0x65f sl@0: _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _d_, _d_, // 0x660 - 0x66f sl@0: _t_, _r_, _r_, _r_, _n_, _r_, _r_, _r_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, // 0x670 - 0x67f sl@0: _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, // 0x680 - 0x68f sl@0: _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _d_, _d_, _d_, _d_, _d_, _d_, // 0x690 - 0x69f sl@0: _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, // 0x6a0 - 0x6af sl@0: _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, // 0x6b0 - 0x6bf sl@0: _r_, _d_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _d_, _r_, _d_, _r_, // 0x6c0 - 0x6cf sl@0: _d_, _d_, _r_, _r_, _n_, _r_, _t_, _t_, _t_, _t_, _t_, _t_, _t_, _x_, _t_, _t_, // 0x6d0 - 0x6df sl@0: _t_, _t_, _t_, _t_, _t_, _n_, _n_, _t_, _t_, _n_, _t_, _t_, _t_, _t_, _r_, _r_, // 0x6e0 - 0x6ef sl@0: _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _d_, _d_, _d_, _n_, _n_, _d_ // 0x6f0 - 0x6ff sl@0: }; sl@0: sl@0: /* sl@0: shaping array holds types for Arabic chars between 0610 and 0700 sl@0: other values are either unshaped, or transparent if a mark or format sl@0: code, except for format codes 200c (zero-width non-joiner) and 200d sl@0: (dual-width joiner) which are both unshaped and non_joining or sl@0: dual-joining, respectively. sl@0: */ sl@0: ArabicShaping::ShapeType ArabicShaping::getShapeType(LEUnicode c) sl@0: { sl@0: if (c >= 0x0610 && c <= 0x206f) { sl@0: if (c < 0x0700) { sl@0: return shapeTypes[c - 0x0610]; sl@0: } else if (c == 0x200c) { // ZWNJ sl@0: return ST_NOSHAPE_NONE; sl@0: } else if (c == 0x200d) { // ZWJ sl@0: return ST_NOSHAPE_DUAL; sl@0: } else if (c >= 0x202a && c <= 0x202e) { // LRE - RLO sl@0: return ST_TRANSPARENT; sl@0: } else if (c >= 0x206a && c <= 0x206f) { // Inhibit Symmetric Swapping - Nominal Digit Shapes sl@0: return ST_TRANSPARENT; sl@0: } sl@0: } sl@0: sl@0: return ST_NOSHAPE_NONE; sl@0: } sl@0: sl@0: static const LETag isolFeatureTag = LE_ISOL_FEATURE_TAG; sl@0: static const LETag initFeatureTag = LE_INIT_FEATURE_TAG; sl@0: static const LETag mediFeatureTag = LE_MEDI_FEATURE_TAG; sl@0: static const LETag finaFeatureTag = LE_FINA_FEATURE_TAG; sl@0: static const LETag ligaFeatureTag = LE_LIGA_FEATURE_TAG; sl@0: static const LETag msetFeatureTag = LE_MSET_FEATURE_TAG; sl@0: static const LETag markFeatureTag = LE_MARK_FEATURE_TAG; sl@0: static const LETag ccmpFeatureTag = LE_CCMP_FEATURE_TAG; sl@0: static const LETag rligFeatureTag = LE_RLIG_FEATURE_TAG; sl@0: static const LETag caltFeatureTag = LE_CALT_FEATURE_TAG; sl@0: static const LETag dligFeatureTag = LE_DLIG_FEATURE_TAG; sl@0: static const LETag cswhFeatureTag = LE_CSWH_FEATURE_TAG; sl@0: static const LETag cursFeatureTag = LE_CURS_FEATURE_TAG; sl@0: static const LETag kernFeatureTag = LE_KERN_FEATURE_TAG; sl@0: static const LETag mkmkFeatureTag = LE_MKMK_FEATURE_TAG; sl@0: sl@0: static const LETag emptyTag = 0x00000000; // '' sl@0: sl@0: static const LETag featureOrder[] = sl@0: { sl@0: ccmpFeatureTag, isolFeatureTag, finaFeatureTag, mediFeatureTag, initFeatureTag, rligFeatureTag, sl@0: caltFeatureTag, ligaFeatureTag, dligFeatureTag, cswhFeatureTag, msetFeatureTag, cursFeatureTag, sl@0: kernFeatureTag, markFeatureTag, mkmkFeatureTag, emptyTag sl@0: }; sl@0: sl@0: const LETag ArabicShaping::tagArray[] = sl@0: { sl@0: isolFeatureTag, ligaFeatureTag, msetFeatureTag, markFeatureTag, ccmpFeatureTag, rligFeatureTag, sl@0: caltFeatureTag, dligFeatureTag, cswhFeatureTag, cursFeatureTag, kernFeatureTag, mkmkFeatureTag, emptyTag, sl@0: sl@0: finaFeatureTag, ligaFeatureTag, msetFeatureTag, markFeatureTag, ccmpFeatureTag, rligFeatureTag, sl@0: caltFeatureTag, dligFeatureTag, cswhFeatureTag, cursFeatureTag, kernFeatureTag, mkmkFeatureTag, emptyTag, sl@0: sl@0: initFeatureTag, ligaFeatureTag, msetFeatureTag, markFeatureTag, ccmpFeatureTag, rligFeatureTag, sl@0: caltFeatureTag, dligFeatureTag, cswhFeatureTag, cursFeatureTag, kernFeatureTag, mkmkFeatureTag, emptyTag, sl@0: sl@0: mediFeatureTag, ligaFeatureTag, msetFeatureTag, markFeatureTag, ccmpFeatureTag, rligFeatureTag, sl@0: caltFeatureTag, dligFeatureTag, cswhFeatureTag, cursFeatureTag, kernFeatureTag, mkmkFeatureTag, emptyTag sl@0: }; sl@0: sl@0: #define TAGS_PER_GLYPH ((sizeof ArabicShaping::tagArray / sizeof ArabicShaping::tagArray[0]) / 4) sl@0: sl@0: const LETag *ArabicShaping::getFeatureOrder() sl@0: { sl@0: return featureOrder; sl@0: } sl@0: sl@0: void ArabicShaping::adjustTags(le_int32 outIndex, le_int32 shapeOffset, LEGlyphStorage &glyphStorage) sl@0: { sl@0: LEErrorCode success = LE_NO_ERROR; sl@0: const LETag *glyphTags = (const LETag *) glyphStorage.getAuxData(outIndex, success); sl@0: sl@0: glyphStorage.setAuxData(outIndex, (void *) &glyphTags[TAGS_PER_GLYPH * shapeOffset], success); sl@0: } sl@0: sl@0: void ArabicShaping::shape(const LEUnicode *chars, le_int32 offset, le_int32 charCount, le_int32 charMax, sl@0: le_bool rightToLeft, LEGlyphStorage &glyphStorage) sl@0: { sl@0: // iterate in logical order, store tags in visible order sl@0: // sl@0: // the effective right char is the most recently encountered sl@0: // non-transparent char sl@0: // sl@0: // four boolean states: sl@0: // the effective right char shapes sl@0: // the effective right char causes left shaping sl@0: // the current char shapes sl@0: // the current char causes right shaping sl@0: // sl@0: // if both cause shaping, then sl@0: // shaper.shape(errout, 2) (isolate to initial, or final to medial) sl@0: // shaper.shape(out, 1) (isolate to final) sl@0: sl@0: ShapeType rightType = ST_NOSHAPE_NONE, leftType = ST_NOSHAPE_NONE; sl@0: LEErrorCode success = LE_NO_ERROR; sl@0: le_int32 i; sl@0: sl@0: for (i = offset - 1; i >= 0; i -= 1) { sl@0: rightType = getShapeType(chars[i]); sl@0: sl@0: if (rightType != ST_TRANSPARENT) { sl@0: break; sl@0: } sl@0: } sl@0: sl@0: for (i = offset + charCount; i < charMax; i += 1) { sl@0: leftType = getShapeType(chars[i]); sl@0: sl@0: if (leftType != ST_TRANSPARENT) { sl@0: break; sl@0: } sl@0: } sl@0: sl@0: // erout is effective right logical index sl@0: le_int32 erout = -1; sl@0: le_bool rightShapes = FALSE; sl@0: le_bool rightCauses = (rightType & MASK_SHAPE_LEFT) != 0; sl@0: le_int32 in, e, out = 0, dir = 1; sl@0: sl@0: if (rightToLeft) { sl@0: out = charCount - 1; sl@0: erout = charCount; sl@0: dir = -1; sl@0: } sl@0: sl@0: for (in = offset, e = offset + charCount; in < e; in += 1, out += dir) { sl@0: LEUnicode c = chars[in]; sl@0: ShapeType t = getShapeType(c); sl@0: sl@0: glyphStorage.setAuxData(out, (void *) tagArray, success); sl@0: sl@0: if ((t & MASK_TRANSPARENT) != 0) { sl@0: continue; sl@0: } sl@0: sl@0: le_bool curShapes = (t & MASK_NOSHAPE) == 0; sl@0: le_bool curCauses = (t & MASK_SHAPE_RIGHT) != 0; sl@0: sl@0: if (rightCauses && curCauses) { sl@0: if (rightShapes) { sl@0: adjustTags(erout, 2, glyphStorage); sl@0: } sl@0: sl@0: if (curShapes) { sl@0: adjustTags(out, 1, glyphStorage); sl@0: } sl@0: } sl@0: sl@0: rightShapes = curShapes; sl@0: rightCauses = (t & MASK_SHAPE_LEFT) != 0; sl@0: erout = out; sl@0: } sl@0: sl@0: if (rightShapes && rightCauses && (leftType & MASK_SHAPE_RIGHT) != 0) { sl@0: adjustTags(erout, 2, glyphStorage); sl@0: } sl@0: } sl@0: sl@0: U_NAMESPACE_END