tor-browser

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

VARC.cc (13217B)


      1 #include "VARC.hh"
      2 
      3 #ifndef HB_NO_VAR_COMPOSITES
      4 
      5 #include "../../../hb-draw.hh"
      6 #include "../../../hb-ot-layout-common.hh"
      7 #include "../../../hb-ot-layout-gdef-table.hh"
      8 
      9 namespace OT {
     10 
     11 //namespace Var {
     12 
     13 
     14 #ifndef HB_NO_DRAW
     15 
     16 struct hb_transforming_pen_context_t
     17 {
     18  hb_transform_t<> transform;
     19  hb_draw_funcs_t *dfuncs;
     20  void *data;
     21  hb_draw_state_t *st;
     22 };
     23 
     24 static void
     25 hb_transforming_pen_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
     26 		     void *data,
     27 		     hb_draw_state_t *st,
     28 		     float to_x, float to_y,
     29 		     void *user_data HB_UNUSED)
     30 {
     31  hb_transforming_pen_context_t *c = (hb_transforming_pen_context_t *) data;
     32 
     33  c->transform.transform_point (to_x, to_y);
     34 
     35  c->dfuncs->move_to (c->data, *c->st, to_x, to_y);
     36 }
     37 
     38 static void
     39 hb_transforming_pen_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
     40 		     void *data,
     41 		     hb_draw_state_t *st,
     42 		     float to_x, float to_y,
     43 		     void *user_data HB_UNUSED)
     44 {
     45  hb_transforming_pen_context_t *c = (hb_transforming_pen_context_t *) data;
     46 
     47  c->transform.transform_point (to_x, to_y);
     48 
     49  c->dfuncs->line_to (c->data, *c->st, to_x, to_y);
     50 }
     51 
     52 static void
     53 hb_transforming_pen_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
     54 			  void *data,
     55 			  hb_draw_state_t *st,
     56 			  float control_x, float control_y,
     57 			  float to_x, float to_y,
     58 			  void *user_data HB_UNUSED)
     59 {
     60  hb_transforming_pen_context_t *c = (hb_transforming_pen_context_t *) data;
     61 
     62  c->transform.transform_point (control_x, control_y);
     63  c->transform.transform_point (to_x, to_y);
     64 
     65  c->dfuncs->quadratic_to (c->data, *c->st, control_x, control_y, to_x, to_y);
     66 }
     67 
     68 static void
     69 hb_transforming_pen_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
     70 		      void *data,
     71 		      hb_draw_state_t *st,
     72 		      float control1_x, float control1_y,
     73 		      float control2_x, float control2_y,
     74 		      float to_x, float to_y,
     75 		      void *user_data HB_UNUSED)
     76 {
     77  hb_transforming_pen_context_t *c = (hb_transforming_pen_context_t *) data;
     78 
     79  c->transform.transform_point (control1_x, control1_y);
     80  c->transform.transform_point (control2_x, control2_y);
     81  c->transform.transform_point (to_x, to_y);
     82 
     83  c->dfuncs->cubic_to (c->data, *c->st, control1_x, control1_y, control2_x, control2_y, to_x, to_y);
     84 }
     85 
     86 static void
     87 hb_transforming_pen_close_path (hb_draw_funcs_t *dfuncs HB_UNUSED,
     88 			void *data,
     89 			hb_draw_state_t *st,
     90 			void *user_data HB_UNUSED)
     91 {
     92  hb_transforming_pen_context_t *c = (hb_transforming_pen_context_t *) data;
     93 
     94  c->dfuncs->close_path (c->data, *c->st);
     95 }
     96 
     97 static inline void free_static_transforming_pen_funcs ();
     98 
     99 static struct hb_transforming_pen_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t<hb_transforming_pen_funcs_lazy_loader_t>
    100 {
    101  static hb_draw_funcs_t *create ()
    102  {
    103    hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
    104 
    105    hb_draw_funcs_set_move_to_func (funcs, hb_transforming_pen_move_to, nullptr, nullptr);
    106    hb_draw_funcs_set_line_to_func (funcs, hb_transforming_pen_line_to, nullptr, nullptr);
    107    hb_draw_funcs_set_quadratic_to_func (funcs, hb_transforming_pen_quadratic_to, nullptr, nullptr);
    108    hb_draw_funcs_set_cubic_to_func (funcs, hb_transforming_pen_cubic_to, nullptr, nullptr);
    109    hb_draw_funcs_set_close_path_func (funcs, hb_transforming_pen_close_path, nullptr, nullptr);
    110 
    111    hb_draw_funcs_make_immutable (funcs);
    112 
    113    hb_atexit (free_static_transforming_pen_funcs);
    114 
    115    return funcs;
    116  }
    117 } static_transforming_pen_funcs;
    118 
    119 static inline
    120 void free_static_transforming_pen_funcs ()
    121 {
    122  static_transforming_pen_funcs.free_instance ();
    123 }
    124 
    125 static hb_draw_funcs_t *
    126 hb_transforming_pen_get_funcs ()
    127 {
    128  return static_transforming_pen_funcs.get_unconst ();
    129 }
    130 
    131 hb_ubytes_t
    132 VarComponent::get_path_at (const hb_varc_context_t &c,
    133 		   hb_codepoint_t parent_gid,
    134 		   hb_array_t<const int> coords,
    135 		   hb_transform_t<> total_transform,
    136 		   hb_ubytes_t total_record,
    137 		   hb_scalar_cache_t *cache) const
    138 {
    139  const unsigned char *end = total_record.arrayZ + total_record.length;
    140  const unsigned char *record = total_record.arrayZ;
    141 
    142  auto &VARC = *c.font->face->table.VARC->table;
    143  auto &varStore = &VARC+VARC.varStore;
    144 
    145 #define READ_UINT32VAR(name) \
    146  HB_STMT_START { \
    147    if (unlikely (unsigned (end - record) < HBUINT32VAR::min_size)) return hb_ubytes_t (); \
    148    hb_barrier (); \
    149    auto &varint = * (const HBUINT32VAR *) record; \
    150    unsigned size = varint.get_size (); \
    151    if (unlikely (unsigned (end - record) < size)) return hb_ubytes_t (); \
    152    name = (uint32_t) varint; \
    153    record += size; \
    154  } HB_STMT_END
    155 
    156  uint32_t flags;
    157  READ_UINT32VAR (flags);
    158 
    159  // gid
    160 
    161  hb_codepoint_t gid = 0;
    162  if (flags & (unsigned) flags_t::GID_IS_24BIT)
    163  {
    164    if (unlikely (unsigned (end - record) < HBGlyphID24::static_size))
    165      return hb_ubytes_t ();
    166    hb_barrier ();
    167    gid = * (const HBGlyphID24 *) record;
    168    record += HBGlyphID24::static_size;
    169  }
    170  else
    171  {
    172    if (unlikely (unsigned (end - record) < HBGlyphID16::static_size))
    173      return hb_ubytes_t ();
    174    hb_barrier ();
    175    gid = * (const HBGlyphID16 *) record;
    176    record += HBGlyphID16::static_size;
    177  }
    178 
    179  // Condition
    180  bool show = true;
    181  if (flags & (unsigned) flags_t::HAVE_CONDITION)
    182  {
    183    unsigned conditionIndex;
    184    READ_UINT32VAR (conditionIndex);
    185    const auto &condition = (&VARC+VARC.conditionList)[conditionIndex];
    186    auto instancer = MultiItemVarStoreInstancer(&varStore, nullptr, coords, cache);
    187    show = condition.evaluate (coords.arrayZ, coords.length, &instancer);
    188  }
    189 
    190  // Axis values
    191 
    192  auto &axisIndices = c.scratch.axisIndices;
    193  axisIndices.clear ();
    194  auto &axisValues = c.scratch.axisValues;
    195  axisValues.clear ();
    196  if (flags & (unsigned) flags_t::HAVE_AXES)
    197  {
    198    unsigned axisIndicesIndex;
    199    READ_UINT32VAR (axisIndicesIndex);
    200    axisIndices.extend ((&VARC+VARC.axisIndicesList)[axisIndicesIndex]);
    201    axisValues.resize (axisIndices.length);
    202    const HBUINT8 *p = (const HBUINT8 *) record;
    203    TupleValues::decompile (p, axisValues, (const HBUINT8 *) end);
    204    record = (const unsigned char *) p;
    205  }
    206 
    207  // Apply variations if any
    208  if (flags & (unsigned) flags_t::AXIS_VALUES_HAVE_VARIATION)
    209  {
    210    uint32_t axisValuesVarIdx;
    211    READ_UINT32VAR (axisValuesVarIdx);
    212    if (show && coords && !axisValues.in_error ())
    213      varStore.get_delta (axisValuesVarIdx, coords, axisValues.as_array (), cache);
    214  }
    215 
    216  auto component_coords = coords;
    217  /* Copying coords is expensive; so we have put an arbitrary
    218   * limit on the max number of coords for now. */
    219  if ((flags & (unsigned) flags_t::RESET_UNSPECIFIED_AXES) ||
    220      coords.length > HB_VAR_COMPOSITE_MAX_AXES)
    221    component_coords = hb_array (c.font->coords, c.font->num_coords);
    222 
    223  // Transform
    224 
    225  uint32_t transformVarIdx = VarIdx::NO_VARIATION;
    226  if (flags & (unsigned) flags_t::TRANSFORM_HAS_VARIATION)
    227    READ_UINT32VAR (transformVarIdx);
    228 
    229 #define PROCESS_TRANSFORM_COMPONENTS \
    230 HB_STMT_START { \
    231 PROCESS_TRANSFORM_COMPONENT (FWORD, 1.0f, HAVE_TRANSLATE_X, translateX); \
    232 PROCESS_TRANSFORM_COMPONENT (FWORD, 1.0f, HAVE_TRANSLATE_Y, translateY); \
    233 PROCESS_TRANSFORM_COMPONENT (F4DOT12, HB_PI, HAVE_ROTATION, rotation); \
    234 PROCESS_TRANSFORM_COMPONENT (F6DOT10, 1.0f, HAVE_SCALE_X, scaleX); \
    235 PROCESS_TRANSFORM_COMPONENT (F6DOT10, 1.0f, HAVE_SCALE_Y, scaleY); \
    236 PROCESS_TRANSFORM_COMPONENT (F4DOT12, HB_PI, HAVE_SKEW_X, skewX); \
    237 PROCESS_TRANSFORM_COMPONENT (F4DOT12, HB_PI, HAVE_SKEW_Y, skewY); \
    238 PROCESS_TRANSFORM_COMPONENT (FWORD, 1.0f, HAVE_TCENTER_X, tCenterX); \
    239 PROCESS_TRANSFORM_COMPONENT (FWORD, 1.0f, HAVE_TCENTER_Y, tCenterY); \
    240 } HB_STMT_END
    241 
    242  hb_transform_decomposed_t<> transform;
    243 
    244  // Read transform components
    245 #define PROCESS_TRANSFORM_COMPONENT(type, mult, flag, name) \
    246 if (flags & (unsigned) flags_t::flag) \
    247 { \
    248   static_assert (type::static_size == HBINT16::static_size, ""); \
    249   if (unlikely (unsigned (end - record) < HBINT16::static_size)) \
    250     return hb_ubytes_t (); \
    251   hb_barrier (); \
    252   transform.name = mult * * (const HBINT16 *) record; \
    253   record += HBINT16::static_size; \
    254 }
    255  PROCESS_TRANSFORM_COMPONENTS;
    256 #undef PROCESS_TRANSFORM_COMPONENT
    257 
    258  // Read reserved records
    259  unsigned i = flags & (unsigned) flags_t::RESERVED_MASK;
    260  while (i)
    261  {
    262    HB_UNUSED uint32_t discard;
    263    READ_UINT32VAR (discard);
    264    i &= i - 1;
    265  }
    266 
    267  /* Parsing is over now. */
    268 
    269  if (show)
    270  {
    271    // Only use coord_setter if there's actually any axis overrides.
    272    coord_setter_t coord_setter (axisIndices ? component_coords : hb_array<int> ());
    273    // Go backwards, to reduce coord_setter vector reallocations.
    274    for (unsigned i = axisIndices.length; i; i--)
    275      coord_setter[axisIndices[i - 1]] = axisValues[i - 1];
    276    if (axisIndices)
    277      component_coords = coord_setter.get_coords ();
    278 
    279    // Apply transform variations if any
    280    if (transformVarIdx != VarIdx::NO_VARIATION && coords)
    281    {
    282      float transformValues[9];
    283      unsigned numTransformValues = 0;
    284 #define PROCESS_TRANSFORM_COMPONENT(type, mult, flag, name) \
    285   if (flags & (unsigned) flags_t::flag) \
    286     transformValues[numTransformValues++] = transform.name / mult;
    287      PROCESS_TRANSFORM_COMPONENTS;
    288 #undef PROCESS_TRANSFORM_COMPONENT
    289      varStore.get_delta (transformVarIdx, coords, hb_array (transformValues, numTransformValues), cache);
    290      numTransformValues = 0;
    291 #define PROCESS_TRANSFORM_COMPONENT(type, mult, flag, name) \
    292   if (flags & (unsigned) flags_t::flag) \
    293     transform.name = transformValues[numTransformValues++] * mult;
    294      PROCESS_TRANSFORM_COMPONENTS;
    295 #undef PROCESS_TRANSFORM_COMPONENT
    296    }
    297 
    298    // Divide them by their divisors
    299 #define PROCESS_TRANSFORM_COMPONENT(type, mult, flag, name) \
    300   if (flags & (unsigned) flags_t::flag) \
    301   { \
    302     HBINT16 int_v; \
    303     int_v = roundf (transform.name); \
    304     type typed_v = * (const type *) &int_v; \
    305     float float_v = (float) typed_v; \
    306     transform.name = float_v; \
    307   }
    308    PROCESS_TRANSFORM_COMPONENTS;
    309 #undef PROCESS_TRANSFORM_COMPONENT
    310 
    311    if (!(flags & (unsigned) flags_t::HAVE_SCALE_Y))
    312      transform.scaleY = transform.scaleX;
    313 
    314    total_transform.transform (transform.to_transform ());
    315    total_transform.scale (c.font->x_mult ? 1.f / c.font->x_multf : 0.f,
    316 		   c.font->y_mult ? 1.f / c.font->y_multf : 0.f);
    317 
    318    bool same_coords = component_coords.length == coords.length &&
    319 	       component_coords.arrayZ == coords.arrayZ;
    320 
    321    c.depth_left--;
    322    VARC.get_path_at (c, gid,
    323 	      component_coords, total_transform,
    324 	      parent_gid,
    325 	      same_coords ? cache : nullptr);
    326    c.depth_left++;
    327  }
    328 
    329 #undef PROCESS_TRANSFORM_COMPONENTS
    330 #undef READ_UINT32VAR
    331 
    332  return hb_ubytes_t (record, end - record);
    333 }
    334 
    335 bool
    336 VARC::get_path_at (const hb_varc_context_t &c,
    337 	   hb_codepoint_t glyph,
    338 	   hb_array_t<const int> coords,
    339 	   hb_transform_t<> transform,
    340 	   hb_codepoint_t parent_glyph,
    341 	   hb_scalar_cache_t *parent_cache) const
    342 {
    343  // Don't recurse on the same glyph.
    344  unsigned idx = glyph == parent_glyph ?
    345 	 NOT_COVERED :
    346 	 (this+coverage).get_coverage (glyph);
    347  if (idx == NOT_COVERED)
    348  {
    349    if (c.draw_session)
    350    {
    351      // Build a transforming pen to apply the transform.
    352      hb_draw_funcs_t *transformer_funcs = hb_transforming_pen_get_funcs ();
    353      hb_transforming_pen_context_t context {transform,
    354 				     c.draw_session->funcs,
    355 				     c.draw_session->draw_data,
    356 				     &c.draw_session->st};
    357      hb_draw_session_t transformer_session {transformer_funcs, &context};
    358      hb_draw_session_t &shape_draw_session = transform.is_identity () ? *c.draw_session : transformer_session;
    359 
    360      if (c.font->face->table.glyf->get_path_at (c.font, glyph, shape_draw_session, coords, c.scratch.glyf_scratch)) return true;
    361 #ifndef HB_NO_CFF
    362      if (c.font->face->table.cff2->get_path_at (c.font, glyph, shape_draw_session, coords)) return true;
    363      if (c.font->face->table.cff1->get_path (c.font, glyph, shape_draw_session)) return true; // Doesn't have variations
    364 #endif
    365      return false;
    366    }
    367    else if (c.extents)
    368    {
    369      hb_glyph_extents_t glyph_extents;
    370      if (!c.font->face->table.glyf->get_extents_at (c.font, glyph, &glyph_extents, coords))
    371 #ifndef HB_NO_CFF
    372      if (!c.font->face->table.cff2->get_extents_at (c.font, glyph, &glyph_extents, coords))
    373      if (!c.font->face->table.cff1->get_extents (c.font, glyph, &glyph_extents)) // Doesn't have variations
    374 #endif
    375 return false;
    376 
    377      hb_extents_t<> comp_extents (glyph_extents);
    378      transform.transform_extents (comp_extents);
    379      c.extents->union_ (comp_extents);
    380    }
    381    return true;
    382  }
    383 
    384  if (c.depth_left <= 0)
    385    return true;
    386 
    387  if (c.edges_left <= 0)
    388    return true;
    389  (c.edges_left)--;
    390 
    391  hb_decycler_node_t node (c.decycler);
    392  if (unlikely (!node.visit (glyph)))
    393    return true;
    394 
    395  hb_ubytes_t record = (this+glyphRecords)[idx];
    396 
    397  hb_scalar_cache_t static_cache;
    398  hb_scalar_cache_t *cache = parent_cache ?
    399 			  parent_cache :
    400 			  (this+varStore).create_cache (&static_cache);
    401 
    402  transform.scale (c.font->x_multf, c.font->y_multf);
    403 
    404  VarCompositeGlyph::get_path_at (c,
    405 			  glyph,
    406 			  coords, transform,
    407 			  record,
    408 			  cache);
    409 
    410  if (cache != parent_cache)
    411    (this+varStore).destroy_cache (cache, &static_cache);
    412 
    413  return true;
    414 }
    415 
    416 #endif
    417 
    418 //} // namespace Var
    419 } // namespace OT
    420 
    421 #endif