tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

hb-ot-shaper-hebrew.cc (5816B)


      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.hh"
     28 
     29 #ifndef HB_NO_OT_SHAPE
     30 
     31 #include "hb-ot-shaper.hh"
     32 
     33 
     34 static bool
     35 compose_hebrew (const hb_ot_shape_normalize_context_t *c,
     36 	hb_codepoint_t  a,
     37 	hb_codepoint_t  b,
     38 	hb_codepoint_t *ab)
     39 {
     40  /* Hebrew presentation-form shaping.
     41   * https://bugzilla.mozilla.org/show_bug.cgi?id=728866
     42   * Hebrew presentation forms with dagesh, for characters U+05D0..05EA;
     43   * Note that some letters do not have a dagesh presForm encoded.
     44   */
     45  static const hb_codepoint_t sDageshForms[0x05EAu - 0x05D0u + 1] = {
     46    0xFB30u, /* ALEF */
     47    0xFB31u, /* BET */
     48    0xFB32u, /* GIMEL */
     49    0xFB33u, /* DALET */
     50    0xFB34u, /* HE */
     51    0xFB35u, /* VAV */
     52    0xFB36u, /* ZAYIN */
     53    0x0000u, /* HET */
     54    0xFB38u, /* TET */
     55    0xFB39u, /* YOD */
     56    0xFB3Au, /* FINAL KAF */
     57    0xFB3Bu, /* KAF */
     58    0xFB3Cu, /* LAMED */
     59    0x0000u, /* FINAL MEM */
     60    0xFB3Eu, /* MEM */
     61    0x0000u, /* FINAL NUN */
     62    0xFB40u, /* NUN */
     63    0xFB41u, /* SAMEKH */
     64    0x0000u, /* AYIN */
     65    0xFB43u, /* FINAL PE */
     66    0xFB44u, /* PE */
     67    0x0000u, /* FINAL TSADI */
     68    0xFB46u, /* TSADI */
     69    0xFB47u, /* QOF */
     70    0xFB48u, /* RESH */
     71    0xFB49u, /* SHIN */
     72    0xFB4Au /* TAV */
     73  };
     74 
     75  bool found = (bool) c->unicode->compose (a, b, ab);
     76 
     77 #ifdef HB_NO_OT_SHAPER_HEBREW_FALLBACK
     78  return found;
     79 #endif
     80 
     81  if (!found && (c->plan && !c->plan->has_gpos_mark))
     82  {
     83      /* Special-case Hebrew presentation forms that are excluded from
     84       * standard normalization, but wanted for old fonts. */
     85      switch (b) {
     86      case 0x05B4u: /* HIRIQ */
     87   if (a == 0x05D9u) { /* YOD */
     88       *ab = 0xFB1Du;
     89       found = true;
     90   }
     91   break;
     92      case 0x05B7u: /* PATAH */
     93   if (a == 0x05F2u) { /* YIDDISH YOD YOD */
     94       *ab = 0xFB1Fu;
     95       found = true;
     96   } else if (a == 0x05D0u) { /* ALEF */
     97       *ab = 0xFB2Eu;
     98       found = true;
     99   }
    100   break;
    101      case 0x05B8u: /* QAMATS */
    102   if (a == 0x05D0u) { /* ALEF */
    103       *ab = 0xFB2Fu;
    104       found = true;
    105   }
    106   break;
    107      case 0x05B9u: /* HOLAM */
    108   if (a == 0x05D5u) { /* VAV */
    109       *ab = 0xFB4Bu;
    110       found = true;
    111   }
    112   break;
    113      case 0x05BCu: /* DAGESH */
    114   if (a >= 0x05D0u && a <= 0x05EAu) {
    115       *ab = sDageshForms[a - 0x05D0u];
    116       found = (*ab != 0);
    117   } else if (a == 0xFB2Au) { /* SHIN WITH SHIN DOT */
    118       *ab = 0xFB2Cu;
    119       found = true;
    120   } else if (a == 0xFB2Bu) { /* SHIN WITH SIN DOT */
    121       *ab = 0xFB2Du;
    122       found = true;
    123   }
    124   break;
    125      case 0x05BFu: /* RAFE */
    126   switch (a) {
    127   case 0x05D1u: /* BET */
    128       *ab = 0xFB4Cu;
    129       found = true;
    130       break;
    131   case 0x05DBu: /* KAF */
    132       *ab = 0xFB4Du;
    133       found = true;
    134       break;
    135   case 0x05E4u: /* PE */
    136       *ab = 0xFB4Eu;
    137       found = true;
    138       break;
    139   }
    140   break;
    141      case 0x05C1u: /* SHIN DOT */
    142   if (a == 0x05E9u) { /* SHIN */
    143       *ab = 0xFB2Au;
    144       found = true;
    145   } else if (a == 0xFB49u) { /* SHIN WITH DAGESH */
    146       *ab = 0xFB2Cu;
    147       found = true;
    148   }
    149   break;
    150      case 0x05C2u: /* SIN DOT */
    151   if (a == 0x05E9u) { /* SHIN */
    152       *ab = 0xFB2Bu;
    153       found = true;
    154   } else if (a == 0xFB49u) { /* SHIN WITH DAGESH */
    155       *ab = 0xFB2Du;
    156       found = true;
    157   }
    158   break;
    159      }
    160  }
    161 
    162  return found;
    163 }
    164 
    165 static void
    166 reorder_marks_hebrew (const hb_ot_shape_plan_t *plan HB_UNUSED,
    167 	      hb_buffer_t              *buffer,
    168 	      unsigned int              start,
    169 	      unsigned int              end)
    170 {
    171  hb_glyph_info_t *info = buffer->info;
    172 
    173  for (unsigned i = start + 2; i < end; i++)
    174  {
    175    unsigned c0 = info_cc (info[i - 2]);
    176    unsigned c1 = info_cc (info[i - 1]);
    177    unsigned c2 = info_cc (info[i - 0]);
    178 
    179    if ((c0 == HB_MODIFIED_COMBINING_CLASS_CCC17 || c0 == HB_MODIFIED_COMBINING_CLASS_CCC18) /* patach or qamats */ &&
    180 (c1 == HB_MODIFIED_COMBINING_CLASS_CCC10 || c1 == HB_MODIFIED_COMBINING_CLASS_CCC14) /* sheva or hiriq */ &&
    181 (c2 == HB_MODIFIED_COMBINING_CLASS_CCC22 || c2 == HB_UNICODE_COMBINING_CLASS_BELOW) /* meteg or below */)
    182    {
    183      buffer->merge_clusters (i - 1, i + 1);
    184      hb_swap (info[i - 1], info[i]);
    185      break;
    186    }
    187  }
    188 
    189 
    190 }
    191 
    192 const hb_ot_shaper_t _hb_ot_shaper_hebrew =
    193 {
    194  nullptr, /* collect_features */
    195  nullptr, /* override_features */
    196  nullptr, /* data_create */
    197  nullptr, /* data_destroy */
    198  nullptr, /* preprocess_text */
    199  nullptr, /* postprocess_glyphs */
    200  nullptr, /* decompose */
    201  compose_hebrew,
    202  nullptr, /* setup_masks */
    203  reorder_marks_hebrew,
    204  HB_TAG ('h','e','b','r'), /* gpos_tag. https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368 */
    205  HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
    206  HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
    207  true, /* fallback_position */
    208 };
    209 
    210 
    211 #endif