michael@0: /* michael@0: * Copyright © 2010,2012 Google, Inc. michael@0: * michael@0: * This is part of HarfBuzz, a text shaping library. michael@0: * michael@0: * Permission is hereby granted, without written agreement and without michael@0: * license or royalty fees, to use, copy, modify, and distribute this michael@0: * software and its documentation for any purpose, provided that the michael@0: * above copyright notice and the following two paragraphs appear in michael@0: * all copies of this software. michael@0: * michael@0: * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR michael@0: * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES michael@0: * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN michael@0: * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH michael@0: * DAMAGE. michael@0: * michael@0: * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, michael@0: * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND michael@0: * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS michael@0: * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO michael@0: * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. michael@0: * michael@0: * Google Author(s): Behdad Esfahbod michael@0: */ michael@0: michael@0: #include "hb-ot-shape-complex-private.hh" michael@0: michael@0: michael@0: static bool michael@0: compose_hebrew (const hb_ot_shape_normalize_context_t *c, michael@0: hb_codepoint_t a, michael@0: hb_codepoint_t b, michael@0: hb_codepoint_t *ab) michael@0: { michael@0: /* Hebrew presentation-form shaping. michael@0: * https://bugzilla.mozilla.org/show_bug.cgi?id=728866 michael@0: * Hebrew presentation forms with dagesh, for characters 0x05D0..0x05EA; michael@0: * Note that some letters do not have a dagesh presForm encoded. michael@0: */ michael@0: static const hb_codepoint_t sDageshForms[0x05EA - 0x05D0 + 1] = { michael@0: 0xFB30, /* ALEF */ michael@0: 0xFB31, /* BET */ michael@0: 0xFB32, /* GIMEL */ michael@0: 0xFB33, /* DALET */ michael@0: 0xFB34, /* HE */ michael@0: 0xFB35, /* VAV */ michael@0: 0xFB36, /* ZAYIN */ michael@0: 0x0000, /* HET */ michael@0: 0xFB38, /* TET */ michael@0: 0xFB39, /* YOD */ michael@0: 0xFB3A, /* FINAL KAF */ michael@0: 0xFB3B, /* KAF */ michael@0: 0xFB3C, /* LAMED */ michael@0: 0x0000, /* FINAL MEM */ michael@0: 0xFB3E, /* MEM */ michael@0: 0x0000, /* FINAL NUN */ michael@0: 0xFB40, /* NUN */ michael@0: 0xFB41, /* SAMEKH */ michael@0: 0x0000, /* AYIN */ michael@0: 0xFB43, /* FINAL PE */ michael@0: 0xFB44, /* PE */ michael@0: 0x0000, /* FINAL TSADI */ michael@0: 0xFB46, /* TSADI */ michael@0: 0xFB47, /* QOF */ michael@0: 0xFB48, /* RESH */ michael@0: 0xFB49, /* SHIN */ michael@0: 0xFB4A /* TAV */ michael@0: }; michael@0: michael@0: bool found = c->unicode->compose (a, b, ab); michael@0: michael@0: if (!found) michael@0: { michael@0: /* Special-case Hebrew presentation forms that are excluded from michael@0: * standard normalization, but wanted for old fonts. */ michael@0: switch (b) { michael@0: case 0x05B4: /* HIRIQ */ michael@0: if (a == 0x05D9) { /* YOD */ michael@0: *ab = 0xFB1D; michael@0: found = true; michael@0: } michael@0: break; michael@0: case 0x05B7: /* patah */ michael@0: if (a == 0x05F2) { /* YIDDISH YOD YOD */ michael@0: *ab = 0xFB1F; michael@0: found = true; michael@0: } else if (a == 0x05D0) { /* ALEF */ michael@0: *ab = 0xFB2E; michael@0: found = true; michael@0: } michael@0: break; michael@0: case 0x05B8: /* QAMATS */ michael@0: if (a == 0x05D0) { /* ALEF */ michael@0: *ab = 0xFB2F; michael@0: found = true; michael@0: } michael@0: break; michael@0: case 0x05B9: /* HOLAM */ michael@0: if (a == 0x05D5) { /* VAV */ michael@0: *ab = 0xFB4B; michael@0: found = true; michael@0: } michael@0: break; michael@0: case 0x05BC: /* DAGESH */ michael@0: if (a >= 0x05D0 && a <= 0x05EA) { michael@0: *ab = sDageshForms[a - 0x05D0]; michael@0: found = (*ab != 0); michael@0: } else if (a == 0xFB2A) { /* SHIN WITH SHIN DOT */ michael@0: *ab = 0xFB2C; michael@0: found = true; michael@0: } else if (a == 0xFB2B) { /* SHIN WITH SIN DOT */ michael@0: *ab = 0xFB2D; michael@0: found = true; michael@0: } michael@0: break; michael@0: case 0x05BF: /* RAFE */ michael@0: switch (a) { michael@0: case 0x05D1: /* BET */ michael@0: *ab = 0xFB4C; michael@0: found = true; michael@0: break; michael@0: case 0x05DB: /* KAF */ michael@0: *ab = 0xFB4D; michael@0: found = true; michael@0: break; michael@0: case 0x05E4: /* PE */ michael@0: *ab = 0xFB4E; michael@0: found = true; michael@0: break; michael@0: } michael@0: break; michael@0: case 0x05C1: /* SHIN DOT */ michael@0: if (a == 0x05E9) { /* SHIN */ michael@0: *ab = 0xFB2A; michael@0: found = true; michael@0: } else if (a == 0xFB49) { /* SHIN WITH DAGESH */ michael@0: *ab = 0xFB2C; michael@0: found = true; michael@0: } michael@0: break; michael@0: case 0x05C2: /* SIN DOT */ michael@0: if (a == 0x05E9) { /* SHIN */ michael@0: *ab = 0xFB2B; michael@0: found = true; michael@0: } else if (a == 0xFB49) { /* SHIN WITH DAGESH */ michael@0: *ab = 0xFB2D; michael@0: found = true; michael@0: } michael@0: break; michael@0: } michael@0: } michael@0: michael@0: return found; michael@0: } michael@0: michael@0: michael@0: const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew = michael@0: { michael@0: "hebrew", michael@0: NULL, /* collect_features */ michael@0: NULL, /* override_features */ michael@0: NULL, /* data_create */ michael@0: NULL, /* data_destroy */ michael@0: NULL, /* preprocess_text */ michael@0: HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT, michael@0: NULL, /* decompose */ michael@0: compose_hebrew, michael@0: NULL, /* setup_masks */ michael@0: HB_OT_SHAPE_ZERO_WIDTH_MARKS_DEFAULT, michael@0: true, /* fallback_position */ michael@0: };