~gabriel1984sibiu/minitube/qt5.6

« back to all changes in this revision

Viewing changes to src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc

  • Committer: Grevutiu Gabriel
  • Date: 2017-06-13 08:43:17 UTC
  • Revision ID: gabriel1984sibiu@gmail.com-20170613084317-ek0zqe0u9g3ocvi8
OriginalĀ upstreamĀ code

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright Ā© 2009,2010  Red Hat, Inc.
 
3
 * Copyright Ā© 2010,2011,2012  Google, Inc.
 
4
 *
 
5
 *  This is part of HarfBuzz, a text shaping library.
 
6
 *
 
7
 * Permission is hereby granted, without written agreement and without
 
8
 * license or royalty fees, to use, copy, modify, and distribute this
 
9
 * software and its documentation for any purpose, provided that the
 
10
 * above copyright notice and the following two paragraphs appear in
 
11
 * all copies of this software.
 
12
 *
 
13
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 
14
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 
15
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 
16
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 
17
 * DAMAGE.
 
18
 *
 
19
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 
20
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 
21
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 
22
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 
23
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 
24
 *
 
25
 * Red Hat Author(s): Behdad Esfahbod
 
26
 * Google Author(s): Behdad Esfahbod
 
27
 */
 
28
 
 
29
#define HB_SHAPER ot
 
30
#define hb_ot_shaper_face_data_t hb_ot_layout_t
 
31
#define hb_ot_shaper_shape_plan_data_t hb_ot_shape_plan_t
 
32
#include "hb-shaper-impl-private.hh"
 
33
 
 
34
#include "hb-ot-shape-private.hh"
 
35
#include "hb-ot-shape-complex-private.hh"
 
36
#include "hb-ot-shape-fallback-private.hh"
 
37
#include "hb-ot-shape-normalize-private.hh"
 
38
 
 
39
#include "hb-ot-layout-private.hh"
 
40
#include "hb-unicode-private.hh"
 
41
#include "hb-set-private.hh"
 
42
 
 
43
 
 
44
static hb_tag_t common_features[] = {
 
45
  HB_TAG('c','c','m','p'),
 
46
  HB_TAG('l','o','c','l'),
 
47
  HB_TAG('m','a','r','k'),
 
48
  HB_TAG('m','k','m','k'),
 
49
  HB_TAG('r','l','i','g'),
 
50
};
 
51
 
 
52
 
 
53
static hb_tag_t horizontal_features[] = {
 
54
  HB_TAG('c','a','l','t'),
 
55
  HB_TAG('c','l','i','g'),
 
56
  HB_TAG('c','u','r','s'),
 
57
  HB_TAG('k','e','r','n'),
 
58
  HB_TAG('l','i','g','a'),
 
59
  HB_TAG('r','c','l','t'),
 
60
};
 
61
 
 
62
 
 
63
 
 
64
static void
 
65
hb_ot_shape_collect_features (hb_ot_shape_planner_t          *planner,
 
66
                              const hb_segment_properties_t  *props,
 
67
                              const hb_feature_t             *user_features,
 
68
                              unsigned int                    num_user_features)
 
69
{
 
70
  hb_ot_map_builder_t *map = &planner->map;
 
71
 
 
72
  switch (props->direction) {
 
73
    case HB_DIRECTION_LTR:
 
74
      map->add_global_bool_feature (HB_TAG ('l','t','r','a'));
 
75
      map->add_global_bool_feature (HB_TAG ('l','t','r','m'));
 
76
      break;
 
77
    case HB_DIRECTION_RTL:
 
78
      map->add_global_bool_feature (HB_TAG ('r','t','l','a'));
 
79
      map->add_feature (HB_TAG ('r','t','l','m'), 1, F_NONE);
 
80
      break;
 
81
    case HB_DIRECTION_TTB:
 
82
    case HB_DIRECTION_BTT:
 
83
    case HB_DIRECTION_INVALID:
 
84
    default:
 
85
      break;
 
86
  }
 
87
 
 
88
  map->add_feature (HB_TAG ('f','r','a','c'), 1, F_NONE);
 
89
  map->add_feature (HB_TAG ('n','u','m','r'), 1, F_NONE);
 
90
  map->add_feature (HB_TAG ('d','n','o','m'), 1, F_NONE);
 
91
 
 
92
  if (planner->shaper->collect_features)
 
93
    planner->shaper->collect_features (planner);
 
94
 
 
95
  for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++)
 
96
    map->add_global_bool_feature (common_features[i]);
 
97
 
 
98
  if (HB_DIRECTION_IS_HORIZONTAL (props->direction))
 
99
    for (unsigned int i = 0; i < ARRAY_LENGTH (horizontal_features); i++)
 
100
      map->add_feature (horizontal_features[i], 1, F_GLOBAL |
 
101
                        (horizontal_features[i] == HB_TAG('k','e','r','n') ?
 
102
                         F_HAS_FALLBACK : F_NONE));
 
103
  else
 
104
  {
 
105
    /* We really want to find a 'vert' feature if there's any in the font, no
 
106
     * matter which script/langsys it is listed (or not) under.
 
107
     * See various bugs referenced from:
 
108
     * https://github.com/behdad/harfbuzz/issues/63 */
 
109
    map->add_feature (HB_TAG ('v','e','r','t'), 1, F_GLOBAL | F_GLOBAL_SEARCH);
 
110
  }
 
111
 
 
112
  if (planner->shaper->override_features)
 
113
    planner->shaper->override_features (planner);
 
114
 
 
115
  for (unsigned int i = 0; i < num_user_features; i++) {
 
116
    const hb_feature_t *feature = &user_features[i];
 
117
    map->add_feature (feature->tag, feature->value,
 
118
                      (feature->start == 0 && feature->end == (unsigned int) -1) ?
 
119
                       F_GLOBAL : F_NONE);
 
120
  }
 
121
}
 
122
 
 
123
 
 
124
/*
 
125
 * shaper face data
 
126
 */
 
127
 
 
128
hb_ot_shaper_face_data_t *
 
129
_hb_ot_shaper_face_data_create (hb_face_t *face)
 
130
{
 
131
  return _hb_ot_layout_create (face);
 
132
}
 
133
 
 
134
void
 
135
_hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data)
 
136
{
 
137
  _hb_ot_layout_destroy (data);
 
138
}
 
139
 
 
140
 
 
141
/*
 
142
 * shaper font data
 
143
 */
 
144
 
 
145
struct hb_ot_shaper_font_data_t {};
 
146
 
 
147
hb_ot_shaper_font_data_t *
 
148
_hb_ot_shaper_font_data_create (hb_font_t *font)
 
149
{
 
150
  return (hb_ot_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
 
151
}
 
152
 
 
153
void
 
154
_hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t *data)
 
155
{
 
156
}
 
157
 
 
158
 
 
159
/*
 
160
 * shaper shape_plan data
 
161
 */
 
162
 
 
163
hb_ot_shaper_shape_plan_data_t *
 
164
_hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan,
 
165
                                      const hb_feature_t *user_features,
 
166
                                      unsigned int        num_user_features)
 
167
{
 
168
  hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t));
 
169
  if (unlikely (!plan))
 
170
    return NULL;
 
171
 
 
172
  hb_ot_shape_planner_t planner (shape_plan);
 
173
 
 
174
  planner.shaper = hb_ot_shape_complex_categorize (&planner);
 
175
 
 
176
  hb_ot_shape_collect_features (&planner, &shape_plan->props, user_features, num_user_features);
 
177
 
 
178
  planner.compile (*plan);
 
179
 
 
180
  if (plan->shaper->data_create) {
 
181
    plan->data = plan->shaper->data_create (plan);
 
182
    if (unlikely (!plan->data))
 
183
      return NULL;
 
184
  }
 
185
 
 
186
  return plan;
 
187
}
 
188
 
 
189
void
 
190
_hb_ot_shaper_shape_plan_data_destroy (hb_ot_shaper_shape_plan_data_t *plan)
 
191
{
 
192
  if (plan->shaper->data_destroy)
 
193
    plan->shaper->data_destroy (const_cast<void *> (plan->data));
 
194
 
 
195
  plan->finish ();
 
196
 
 
197
  free (plan);
 
198
}
 
199
 
 
200
 
 
201
/*
 
202
 * shaper
 
203
 */
 
204
 
 
205
struct hb_ot_shape_context_t
 
206
{
 
207
  hb_ot_shape_plan_t *plan;
 
208
  hb_font_t *font;
 
209
  hb_face_t *face;
 
210
  hb_buffer_t  *buffer;
 
211
  const hb_feature_t *user_features;
 
212
  unsigned int        num_user_features;
 
213
 
 
214
  /* Transient stuff */
 
215
  hb_direction_t target_direction;
 
216
};
 
217
 
 
218
 
 
219
 
 
220
/* Main shaper */
 
221
 
 
222
 
 
223
/* Prepare */
 
224
 
 
225
static void
 
226
hb_set_unicode_props (hb_buffer_t *buffer)
 
227
{
 
228
  unsigned int count = buffer->len;
 
229
  hb_glyph_info_t *info = buffer->info;
 
230
  for (unsigned int i = 0; i < count; i++)
 
231
    _hb_glyph_info_set_unicode_props (&info[i], buffer->unicode);
 
232
}
 
233
 
 
234
static void
 
235
hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
 
236
{
 
237
  if (!(buffer->flags & HB_BUFFER_FLAG_BOT) ||
 
238
      buffer->context_len[0] ||
 
239
      _hb_glyph_info_get_general_category (&buffer->info[0]) !=
 
240
      HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
 
241
    return;
 
242
 
 
243
  if (!font->has_glyph (0x25CCu))
 
244
    return;
 
245
 
 
246
  hb_glyph_info_t dottedcircle = {0};
 
247
  dottedcircle.codepoint = 0x25CCu;
 
248
  _hb_glyph_info_set_unicode_props (&dottedcircle, buffer->unicode);
 
249
 
 
250
  buffer->clear_output ();
 
251
 
 
252
  buffer->idx = 0;
 
253
  hb_glyph_info_t info = dottedcircle;
 
254
  info.cluster = buffer->cur().cluster;
 
255
  info.mask = buffer->cur().mask;
 
256
  buffer->output_info (info);
 
257
  while (buffer->idx < buffer->len)
 
258
    buffer->next_glyph ();
 
259
 
 
260
  buffer->swap_buffers ();
 
261
}
 
262
 
 
263
static void
 
264
hb_form_clusters (hb_buffer_t *buffer)
 
265
{
 
266
  if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
 
267
    return;
 
268
 
 
269
  /* Loop duplicated in hb_ensure_native_direction(). */
 
270
  unsigned int base = 0;
 
271
  unsigned int count = buffer->len;
 
272
  hb_glyph_info_t *info = buffer->info;
 
273
  for (unsigned int i = 1; i < count; i++)
 
274
  {
 
275
    if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i]))))
 
276
    {
 
277
      buffer->merge_clusters (base, i);
 
278
      base = i;
 
279
    }
 
280
  }
 
281
  buffer->merge_clusters (base, count);
 
282
}
 
283
 
 
284
static void
 
285
hb_ensure_native_direction (hb_buffer_t *buffer)
 
286
{
 
287
  hb_direction_t direction = buffer->props.direction;
 
288
 
 
289
  /* TODO vertical:
 
290
   * The only BTT vertical script is Ogham, but it's not clear to me whether OpenType
 
291
   * Ogham fonts are supposed to be implemented BTT or not.  Need to research that
 
292
   * first. */
 
293
  if ((HB_DIRECTION_IS_HORIZONTAL (direction) && direction != hb_script_get_horizontal_direction (buffer->props.script)) ||
 
294
      (HB_DIRECTION_IS_VERTICAL   (direction) && direction != HB_DIRECTION_TTB))
 
295
  {
 
296
    /* Same loop as hb_form_clusters().
 
297
     * Since form_clusters() merged clusters already, we don't merge. */
 
298
    unsigned int base = 0;
 
299
    unsigned int count = buffer->len;
 
300
    hb_glyph_info_t *info = buffer->info;
 
301
    for (unsigned int i = 1; i < count; i++)
 
302
    {
 
303
      if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i]))))
 
304
      {
 
305
        if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
 
306
          buffer->merge_clusters (base, i);
 
307
        buffer->reverse_range (base, i);
 
308
 
 
309
        base = i;
 
310
      }
 
311
    }
 
312
    if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
 
313
      buffer->merge_clusters (base, count);
 
314
    buffer->reverse_range (base, count);
 
315
 
 
316
    buffer->reverse ();
 
317
 
 
318
    buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction);
 
319
  }
 
320
}
 
321
 
 
322
 
 
323
/* Substitute */
 
324
 
 
325
static inline void
 
326
hb_ot_mirror_chars (hb_ot_shape_context_t *c)
 
327
{
 
328
  if (HB_DIRECTION_IS_FORWARD (c->target_direction))
 
329
    return;
 
330
 
 
331
  hb_buffer_t *buffer = c->buffer;
 
332
  hb_unicode_funcs_t *unicode = buffer->unicode;
 
333
  hb_mask_t rtlm_mask = c->plan->rtlm_mask;
 
334
 
 
335
  unsigned int count = buffer->len;
 
336
  hb_glyph_info_t *info = buffer->info;
 
337
  for (unsigned int i = 0; i < count; i++) {
 
338
    hb_codepoint_t codepoint = unicode->mirroring (info[i].codepoint);
 
339
    if (likely (codepoint == info[i].codepoint || !c->font->has_glyph (codepoint)))
 
340
      info[i].mask |= rtlm_mask;
 
341
    else
 
342
      info[i].codepoint = codepoint;
 
343
  }
 
344
}
 
345
 
 
346
static inline void
 
347
hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c)
 
348
{
 
349
  if (!c->plan->has_frac)
 
350
    return;
 
351
 
 
352
  hb_buffer_t *buffer = c->buffer;
 
353
 
 
354
  /* TODO look in pre/post context text also. */
 
355
  unsigned int count = buffer->len;
 
356
  hb_glyph_info_t *info = buffer->info;
 
357
  for (unsigned int i = 0; i < count; i++)
 
358
  {
 
359
    if (info[i].codepoint == 0x2044u) /* FRACTION SLASH */
 
360
    {
 
361
      unsigned int start = i, end = i + 1;
 
362
      while (start &&
 
363
             _hb_glyph_info_get_general_category (&info[start - 1]) ==
 
364
             HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
 
365
        start--;
 
366
      while (end < count &&
 
367
             _hb_glyph_info_get_general_category (&info[end]) ==
 
368
             HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
 
369
        end++;
 
370
 
 
371
      for (unsigned int j = start; j < i; j++)
 
372
        info[j].mask |= c->plan->numr_mask | c->plan->frac_mask;
 
373
      info[i].mask |= c->plan->frac_mask;
 
374
      for (unsigned int j = i + 1; j < end; j++)
 
375
        info[j].mask |= c->plan->frac_mask | c->plan->dnom_mask;
 
376
 
 
377
      i = end - 1;
 
378
    }
 
379
  }
 
380
}
 
381
 
 
382
static inline void
 
383
hb_ot_shape_initialize_masks (hb_ot_shape_context_t *c)
 
384
{
 
385
  hb_ot_map_t *map = &c->plan->map;
 
386
  hb_buffer_t *buffer = c->buffer;
 
387
 
 
388
  hb_mask_t global_mask = map->get_global_mask ();
 
389
  buffer->reset_masks (global_mask);
 
390
}
 
391
 
 
392
static inline void
 
393
hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
 
394
{
 
395
  hb_ot_map_t *map = &c->plan->map;
 
396
  hb_buffer_t *buffer = c->buffer;
 
397
 
 
398
  hb_ot_shape_setup_masks_fraction (c);
 
399
 
 
400
  if (c->plan->shaper->setup_masks)
 
401
    c->plan->shaper->setup_masks (c->plan, buffer, c->font);
 
402
 
 
403
  for (unsigned int i = 0; i < c->num_user_features; i++)
 
404
  {
 
405
    const hb_feature_t *feature = &c->user_features[i];
 
406
    if (!(feature->start == 0 && feature->end == (unsigned int)-1)) {
 
407
      unsigned int shift;
 
408
      hb_mask_t mask = map->get_mask (feature->tag, &shift);
 
409
      buffer->set_masks (feature->value << shift, mask, feature->start, feature->end);
 
410
    }
 
411
  }
 
412
}
 
413
 
 
414
static void
 
415
hb_ot_zero_width_default_ignorables (hb_ot_shape_context_t *c)
 
416
{
 
417
  hb_buffer_t *buffer = c->buffer;
 
418
 
 
419
  if (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES)
 
420
    return;
 
421
 
 
422
  unsigned int count = buffer->len;
 
423
  hb_glyph_info_t *info = buffer->info;
 
424
  hb_glyph_position_t *pos = buffer->pos;
 
425
  unsigned int i = 0;
 
426
  for (i = 0; i < count; i++)
 
427
    if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i])))
 
428
      pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
 
429
}
 
430
 
 
431
static void
 
432
hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
 
433
{
 
434
  hb_buffer_t *buffer = c->buffer;
 
435
 
 
436
  if (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES)
 
437
    return;
 
438
 
 
439
  unsigned int count = buffer->len;
 
440
  hb_glyph_info_t *info = buffer->info;
 
441
  hb_glyph_position_t *pos = buffer->pos;
 
442
  unsigned int i = 0;
 
443
  for (i = 0; i < count; i++)
 
444
  {
 
445
    if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i])))
 
446
      break;
 
447
  }
 
448
 
 
449
  /* No default-ignorables found; return. */
 
450
  if (i == count)
 
451
    return;
 
452
 
 
453
  hb_codepoint_t space;
 
454
  if (c->font->get_glyph (' ', 0, &space))
 
455
  {
 
456
    /* Replace default-ignorables with a zero-advance space glyph. */
 
457
    for (/*continue*/; i < count; i++)
 
458
    {
 
459
      if (_hb_glyph_info_is_default_ignorable (&info[i]))
 
460
        info[i].codepoint = space;
 
461
    }
 
462
  }
 
463
  else
 
464
  {
 
465
    /* Merge clusters and delete default-ignorables.
 
466
     * NOTE! We can't use out-buffer as we have positioning data. */
 
467
    unsigned int j = i;
 
468
    for (; i < count; i++)
 
469
    {
 
470
      if (_hb_glyph_info_is_default_ignorable (&info[i]))
 
471
      {
 
472
        /* Merge clusters.
 
473
         * Same logic as buffer->delete_glyph(), but for in-place removal. */
 
474
 
 
475
        unsigned int cluster = info[i].cluster;
 
476
        if (i + 1 < count && cluster == info[i + 1].cluster)
 
477
          continue; /* Cluster survives; do nothing. */
 
478
 
 
479
        if (j)
 
480
        {
 
481
          /* Merge cluster backward. */
 
482
          if (cluster < info[j - 1].cluster)
 
483
          {
 
484
            unsigned int old_cluster = info[j - 1].cluster;
 
485
            for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
 
486
              info[k - 1].cluster = cluster;
 
487
          }
 
488
          continue;
 
489
        }
 
490
 
 
491
        if (i + 1 < count)
 
492
          buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */
 
493
 
 
494
        continue;
 
495
      }
 
496
 
 
497
      if (j != i)
 
498
      {
 
499
        info[j] = info[i];
 
500
        pos[j] = pos[i];
 
501
      }
 
502
      j++;
 
503
    }
 
504
    buffer->len = j;
 
505
  }
 
506
}
 
507
 
 
508
 
 
509
static inline void
 
510
hb_ot_map_glyphs_fast (hb_buffer_t  *buffer)
 
511
{
 
512
  /* Normalization process sets up glyph_index(), we just copy it. */
 
513
  unsigned int count = buffer->len;
 
514
  hb_glyph_info_t *info = buffer->info;
 
515
  for (unsigned int i = 0; i < count; i++)
 
516
    info[i].codepoint = info[i].glyph_index();
 
517
 
 
518
  buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
 
519
}
 
520
 
 
521
static inline void
 
522
hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
 
523
{
 
524
  unsigned int count = c->buffer->len;
 
525
  hb_glyph_info_t *info = c->buffer->info;
 
526
  for (unsigned int i = 0; i < count; i++)
 
527
  {
 
528
    hb_ot_layout_glyph_class_mask_t klass;
 
529
 
 
530
    /* Never mark default-ignorables as marks.
 
531
     * They won't get in the way of lookups anyway,
 
532
     * but having them as mark will cause them to be skipped
 
533
     * over if the lookup-flag says so, but at least for the
 
534
     * Mongolian variation selectors, looks like Uniscribe
 
535
     * marks them as non-mark.  Some Mongolian fonts without
 
536
     * GDEF rely on this.  Another notable character that
 
537
     * this applies to is COMBINING GRAPHEME JOINER. */
 
538
    klass = (_hb_glyph_info_get_general_category (&info[i]) !=
 
539
             HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
 
540
             _hb_glyph_info_is_default_ignorable (&info[i])) ?
 
541
            HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
 
542
            HB_OT_LAYOUT_GLYPH_PROPS_MARK;
 
543
    _hb_glyph_info_set_glyph_props (&info[i], klass);
 
544
  }
 
545
}
 
546
 
 
547
static inline void
 
548
hb_ot_substitute_default (hb_ot_shape_context_t *c)
 
549
{
 
550
  hb_buffer_t *buffer = c->buffer;
 
551
 
 
552
  if (c->plan->shaper->preprocess_text)
 
553
    c->plan->shaper->preprocess_text (c->plan, buffer, c->font);
 
554
 
 
555
  hb_ot_shape_initialize_masks (c);
 
556
 
 
557
  hb_ot_mirror_chars (c);
 
558
 
 
559
  HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index);
 
560
 
 
561
  _hb_ot_shape_normalize (c->plan, buffer, c->font);
 
562
 
 
563
  hb_ot_shape_setup_masks (c);
 
564
 
 
565
  /* This is unfortunate to go here, but necessary... */
 
566
  if (!hb_ot_layout_has_positioning (c->face))
 
567
    _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, buffer);
 
568
 
 
569
  hb_ot_map_glyphs_fast (buffer);
 
570
 
 
571
  HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_index);
 
572
}
 
573
 
 
574
static inline void
 
575
hb_ot_substitute_complex (hb_ot_shape_context_t *c)
 
576
{
 
577
  hb_buffer_t *buffer = c->buffer;
 
578
 
 
579
  _hb_buffer_allocate_gsubgpos_vars (buffer);
 
580
  hb_ot_layout_substitute_start (c->font, buffer);
 
581
 
 
582
  if (!hb_ot_layout_has_glyph_classes (c->face))
 
583
    hb_synthesize_glyph_classes (c);
 
584
 
 
585
  c->plan->substitute (c->font, buffer);
 
586
 
 
587
  hb_ot_layout_substitute_finish (c->font, buffer);
 
588
 
 
589
  return;
 
590
}
 
591
 
 
592
static inline void
 
593
hb_ot_substitute (hb_ot_shape_context_t *c)
 
594
{
 
595
  hb_ot_substitute_default (c);
 
596
  hb_ot_substitute_complex (c);
 
597
}
 
598
 
 
599
/* Position */
 
600
 
 
601
static inline void
 
602
adjust_mark_offsets (hb_glyph_position_t *pos)
 
603
{
 
604
  pos->x_offset -= pos->x_advance;
 
605
  pos->y_offset -= pos->y_advance;
 
606
}
 
607
 
 
608
static inline void
 
609
zero_mark_width (hb_glyph_position_t *pos)
 
610
{
 
611
  pos->x_advance = 0;
 
612
  pos->y_advance = 0;
 
613
}
 
614
 
 
615
static inline void
 
616
zero_mark_widths_by_unicode (hb_buffer_t *buffer, bool adjust_offsets)
 
617
{
 
618
  unsigned int count = buffer->len;
 
619
  hb_glyph_info_t *info = buffer->info;
 
620
  for (unsigned int i = 0; i < count; i++)
 
621
    if (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
 
622
    {
 
623
      if (adjust_offsets)
 
624
        adjust_mark_offsets (&buffer->pos[i]);
 
625
      zero_mark_width (&buffer->pos[i]);
 
626
    }
 
627
}
 
628
 
 
629
static inline void
 
630
zero_mark_widths_by_gdef (hb_buffer_t *buffer, bool adjust_offsets)
 
631
{
 
632
  unsigned int count = buffer->len;
 
633
  hb_glyph_info_t *info = buffer->info;
 
634
  for (unsigned int i = 0; i < count; i++)
 
635
    if (_hb_glyph_info_is_mark (&info[i]))
 
636
    {
 
637
      if (adjust_offsets)
 
638
        adjust_mark_offsets (&buffer->pos[i]);
 
639
      zero_mark_width (&buffer->pos[i]);
 
640
    }
 
641
}
 
642
 
 
643
static inline void
 
644
hb_ot_position_default (hb_ot_shape_context_t *c)
 
645
{
 
646
  hb_direction_t direction = c->buffer->props.direction;
 
647
  unsigned int count = c->buffer->len;
 
648
  hb_glyph_info_t *info = c->buffer->info;
 
649
  hb_glyph_position_t *pos = c->buffer->pos;
 
650
  for (unsigned int i = 0; i < count; i++)
 
651
  {
 
652
    c->font->get_glyph_advance_for_direction (info[i].codepoint,
 
653
                                              direction,
 
654
                                              &pos[i].x_advance,
 
655
                                              &pos[i].y_advance);
 
656
    c->font->subtract_glyph_origin_for_direction (info[i].codepoint,
 
657
                                                  direction,
 
658
                                                  &pos[i].x_offset,
 
659
                                                  &pos[i].y_offset);
 
660
 
 
661
  }
 
662
}
 
663
 
 
664
static inline bool
 
665
hb_ot_position_complex (hb_ot_shape_context_t *c)
 
666
{
 
667
  bool ret = false;
 
668
  unsigned int count = c->buffer->len;
 
669
  bool has_positioning = hb_ot_layout_has_positioning (c->face);
 
670
  /* If the font has no GPOS, AND, no fallback positioning will
 
671
   * happen, AND, direction is forward, then when zeroing mark
 
672
   * widths, we shift the mark with it, such that the mark
 
673
   * is positioned hanging over the previous glyph.  When
 
674
   * direction is backward we don't shift and it will end up
 
675
   * hanging over the next glyph after the final reordering.
 
676
   * If fallback positinoing happens or GPOS is present, we don't
 
677
   * care.
 
678
   */
 
679
  bool adjust_offsets_when_zeroing = !(has_positioning || c->plan->shaper->fallback_position ||
 
680
                                       HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction));
 
681
 
 
682
  switch (c->plan->shaper->zero_width_marks)
 
683
  {
 
684
    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
 
685
      zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
 
686
      break;
 
687
 
 
688
    /* Not currently used for any shaper:
 
689
    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY:
 
690
      zero_mark_widths_by_unicode (c->buffer, adjust_offsets_when_zeroing);
 
691
      break;
 
692
    */
 
693
 
 
694
    default:
 
695
    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
 
696
    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE:
 
697
    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
 
698
      break;
 
699
  }
 
700
 
 
701
  if (has_positioning)
 
702
  {
 
703
    hb_glyph_info_t *info = c->buffer->info;
 
704
    hb_glyph_position_t *pos = c->buffer->pos;
 
705
 
 
706
    /* Change glyph origin to what GPOS expects, apply GPOS, change it back. */
 
707
 
 
708
    for (unsigned int i = 0; i < count; i++) {
 
709
      c->font->add_glyph_origin_for_direction (info[i].codepoint,
 
710
                                               HB_DIRECTION_LTR,
 
711
                                               &pos[i].x_offset,
 
712
                                               &pos[i].y_offset);
 
713
    }
 
714
 
 
715
    c->plan->position (c->font, c->buffer);
 
716
 
 
717
    for (unsigned int i = 0; i < count; i++) {
 
718
      c->font->subtract_glyph_origin_for_direction (info[i].codepoint,
 
719
                                                    HB_DIRECTION_LTR,
 
720
                                                    &pos[i].x_offset,
 
721
                                                    &pos[i].y_offset);
 
722
    }
 
723
 
 
724
    ret = true;
 
725
  }
 
726
 
 
727
  switch (c->plan->shaper->zero_width_marks)
 
728
  {
 
729
    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_LATE:
 
730
      zero_mark_widths_by_unicode (c->buffer, adjust_offsets_when_zeroing);
 
731
      break;
 
732
 
 
733
    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
 
734
      zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
 
735
      break;
 
736
 
 
737
    default:
 
738
    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
 
739
    //case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_UNICODE_EARLY:
 
740
    case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
 
741
      break;
 
742
  }
 
743
 
 
744
  return ret;
 
745
}
 
746
 
 
747
static inline void
 
748
hb_ot_position (hb_ot_shape_context_t *c)
 
749
{
 
750
  hb_ot_layout_position_start (c->font, c->buffer);
 
751
 
 
752
  hb_ot_position_default (c);
 
753
 
 
754
  hb_bool_t fallback = !hb_ot_position_complex (c);
 
755
 
 
756
  hb_ot_zero_width_default_ignorables (c);
 
757
 
 
758
  hb_ot_layout_position_finish (c->font, c->buffer);
 
759
 
 
760
  if (fallback && c->plan->shaper->fallback_position)
 
761
    _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer);
 
762
 
 
763
  if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
 
764
    hb_buffer_reverse (c->buffer);
 
765
 
 
766
  /* Visual fallback goes here. */
 
767
 
 
768
  if (fallback)
 
769
    _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
 
770
 
 
771
  _hb_buffer_deallocate_gsubgpos_vars (c->buffer);
 
772
}
 
773
 
 
774
 
 
775
/* Pull it all together! */
 
776
 
 
777
static void
 
778
hb_ot_shape_internal (hb_ot_shape_context_t *c)
 
779
{
 
780
  c->buffer->deallocate_var_all ();
 
781
 
 
782
  /* Save the original direction, we use it later. */
 
783
  c->target_direction = c->buffer->props.direction;
 
784
 
 
785
  _hb_buffer_allocate_unicode_vars (c->buffer);
 
786
 
 
787
  c->buffer->clear_output ();
 
788
 
 
789
  hb_set_unicode_props (c->buffer);
 
790
  hb_insert_dotted_circle (c->buffer, c->font);
 
791
  hb_form_clusters (c->buffer);
 
792
 
 
793
  hb_ensure_native_direction (c->buffer);
 
794
 
 
795
  hb_ot_substitute (c);
 
796
  hb_ot_position (c);
 
797
 
 
798
  hb_ot_hide_default_ignorables (c);
 
799
 
 
800
  _hb_buffer_deallocate_unicode_vars (c->buffer);
 
801
 
 
802
  c->buffer->props.direction = c->target_direction;
 
803
 
 
804
  c->buffer->deallocate_var_all ();
 
805
}
 
806
 
 
807
 
 
808
hb_bool_t
 
809
_hb_ot_shape (hb_shape_plan_t    *shape_plan,
 
810
              hb_font_t          *font,
 
811
              hb_buffer_t        *buffer,
 
812
              const hb_feature_t *features,
 
813
              unsigned int        num_features)
 
814
{
 
815
  hb_ot_shape_context_t c = {HB_SHAPER_DATA_GET (shape_plan), font, font->face, buffer, features, num_features};
 
816
  hb_ot_shape_internal (&c);
 
817
 
 
818
  return true;
 
819
}
 
820
 
 
821
 
 
822
/**
 
823
 * Since: 0.9.7
 
824
 **/
 
825
void
 
826
hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
 
827
                                  hb_tag_t         table_tag,
 
828
                                  hb_set_t        *lookup_indexes /* OUT */)
 
829
{
 
830
  /* XXX Does the first part always succeed? */
 
831
  HB_SHAPER_DATA_GET (shape_plan)->collect_lookups (table_tag, lookup_indexes);
 
832
}
 
833
 
 
834
 
 
835
/* TODO Move this to hb-ot-shape-normalize, make it do decompose, and make it public. */
 
836
static void
 
837
add_char (hb_font_t          *font,
 
838
          hb_unicode_funcs_t *unicode,
 
839
          hb_bool_t           mirror,
 
840
          hb_codepoint_t      u,
 
841
          hb_set_t           *glyphs)
 
842
{
 
843
  hb_codepoint_t glyph;
 
844
  if (font->get_glyph (u, 0, &glyph))
 
845
    glyphs->add (glyph);
 
846
  if (mirror)
 
847
  {
 
848
    hb_codepoint_t m = unicode->mirroring (u);
 
849
    if (m != u && font->get_glyph (m, 0, &glyph))
 
850
      glyphs->add (glyph);
 
851
  }
 
852
}
 
853
 
 
854
 
 
855
/**
 
856
 * Since: 0.9.2
 
857
 **/
 
858
void
 
859
hb_ot_shape_glyphs_closure (hb_font_t          *font,
 
860
                            hb_buffer_t        *buffer,
 
861
                            const hb_feature_t *features,
 
862
                            unsigned int        num_features,
 
863
                            hb_set_t           *glyphs)
 
864
{
 
865
  hb_ot_shape_plan_t plan;
 
866
 
 
867
  const char *shapers[] = {"ot", NULL};
 
868
  hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props,
 
869
                                                             features, num_features, shapers);
 
870
 
 
871
  bool mirror = hb_script_get_horizontal_direction (buffer->props.script) == HB_DIRECTION_RTL;
 
872
 
 
873
  unsigned int count = buffer->len;
 
874
  hb_glyph_info_t *info = buffer->info;
 
875
  for (unsigned int i = 0; i < count; i++)
 
876
    add_char (font, buffer->unicode, mirror, info[i].codepoint, glyphs);
 
877
 
 
878
  hb_set_t lookups;
 
879
  lookups.init ();
 
880
  hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, &lookups);
 
881
 
 
882
  /* And find transitive closure. */
 
883
  hb_set_t copy;
 
884
  copy.init ();
 
885
  do {
 
886
    copy.set (glyphs);
 
887
    for (hb_codepoint_t lookup_index = -1; hb_set_next (&lookups, &lookup_index);)
 
888
      hb_ot_layout_lookup_substitute_closure (font->face, lookup_index, glyphs);
 
889
  } while (!copy.is_equal (glyphs));
 
890
 
 
891
  hb_shape_plan_destroy (shape_plan);
 
892
}