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