~ubuntu-branches/ubuntu/karmic/pango1.0/karmic-security

« back to all changes in this revision

Viewing changes to modules/syriac/syriac-ot.c

Tags: upstream-1.15.4
ImportĀ upstreamĀ versionĀ 1.15.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Pango
 
2
 * syriac-ot.h: Determine what OpenType features to apply to characters based
 
3
 *              on the rules for Syriac from the OpenType standard.
 
4
 *
 
5
 * Copyright (C) 2004 Emil Soleyman-Zomalan
 
6
 * Author: Emil Soleyman-Zomalan <emil@soleyman.com>
 
7
 *
 
8
 * This file is based on the Arabic shaping code from FreeType 1 tree; original
 
9
 * copyright notice:
 
10
 *
 
11
 *  The FreeType project -- a free and portable quality TrueType renderer.
 
12
 *
 
13
 *  Copyright 1996-2000 by
 
14
 *  D. Turner, R.Wilhelm, and W. Lemberg
 
15
 *
 
16
 * The code, like the FreeType code it is derived from is dual-licensed
 
17
 * under the GNU General Public License and the FreeType license. See
 
18
 * pango/opentype/COPYING for full details of this licensing scheme.
 
19
 */
 
20
#include <config.h>
 
21
#include "syriac-ot.h"
 
22
 
 
23
/*     Here a table of the joining classes for characters in the range
 
24
 *     U+0700 - U+074F.
 
25
 *
 
26
 *     The following character also has a joining class:
 
27
 *
 
28
 *     U+200C  ZERO WIDTH NON-JOINER  -> causing
 
29
 *
 
30
 *     All other characters are given the joining class `none'.
 
31
 */
 
32
static const JoiningClass syriac[] =
 
33
{
 
34
  /* U+0700 */
 
35
  none, none, none, none,
 
36
  none, none, none, none,
 
37
  none, none, none, none,
 
38
  none, none, none, transparent,
 
39
 
 
40
  /* U+0710 */
 
41
  right, none, dual, dual,
 
42
  dual, right, right, right,
 
43
  right, right, dual, dual,
 
44
  dual, dual, right, dual,
 
45
 
 
46
  /* U+0720 */
 
47
  dual, dual, dual, dual,
 
48
  dual, dual, dual, dual,
 
49
  right, dual, right, dual,
 
50
  right, none, none, none,
 
51
 
 
52
  /* U+0730 */
 
53
  transparent, transparent, transparent, transparent,
 
54
  transparent, transparent, transparent, transparent,
 
55
  transparent, transparent, transparent, transparent,
 
56
  transparent, transparent, transparent, transparent,
 
57
 
 
58
  /* U+0740 */
 
59
  transparent, transparent, transparent, transparent,
 
60
  transparent, transparent, transparent, transparent,
 
61
  transparent, transparent, transparent, none,
 
62
  none, right, dual, dual
 
63
};
 
64
 
 
65
/* `direction' can be -1, 0, or 1 to indicate the last non-transparent
 
66
 * glyph, the current glyph, and the next non-transparent glyph,
 
67
 * respectively.
 
68
 */
 
69
static JoiningClass
 
70
Get_Joining_Class (gunichar*   string,
 
71
                   int         pos,
 
72
                   int         length,
 
73
                   int         direction)
 
74
{
 
75
  JoiningClass  j;
 
76
 
 
77
  while (1)
 
78
    {
 
79
      if (pos == 0 && direction < 0)
 
80
        return none;
 
81
 
 
82
      pos += direction;
 
83
 
 
84
      if (pos >= length)
 
85
        return none;
 
86
 
 
87
      if (string[pos] < 0x0700 ||
 
88
          string[pos] >= 0x074F)
 
89
        {
 
90
          if (string[pos] == 0x200C)
 
91
            return causing;
 
92
          else
 
93
            return none;
 
94
        }
 
95
      else
 
96
        j =  syriac[string[pos] - 0x0700];
 
97
 
 
98
      if (!direction || j != transparent)
 
99
        return j;
 
100
    }
 
101
}
 
102
 
 
103
 
 
104
/* The rules here are roughly based on the Arabic rules from the Unicode
 
105
 * 2.0 standard (which differ from the Unicode-4.0 rules), augmented
 
106
 * with the Syriac rules from the Unicode-4.0 standard. The numbers
 
107
 * R1...R11  below do not correspond to either the Arabic or the Syriac
 
108
 * rule numbering from the Unicode standard.
 
109
 *
 
110
 * Characters are here specified as appearing in the byte stream, i.e.
 
111
 * *not* in visual order. Joining classes are given in angle brackets,
 
112
 * glyph forms in square brackets.  Glyphs affected by a specific rule are
 
113
 * enclosed with vertical bars.
 
114
 *
 
115
 *
 
116
 * Glyphs: 0x0715 (Dalath), 0x0716 (Dalath Rish), 0x072A (Rish),
 
117
 *         0x0722 (Nun), 0x071F (Kaph)
 
118
 *
 
119
 *
 
120
 *   R1: <anything1> <transparent> <anything2>
 
121
 *
 
122
 *       apply joining rules for
 
123
 *       <anything1> <anything2> -> [shape1] [shape2]
 
124
 *       -> [shape1] [isolated] [shape2]
 
125
 *
 
126
 *
 
127
 *   R2: <causing|right> <0x0722|0x071F> <!(causing|right|dual)>
 
128
 *       -> [isolated]
 
129
 *
 
130
 *       The Nun and Kaph characters each have 3 different glyphs
 
131
 *       with two of those glyphs coming at the final position.
 
132
 *       However, one of those final glyphs should really be of the
 
133
 *       isolated glyph form where the preceding character cannot be
 
134
 *       joined to and there is no next character.
 
135
 *
 
136
 *       This rule exists to combine similar exception for both
 
137
 *       characters without increasing the complexity in the other
 
138
 *       rules.
 
139
 *
 
140
 *
 
141
 *   R3: <causing|right|dual> && <!(0x0715|0x0716|0x072A)> |<alaph>|
 
142
 *
 
143
 *       -> [final2]
 
144
 *
 
145
 *       If the preceding glyph cannot be joined to the current
 
146
 *       glyph and the preceding character is not a Dalath, Rish,
 
147
 *       or Dotless Dalath Rish, then the Alaph takes this contextual
 
148
 *       position.
 
149
 *
 
150
 *       The [final2] joining rule is placed ahead of the [final] to
 
151
 *       give it greater precedence when choosing the correct glyph.
 
152
 *       If it comes after the [final] rule, the incorrect glyph is
 
153
 *       inserted into position.
 
154
 *
 
155
 *
 
156
 *   R4: <0x0715|0x0715|0x072A> |<alaph>|
 
157
 *
 
158
 *       -> [final3]
 
159
 *
 
160
 *       If the previous glyph is a Dalath, Rish, or Dotless Dalath
 
161
 *       Rish, then the Alaph takes this contextual position.
 
162
 *
 
163
 *       The [final3] joining rule is placed ahead of the [final] to
 
164
 *       give it greater precedence when choosing the correct glyph.
 
165
 *       If it comes after the [final] rule, the incorrect glyph is
 
166
 *       inserted into position.
 
167
 *
 
168
 *
 
169
 *   R5: <causing|right|dual> |<right>|
 
170
 *
 
171
 *       -> [final]
 
172
 *
 
173
 *
 
174
 *   R6: <causing|right|dual> |<dual>| <!(causing|right|dual)>
 
175
 *
 
176
 *       -> [final]
 
177
 *
 
178
 *
 
179
 *   R7: <causing|left|dual> |<dual>| <causing|right|dual>
 
180
 *
 
181
 *       -> [medial]
 
182
 *
 
183
 *
 
184
 *   R8: <causing|right> |<alaph>| <causing|right|dual>
 
185
 *
 
186
 *       -> [medial2]
 
187
 *
 
188
 *       If the Alaph glyph falls in the middle of a Syriac word and
 
189
 *       the preceding character cannot be joined to, then the Alaph
 
190
 *       takes this contextual position.
 
191
 *
 
192
 *
 
193
 *   R9: |<left>| <causing|right|dual>
 
194
 *
 
195
 *       -> [initial]
 
196
 *
 
197
 *
 
198
 *   R10: <!(causing|left|dual)> |<dual>| <causing|right|dual>
 
199
 *
 
200
 *       -> [initial]
 
201
 *
 
202
 *
 
203
 *   R11: <anything> -> [isolated]
 
204
 *
 
205
 *        This joining rule is placed at the end of these features
 
206
 *        because when it is placed at the beginning of all of them
 
207
 *        it tends to break the cursive nature of Syriac writing --
 
208
 *        it inserts the isolated glyph of each character into that
 
209
 *        position with no joining occurring all throughout a text
 
210
 *        document.
 
211
 */
 
212
 
 
213
FT_Error
 
214
syriac_assign_properties (gunichar    *string,
 
215
                          gulong      *properties,
 
216
                          int          length)
 
217
{
 
218
  JoiningClass previous, current, next;
 
219
  int i;
 
220
 
 
221
  if (!string || !properties || length == 0)
 
222
    return FT_Err_Invalid_Argument;
 
223
 
 
224
  for (i = 0; i < length; i++)
 
225
    {
 
226
      previous = Get_Joining_Class (string, i, length, -1);
 
227
      current  = Get_Joining_Class (string, i, length,  0);
 
228
      next     = Get_Joining_Class (string, i, length,  1);
 
229
 
 
230
      /* R1 */
 
231
 
 
232
      if (current == transparent)
 
233
        {
 
234
          properties[i] |= isolated_p;
 
235
          continue;
 
236
        }
 
237
 
 
238
      /* R2 */
 
239
 
 
240
      if (string[i] == 0x0722 ||
 
241
          string[i] == 0x071F)
 
242
        if (previous == causing ||
 
243
            previous == right)
 
244
          if (!(next == causing ||
 
245
                next == right ||
 
246
                next == dual))
 
247
          {
 
248
            properties[i] |= isolated_p;
 
249
            continue;
 
250
          }
 
251
 
 
252
      /* R3 */
 
253
 
 
254
      if (string[i] == 0x0710)
 
255
        if (previous == causing ||
 
256
            previous == right)
 
257
          if (!(string[i - 1] == 0x0715 ||
 
258
                string[i - 1] == 0x0716 ||
 
259
                string[i - 1] == 0x072A))
 
260
          {
 
261
            properties[i] |= final2_p;
 
262
            continue;
 
263
          }
 
264
 
 
265
      /* R4 */
 
266
 
 
267
      if (string[i] == 0x0710)
 
268
        if (previous == causing ||
 
269
            previous == right)
 
270
         if (string[i - 1] == 0x0715 ||
 
271
              string[i - 1] == 0x0716 ||
 
272
              string[i - 1] == 0x072A)
 
273
          {
 
274
            properties[i] |= final3_p;
 
275
            continue;
 
276
          }
 
277
 
 
278
      /* R5 */
 
279
 
 
280
      if (previous == causing ||
 
281
          previous == right   ||
 
282
          previous == dual)
 
283
        if (current == right)
 
284
            {
 
285
              properties[i] |= final_p;
 
286
              continue;
 
287
            }
 
288
 
 
289
      /* R6 */
 
290
 
 
291
      if (previous == causing ||
 
292
          previous == right   ||
 
293
          previous == dual)
 
294
        if (current == dual)
 
295
          if (!(next == causing ||
 
296
                    next == right   ||
 
297
                    next == dual   ))
 
298
              {
 
299
                properties[i] |= final_p;
 
300
                continue;
 
301
              }
 
302
 
 
303
      /* R7 */
 
304
 
 
305
      if (previous == causing ||
 
306
          previous == left    ||
 
307
          previous == dual)
 
308
        if (current == dual)
 
309
          if (next == causing ||
 
310
              next == right   ||
 
311
              next == dual   )
 
312
              {
 
313
                properties[i] |= medial_p;
 
314
                continue;
 
315
              }
 
316
 
 
317
      /* R8 */
 
318
 
 
319
      if (string[i] == 0x0710)
 
320
        if (previous == causing ||
 
321
            previous == right)
 
322
            if (next == causing ||
 
323
                next == right ||
 
324
                next == dual)
 
325
            {
 
326
              properties[i] |= medial2_p;
 
327
              continue;
 
328
            }
 
329
 
 
330
      /* R9 */
 
331
 
 
332
      if (current == left)
 
333
        if (next == causing ||
 
334
            next == right   ||
 
335
            next == dual)
 
336
            {
 
337
              properties[i] |= initial_p;
 
338
              continue;
 
339
            }
 
340
 
 
341
      /* R10 */
 
342
 
 
343
      if (!(previous == causing ||
 
344
            previous == left ||
 
345
            previous == dual   ))
 
346
        if (current == dual)
 
347
          if (next == causing ||
 
348
              next == right   ||
 
349
              next == dual)
 
350
              {
 
351
                properties[i] |= initial_p;
 
352
                continue;
 
353
              }
 
354
 
 
355
      /* R11 */
 
356
 
 
357
      properties[i] |= isolated_p;
 
358
    }
 
359
 
 
360
  return FT_Err_Ok;
 
361
}