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 */ 193 OT_TABLE_START 194 195 196 /* 197 * Manifest 198 */ 199 MANIFEST( 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 */ 210 OT_LOOKUP(initLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS, 211 OT_OFFSET(initLookup, initmediSubLookup) 212 OT_OFFSET(initLookup, initSubLookup) 213 ) 214 OT_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 ) 219 OT_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 ) 226 OT_LOOKUP(rligLookup, OT_LOOKUP_TYPE_SUBST_LIGATURE, OT_LOOKUP_FLAG_IGNORE_MARKS, 227 OT_OFFSET(rligLookup, lamAlefLigaturesSubLookup) 228 ) 229 OT_LOOKUP(rligMarksLookup, OT_LOOKUP_TYPE_SUBST_LIGATURE, 0, 230 OT_OFFSET(rligMarksLookup, shaddaLigaturesSubLookup) 231 ) 232 233 /* 234 * init/medi/fina forms 235 */ 236 OT_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 ) 242 OT_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 ) 246 OT_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 ) 250 OT_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 ) 256 OT_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 */ 264 OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(lamAlefLigaturesSubLookup, 265 G(225), 266 OT_OFFSET(lamAlefLigaturesSubLookup, lamLigatureSet) 267 ) 268 OT_LIGATURE_SET(lamLigatureSet, 269 OT_OFFSET(lamLigatureSet, lamInitLigature1) 270 OT_OFFSET(lamLigatureSet, lamInitLigature2) 271 OT_OFFSET(lamLigatureSet, lamInitLigature3) 272 OT_OFFSET(lamLigatureSet, lamInitLigature4) 273 ) 274 OT_LIGATURE(lamInitLigature1, G(199), G(165)) 275 OT_LIGATURE(lamInitLigature2, G(195), G(178)) 276 OT_LIGATURE(lamInitLigature3, G(194), G(180)) 277 OT_LIGATURE(lamInitLigature4, G(197), G(252)) 278 279 /* 280 * Shadda ligatures 281 */ 282 OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(shaddaLigaturesSubLookup, 283 G(248), 284 OT_OFFSET(shaddaLigaturesSubLookup, shaddaLigatureSet) 285 ) 286 OT_LIGATURE_SET(shaddaLigatureSet, 287 OT_OFFSET(shaddaLigatureSet, shaddaLigature1) 288 OT_OFFSET(shaddaLigatureSet, shaddaLigature2) 289 OT_OFFSET(shaddaLigatureSet, shaddaLigature3) 290 ) 291 OT_LIGATURE(shaddaLigature1, G(243), G(172)) 292 OT_LIGATURE(shaddaLigature2, G(245), G(173)) 293 OT_LIGATURE(shaddaLigature3, G(246), G(175)) 294 295 /* 296 * Table end 297 */ 298 OT_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 #if 0 317 #include "hb-private.hh" /* Make check-includes.sh happy. */ 318 #endif 319 #ifdef OT_MEASURE 320 #include "hb-ot-shape-complex-arabic-win1256.hh" 321 #endif 322 323 #define HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH 324 #endif /* HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH */ 325