tor-browser

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

hb-draw.cc (14346B)


      1 /*
      2 * Copyright © 2019-2020  Ebrahim Byagowi
      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 
     25 #include "hb.hh"
     26 
     27 #ifndef HB_NO_DRAW
     28 
     29 #include "hb-draw.hh"
     30 
     31 #include "hb-geometry.hh"
     32 
     33 #include "hb-machinery.hh"
     34 
     35 
     36 /**
     37 * SECTION:hb-draw
     38 * @title: hb-draw
     39 * @short_description: Glyph drawing
     40 * @include: hb.h
     41 *
     42 * Functions for drawing (extracting) glyph shapes.
     43 *
     44 * The #hb_draw_funcs_t struct can be used with hb_font_draw_glyph().
     45 **/
     46 
     47 static void
     48 hb_draw_move_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
     49 	     hb_draw_state_t *st HB_UNUSED,
     50 	     float to_x HB_UNUSED, float to_y HB_UNUSED,
     51 	     void *user_data HB_UNUSED) {}
     52 
     53 static void
     54 hb_draw_line_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
     55 	     hb_draw_state_t *st HB_UNUSED,
     56 	     float to_x HB_UNUSED, float to_y HB_UNUSED,
     57 	     void *user_data HB_UNUSED) {}
     58 
     59 static void
     60 hb_draw_quadratic_to_nil (hb_draw_funcs_t *dfuncs, void *draw_data,
     61 		  hb_draw_state_t *st,
     62 		  float control_x, float control_y,
     63 		  float to_x, float to_y,
     64 		  void *user_data HB_UNUSED)
     65 {
     66 #define HB_TWO_THIRD 0.66666666666666666666666667f
     67  dfuncs->emit_cubic_to (draw_data, *st,
     68 		 st->current_x + (control_x - st->current_x) * HB_TWO_THIRD,
     69 		 st->current_y + (control_y - st->current_y) * HB_TWO_THIRD,
     70 		 to_x + (control_x - to_x) * HB_TWO_THIRD,
     71 		 to_y + (control_y - to_y) * HB_TWO_THIRD,
     72 		 to_x, to_y);
     73 #undef HB_TWO_THIRD
     74 }
     75 
     76 static void
     77 hb_draw_cubic_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
     78 	      hb_draw_state_t *st HB_UNUSED,
     79 	      float control1_x HB_UNUSED, float control1_y HB_UNUSED,
     80 	      float control2_x HB_UNUSED, float control2_y HB_UNUSED,
     81 	      float to_x HB_UNUSED, float to_y HB_UNUSED,
     82 	      void *user_data HB_UNUSED) {}
     83 
     84 static void
     85 hb_draw_close_path_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
     86 		hb_draw_state_t *st HB_UNUSED,
     87 		void *user_data HB_UNUSED) {}
     88 
     89 
     90 static bool
     91 _hb_draw_funcs_set_preamble (hb_draw_funcs_t    *dfuncs,
     92 		     bool                func_is_null,
     93 		     void              **user_data,
     94 		     hb_destroy_func_t  *destroy)
     95 {
     96  if (hb_object_is_immutable (dfuncs))
     97  {
     98    if (*destroy)
     99      (*destroy) (*user_data);
    100    return false;
    101  }
    102 
    103  if (func_is_null)
    104  {
    105    if (*destroy)
    106      (*destroy) (*user_data);
    107    *destroy = nullptr;
    108    *user_data = nullptr;
    109  }
    110 
    111  return true;
    112 }
    113 
    114 static bool
    115 _hb_draw_funcs_set_middle (hb_draw_funcs_t   *dfuncs,
    116 		   void              *user_data,
    117 		   hb_destroy_func_t  destroy)
    118 {
    119  if (user_data && !dfuncs->user_data)
    120  {
    121    dfuncs->user_data = (decltype (dfuncs->user_data)) hb_calloc (1, sizeof (*dfuncs->user_data));
    122    if (unlikely (!dfuncs->user_data))
    123      goto fail;
    124  }
    125  if (destroy && !dfuncs->destroy)
    126  {
    127    dfuncs->destroy = (decltype (dfuncs->destroy)) hb_calloc (1, sizeof (*dfuncs->destroy));
    128    if (unlikely (!dfuncs->destroy))
    129      goto fail;
    130  }
    131 
    132  return true;
    133 
    134 fail:
    135  if (destroy)
    136    (destroy) (user_data);
    137  return false;
    138 }
    139 
    140 #define HB_DRAW_FUNC_IMPLEMENT(name)						\
    141 									\
    142 void										\
    143 hb_draw_funcs_set_##name##_func (hb_draw_funcs_t	 *dfuncs,		\
    144 			 hb_draw_##name##_func_t  func,			\
    145 			 void			 *user_data,		\
    146 			 hb_destroy_func_t	  destroy)		\
    147 {										\
    148  if (!_hb_draw_funcs_set_preamble (dfuncs, !func, &user_data, &destroy))\
    149      return;                                                            \
    150 									\
    151  if (dfuncs->destroy && dfuncs->destroy->name)					\
    152    dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name); \
    153 								 \
    154  if (!_hb_draw_funcs_set_middle (dfuncs, user_data, destroy))           \
    155      return;                                                            \
    156 								\
    157  if (func)								\
    158    dfuncs->func.name = func;						\
    159  else									\
    160    dfuncs->func.name = hb_draw_##name##_nil;				\
    161 								\
    162  if (dfuncs->user_data)						\
    163    dfuncs->user_data->name = user_data;				\
    164  if (dfuncs->destroy)							\
    165    dfuncs->destroy->name = destroy;					\
    166 }
    167 
    168 HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
    169 #undef HB_DRAW_FUNC_IMPLEMENT
    170 
    171 /**
    172 * hb_draw_funcs_create:
    173 *
    174 * Creates a new draw callbacks object.
    175 *
    176 * Return value: (transfer full):
    177 * A newly allocated #hb_draw_funcs_t with a reference count of 1. The initial
    178 * reference count should be released with hb_draw_funcs_destroy when you are
    179 * done using the #hb_draw_funcs_t. This function never returns `NULL`. If
    180 * memory cannot be allocated, a special singleton #hb_draw_funcs_t object will
    181 * be returned.
    182 *
    183 * Since: 4.0.0
    184 **/
    185 hb_draw_funcs_t *
    186 hb_draw_funcs_create ()
    187 {
    188  hb_draw_funcs_t *dfuncs;
    189  if (unlikely (!(dfuncs = hb_object_create<hb_draw_funcs_t> ())))
    190    return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
    191 
    192  dfuncs->func =  Null (hb_draw_funcs_t).func;
    193 
    194  return dfuncs;
    195 }
    196 
    197 DEFINE_NULL_INSTANCE (hb_draw_funcs_t) =
    198 {
    199  HB_OBJECT_HEADER_STATIC,
    200 
    201  {
    202 #define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_nil,
    203    HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
    204 #undef HB_DRAW_FUNC_IMPLEMENT
    205  }
    206 };
    207 
    208 /**
    209 * hb_draw_funcs_get_empty:
    210 *
    211 * Fetches the singleton empty draw-functions structure.
    212 *
    213 * Return value: (transfer full): The empty draw-functions structure
    214 *
    215 * Since: 7.0.0
    216 **/
    217 hb_draw_funcs_t *
    218 hb_draw_funcs_get_empty ()
    219 {
    220  return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
    221 }
    222 
    223 /**
    224 * hb_draw_funcs_reference: (skip)
    225 * @dfuncs: draw functions
    226 *
    227 * Increases the reference count on @dfuncs by one.
    228 *
    229 * This prevents @dfuncs from being destroyed until a matching
    230 * call to hb_draw_funcs_destroy() is made.
    231 *
    232 * Return value: (transfer full):
    233 * The referenced #hb_draw_funcs_t.
    234 *
    235 * Since: 4.0.0
    236 **/
    237 hb_draw_funcs_t *
    238 hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs)
    239 {
    240  return hb_object_reference (dfuncs);
    241 }
    242 
    243 /**
    244 * hb_draw_funcs_destroy: (skip)
    245 * @dfuncs: draw functions
    246 *
    247 * Deallocate the @dfuncs.
    248 * Decreases the reference count on @dfuncs by one. If the result is zero, then
    249 * @dfuncs and all associated resources are freed. See hb_draw_funcs_reference().
    250 *
    251 * Since: 4.0.0
    252 **/
    253 void
    254 hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs)
    255 {
    256  if (!hb_object_destroy (dfuncs)) return;
    257 
    258  if (dfuncs->destroy)
    259  {
    260 #define HB_DRAW_FUNC_IMPLEMENT(name) \
    261    if (dfuncs->destroy->name) dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name);
    262      HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
    263 #undef HB_DRAW_FUNC_IMPLEMENT
    264  }
    265 
    266  hb_free (dfuncs->destroy);
    267  hb_free (dfuncs->user_data);
    268 
    269  hb_free (dfuncs);
    270 }
    271 
    272 /**
    273 * hb_draw_funcs_set_user_data: (skip)
    274 * @dfuncs: The draw-functions structure
    275 * @key: The user-data key
    276 * @data: A pointer to the user data
    277 * @destroy: (nullable): A callback to call when @data is not needed anymore
    278 * @replace: Whether to replace an existing data with the same key
    279 *
    280 * Attaches a user-data key/data pair to the specified draw-functions structure.
    281 *
    282 * Return value: `true` if success, `false` otherwise
    283 *
    284 * Since: 7.0.0
    285 **/
    286 hb_bool_t
    287 hb_draw_funcs_set_user_data (hb_draw_funcs_t *dfuncs,
    288 		     hb_user_data_key_t *key,
    289 		     void *              data,
    290 		     hb_destroy_func_t   destroy,
    291 		     hb_bool_t           replace)
    292 {
    293  return hb_object_set_user_data (dfuncs, key, data, destroy, replace);
    294 }
    295 
    296 /**
    297 * hb_draw_funcs_get_user_data: (skip)
    298 * @dfuncs: The draw-functions structure
    299 * @key: The user-data key to query
    300 *
    301 * Fetches the user-data associated with the specified key,
    302 * attached to the specified draw-functions structure.
    303 *
    304 * Return value: (transfer none): A pointer to the user data
    305 *
    306 * Since: 7.0.0
    307 **/
    308 void *
    309 hb_draw_funcs_get_user_data (const hb_draw_funcs_t *dfuncs,
    310 		     hb_user_data_key_t       *key)
    311 {
    312  return hb_object_get_user_data (dfuncs, key);
    313 }
    314 
    315 /**
    316 * hb_draw_funcs_make_immutable:
    317 * @dfuncs: draw functions
    318 *
    319 * Makes @dfuncs object immutable.
    320 *
    321 * Since: 4.0.0
    322 **/
    323 void
    324 hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs)
    325 {
    326  if (hb_object_is_immutable (dfuncs))
    327    return;
    328 
    329  hb_object_make_immutable (dfuncs);
    330 }
    331 
    332 /**
    333 * hb_draw_funcs_is_immutable:
    334 * @dfuncs: draw functions
    335 *
    336 * Checks whether @dfuncs is immutable.
    337 *
    338 * Return value: `true` if @dfuncs is immutable, `false` otherwise
    339 *
    340 * Since: 4.0.0
    341 **/
    342 hb_bool_t
    343 hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs)
    344 {
    345  return hb_object_is_immutable (dfuncs);
    346 }
    347 
    348 
    349 /**
    350 * hb_draw_move_to:
    351 * @dfuncs: draw functions
    352 * @draw_data: associated draw data passed by the caller
    353 * @st: current draw state
    354 * @to_x: X component of target point
    355 * @to_y: Y component of target point
    356 *
    357 * Perform a "move-to" draw operation.
    358 *
    359 * Since: 4.0.0
    360 **/
    361 void
    362 hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data,
    363 	 hb_draw_state_t *st,
    364 	 float to_x, float to_y)
    365 {
    366  dfuncs->move_to (draw_data, *st,
    367 	   to_x, to_y);
    368 }
    369 
    370 /**
    371 * hb_draw_line_to:
    372 * @dfuncs: draw functions
    373 * @draw_data: associated draw data passed by the caller
    374 * @st: current draw state
    375 * @to_x: X component of target point
    376 * @to_y: Y component of target point
    377 *
    378 * Perform a "line-to" draw operation.
    379 *
    380 * Since: 4.0.0
    381 **/
    382 void
    383 hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data,
    384 	 hb_draw_state_t *st,
    385 	 float to_x, float to_y)
    386 {
    387  dfuncs->line_to (draw_data, *st,
    388 	   to_x, to_y);
    389 }
    390 
    391 /**
    392 * hb_draw_quadratic_to:
    393 * @dfuncs: draw functions
    394 * @draw_data: associated draw data passed by the caller
    395 * @st: current draw state
    396 * @control_x: X component of control point
    397 * @control_y: Y component of control point
    398 * @to_x: X component of target point
    399 * @to_y: Y component of target point
    400 *
    401 * Perform a "quadratic-to" draw operation.
    402 *
    403 * Since: 4.0.0
    404 **/
    405 void
    406 hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
    407 	      hb_draw_state_t *st,
    408 	      float control_x, float control_y,
    409 	      float to_x, float to_y)
    410 {
    411  dfuncs->quadratic_to (draw_data, *st,
    412 		control_x, control_y,
    413 		to_x, to_y);
    414 }
    415 
    416 /**
    417 * hb_draw_cubic_to:
    418 * @dfuncs: draw functions
    419 * @draw_data: associated draw data passed by the caller
    420 * @st: current draw state
    421 * @control1_x: X component of first control point
    422 * @control1_y: Y component of first control point
    423 * @control2_x: X component of second control point
    424 * @control2_y: Y component of second control point
    425 * @to_x: X component of target point
    426 * @to_y: Y component of target point
    427 *
    428 * Perform a "cubic-to" draw operation.
    429 *
    430 * Since: 4.0.0
    431 **/
    432 void
    433 hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
    434 	  hb_draw_state_t *st,
    435 	  float control1_x, float control1_y,
    436 	  float control2_x, float control2_y,
    437 	  float to_x, float to_y)
    438 {
    439  dfuncs->cubic_to (draw_data, *st,
    440 	    control1_x, control1_y,
    441 	    control2_x, control2_y,
    442 	    to_x, to_y);
    443 }
    444 
    445 /**
    446 * hb_draw_close_path:
    447 * @dfuncs: draw functions
    448 * @draw_data: associated draw data passed by the caller
    449 * @st: current draw state
    450 *
    451 * Perform a "close-path" draw operation.
    452 *
    453 * Since: 4.0.0
    454 **/
    455 void
    456 hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data,
    457 	    hb_draw_state_t *st)
    458 {
    459  dfuncs->close_path (draw_data, *st);
    460 }
    461 
    462 
    463 static void
    464 hb_draw_extents_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
    465 		 void *data,
    466 		 hb_draw_state_t *st,
    467 		 float to_x, float to_y,
    468 		 void *user_data HB_UNUSED)
    469 {
    470  hb_extents_t<> *extents = (hb_extents_t<> *) data;
    471 
    472  extents->add_point (to_x, to_y);
    473 }
    474 
    475 static void
    476 hb_draw_extents_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
    477 		 void *data,
    478 		 hb_draw_state_t *st,
    479 		 float to_x, float to_y,
    480 		 void *user_data HB_UNUSED)
    481 {
    482  hb_extents_t<> *extents = (hb_extents_t<> *) data;
    483 
    484  extents->add_point (to_x, to_y);
    485 }
    486 
    487 static void
    488 hb_draw_extents_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
    489 		      void *data,
    490 		      hb_draw_state_t *st,
    491 		      float control_x, float control_y,
    492 		      float to_x, float to_y,
    493 		      void *user_data HB_UNUSED)
    494 {
    495  hb_extents_t<> *extents = (hb_extents_t<> *) data;
    496 
    497  extents->add_point (control_x, control_y);
    498  extents->add_point (to_x, to_y);
    499 }
    500 
    501 static void
    502 hb_draw_extents_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
    503 		  void *data,
    504 		  hb_draw_state_t *st,
    505 		  float control1_x, float control1_y,
    506 		  float control2_x, float control2_y,
    507 		  float to_x, float to_y,
    508 		  void *user_data HB_UNUSED)
    509 {
    510  hb_extents_t<> *extents = (hb_extents_t<> *) data;
    511 
    512  extents->add_point (control1_x, control1_y);
    513  extents->add_point (control2_x, control2_y);
    514  extents->add_point (to_x, to_y);
    515 }
    516 
    517 static inline void free_static_draw_extents_funcs ();
    518 
    519 static struct hb_draw_extents_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t<hb_draw_extents_funcs_lazy_loader_t>
    520 {
    521  static hb_draw_funcs_t *create ()
    522  {
    523    hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
    524 
    525    hb_draw_funcs_set_move_to_func (funcs, hb_draw_extents_move_to, nullptr, nullptr);
    526    hb_draw_funcs_set_line_to_func (funcs, hb_draw_extents_line_to, nullptr, nullptr);
    527    hb_draw_funcs_set_quadratic_to_func (funcs, hb_draw_extents_quadratic_to, nullptr, nullptr);
    528    hb_draw_funcs_set_cubic_to_func (funcs, hb_draw_extents_cubic_to, nullptr, nullptr);
    529 
    530    hb_draw_funcs_make_immutable (funcs);
    531 
    532    hb_atexit (free_static_draw_extents_funcs);
    533 
    534    return funcs;
    535  }
    536 } static_draw_extents_funcs;
    537 
    538 static inline
    539 void free_static_draw_extents_funcs ()
    540 {
    541  static_draw_extents_funcs.free_instance ();
    542 }
    543 
    544 hb_draw_funcs_t *
    545 hb_draw_extents_get_funcs ()
    546 {
    547  return static_draw_extents_funcs.get_unconst ();
    548 }
    549 
    550 
    551 #endif