1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho * (C) Copyright IBM Corp. 1998-2008 - All Rights Reserved
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LETypes.h"
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "OpenTypeTables.h"
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ArabicShaping.h"
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LEGlyphStorage.h"
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "ClassDefinitionTables.h"
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// This table maps Unicode joining types to
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ShapeTypes.
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst ArabicShaping::ShapeType ArabicShaping::shapeTypes[] =
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ArabicShaping::ST_NOSHAPE_NONE, // [U]
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ArabicShaping::ST_NOSHAPE_DUAL, // [C]
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ArabicShaping::ST_DUAL,         // [D]
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ArabicShaping::ST_LEFT,         // [L]
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ArabicShaping::ST_RIGHT,        // [R]
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ArabicShaping::ST_TRANSPARENT   // [T]
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    shaping array holds types for Arabic chars between 0610 and 0700
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    other values are either unshaped, or transparent if a mark or format
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    code, except for format codes 200c (zero-width non-joiner) and 200d
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    (dual-width joiner) which are both unshaped and non_joining or
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    dual-joining, respectively.
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruArabicShaping::ShapeType ArabicShaping::getShapeType(LEUnicode c)
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const ClassDefinitionTable *joiningTypes = (const ClassDefinitionTable *) ArabicShaping::shapingTypeTable;
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 joiningType = joiningTypes->getGlyphClass(c);
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (joiningType >= 0 && joiningType < ArabicShaping::JT_COUNT) {
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return ArabicShaping::shapeTypes[joiningType];
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return ArabicShaping::ST_NOSHAPE_NONE;
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define isolFeatureTag LE_ISOL_FEATURE_TAG
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define initFeatureTag LE_INIT_FEATURE_TAG
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define mediFeatureTag LE_MEDI_FEATURE_TAG
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define finaFeatureTag LE_FINA_FEATURE_TAG
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ligaFeatureTag LE_LIGA_FEATURE_TAG
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define msetFeatureTag LE_MSET_FEATURE_TAG
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define markFeatureTag LE_MARK_FEATURE_TAG
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ccmpFeatureTag LE_CCMP_FEATURE_TAG
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define rligFeatureTag LE_RLIG_FEATURE_TAG
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define caltFeatureTag LE_CALT_FEATURE_TAG
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define dligFeatureTag LE_DLIG_FEATURE_TAG
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define cswhFeatureTag LE_CSWH_FEATURE_TAG
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define cursFeatureTag LE_CURS_FEATURE_TAG
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define kernFeatureTag LE_KERN_FEATURE_TAG
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define mkmkFeatureTag LE_MKMK_FEATURE_TAG
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// NOTE:
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// The isol, fina, init and medi features must be
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// defined in the above order, and have masks that
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// are all in the same nibble.
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define isolFeatureMask 0x80000000UL
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define finaFeatureMask 0x40000000UL
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define initFeatureMask 0x20000000UL
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define mediFeatureMask 0x10000000UL
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ccmpFeatureMask 0x08000000UL
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define rligFeatureMask 0x04000000UL
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define caltFeatureMask 0x02000000UL
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ligaFeatureMask 0x01000000UL
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define dligFeatureMask 0x00800000UL
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define cswhFeatureMask 0x00400000UL
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define msetFeatureMask 0x00200000UL
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define cursFeatureMask 0x00100000UL
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define kernFeatureMask 0x00080000UL
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define markFeatureMask 0x00040000UL
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define mkmkFeatureMask 0x00020000UL
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
8285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#define NO_FEATURES   0
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ISOL_FEATURES (isolFeatureMask | ligaFeatureMask | msetFeatureMask | markFeatureMask | ccmpFeatureMask | rligFeatureMask | caltFeatureMask | dligFeatureMask | cswhFeatureMask | cursFeatureMask | kernFeatureMask | mkmkFeatureMask)
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SHAPE_MASK 0xF0000000UL
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const FeatureMap featureMap[] = {
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {ccmpFeatureTag, ccmpFeatureMask},
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {isolFeatureTag, isolFeatureMask},
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {finaFeatureTag, finaFeatureMask},
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {mediFeatureTag, mediFeatureMask},
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {initFeatureTag, initFeatureMask},
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {rligFeatureTag, rligFeatureMask},
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {caltFeatureTag, caltFeatureMask},
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {ligaFeatureTag, ligaFeatureMask},
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {dligFeatureTag, dligFeatureMask},
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {cswhFeatureTag, cswhFeatureMask},
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {msetFeatureTag, msetFeatureMask},
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {cursFeatureTag, cursFeatureMask},
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {kernFeatureTag, kernFeatureMask},
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {markFeatureTag, markFeatureMask},
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {mkmkFeatureTag, mkmkFeatureMask}
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst FeatureMap *ArabicShaping::getFeatureMap(le_int32 &count)
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    count = LE_ARRAY_SIZE(featureMap);
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return featureMap;
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid ArabicShaping::adjustTags(le_int32 outIndex, le_int32 shapeOffset, LEGlyphStorage &glyphStorage)
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LEErrorCode success = LE_NO_ERROR;
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    FeatureMask featureMask = (FeatureMask) glyphStorage.getAuxData(outIndex, success);
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    FeatureMask shape = featureMask & SHAPE_MASK;
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    shape >>= shapeOffset;
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    glyphStorage.setAuxData(outIndex, ((featureMask & ~SHAPE_MASK) | shape), success);
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid ArabicShaping::shape(const LEUnicode *chars, le_int32 offset, le_int32 charCount, le_int32 charMax,
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          le_bool rightToLeft, LEGlyphStorage &glyphStorage)
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // iterate in logical order, store tags in visible order
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // the effective right char is the most recently encountered
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // non-transparent char
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // four boolean states:
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //   the effective right char shapes
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //   the effective right char causes left shaping
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //   the current char shapes
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //   the current char causes right shaping
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // if both cause shaping, then
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //   shaper.shape(errout, 2) (isolate to initial, or final to medial)
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    //   shaper.shape(out, 1) (isolate to final)
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ShapeType rightType = ST_NOSHAPE_NONE, leftType = ST_NOSHAPE_NONE;
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LEErrorCode success = LE_NO_ERROR;
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 i;
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (i = offset - 1; i >= 0; i -= 1) {
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        rightType = getShapeType(chars[i]);
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (rightType != ST_TRANSPARENT) {
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (i = offset + charCount; i < charMax; i += 1) {
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        leftType = getShapeType(chars[i]);
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (leftType != ST_TRANSPARENT) {
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // erout is effective right logical index
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 erout = -1;
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_bool rightShapes = FALSE;
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_bool rightCauses = (rightType & MASK_SHAPE_LEFT) != 0;
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    le_int32 in, e, out = 0, dir = 1;
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (rightToLeft) {
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        out = charCount - 1;
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        erout = charCount;
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        dir = -1;
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (in = offset, e = offset + charCount; in < e; in += 1, out += dir) {
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        LEUnicode c = chars[in];
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ShapeType t = getShapeType(c);
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
17785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (t == ST_NOSHAPE_NONE) {
17885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            glyphStorage.setAuxData(out, NO_FEATURES, success);
17985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else {
18085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            glyphStorage.setAuxData(out, ISOL_FEATURES, success);
18185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if ((t & MASK_TRANSPARENT) != 0) {
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            continue;
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        le_bool curShapes = (t & MASK_NOSHAPE) == 0;
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        le_bool curCauses = (t & MASK_SHAPE_RIGHT) != 0;
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (rightCauses && curCauses) {
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (rightShapes) {
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                adjustTags(erout, 2, glyphStorage);
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (curShapes) {
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                adjustTags(out, 1, glyphStorage);
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        rightShapes = curShapes;
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        rightCauses = (t & MASK_SHAPE_LEFT) != 0;
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        erout = out;
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (rightShapes && rightCauses && (leftType & MASK_SHAPE_RIGHT) != 0) {
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        adjustTags(erout, 2, glyphStorage);
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END
211