1 /* 2 * Copyright 2010,2012 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 #include "hb-ot-shape-complex-private.hh" 28 29 30 static bool 31 compose_hebrew (const hb_ot_shape_normalize_context_t *c, 32 hb_codepoint_t a, 33 hb_codepoint_t b, 34 hb_codepoint_t *ab) 35 { 36 /* Hebrew presentation-form shaping. 37 * https://bugzilla.mozilla.org/show_bug.cgi?id=728866 38 * Hebrew presentation forms with dagesh, for characters 0x05D0..0x05EA; 39 * Note that some letters do not have a dagesh presForm encoded. 40 */ 41 static const hb_codepoint_t sDageshForms[0x05EA - 0x05D0 + 1] = { 42 0xFB30, /* ALEF */ 43 0xFB31, /* BET */ 44 0xFB32, /* GIMEL */ 45 0xFB33, /* DALET */ 46 0xFB34, /* HE */ 47 0xFB35, /* VAV */ 48 0xFB36, /* ZAYIN */ 49 0x0000, /* HET */ 50 0xFB38, /* TET */ 51 0xFB39, /* YOD */ 52 0xFB3A, /* FINAL KAF */ 53 0xFB3B, /* KAF */ 54 0xFB3C, /* LAMED */ 55 0x0000, /* FINAL MEM */ 56 0xFB3E, /* MEM */ 57 0x0000, /* FINAL NUN */ 58 0xFB40, /* NUN */ 59 0xFB41, /* SAMEKH */ 60 0x0000, /* AYIN */ 61 0xFB43, /* FINAL PE */ 62 0xFB44, /* PE */ 63 0x0000, /* FINAL TSADI */ 64 0xFB46, /* TSADI */ 65 0xFB47, /* QOF */ 66 0xFB48, /* RESH */ 67 0xFB49, /* SHIN */ 68 0xFB4A /* TAV */ 69 }; 70 71 bool found = c->unicode->compose (a, b, ab); 72 73 if (!found && !c->plan->has_mark) 74 { 75 /* Special-case Hebrew presentation forms that are excluded from 76 * standard normalization, but wanted for old fonts. */ 77 switch (b) { 78 case 0x05B4: /* HIRIQ */ 79 if (a == 0x05D9) { /* YOD */ 80 *ab = 0xFB1D; 81 found = true; 82 } 83 break; 84 case 0x05B7: /* patah */ 85 if (a == 0x05F2) { /* YIDDISH YOD YOD */ 86 *ab = 0xFB1F; 87 found = true; 88 } else if (a == 0x05D0) { /* ALEF */ 89 *ab = 0xFB2E; 90 found = true; 91 } 92 break; 93 case 0x05B8: /* QAMATS */ 94 if (a == 0x05D0) { /* ALEF */ 95 *ab = 0xFB2F; 96 found = true; 97 } 98 break; 99 case 0x05B9: /* HOLAM */ 100 if (a == 0x05D5) { /* VAV */ 101 *ab = 0xFB4B; 102 found = true; 103 } 104 break; 105 case 0x05BC: /* DAGESH */ 106 if (a >= 0x05D0 && a <= 0x05EA) { 107 *ab = sDageshForms[a - 0x05D0]; 108 found = (*ab != 0); 109 } else if (a == 0xFB2A) { /* SHIN WITH SHIN DOT */ 110 *ab = 0xFB2C; 111 found = true; 112 } else if (a == 0xFB2B) { /* SHIN WITH SIN DOT */ 113 *ab = 0xFB2D; 114 found = true; 115 } 116 break; 117 case 0x05BF: /* RAFE */ 118 switch (a) { 119 case 0x05D1: /* BET */ 120 *ab = 0xFB4C; 121 found = true; 122 break; 123 case 0x05DB: /* KAF */ 124 *ab = 0xFB4D; 125 found = true; 126 break; 127 case 0x05E4: /* PE */ 128 *ab = 0xFB4E; 129 found = true; 130 break; 131 } 132 break; 133 case 0x05C1: /* SHIN DOT */ 134 if (a == 0x05E9) { /* SHIN */ 135 *ab = 0xFB2A; 136 found = true; 137 } else if (a == 0xFB49) { /* SHIN WITH DAGESH */ 138 *ab = 0xFB2C; 139 found = true; 140 } 141 break; 142 case 0x05C2: /* SIN DOT */ 143 if (a == 0x05E9) { /* SHIN */ 144 *ab = 0xFB2B; 145 found = true; 146 } else if (a == 0xFB49) { /* SHIN WITH DAGESH */ 147 *ab = 0xFB2D; 148 found = true; 149 } 150 break; 151 } 152 } 153 154 return found; 155 } 156 157 158 const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew = 159 { 160 "hebrew", 161 NULL, /* collect_features */ 162 NULL, /* override_features */ 163 NULL, /* data_create */ 164 NULL, /* data_destroy */ 165 NULL, /* preprocess_text */ 166 HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, 167 NULL, /* decompose */ 168 compose_hebrew, 169 NULL, /* setup_masks */ 170 HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, 171 true, /* fallback_position */ 172 }; 173