1/*
2 * Copyright © 2014  Google, Inc.
3 *
4 *  This is part of HarfBuzz, a text shaping library.
5 *
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
11 *
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16 * DAMAGE.
17 *
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23 *
24 * Google Author(s): Behdad Esfahbod
25 */
26
27#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH
28
29
30/*
31 * The macros in the first part of this file are generic macros that can
32 * be used to define the bytes for OpenType table data in code in a
33 * readable manner.  We can move the macros to reside with their respective
34 * struct types, but since we only use these to define one data table, the
35 * Windows-1256 Arabic shaping table in this file, we keep them here.
36 */
37
38
39/* First we measure, then we cut. */
40#ifndef OT_MEASURE
41#define OT_MEASURE
42#define OT_TABLE_START			static const struct TABLE_NAME {
43#define OT_TABLE_END			}
44#define OT_LABEL_START(Name)		unsigned char Name[
45#define OT_LABEL_END			];
46#define OT_BYTE(u8)			+1/*byte*/
47#define OT_USHORT(u16)			+2/*bytes*/
48#else
49#undef  OT_MEASURE
50#define OT_TABLE_START			TABLE_NAME = {
51#define OT_TABLE_END			};
52#define OT_LABEL_START(Name)		{
53#define OT_LABEL_END			},
54#define OT_BYTE(u8)			(u8),
55#define OT_USHORT(u16)			(unsigned char)((u16)>>8), (unsigned char)((u16)&0xFFu),
56#define OT_COUNT(Name, ItemSize)	((unsigned int) sizeof(((struct TABLE_NAME*)0)->Name) \
57					 / (unsigned int)(ItemSize) \
58					 /* OT_ASSERT it's divisible (and positive). */)
59#define OT_DISTANCE(From,To)		((unsigned int) \
60					 ((char*)(&((struct TABLE_NAME*)0)->To) - \
61					  (char*)(&((struct TABLE_NAME*)0)->From)) \
62					 /* OT_ASSERT it's positive. */)
63#endif
64
65
66#define OT_LABEL(Name) \
67	OT_LABEL_END \
68	OT_LABEL_START(Name)
69
70/* Whenever we receive an argument that is a list, it will expand to
71 * contain commas.  That cannot be passed to another macro because the
72 * commas will throw off the preprocessor.  The solution is to wrap
73 * the passed-in argument in OT_LIST() before passing to the next macro.
74 * Unfortunately this trick requires vararg macros. */
75#define OT_LIST(...) __VA_ARGS__
76
77
78/*
79 * Basic Types
80 */
81
82#define OT_TAG(a,b,c,d) \
83	OT_BYTE(a) OT_BYTE(b) OT_BYTE(c) OT_BYTE(d)
84
85#define OT_OFFSET(From, To) /* Offset from From to To in bytes */ \
86	OT_USHORT(OT_DISTANCE(From, To))
87
88#define OT_GLYPHID /* GlyphID */ \
89	OT_USHORT
90
91#define OT_UARRAY(Name, Items) \
92	OT_LABEL_START(Name) \
93	OT_USHORT(OT_COUNT(Name##Data, 2)) \
94	OT_LABEL(Name##Data) \
95	Items \
96	OT_LABEL_END
97
98#define OT_UHEADLESSARRAY(Name, Items) \
99	OT_LABEL_START(Name) \
100	OT_USHORT(OT_COUNT(Name##Data, 2) + 1) \
101	OT_LABEL(Name##Data) \
102	Items \
103	OT_LABEL_END
104
105
106/*
107 * Common Types
108 */
109
110#define OT_LOOKUP_FLAG_IGNORE_MARKS	0x08u
111
112#define OT_LOOKUP(Name, LookupType, LookupFlag, SubLookupOffsets) \
113	OT_LABEL_START(Name) \
114	OT_USHORT(LookupType) \
115	OT_USHORT(LookupFlag) \
116	OT_LABEL_END \
117	OT_UARRAY(Name##SubLookupOffsetsArray, OT_LIST(SubLookupOffsets))
118
119#define OT_SUBLOOKUP(Name, SubFormat, Items) \
120	OT_LABEL_START(Name) \
121	OT_USHORT(SubFormat) \
122	Items
123
124#define OT_COVERAGE1(Name, Items) \
125	OT_LABEL_START(Name) \
126	OT_USHORT(1) \
127	OT_LABEL_END \
128	OT_UARRAY(Name##Glyphs, OT_LIST(Items))
129
130
131/*
132 * GSUB
133 */
134
135#define OT_LOOKUP_TYPE_SUBST_SINGLE	1u
136#define OT_LOOKUP_TYPE_SUBST_MULTIPLE	2u
137#define OT_LOOKUP_TYPE_SUBST_LIGATURE	4u
138
139#define OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(Name, FromGlyphs, ToGlyphs) \
140	OT_SUBLOOKUP(Name, 2, \
141		OT_OFFSET(Name, Name##Coverage) \
142		OT_LABEL_END \
143		OT_UARRAY(Name##Substitute, OT_LIST(ToGlyphs)) \
144	) \
145	OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \
146	/* ASSERT_STATIC_EXPR len(FromGlyphs) == len(ToGlyphs) */
147
148#define OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(Name, FirstGlyphs, LigatureSetOffsets) \
149	OT_SUBLOOKUP(Name, 1, \
150		OT_OFFSET(Name, Name##Coverage) \
151		OT_LABEL_END \
152		OT_UARRAY(Name##LigatureSetOffsetsArray, OT_LIST(LigatureSetOffsets)) \
153	) \
154	OT_COVERAGE1(Name##Coverage, OT_LIST(FirstGlyphs)) \
155	/* ASSERT_STATIC_EXPR len(FirstGlyphs) == len(LigatureSetOffsets) */
156
157#define OT_LIGATURE_SET(Name, LigatureSetOffsets) \
158	OT_UARRAY(Name, OT_LIST(LigatureSetOffsets))
159
160#define OT_LIGATURE(Name, Components, LigGlyph) \
161	OT_LABEL_START(Name) \
162	LigGlyph \
163	OT_LABEL_END \
164	OT_UHEADLESSARRAY(Name##ComponentsArray, OT_LIST(Components))
165
166/*
167 *
168 * Start of Windows-1256 shaping table.
169 *
170 */
171
172/* Table name. */
173#define TABLE_NAME arabic_win1256_gsub_lookups
174
175/* Table manifest. */
176#define MANIFEST(Items) \
177	OT_LABEL_START(manifest) \
178	OT_USHORT(OT_COUNT(manifestData, 6)) \
179	OT_LABEL(manifestData) \
180	Items \
181	OT_LABEL_END
182
183#define MANIFEST_LOOKUP(Tag, Name) \
184	Tag \
185	OT_OFFSET(manifest, Name)
186
187/* Shorthand. */
188#define G	OT_GLYPHID
189
190/*
191 * Table Start
192 */
193OT_TABLE_START
194
195
196/*
197 * Manifest
198 */
199MANIFEST(
200	MANIFEST_LOOKUP(OT_TAG('r','l','i','g'), rligLookup)
201	MANIFEST_LOOKUP(OT_TAG('i','n','i','t'), initLookup)
202	MANIFEST_LOOKUP(OT_TAG('m','e','d','i'), mediLookup)
203	MANIFEST_LOOKUP(OT_TAG('f','i','n','a'), finaLookup)
204	MANIFEST_LOOKUP(OT_TAG('r','l','i','g'), rligMarksLookup)
205)
206
207/*
208 * Lookups
209 */
210OT_LOOKUP(initLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS,
211	OT_OFFSET(initLookup, initmediSubLookup)
212	OT_OFFSET(initLookup, initSubLookup)
213)
214OT_LOOKUP(mediLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS,
215	OT_OFFSET(mediLookup, initmediSubLookup)
216	OT_OFFSET(mediLookup, mediSubLookup)
217	OT_OFFSET(mediLookup, medifinaLamAlefSubLookup)
218)
219OT_LOOKUP(finaLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS,
220	OT_OFFSET(finaLookup, finaSubLookup)
221	/* We don't need this one currently as the sequence inherits masks
222	 * from the first item.  Just in case we change that in the future
223	 * to be smart about Arabic masks when ligating... */
224	OT_OFFSET(finaLookup, medifinaLamAlefSubLookup)
225)
226OT_LOOKUP(rligLookup, OT_LOOKUP_TYPE_SUBST_LIGATURE, OT_LOOKUP_FLAG_IGNORE_MARKS,
227	OT_OFFSET(rligLookup, lamAlefLigaturesSubLookup)
228)
229OT_LOOKUP(rligMarksLookup, OT_LOOKUP_TYPE_SUBST_LIGATURE, 0,
230	OT_OFFSET(rligMarksLookup, shaddaLigaturesSubLookup)
231)
232
233/*
234 * init/medi/fina forms
235 */
236OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(initmediSubLookup,
237	G(198)	G(200)	G(201)	G(202)	G(203)	G(204)	G(205)	G(206)	G(211)
238	G(212)	G(213)	G(214)	G(223)	G(225)	G(227)	G(228)	G(236)	G(237),
239	G(162)	G(4)	G(5)	G(5)	G(6)	G(7)	G(9)	G(11)	G(13)
240	G(14)	G(15)	G(26)	G(140)	G(141)	G(142)	G(143)	G(154)	G(154)
241)
242OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(initSubLookup,
243	G(218)	G(219)	G(221)	G(222)	G(229),
244	G(27)	G(30)	G(128)	G(131)	G(144)
245)
246OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(mediSubLookup,
247	G(218)	G(219)	G(221)	G(222)	G(229),
248	G(28)	G(31)	G(129)	G(138)	G(149)
249)
250OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(finaSubLookup,
251	G(194)	G(195)	G(197)	G(198)	G(199)	G(201)	G(204)	G(205)	G(206)
252	G(218)	G(219)	G(229)	G(236)	G(237),
253	G(2)	G(1)	G(3)	G(181)	G(0)	G(159)	G(8)	G(10)	G(12)
254	G(29)	G(127)	G(152) G(160)	G(156)
255)
256OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(medifinaLamAlefSubLookup,
257	G(165)	G(178)	G(180)	G(252),
258	G(170)	G(179)	G(185)	G(255)
259)
260
261/*
262 * Lam+Alef ligatures
263 */
264OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(lamAlefLigaturesSubLookup,
265	G(225),
266	OT_OFFSET(lamAlefLigaturesSubLookup, lamLigatureSet)
267)
268OT_LIGATURE_SET(lamLigatureSet,
269	OT_OFFSET(lamLigatureSet, lamInitLigature1)
270	OT_OFFSET(lamLigatureSet, lamInitLigature2)
271	OT_OFFSET(lamLigatureSet, lamInitLigature3)
272	OT_OFFSET(lamLigatureSet, lamInitLigature4)
273)
274OT_LIGATURE(lamInitLigature1, G(199), G(165))
275OT_LIGATURE(lamInitLigature2, G(195), G(178))
276OT_LIGATURE(lamInitLigature3, G(194), G(180))
277OT_LIGATURE(lamInitLigature4, G(197), G(252))
278
279/*
280 * Shadda ligatures
281 */
282OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(shaddaLigaturesSubLookup,
283	G(248),
284	OT_OFFSET(shaddaLigaturesSubLookup, shaddaLigatureSet)
285)
286OT_LIGATURE_SET(shaddaLigatureSet,
287	OT_OFFSET(shaddaLigatureSet, shaddaLigature1)
288	OT_OFFSET(shaddaLigatureSet, shaddaLigature2)
289	OT_OFFSET(shaddaLigatureSet, shaddaLigature3)
290)
291OT_LIGATURE(shaddaLigature1, G(243), G(172))
292OT_LIGATURE(shaddaLigature2, G(245), G(173))
293OT_LIGATURE(shaddaLigature3, G(246), G(175))
294
295/*
296 * Table end
297 */
298OT_TABLE_END
299
300
301/*
302 * Clean up
303 */
304#undef OT_TABLE_START
305#undef OT_TABLE_END
306#undef OT_LABEL_START
307#undef OT_LABEL_END
308#undef OT_BYTE
309#undef OT_USHORT
310#undef OT_DISTANCE
311#undef OT_COUNT
312
313/*
314 * Include a second time to get the table data...
315 */
316#ifdef OT_MEASURE
317#include "hb-ot-shape-complex-arabic-win1256.hh"
318#endif
319
320#define HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH
321#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH */
322