os/textandloc/fontservices/textshaperplugin/IcuSource/layout/ArabicShaping.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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