2
* syriac-ot.h: Determine what OpenType features to apply to characters based
3
* on the rules for Syriac from the OpenType standard.
5
* Copyright (C) 2004 Emil Soleyman-Zomalan
6
* Author: Emil Soleyman-Zomalan <emil@soleyman.com>
8
* This file is based on the Arabic shaping code from FreeType 1 tree; original
11
* The FreeType project -- a free and portable quality TrueType renderer.
13
* Copyright 1996-2000 by
14
* D. Turner, R.Wilhelm, and W. Lemberg
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.
21
#include "syriac-ot.h"
23
/* Here a table of the joining classes for characters in the range
26
* The following character also has a joining class:
28
* U+200C ZERO WIDTH NON-JOINER -> causing
30
* All other characters are given the joining class `none'.
32
static const JoiningClass syriac[] =
35
none, none, none, none,
36
none, none, none, none,
37
none, none, none, none,
38
none, none, none, transparent,
41
right, none, dual, dual,
42
dual, right, right, right,
43
right, right, dual, dual,
44
dual, dual, right, dual,
47
dual, dual, dual, dual,
48
dual, dual, dual, dual,
49
right, dual, right, dual,
50
right, none, none, none,
53
transparent, transparent, transparent, transparent,
54
transparent, transparent, transparent, transparent,
55
transparent, transparent, transparent, transparent,
56
transparent, transparent, transparent, transparent,
59
transparent, transparent, transparent, transparent,
60
transparent, transparent, transparent, transparent,
61
transparent, transparent, transparent, none,
62
none, right, dual, dual
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,
70
Get_Joining_Class (gunichar* string,
79
if (pos == 0 && direction < 0)
87
if (string[pos] < 0x0700 ||
88
string[pos] >= 0x074F)
90
if (string[pos] == 0x200C)
96
j = syriac[string[pos] - 0x0700];
98
if (!direction || j != transparent)
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.
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.
116
* Glyphs: 0x0715 (Dalath), 0x0716 (Dalath Rish), 0x072A (Rish),
117
* 0x0722 (Nun), 0x071F (Kaph)
120
* R1: <anything1> <transparent> <anything2>
122
* apply joining rules for
123
* <anything1> <anything2> -> [shape1] [shape2]
124
* -> [shape1] [isolated] [shape2]
127
* R2: <causing|right> <0x0722|0x071F> <!(causing|right|dual)>
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.
136
* This rule exists to combine similar exception for both
137
* characters without increasing the complexity in the other
141
* R3: <causing|right|dual> && <!(0x0715|0x0716|0x072A)> |<alaph>|
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
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.
156
* R4: <0x0715|0x0715|0x072A> |<alaph>|
160
* If the previous glyph is a Dalath, Rish, or Dotless Dalath
161
* Rish, then the Alaph takes this contextual position.
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.
169
* R5: <causing|right|dual> |<right>|
174
* R6: <causing|right|dual> |<dual>| <!(causing|right|dual)>
179
* R7: <causing|left|dual> |<dual>| <causing|right|dual>
184
* R8: <causing|right> |<alaph>| <causing|right|dual>
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.
193
* R9: |<left>| <causing|right|dual>
198
* R10: <!(causing|left|dual)> |<dual>| <causing|right|dual>
203
* R11: <anything> -> [isolated]
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
214
syriac_assign_properties (gunichar *string,
218
JoiningClass previous, current, next;
221
if (!string || !properties || length == 0)
222
return FT_Err_Invalid_Argument;
224
for (i = 0; i < length; i++)
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);
232
if (current == transparent)
234
properties[i] |= isolated_p;
240
if (string[i] == 0x0722 ||
242
if (previous == causing ||
244
if (!(next == causing ||
248
properties[i] |= isolated_p;
254
if (string[i] == 0x0710)
255
if (previous == causing ||
257
if (!(string[i - 1] == 0x0715 ||
258
string[i - 1] == 0x0716 ||
259
string[i - 1] == 0x072A))
261
properties[i] |= final2_p;
267
if (string[i] == 0x0710)
268
if (previous == causing ||
270
if (string[i - 1] == 0x0715 ||
271
string[i - 1] == 0x0716 ||
272
string[i - 1] == 0x072A)
274
properties[i] |= final3_p;
280
if (previous == causing ||
283
if (current == right)
285
properties[i] |= final_p;
291
if (previous == causing ||
295
if (!(next == causing ||
299
properties[i] |= final_p;
305
if (previous == causing ||
309
if (next == causing ||
313
properties[i] |= medial_p;
319
if (string[i] == 0x0710)
320
if (previous == causing ||
322
if (next == causing ||
326
properties[i] |= medial2_p;
333
if (next == causing ||
337
properties[i] |= initial_p;
343
if (!(previous == causing ||
347
if (next == causing ||
351
properties[i] |= initial_p;
357
properties[i] |= isolated_p;