QtBase  v6.3.1
hb-shape-plan.cc
Go to the documentation of this file.
1 /*
2  * Copyright © 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 #include "hb-shape-plan.hh"
29 #include "hb-shaper.hh"
30 #include "hb-font.hh"
31 #include "hb-buffer.hh"
32 
33 
54 /*
55  * hb_shape_plan_key_t
56  */
57 
58 bool
60  hb_face_t *face,
62  const hb_feature_t *user_features,
63  unsigned int num_user_features,
64  const int *coords,
65  unsigned int num_coords,
66  const char * const *shaper_list)
67 {
68  hb_feature_t *features = nullptr;
69  if (copy && num_user_features && !(features = (hb_feature_t *) hb_calloc (num_user_features, sizeof (hb_feature_t))))
70  goto bail;
71 
72  this->props = *props;
73  this->num_user_features = num_user_features;
74  this->user_features = copy ? features : user_features;
75  if (copy && num_user_features)
76  {
77  memcpy (features, user_features, num_user_features * sizeof (hb_feature_t));
78  /* Make start/end uniform to easier catch bugs. */
79  for (unsigned int i = 0; i < num_user_features; i++)
80  {
81  if (features[0].start != HB_FEATURE_GLOBAL_START)
82  features[0].start = 1;
83  if (features[0].end != HB_FEATURE_GLOBAL_END)
84  features[0].end = 2;
85  }
86  }
87  this->shaper_func = nullptr;
88  this->shaper_name = nullptr;
89 #ifndef HB_NO_OT_SHAPE
90  this->ot.init (face, coords, num_coords);
91 #endif
92 
93  /*
94  * Choose shaper.
95  */
96 
97 #define HB_SHAPER_PLAN(shaper) \
98  HB_STMT_START { \
99  if (face->data.shaper) \
100  { \
101  this->shaper_func = _hb_##shaper##_shape; \
102  this->shaper_name = #shaper; \
103  return true; \
104  } \
105  } HB_STMT_END
106 
107  if (unlikely (shaper_list))
108  {
109  for (; *shaper_list; shaper_list++)
110  if (false)
111  ;
112 #define HB_SHAPER_IMPLEMENT(shaper) \
113  else if (0 == strcmp (*shaper_list, #shaper)) \
114  HB_SHAPER_PLAN (shaper);
115 #include "hb-shaper-list.hh"
116 #undef HB_SHAPER_IMPLEMENT
117  }
118  else
119  {
120  const hb_shaper_entry_t *shapers = _hb_shapers_get ();
121  for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
122  if (false)
123  ;
124 #define HB_SHAPER_IMPLEMENT(shaper) \
125  else if (shapers[i].func == _hb_##shaper##_shape) \
126  HB_SHAPER_PLAN (shaper);
127 #include "hb-shaper-list.hh"
128 #undef HB_SHAPER_IMPLEMENT
129  }
130 #undef HB_SHAPER_PLAN
131 
132 bail:
133  ::hb_free (features);
134  return false;
135 }
136 
137 bool
139 {
140  if (this->num_user_features != other->num_user_features)
141  return false;
142  for (unsigned int i = 0; i < num_user_features; i++)
143  {
144  if (this->user_features[i].tag != other->user_features[i].tag ||
145  this->user_features[i].value != other->user_features[i].value ||
146  (this->user_features[i].start == HB_FEATURE_GLOBAL_START &&
147  this->user_features[i].end == HB_FEATURE_GLOBAL_END) !=
148  (other->user_features[i].start == HB_FEATURE_GLOBAL_START &&
149  other->user_features[i].end == HB_FEATURE_GLOBAL_END))
150  return false;
151  }
152  return true;
153 }
154 
155 bool
157 {
158  return hb_segment_properties_equal (&this->props, &other->props) &&
159  this->user_features_match (other) &&
160 #ifndef HB_NO_OT_SHAPE
161  this->ot.equal (&other->ot) &&
162 #endif
163  this->shaper_func == other->shaper_func;
164 }
165 
166 
167 /*
168  * hb_shape_plan_t
169  */
170 
171 
190  const hb_feature_t *user_features,
191  unsigned int num_user_features,
192  const char * const *shaper_list)
193 {
195  user_features, num_user_features,
196  nullptr, 0,
197  shaper_list);
198 }
199 
221  const hb_feature_t *user_features,
222  unsigned int num_user_features,
223  const int *coords,
224  unsigned int num_coords,
225  const char * const *shaper_list)
226 {
227  DEBUG_MSG_FUNC (SHAPE_PLAN, nullptr,
228  "face=%p num_features=%d num_coords=%d shaper_list=%p",
229  face,
230  num_user_features,
231  num_coords,
232  shaper_list);
233 
234  assert (props->direction != HB_DIRECTION_INVALID);
235 
236  hb_shape_plan_t *shape_plan;
237 
238  if (unlikely (!props))
239  goto bail;
240  if (!(shape_plan = hb_object_create<hb_shape_plan_t> ()))
241  goto bail;
242 
243  if (unlikely (!face))
244  face = hb_face_get_empty ();
246  shape_plan->face_unsafe = face;
247 
248  if (unlikely (!shape_plan->key.init (true,
249  face,
250  props,
251  user_features,
252  num_user_features,
253  coords,
254  num_coords,
255  shaper_list)))
256  goto bail2;
257 #ifndef HB_NO_OT_SHAPE
258  if (unlikely (!shape_plan->ot.init0 (face, &shape_plan->key)))
259  goto bail3;
260 #endif
261 
262  return shape_plan;
263 
264 #ifndef HB_NO_OT_SHAPE
265 bail3:
266 #endif
267  shape_plan->key.fini ();
268 bail2:
269  hb_free (shape_plan);
270 bail:
271  return hb_shape_plan_get_empty ();
272 }
273 
285 {
286  return const_cast<hb_shape_plan_t *> (&Null (hb_shape_plan_t));
287 }
288 
301 {
302  return hb_object_reference (shape_plan);
303 }
304 
315 void
317 {
318  if (!hb_object_destroy (shape_plan)) return;
319 
320 #ifndef HB_NO_OT_SHAPE
321  shape_plan->ot.fini ();
322 #endif
323  shape_plan->key.fini ();
324  hb_free (shape_plan);
325 }
326 
341 hb_bool_t
344  void * data,
346  hb_bool_t replace)
347 {
348  return hb_object_set_user_data (shape_plan, key, data, destroy, replace);
349 }
350 
363 void *
366 {
367  return hb_object_get_user_data (shape_plan, key);
368 }
369 
380 const char *
382 {
383  return shape_plan->key.shaper_name;
384 }
385 
386 
387 static bool
388 _hb_shape_plan_execute_internal (hb_shape_plan_t *shape_plan,
389  hb_font_t *font,
391  const hb_feature_t *features,
392  unsigned int num_features)
393 {
394  DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan,
395  "num_features=%d shaper_func=%p, shaper_name=%s",
396  num_features,
397  shape_plan->key.shaper_func,
398  shape_plan->key.shaper_name);
399 
400  if (unlikely (!buffer->len))
401  return true;
402 
403  assert (!hb_object_is_immutable (buffer));
404 
405  buffer->assert_unicode ();
406 
407  if (unlikely (!hb_object_is_valid (shape_plan)))
408  return false;
409 
410  assert (shape_plan->face_unsafe == font->face);
411  assert (hb_segment_properties_equal (&shape_plan->key.props, &buffer->props));
412 
413 #define HB_SHAPER_EXECUTE(shaper) \
414  HB_STMT_START { \
415  return font->data.shaper && \
416  _hb_##shaper##_shape (shape_plan, font, buffer, features, num_features); \
417  } HB_STMT_END
418 
419  if (false)
420  ;
421 #define HB_SHAPER_IMPLEMENT(shaper) \
422  else if (shape_plan->key.shaper_func == _hb_##shaper##_shape) \
423  HB_SHAPER_EXECUTE (shaper);
424 #include "hb-shaper-list.hh"
425 #undef HB_SHAPER_IMPLEMENT
426 
427 #undef HB_SHAPER_EXECUTE
428 
429  return false;
430 }
446 hb_bool_t
448  hb_font_t *font,
450  const hb_feature_t *features,
451  unsigned int num_features)
452 {
453  bool ret = _hb_shape_plan_execute_internal (shape_plan, font, buffer,
454  features, num_features);
455 
456  if (ret && buffer->content_type == HB_BUFFER_CONTENT_TYPE_UNICODE)
457  buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
458 
459  return ret;
460 }
461 
462 
463 /*
464  * Caching
465  */
466 
485  const hb_feature_t *user_features,
486  unsigned int num_user_features,
487  const char * const *shaper_list)
488 {
490  user_features, num_user_features,
491  nullptr, 0,
492  shaper_list);
493 }
494 
517  const hb_feature_t *user_features,
518  unsigned int num_user_features,
519  const int *coords,
520  unsigned int num_coords,
521  const char * const *shaper_list)
522 {
523  DEBUG_MSG_FUNC (SHAPE_PLAN, nullptr,
524  "face=%p num_features=%d shaper_list=%p",
525  face,
526  num_user_features,
527  shaper_list);
528 
529 retry:
530  hb_face_t::plan_node_t *cached_plan_nodes = face->shape_plans;
531 
532  bool dont_cache = !hb_object_is_valid (face);
533 
534  if (likely (!dont_cache))
535  {
537  if (!key.init (false,
538  face,
539  props,
540  user_features,
541  num_user_features,
542  coords,
543  num_coords,
544  shaper_list))
545  return hb_shape_plan_get_empty ();
546 
547  for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next)
548  if (node->shape_plan->key.equal (&key))
549  {
550  DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache");
551  return hb_shape_plan_reference (node->shape_plan);
552  }
553  }
554 
556  user_features, num_user_features,
557  coords, num_coords,
558  shaper_list);
559 
560  if (unlikely (dont_cache))
561  return shape_plan;
562 
564  if (unlikely (!node))
565  return shape_plan;
566 
567  node->shape_plan = shape_plan;
568  node->next = cached_plan_nodes;
569 
570  if (unlikely (!face->shape_plans.cmpexch (cached_plan_nodes, node)))
571  {
572  hb_shape_plan_destroy (shape_plan);
573  hb_free (node);
574  goto retry;
575  }
576  DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, "inserted into cache");
577 
578  return hb_shape_plan_reference (shape_plan);
579 }
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
#define this
Definition: dialogs.cpp:56
hb_bool_t hb_segment_properties_equal(const hb_segment_properties_t *a, const hb_segment_properties_t *b)
Definition: hb-buffer.cc:59
#define DEBUG_MSG_FUNC(WHAT, OBJ,...)
void hb_face_make_immutable(hb_face_t *face)
Definition: hb-face.cc:360
hb_face_t * hb_face_get_empty()
Definition: hb-face.cc:254
#define Null(Type)
Definition: hb-null.hh:106
hb_shape_plan_t * hb_shape_plan_create2(hb_face_t *face, const hb_segment_properties_t *props, const hb_feature_t *user_features, unsigned int num_user_features, const int *coords, unsigned int num_coords, const char *const *shaper_list)
void hb_shape_plan_destroy(hb_shape_plan_t *shape_plan)
hb_shape_plan_t * hb_shape_plan_get_empty()
hb_bool_t hb_shape_plan_set_user_data(hb_shape_plan_t *shape_plan, hb_user_data_key_t *key, void *data, hb_destroy_func_t destroy, hb_bool_t replace)
hb_bool_t hb_shape_plan_execute(hb_shape_plan_t *shape_plan, hb_font_t *font, hb_buffer_t *buffer, const hb_feature_t *features, unsigned int num_features)
hb_shape_plan_t * hb_shape_plan_reference(hb_shape_plan_t *shape_plan)
void * hb_shape_plan_get_user_data(hb_shape_plan_t *shape_plan, hb_user_data_key_t *key)
hb_shape_plan_t * hb_shape_plan_create_cached(hb_face_t *face, const hb_segment_properties_t *props, const hb_feature_t *user_features, unsigned int num_user_features, const char *const *shaper_list)
hb_shape_plan_t * hb_shape_plan_create_cached2(hb_face_t *face, const hb_segment_properties_t *props, const hb_feature_t *user_features, unsigned int num_user_features, const int *coords, unsigned int num_coords, const char *const *shaper_list)
hb_shape_plan_t * hb_shape_plan_create(hb_face_t *face, const hb_segment_properties_t *props, const hb_feature_t *user_features, unsigned int num_user_features, const char *const *shaper_list)
const char * hb_shape_plan_get_shaper(hb_shape_plan_t *shape_plan)
const hb_shaper_entry_t * _hb_shapers_get()
Definition: hb-shaper.cc:99
@ HB_SHAPERS_COUNT
Definition: hb-shaper.hh:66
#define hb_calloc
Definition: hb.hh:236
#define likely(expr)
Definition: hb.hh:250
#define unlikely(expr)
Definition: hb.hh:251
#define hb_free
Definition: hb.hh:238
QPainterPath node()
Definition: paths.cpp:574
#define assert
Definition: qcborcommon_p.h:63
GLuint64 key
GLuint GLuint end
GLsizei const GLubyte GLsizei GLenum const void * coords
GLenum face
GLenum GLuint buffer
GLenum GLuint GLsizei const GLenum * props
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint start
@ HB_BUFFER_CONTENT_TYPE_GLYPHS
Definition: hb-buffer.h:284
@ HB_BUFFER_CONTENT_TYPE_UNICODE
Definition: hb-buffer.h:283
void(* hb_destroy_func_t)(void *user_data)
Definition: hb-common.h:771
HB_BEGIN_DECLS typedef int hb_bool_t
Definition: hb-common.h:97
#define HB_FEATURE_GLOBAL_END
Definition: hb-common.h:794
@ HB_DIRECTION_INVALID
Definition: hb-common.h:230
#define HB_FEATURE_GLOBAL_START
Definition: hb-common.h:784
HB_EXTERN hb_font_get_glyph_func_t void hb_destroy_func_t destroy
QSharedPointer< T > other(t)
[5]
unsigned int end
Definition: hb-common.h:815
unsigned int start
Definition: hb-common.h:814
hb_tag_t tag
Definition: hb-common.h:812
void init(hb_face_t *face, const int *coords, unsigned num_coords)
Definition: hb-ot-shape.hh:40
bool equal(const hb_ot_shape_plan_key_t *other)
Definition: hb-ot-shape.hh:52
HB_INTERNAL bool init0(hb_face_t *face, const hb_shape_plan_key_t *key)
Definition: hb-ot-shape.cc:219
HB_INTERNAL void fini()
Definition: hb-ot-shape.cc:253
HB_INTERNAL void fini()
hb_ot_shape_plan_key_t ot
const hb_feature_t * user_features
unsigned int num_user_features
HB_INTERNAL bool equal(const hb_shape_plan_key_t *other)
hb_segment_properties_t props
hb_shape_func_t * shaper_func
HB_INTERNAL bool init(bool copy, hb_face_t *face, const hb_segment_properties_t *props, const hb_feature_t *user_features, unsigned int num_user_features, const int *coords, unsigned int num_coords, const char *const *shaper_list)
const char * shaper_name
HB_INTERNAL bool user_features_match(const hb_shape_plan_key_t *other)
hb_face_t * face_unsafe
hb_ot_shape_plan_t ot
hb_shape_plan_key_t key
Definition: hb-shaper.hh:44
XmlOutput::xml_output tag(const QString &name)
Definition: xmloutput.h:154