1 /****************************************************************************/
3 /* The FreeType project -- a free and portable quality TrueType renderer. */
5 /* Copyright 1996-1999 by */
6 /* D. Turner, R.Wilhelm, and W. Lemberg */
8 /* arabic -- An implementation of the contextual algorithm given in the */
9 /* Unicode 2.0 book to assign the `isolated', `initial', `medial', and */
10 /* `final' properties to an input string of character codes for the Arabic */
13 /****************************************************************************/
25 Here a table of the joining classes for characters in the range
28 The following character also has a joining class:
30 U+200C ZERO WIDTH NON-JOINER -> causing
32 All other characters are given the joining class `none'.
36 joining_class arabic
[] =
39 none
, none
, right
, right
,
40 right
, right
, dual
, right
,
41 dual
, right
, dual
, dual
,
42 dual
, dual
, dual
, right
,
45 right
, right
, right
, dual
,
46 dual
, dual
, dual
, dual
,
47 dual
, dual
, dual
, none
,
48 none
, none
, none
, none
,
51 causing
, dual
, dual
, dual
,
52 dual
, dual
, dual
, dual
,
53 right
, right
, dual
, transparent
,
54 transparent
, transparent
, transparent
, transparent
,
57 transparent
, transparent
, transparent
, none
,
58 none
, none
, none
, none
,
59 none
, none
, none
, none
,
60 none
, none
, none
, none
,
63 none
, none
, none
, none
,
64 none
, none
, none
, none
,
65 none
, none
, none
, none
,
66 none
, none
, none
, none
,
69 transparent
, none
, right
, right
,
70 none
, right
, right
, right
,
71 dual
, dual
, dual
, dual
,
72 dual
, dual
, dual
, dual
,
75 dual
, dual
, dual
, dual
,
76 dual
, dual
, dual
, dual
,
77 right
, right
, right
, right
,
78 right
, right
, right
, right
,
81 right
, right
, right
, right
,
82 right
, right
, right
, right
,
83 right
, right
, dual
, dual
,
84 dual
, dual
, dual
, dual
,
87 dual
, dual
, dual
, dual
,
88 dual
, dual
, dual
, dual
,
89 dual
, dual
, dual
, dual
,
90 dual
, dual
, dual
, dual
,
93 dual
, dual
, dual
, dual
,
94 dual
, dual
, dual
, dual
,
95 dual
, dual
, dual
, dual
,
96 dual
, dual
, dual
, dual
,
99 right
, dual
, right
, right
,
100 right
, right
, right
, right
,
101 right
, right
, right
, right
,
102 dual
, right
, dual
, right
,
105 dual
, dual
, right
, right
,
106 none
, none
, none
, transparent
,
107 transparent
, transparent
, transparent
, transparent
,
108 transparent
, transparent
, transparent
, transparent
,
111 transparent
, transparent
, transparent
, transparent
,
112 transparent
, none
, none
, transparent
,
113 transparent
, none
, transparent
, transparent
,
114 transparent
, transparent
, none
, none
,
117 none
, none
, none
, none
,
118 none
, none
, none
, none
,
119 none
, none
, dual
, dual
,
120 dual
, none
, none
, none
127 TT_UShort glyph_index
;
131 typedef struct cgc_ cgc
;
134 int compare_cgc( const void* a
,
137 return ( ((cgc
*)a
)->glyph_index
> ((cgc
*)b
)->glyph_index
) ?
138 1 : ( ( ((cgc
*)a
)->glyph_index
== ((cgc
*)b
)->glyph_index
) ?
143 TT_Error
Build_Arabic_Glyph_Properties( TT_CharMap char_map
,
144 TT_UShort max_glyphs
,
145 TTO_GDEFHeader
** gdef
)
147 TT_UShort i
, j
, num_glyphs
;
149 cgc Arabic
[0x0700 - 0x0620];
151 TT_UShort glyph_indices
[0x700 - 0x0620];
152 TT_UShort classes
[0x700 - 0x0620];
155 return TT_Err_Invalid_Argument
;
159 for ( i
= 0x0620; i
< 0x0700; i
++ )
161 Arabic
[j
].char_code
= i
;
162 Arabic
[j
].class = ( arabic
[i
- 0x0620] == transparent
) ?
163 MARK_GLYPH
: SIMPLE_GLYPH
;
164 Arabic
[j
].glyph_index
= TT_Char_Index( char_map
, i
);
165 if ( Arabic
[j
].glyph_index
)
179 qsort( Arabic
, num_glyphs
, sizeof ( cgc
), compare_cgc
);
181 /* write it to the arrays, removing duplicates */
183 glyph_indices
[0] = Arabic
[0].glyph_index
;
184 classes
[0] = Arabic
[0].class;
188 for ( i
= 1; i
< num_glyphs
; i
++ )
190 glyph_indices
[j
] = Arabic
[i
].glyph_index
;
191 classes
[j
] = Arabic
[i
].class;
193 if ( glyph_indices
[j
- 1] != glyph_indices
[j
] )
198 TT_GDEF_Build_ClassDefinition( *gdef
, max_glyphs
, num_glyphs
,
199 glyph_indices
, classes
);
205 /* The joining rules as given in the Unicode 2.0 book (characters are
206 here specified as appearing in the byte stream, i.e. *not* in
207 visual order). Joining classes are given in angle brackets, glyph
208 forms in square brackets. Glyphs affected by a specific rule are
209 enclosed with vertical bars.
211 Note: The description of the joining algorithm in the book is
212 severely broken. You can get a corrected version from
213 www.unicode.org (as of 29-Jun-1999, this hasn't appeared).
215 R1: <anything1> <transparent> <anything2>
217 apply joining rules for
218 <anything1> <anything2> -> [shape1] [shape2]
220 -> [shape1] [isolated] [shape2]
222 R2: <causing|left|dual> |<right>|
226 R3: |<left>| <causing|right|dual>
230 R4: <causing|left|dual> |<dual>| <causing|right|dual>
234 R5: <causing|left|dual> |<dual>| <!(causing|right|dual)>
238 R6: <!(causing|left|dual)> |<dual>| <causing|right|dual>
244 <anything> -> [isolated] */
247 /* `direction' can be -1, 0, or 1 to indicate the last non-transparent
248 glyph, the current glyph, and the next non-transparent glyph,
251 static joining_class
Get_Joining_Class( TT_UShort
* string
,
261 if ( pos
== 0 && direction
< 0 )
269 if ( string
[pos
] < 0x0620 ||
270 string
[pos
] >= 0x0700 )
272 if ( string
[pos
] == 0x200C )
278 j
= arabic
[string
[pos
] - 0x0620];
280 if ( !direction
|| j
!= transparent
)
286 TT_Error
Assign_Arabic_Properties( TT_UShort
* string
,
287 TT_UShort
* properties
,
290 joining_class previous
, current
, next
;
295 if ( !string
|| !properties
|| length
== 0 )
296 return TT_Err_Invalid_Argument
;
298 for ( i
= 0; i
< length
; i
++ )
300 previous
= Get_Joining_Class( string
, i
, length
, -1 );
301 current
= Get_Joining_Class( string
, i
, length
, 0 );
302 next
= Get_Joining_Class( string
, i
, length
, 1 );
306 if ( current
== transparent
)
308 properties
[i
] |= isolated_p
;
314 if ( previous
== causing
||
317 if ( current
== right
)
319 properties
[i
] |= final_p
;
325 if ( current
== left
)
326 if ( next
== causing
||
330 properties
[i
] |= initial_p
;
336 if ( previous
== causing
||
339 if ( current
== dual
)
340 if ( next
== causing
||
344 properties
[i
] |= medial_p
;
350 if ( previous
== causing
||
353 if ( current
== dual
)
354 if ( !( next
== causing
||
358 properties
[i
] |= final_p
;
364 if ( !( previous
== causing
||
367 if ( current
== dual
)
368 if ( next
== causing
||
372 properties
[i
] |= initial_p
;
378 if ( current
!= none
)
379 properties
[i
] |= isolated_p
;