fontservices/textshaperplugin/IcuSource/layout/ArabicShaping.cpp
changeset 0 1fb32624e06b
equal deleted inserted replaced
-1:000000000000 0:1fb32624e06b
       
     1 /*
       
     2  *
       
     3  * (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved
       
     4  *
       
     5  */
       
     6 
       
     7 #include "LETypes.h"
       
     8 #include "OpenTypeTables.h"
       
     9 #include "ArabicShaping.h"
       
    10 #include "LEGlyphStorage.h"
       
    11 
       
    12 U_NAMESPACE_BEGIN
       
    13 
       
    14 enum {
       
    15     _c_ = ArabicShaping::ST_NOSHAPE_DUAL,
       
    16     _d_ = ArabicShaping::ST_DUAL,
       
    17     _n_ = ArabicShaping::ST_NONE,
       
    18     _r_ = ArabicShaping::ST_RIGHT,
       
    19     _t_ = ArabicShaping::ST_TRANSPARENT,
       
    20     _x_ = ArabicShaping::ST_NOSHAPE_NONE
       
    21 };
       
    22 
       
    23 const ArabicShaping::ShapeType ArabicShaping::shapeTypes[] =
       
    24 {
       
    25     _t_, _t_, _t_, _t_, _t_, _t_, _x_, _x_, _x_, _x_, _x_, _n_, _x_, _x_, _x_, _n_,   // 0x610 - 0x61f
       
    26     _x_, _n_, _r_, _r_, _r_, _r_, _d_, _r_, _d_, _r_, _d_, _d_, _d_, _d_, _d_, _r_,   // 0x620 - 0x62f
       
    27     _r_, _r_, _r_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _x_, _x_, _x_, _x_, _x_,   // 0x630 - 0x63f
       
    28     _c_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _r_, _d_, _d_, _t_, _t_, _t_, _t_, _t_,   // 0x640 - 0x64f
       
    29     _t_, _t_, _t_, _t_, _t_, _t_, _t_, _t_, _t_, _x_, _x_, _x_, _x_, _x_, _x_, _x_,   // 0x650 - 0x65f
       
    30     _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _d_, _d_,   // 0x660 - 0x66f
       
    31     _t_, _r_, _r_, _r_, _n_, _r_, _r_, _r_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_,   // 0x670 - 0x67f
       
    32     _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_,   // 0x680 - 0x68f
       
    33     _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _d_, _d_, _d_, _d_, _d_, _d_,   // 0x690 - 0x69f
       
    34     _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_,   // 0x6a0 - 0x6af
       
    35     _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_, _d_,   // 0x6b0 - 0x6bf
       
    36     _r_, _d_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _r_, _d_, _r_, _d_, _r_,   // 0x6c0 - 0x6cf
       
    37     _d_, _d_, _r_, _r_, _n_, _r_, _t_, _t_, _t_, _t_, _t_, _t_, _t_, _x_, _t_, _t_,   // 0x6d0 - 0x6df
       
    38     _t_, _t_, _t_, _t_, _t_, _n_, _n_, _t_, _t_, _n_, _t_, _t_, _t_, _t_, _r_, _r_,   // 0x6e0 - 0x6ef
       
    39     _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _n_, _d_, _d_, _d_, _n_, _n_, _d_    // 0x6f0 - 0x6ff
       
    40 };
       
    41 
       
    42 /*
       
    43     shaping array holds types for Arabic chars between 0610 and 0700
       
    44     other values are either unshaped, or transparent if a mark or format
       
    45     code, except for format codes 200c (zero-width non-joiner) and 200d 
       
    46     (dual-width joiner) which are both unshaped and non_joining or
       
    47     dual-joining, respectively.
       
    48 */
       
    49 ArabicShaping::ShapeType ArabicShaping::getShapeType(LEUnicode c)
       
    50 {
       
    51     if (c >= 0x0610 && c <= 0x206f) {
       
    52         if (c < 0x0700) {
       
    53             return shapeTypes[c - 0x0610];
       
    54         } else if (c == 0x200c) {   // ZWNJ
       
    55             return ST_NOSHAPE_NONE;
       
    56         } else if (c == 0x200d) {   // ZWJ
       
    57             return ST_NOSHAPE_DUAL;
       
    58         } else if (c >= 0x202a && c <= 0x202e) { // LRE - RLO
       
    59             return ST_TRANSPARENT;
       
    60         } else if (c >= 0x206a && c <= 0x206f) { // Inhibit Symmetric Swapping - Nominal Digit Shapes
       
    61             return ST_TRANSPARENT;
       
    62         }
       
    63     }
       
    64 
       
    65     return ST_NOSHAPE_NONE;
       
    66 }
       
    67 
       
    68 static const LETag isolFeatureTag = LE_ISOL_FEATURE_TAG;
       
    69 static const LETag initFeatureTag = LE_INIT_FEATURE_TAG;
       
    70 static const LETag mediFeatureTag = LE_MEDI_FEATURE_TAG;
       
    71 static const LETag finaFeatureTag = LE_FINA_FEATURE_TAG;
       
    72 static const LETag ligaFeatureTag = LE_LIGA_FEATURE_TAG;
       
    73 static const LETag msetFeatureTag = LE_MSET_FEATURE_TAG;
       
    74 static const LETag markFeatureTag = LE_MARK_FEATURE_TAG;
       
    75 static const LETag ccmpFeatureTag = LE_CCMP_FEATURE_TAG;
       
    76 static const LETag rligFeatureTag = LE_RLIG_FEATURE_TAG;
       
    77 static const LETag caltFeatureTag = LE_CALT_FEATURE_TAG;
       
    78 static const LETag dligFeatureTag = LE_DLIG_FEATURE_TAG;
       
    79 static const LETag cswhFeatureTag = LE_CSWH_FEATURE_TAG;
       
    80 static const LETag cursFeatureTag = LE_CURS_FEATURE_TAG;
       
    81 static const LETag kernFeatureTag = LE_KERN_FEATURE_TAG;
       
    82 static const LETag mkmkFeatureTag = LE_MKMK_FEATURE_TAG;
       
    83 
       
    84 static const LETag emptyTag       = 0x00000000; // ''
       
    85 
       
    86 static const LETag featureOrder[] = 
       
    87 {
       
    88     ccmpFeatureTag, isolFeatureTag, finaFeatureTag, mediFeatureTag, initFeatureTag, rligFeatureTag,
       
    89     caltFeatureTag, ligaFeatureTag, dligFeatureTag, cswhFeatureTag, msetFeatureTag, cursFeatureTag,
       
    90     kernFeatureTag, markFeatureTag, mkmkFeatureTag, emptyTag
       
    91 };
       
    92 
       
    93 const LETag ArabicShaping::tagArray[] =
       
    94 {
       
    95     isolFeatureTag, ligaFeatureTag, msetFeatureTag, markFeatureTag, ccmpFeatureTag, rligFeatureTag,
       
    96         caltFeatureTag, dligFeatureTag, cswhFeatureTag, cursFeatureTag, kernFeatureTag, mkmkFeatureTag, emptyTag,
       
    97 
       
    98     finaFeatureTag, ligaFeatureTag, msetFeatureTag, markFeatureTag, ccmpFeatureTag, rligFeatureTag,
       
    99         caltFeatureTag, dligFeatureTag, cswhFeatureTag, cursFeatureTag, kernFeatureTag, mkmkFeatureTag, emptyTag,
       
   100 
       
   101     initFeatureTag, ligaFeatureTag, msetFeatureTag, markFeatureTag, ccmpFeatureTag, rligFeatureTag,
       
   102         caltFeatureTag, dligFeatureTag, cswhFeatureTag, cursFeatureTag, kernFeatureTag, mkmkFeatureTag, emptyTag,
       
   103 
       
   104     mediFeatureTag, ligaFeatureTag, msetFeatureTag, markFeatureTag, ccmpFeatureTag, rligFeatureTag,
       
   105         caltFeatureTag, dligFeatureTag, cswhFeatureTag, cursFeatureTag, kernFeatureTag, mkmkFeatureTag, emptyTag
       
   106 };
       
   107 
       
   108 #define TAGS_PER_GLYPH ((sizeof ArabicShaping::tagArray / sizeof ArabicShaping::tagArray[0]) / 4)
       
   109 
       
   110 const LETag *ArabicShaping::getFeatureOrder()
       
   111 {
       
   112     return featureOrder;
       
   113 }
       
   114 
       
   115 void ArabicShaping::adjustTags(le_int32 outIndex, le_int32 shapeOffset, LEGlyphStorage &glyphStorage)
       
   116 {
       
   117     LEErrorCode success = LE_NO_ERROR;
       
   118     const LETag *glyphTags = (const LETag *) glyphStorage.getAuxData(outIndex, success);
       
   119 
       
   120     glyphStorage.setAuxData(outIndex, (void *) &glyphTags[TAGS_PER_GLYPH * shapeOffset], success);
       
   121 }
       
   122 
       
   123 void ArabicShaping::shape(const LEUnicode *chars, le_int32 offset, le_int32 charCount, le_int32 charMax,
       
   124                           le_bool rightToLeft, LEGlyphStorage &glyphStorage)
       
   125 {
       
   126     // iterate in logical order, store tags in visible order
       
   127     // 
       
   128     // the effective right char is the most recently encountered 
       
   129     // non-transparent char
       
   130     //
       
   131     // four boolean states:
       
   132     //   the effective right char shapes
       
   133     //   the effective right char causes left shaping
       
   134     //   the current char shapes
       
   135     //   the current char causes right shaping
       
   136     // 
       
   137     // if both cause shaping, then
       
   138     //   shaper.shape(errout, 2) (isolate to initial, or final to medial)
       
   139     //   shaper.shape(out, 1) (isolate to final)
       
   140 
       
   141     ShapeType rightType = ST_NOSHAPE_NONE, leftType = ST_NOSHAPE_NONE;
       
   142     LEErrorCode success = LE_NO_ERROR;
       
   143     le_int32 i;
       
   144 
       
   145     for (i = offset - 1; i >= 0; i -= 1) {
       
   146         rightType = getShapeType(chars[i]);
       
   147         
       
   148         if (rightType != ST_TRANSPARENT) {
       
   149             break;
       
   150         }
       
   151     }
       
   152 
       
   153     for (i = offset + charCount; i < charMax; i += 1) {
       
   154         leftType = getShapeType(chars[i]);
       
   155 
       
   156         if (leftType != ST_TRANSPARENT) {
       
   157             break;
       
   158         }
       
   159     }
       
   160 
       
   161     // erout is effective right logical index
       
   162     le_int32 erout = -1;
       
   163     le_bool rightShapes = FALSE;
       
   164     le_bool rightCauses = (rightType & MASK_SHAPE_LEFT) != 0;
       
   165     le_int32 in, e, out = 0, dir = 1;
       
   166 
       
   167     if (rightToLeft) {
       
   168         out = charCount - 1;
       
   169         erout = charCount;
       
   170         dir = -1;
       
   171     }
       
   172 
       
   173     for (in = offset, e = offset + charCount; in < e; in += 1, out += dir) {
       
   174         LEUnicode c = chars[in];
       
   175         ShapeType t = getShapeType(c);
       
   176 
       
   177         glyphStorage.setAuxData(out, (void *) tagArray, success);
       
   178 
       
   179         if ((t & MASK_TRANSPARENT) != 0) {
       
   180             continue;
       
   181         }
       
   182 
       
   183         le_bool curShapes = (t & MASK_NOSHAPE) == 0;
       
   184         le_bool curCauses = (t & MASK_SHAPE_RIGHT) != 0;
       
   185 
       
   186         if (rightCauses && curCauses) {
       
   187             if (rightShapes) {
       
   188                 adjustTags(erout, 2, glyphStorage);
       
   189             }
       
   190 
       
   191             if (curShapes) {
       
   192                 adjustTags(out, 1, glyphStorage);
       
   193             }
       
   194         }
       
   195 
       
   196         rightShapes = curShapes;
       
   197         rightCauses = (t & MASK_SHAPE_LEFT) != 0;
       
   198         erout = out;
       
   199     }
       
   200 
       
   201     if (rightShapes && rightCauses && (leftType & MASK_SHAPE_RIGHT) != 0) {
       
   202         adjustTags(erout, 2, glyphStorage);
       
   203     }
       
   204 }
       
   205 
       
   206 U_NAMESPACE_END