1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/textandloc/fontservices/textshaperplugin/IcuSource/layout/ArabicShaping.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,206 @@
1.4 +/*
1.5 + *
1.6 + * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
1.7 + *
1.8 + */
1.9 +
1.10 +#include "LETypes.h"
1.11 +#include "OpenTypeTables.h"
1.12 +#include "ArabicShaping.h"
1.13 +#include "LEGlyphStorage.h"
1.14 +
1.15 +U_NAMESPACE_BEGIN
1.16 +
1.17 +enum {
1.18 + _c_ = ArabicShaping::ST_NOSHAPE_DUAL,
1.19 + _d_ = ArabicShaping::ST_DUAL,
1.20 + _n_ = ArabicShaping::ST_NONE,
1.21 + _r_ = ArabicShaping::ST_RIGHT,
1.22 + _t_ = ArabicShaping::ST_TRANSPARENT,
1.23 + _x_ = ArabicShaping::ST_NOSHAPE_NONE
1.24 +};
1.25 +
1.26 +const ArabicShaping::ShapeType ArabicShaping::shapeTypes[] =
1.27 +{
1.28 + _t_, _t_, _t_, _t_, _t_, _t_, _x_, _x_, _x_, _x_, _x_, _n_, _x_, _x_, _x_, _n_, // 0x610 - 0x61f
1.29 + _x_, _n_, _r_, _r_, _r_, _r_, _d_, _r_, _d_, _r_, _d_, _d_, _d_, _d_, _d_, _r_, // 0x620 - 0x62f
1.30 + _r_, _r_, _r_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _x_, _x_, _x_, _x_, _x_, // 0x630 - 0x63f
1.31 + _c_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _r_, _d_, _d_, _t_, _t_, _t_, _t_, _t_, // 0x640 - 0x64f
1.32 + _t_, _t_, _t_, _t_, _t_, _t_, _t_, _t_, _t_, _x_, _x_, _x_, _x_, _x_, _x_, _x_, // 0x650 - 0x65f
1.33 + _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _d_, _d_, // 0x660 - 0x66f
1.34 + _t_, _r_, _r_, _r_, _n_, _r_, _r_, _r_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, // 0x670 - 0x67f
1.35 + _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, // 0x680 - 0x68f
1.36 + _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _d_, _d_, _d_, _d_, _d_, _d_, // 0x690 - 0x69f
1.37 + _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, // 0x6a0 - 0x6af
1.38 + _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, // 0x6b0 - 0x6bf
1.39 + _r_, _d_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _d_, _r_, _d_, _r_, // 0x6c0 - 0x6cf
1.40 + _d_, _d_, _r_, _r_, _n_, _r_, _t_, _t_, _t_, _t_, _t_, _t_, _t_, _x_, _t_, _t_, // 0x6d0 - 0x6df
1.41 + _t_, _t_, _t_, _t_, _t_, _n_, _n_, _t_, _t_, _n_, _t_, _t_, _t_, _t_, _r_, _r_, // 0x6e0 - 0x6ef
1.42 + _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _d_, _d_, _d_, _n_, _n_, _d_ // 0x6f0 - 0x6ff
1.43 +};
1.44 +
1.45 +/*
1.46 + shaping array holds types for Arabic chars between 0610 and 0700
1.47 + other values are either unshaped, or transparent if a mark or format
1.48 + code, except for format codes 200c (zero-width non-joiner) and 200d
1.49 + (dual-width joiner) which are both unshaped and non_joining or
1.50 + dual-joining, respectively.
1.51 +*/
1.52 +ArabicShaping::ShapeType ArabicShaping::getShapeType(LEUnicode c)
1.53 +{
1.54 + if (c >= 0x0610 && c <= 0x206f) {
1.55 + if (c < 0x0700) {
1.56 + return shapeTypes[c - 0x0610];
1.57 + } else if (c == 0x200c) { // ZWNJ
1.58 + return ST_NOSHAPE_NONE;
1.59 + } else if (c == 0x200d) { // ZWJ
1.60 + return ST_NOSHAPE_DUAL;
1.61 + } else if (c >= 0x202a && c <= 0x202e) { // LRE - RLO
1.62 + return ST_TRANSPARENT;
1.63 + } else if (c >= 0x206a && c <= 0x206f) { // Inhibit Symmetric Swapping - Nominal Digit Shapes
1.64 + return ST_TRANSPARENT;
1.65 + }
1.66 + }
1.67 +
1.68 + return ST_NOSHAPE_NONE;
1.69 +}
1.70 +
1.71 +static const LETag isolFeatureTag = LE_ISOL_FEATURE_TAG;
1.72 +static const LETag initFeatureTag = LE_INIT_FEATURE_TAG;
1.73 +static const LETag mediFeatureTag = LE_MEDI_FEATURE_TAG;
1.74 +static const LETag finaFeatureTag = LE_FINA_FEATURE_TAG;
1.75 +static const LETag ligaFeatureTag = LE_LIGA_FEATURE_TAG;
1.76 +static const LETag msetFeatureTag = LE_MSET_FEATURE_TAG;
1.77 +static const LETag markFeatureTag = LE_MARK_FEATURE_TAG;
1.78 +static const LETag ccmpFeatureTag = LE_CCMP_FEATURE_TAG;
1.79 +static const LETag rligFeatureTag = LE_RLIG_FEATURE_TAG;
1.80 +static const LETag caltFeatureTag = LE_CALT_FEATURE_TAG;
1.81 +static const LETag dligFeatureTag = LE_DLIG_FEATURE_TAG;
1.82 +static const LETag cswhFeatureTag = LE_CSWH_FEATURE_TAG;
1.83 +static const LETag cursFeatureTag = LE_CURS_FEATURE_TAG;
1.84 +static const LETag kernFeatureTag = LE_KERN_FEATURE_TAG;
1.85 +static const LETag mkmkFeatureTag = LE_MKMK_FEATURE_TAG;
1.86 +
1.87 +static const LETag emptyTag = 0x00000000; // ''
1.88 +
1.89 +static const LETag featureOrder[] =
1.90 +{
1.91 + ccmpFeatureTag, isolFeatureTag, finaFeatureTag, mediFeatureTag, initFeatureTag, rligFeatureTag,
1.92 + caltFeatureTag, ligaFeatureTag, dligFeatureTag, cswhFeatureTag, msetFeatureTag, cursFeatureTag,
1.93 + kernFeatureTag, markFeatureTag, mkmkFeatureTag, emptyTag
1.94 +};
1.95 +
1.96 +const LETag ArabicShaping::tagArray[] =
1.97 +{
1.98 + isolFeatureTag, ligaFeatureTag, msetFeatureTag, markFeatureTag, ccmpFeatureTag, rligFeatureTag,
1.99 + caltFeatureTag, dligFeatureTag, cswhFeatureTag, cursFeatureTag, kernFeatureTag, mkmkFeatureTag, emptyTag,
1.100 +
1.101 + finaFeatureTag, ligaFeatureTag, msetFeatureTag, markFeatureTag, ccmpFeatureTag, rligFeatureTag,
1.102 + caltFeatureTag, dligFeatureTag, cswhFeatureTag, cursFeatureTag, kernFeatureTag, mkmkFeatureTag, emptyTag,
1.103 +
1.104 + initFeatureTag, ligaFeatureTag, msetFeatureTag, markFeatureTag, ccmpFeatureTag, rligFeatureTag,
1.105 + caltFeatureTag, dligFeatureTag, cswhFeatureTag, cursFeatureTag, kernFeatureTag, mkmkFeatureTag, emptyTag,
1.106 +
1.107 + mediFeatureTag, ligaFeatureTag, msetFeatureTag, markFeatureTag, ccmpFeatureTag, rligFeatureTag,
1.108 + caltFeatureTag, dligFeatureTag, cswhFeatureTag, cursFeatureTag, kernFeatureTag, mkmkFeatureTag, emptyTag
1.109 +};
1.110 +
1.111 +#define TAGS_PER_GLYPH ((sizeof ArabicShaping::tagArray / sizeof ArabicShaping::tagArray[0]) / 4)
1.112 +
1.113 +const LETag *ArabicShaping::getFeatureOrder()
1.114 +{
1.115 + return featureOrder;
1.116 +}
1.117 +
1.118 +void ArabicShaping::adjustTags(le_int32 outIndex, le_int32 shapeOffset, LEGlyphStorage &glyphStorage)
1.119 +{
1.120 + LEErrorCode success = LE_NO_ERROR;
1.121 + const LETag *glyphTags = (const LETag *) glyphStorage.getAuxData(outIndex, success);
1.122 +
1.123 + glyphStorage.setAuxData(outIndex, (void *) &glyphTags[TAGS_PER_GLYPH * shapeOffset], success);
1.124 +}
1.125 +
1.126 +void ArabicShaping::shape(const LEUnicode *chars, le_int32 offset, le_int32 charCount, le_int32 charMax,
1.127 + le_bool rightToLeft, LEGlyphStorage &glyphStorage)
1.128 +{
1.129 + // iterate in logical order, store tags in visible order
1.130 + //
1.131 + // the effective right char is the most recently encountered
1.132 + // non-transparent char
1.133 + //
1.134 + // four boolean states:
1.135 + // the effective right char shapes
1.136 + // the effective right char causes left shaping
1.137 + // the current char shapes
1.138 + // the current char causes right shaping
1.139 + //
1.140 + // if both cause shaping, then
1.141 + // shaper.shape(errout, 2) (isolate to initial, or final to medial)
1.142 + // shaper.shape(out, 1) (isolate to final)
1.143 +
1.144 + ShapeType rightType = ST_NOSHAPE_NONE, leftType = ST_NOSHAPE_NONE;
1.145 + LEErrorCode success = LE_NO_ERROR;
1.146 + le_int32 i;
1.147 +
1.148 + for (i = offset - 1; i >= 0; i -= 1) {
1.149 + rightType = getShapeType(chars[i]);
1.150 +
1.151 + if (rightType != ST_TRANSPARENT) {
1.152 + break;
1.153 + }
1.154 + }
1.155 +
1.156 + for (i = offset + charCount; i < charMax; i += 1) {
1.157 + leftType = getShapeType(chars[i]);
1.158 +
1.159 + if (leftType != ST_TRANSPARENT) {
1.160 + break;
1.161 + }
1.162 + }
1.163 +
1.164 + // erout is effective right logical index
1.165 + le_int32 erout = -1;
1.166 + le_bool rightShapes = FALSE;
1.167 + le_bool rightCauses = (rightType & MASK_SHAPE_LEFT) != 0;
1.168 + le_int32 in, e, out = 0, dir = 1;
1.169 +
1.170 + if (rightToLeft) {
1.171 + out = charCount - 1;
1.172 + erout = charCount;
1.173 + dir = -1;
1.174 + }
1.175 +
1.176 + for (in = offset, e = offset + charCount; in < e; in += 1, out += dir) {
1.177 + LEUnicode c = chars[in];
1.178 + ShapeType t = getShapeType(c);
1.179 +
1.180 + glyphStorage.setAuxData(out, (void *) tagArray, success);
1.181 +
1.182 + if ((t & MASK_TRANSPARENT) != 0) {
1.183 + continue;
1.184 + }
1.185 +
1.186 + le_bool curShapes = (t & MASK_NOSHAPE) == 0;
1.187 + le_bool curCauses = (t & MASK_SHAPE_RIGHT) != 0;
1.188 +
1.189 + if (rightCauses && curCauses) {
1.190 + if (rightShapes) {
1.191 + adjustTags(erout, 2, glyphStorage);
1.192 + }
1.193 +
1.194 + if (curShapes) {
1.195 + adjustTags(out, 1, glyphStorage);
1.196 + }
1.197 + }
1.198 +
1.199 + rightShapes = curShapes;
1.200 + rightCauses = (t & MASK_SHAPE_LEFT) != 0;
1.201 + erout = out;
1.202 + }
1.203 +
1.204 + if (rightShapes && rightCauses && (leftType & MASK_SHAPE_RIGHT) != 0) {
1.205 + adjustTags(erout, 2, glyphStorage);
1.206 + }
1.207 +}
1.208 +
1.209 +U_NAMESPACE_END