hb-ot-shape.cc 15.2 KB
Newer Older
B
Behdad Esfahbod 已提交
1
/*
B
Behdad Esfahbod 已提交
2
 * Copyright (C) 2009,2010  Red Hat, Inc.
B
Rename  
Behdad Esfahbod 已提交
3
 * Copyright (C) 2010  Google, Inc.
B
Behdad Esfahbod 已提交
4
 *
B
Behdad Esfahbod 已提交
5
 *  This is part of HarfBuzz, a text shaping library.
B
Behdad Esfahbod 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the
 * above copyright notice and the following two paragraphs appear in
 * all copies of this software.
 *
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 * Red Hat Author(s): Behdad Esfahbod
B
Rename  
Behdad Esfahbod 已提交
26
 * Google Author(s): Behdad Esfahbod
B
Behdad Esfahbod 已提交
27 28
 */

29
#include "hb-ot-shape-private.h"
B
Behdad Esfahbod 已提交
30

B
Behdad Esfahbod 已提交
31 32
#include "hb-open-type-private.hh"

B
Behdad Esfahbod 已提交
33 34
#include "hb-ot-layout.h"

B
Behdad Esfahbod 已提交
35 36 37
HB_BEGIN_DECLS


B
Behdad Esfahbod 已提交
38
/* XXX vertical */
B
Behdad Esfahbod 已提交
39
hb_tag_t default_features[] = {
40
  HB_TAG('c','a','l','t'),
B
Behdad Esfahbod 已提交
41 42
  HB_TAG('c','c','m','p'),
  HB_TAG('c','l','i','g'),
43 44
  HB_TAG('c','s','w','h'),
  HB_TAG('c','u','r','s'),
B
Behdad Esfahbod 已提交
45
  HB_TAG('k','e','r','n'),
46 47
  HB_TAG('l','i','g','a'),
  HB_TAG('l','o','c','l'),
B
Behdad Esfahbod 已提交
48 49
  HB_TAG('m','a','r','k'),
  HB_TAG('m','k','m','k'),
50
  HB_TAG('r','l','i','g')
B
Behdad Esfahbod 已提交
51 52
};

B
Behdad Esfahbod 已提交
53 54 55 56 57
struct lookup_map {
  unsigned int index;
  hb_mask_t mask;
};

B
Behdad Esfahbod 已提交
58 59

static void
B
Rename  
Behdad Esfahbod 已提交
60
add_lookups (hb_face_t    *face,
B
Behdad Esfahbod 已提交
61 62
	     hb_tag_t      table_tag,
	     unsigned int  feature_index,
B
Behdad Esfahbod 已提交
63 64
	     hb_mask_t     mask,
	     lookup_map   *lookups,
B
Behdad Esfahbod 已提交
65 66 67 68
	     unsigned int *num_lookups,
	     unsigned int  room_lookups)
{
  unsigned int i = room_lookups - *num_lookups;
B
Behdad Esfahbod 已提交
69 70 71 72
  lookups += *num_lookups;

  unsigned int *lookup_indices = (unsigned int *) lookups;

B
Behdad Esfahbod 已提交
73 74
  hb_ot_layout_feature_get_lookup_indexes (face, table_tag, feature_index, 0,
					   &i,
B
Behdad Esfahbod 已提交
75 76
					   lookup_indices);

B
Behdad Esfahbod 已提交
77
  *num_lookups += i;
B
Behdad Esfahbod 已提交
78 79 80 81 82

  while (i--) {
    lookups[i].mask = mask;
    lookups[i].index = lookup_indices[i];
  }
B
Behdad Esfahbod 已提交
83 84 85 86 87
}

static int
cmp_lookups (const void *p1, const void *p2)
{
B
Behdad Esfahbod 已提交
88 89
  const lookup_map *a = (const lookup_map *) p1;
  const lookup_map *b = (const lookup_map *) p2;
B
Behdad Esfahbod 已提交
90

B
Behdad Esfahbod 已提交
91
  return a->index - b->index;
B
Behdad Esfahbod 已提交
92 93
}

94

B
Behdad Esfahbod 已提交
95
#define MAX_FEATURES 100 /* FIXME */
96

B
Behdad Esfahbod 已提交
97
struct hb_mask_allocator_t {
98

B
Behdad Esfahbod 已提交
99 100 101
  struct feature_info_t {
    hb_tag_t tag;
    unsigned int value;
B
Behdad Esfahbod 已提交
102
    unsigned int seq;
B
Behdad Esfahbod 已提交
103
    bool global;
104

B
Behdad Esfahbod 已提交
105 106 107
    static int
    cmp (const void *p1, const void *p2)
    {
108 109
      const feature_info_t *a = reinterpret_cast<const feature_info_t *>(p1);
      const feature_info_t *b = reinterpret_cast<const feature_info_t *>(p2);
110

B
Behdad Esfahbod 已提交
111 112
      if (a->tag != b->tag)
        return a->tag < b->tag ? -1 : 1;
113

B
Behdad Esfahbod 已提交
114
      return a->seq < b->seq ? -1 : 1;
B
Behdad Esfahbod 已提交
115 116
    }
  };
117

B
Behdad Esfahbod 已提交
118 119 120 121 122 123 124 125
  struct feature_map_t {
    hb_tag_t tag; /* should be first */
    unsigned int index;
    unsigned int shift;
    hb_mask_t mask;

    static int
    cmp (const void *p1, const void *p2)
126
    {
127 128
      const feature_map_t *a = reinterpret_cast<const feature_map_t *>(p1);
      const feature_map_t *b = reinterpret_cast<const feature_map_t *>(p2);
B
Behdad Esfahbod 已提交
129 130 131 132 133

      return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0;
    }
  };

134
  hb_mask_allocator_t (void) : count (0) {}
B
Behdad Esfahbod 已提交
135

B
Behdad Esfahbod 已提交
136 137 138
  void add_feature (hb_tag_t tag,
		    unsigned int value,
		    bool global)
139
  {
B
Behdad Esfahbod 已提交
140 141
    feature_info_t *info = &infos[count++];
    info->tag = tag;
B
Behdad Esfahbod 已提交
142
    info->value = value;
B
Behdad Esfahbod 已提交
143
    info->seq = count;
B
Behdad Esfahbod 已提交
144
    info->global = global;
145 146
  }

147 148 149 150
  void compile (hb_face_t *face,
		hb_tag_t table_tag,
		unsigned int script_index,
		unsigned int language_index)
151
  {
B
Behdad Esfahbod 已提交
152
    global_mask = 0;
153
    unsigned int next_bit = 1;
B
Behdad Esfahbod 已提交
154 155 156 157 158 159 160 161 162 163 164

    if (!count)
      return;

    qsort (infos, count, sizeof (infos[0]), feature_info_t::cmp);

    unsigned int j = 0;
    for (unsigned int i = 1; i < count; i++)
      if (infos[i].tag != infos[j].tag)
	infos[++j] = infos[i];
      else {
B
Behdad Esfahbod 已提交
165 166 167 168
	if (infos[i].global)
	  infos[j] = infos[i];
	else {
	  infos[j].global = infos[j].global && (infos[j].value == infos[i].value);
B
Behdad Esfahbod 已提交
169
	  infos[j].value = MAX (infos[j].value, infos[i].value);
B
Behdad Esfahbod 已提交
170
	}
B
Behdad Esfahbod 已提交
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
      }
    count = j + 1;

    /* Allocate bits now */
    j = 0;
    for (unsigned int i = 0; i < count; i++) {
      const feature_info_t *info = &infos[i];

      unsigned int bits_needed;

      if (info->global && info->value == 1)
        /* Uses the global bit */
        bits_needed = 0;
      else
        bits_needed = _hb_bit_storage (info->value);

      if (!info->value || next_bit + bits_needed > 8 * sizeof (hb_mask_t))
        continue; /* Feature disabled, or not enough bits. */

      unsigned int feature_index;
      if (!hb_ot_layout_language_find_feature (face, table_tag, script_index, language_index,
					       info->tag, &feature_index))
        continue;

      feature_map_t *map = &maps[j++];

      map->tag = info->tag;
      map->index = feature_index;
      if (info->global && info->value == 1) {
B
Minor  
Behdad Esfahbod 已提交
200
        /* Use the global bit */
B
Behdad Esfahbod 已提交
201 202 203 204 205 206 207 208 209 210 211 212
        map->shift = 0;
	map->mask = 1;
      } else {
	map->shift = next_bit;
	map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit);
	next_bit += bits_needed;
      }

      if (info->global && map->mask != 1)
        global_mask |= map->mask;
    }
    count = j;
213 214
  }

B
Behdad Esfahbod 已提交
215
  hb_mask_t get_global_mask (void) { return global_mask; }
B
Behdad Esfahbod 已提交
216 217 218 219 220 221 222

  const feature_map_t *get_features (unsigned int *num_features) const {
    *num_features = count;
    return maps;
  }


B
Behdad Esfahbod 已提交
223 224 225 226
  const feature_map_t *find_feature (hb_tag_t tag) const {
    static const feature_map_t off_map = { HB_TAG_NONE, Index::NOT_FOUND_INDEX, 0, 0 };
    const feature_map_t *map = (const feature_map_t *) bsearch (&tag, maps, count, sizeof (maps[0]), feature_map_t::cmp);
    return map ? map : &off_map;
227 228
  }

B
Behdad Esfahbod 已提交
229 230 231 232 233 234

  private:

  unsigned int count;
  feature_info_t infos[MAX_FEATURES];

235
  feature_map_t maps[MAX_FEATURES];
B
Behdad Esfahbod 已提交
236 237
  hb_mask_t global_mask;
};
238

B
Behdad Esfahbod 已提交
239
static void
240 241
hb_ot_shape_collect_features (hb_ot_shape_context_t *c,
			      hb_mask_allocator_t   *allocator)
B
Behdad Esfahbod 已提交
242
{
243
  switch (c->original_direction) {
B
Behdad Esfahbod 已提交
244
    case HB_DIRECTION_LTR:
245 246
      allocator->add_feature (HB_TAG ('l','t','r','a'), 1, true);
      allocator->add_feature (HB_TAG ('l','t','r','m'), 1, true);
B
Behdad Esfahbod 已提交
247 248
      break;
    case HB_DIRECTION_RTL:
249 250
      allocator->add_feature (HB_TAG ('r','t','l','a'), 1, true);
      allocator->add_feature (HB_TAG ('r','t','l','m'), 1, false);
B
Behdad Esfahbod 已提交
251 252 253 254 255 256 257
      break;
    case HB_DIRECTION_TTB:
    case HB_DIRECTION_BTT:
    default:
      break;
  }

B
Minor  
Behdad Esfahbod 已提交
258
  for (unsigned int i = 0; i < ARRAY_LENGTH (default_features); i++)
259
    allocator->add_feature (default_features[i], 1, true);
B
Behdad Esfahbod 已提交
260

B
Minor  
Behdad Esfahbod 已提交
261
  /* complex */
B
Behdad Esfahbod 已提交
262

263 264
  for (unsigned int i = 0; i < c->num_features; i++) {
    const hb_feature_t *feature = &c->features[i];
265
    allocator->add_feature (feature->tag, feature->value, (feature->start == 0 && feature->end == (unsigned int) -1));
B
Behdad Esfahbod 已提交
266
  }
267 268 269 270 271 272 273 274 275
}


static void
hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
			   lookup_map            *lookups,
			   unsigned int          *num_lookups)
{
  hb_mask_allocator_t allocator;
B
Behdad Esfahbod 已提交
276

277
  hb_ot_shape_collect_features (c, &allocator);
B
Behdad Esfahbod 已提交
278 279

  /* Compile features */
B
Behdad Esfahbod 已提交
280 281 282 283 284 285 286 287 288 289
  unsigned int script_index, language_index, feature_index;
  unsigned int room_lookups;

  hb_ot_layout_table_choose_script (c->face, c->table_tag,
				    hb_ot_tags_from_script (c->buffer->props.script),
				    &script_index);
  hb_ot_layout_script_find_language (c->face, c->table_tag, script_index,
				     hb_ot_tag_from_language (c->buffer->props.language),
				     &language_index);

290
  allocator.compile (c->face, c->table_tag, script_index, language_index);
B
Behdad Esfahbod 已提交
291 292


B
Behdad Esfahbod 已提交
293
  /* Gather lookup indices for features */
B
Behdad Esfahbod 已提交
294

B
Behdad Esfahbod 已提交
295 296 297
  room_lookups = *num_lookups;
  *num_lookups = 0;

298
  if (hb_ot_layout_language_get_required_feature_index (c->face, c->table_tag, script_index, language_index,
299
							&feature_index))
B
Rename  
Behdad Esfahbod 已提交
300
    add_lookups (c->face, c->table_tag, feature_index, 1, lookups, num_lookups, room_lookups);
301

B
Behdad Esfahbod 已提交
302
  const hb_mask_allocator_t::feature_map_t *map;
B
Behdad Esfahbod 已提交
303
  unsigned int num_features;
304

B
Behdad Esfahbod 已提交
305
  map = allocator.get_features (&num_features);
B
Minor  
Behdad Esfahbod 已提交
306
  for (unsigned i = 0; i < num_features; i++)
B
Behdad Esfahbod 已提交
307
    add_lookups (c->face, c->table_tag, map[i].index, map[i].mask, lookups, num_lookups, room_lookups);
308

B
Behdad Esfahbod 已提交
309
  /* Sort lookups and merge duplicates */
B
Behdad Esfahbod 已提交
310

B
Behdad Esfahbod 已提交
311 312 313 314
  qsort (lookups, *num_lookups, sizeof (lookups[0]), cmp_lookups);

  if (*num_lookups)
  {
B
Minor  
Behdad Esfahbod 已提交
315 316
    unsigned int j = 0;
    for (unsigned int i = 1; i < *num_lookups; i++)
B
Behdad Esfahbod 已提交
317
      if (lookups[i].index != lookups[j].index)
B
Behdad Esfahbod 已提交
318
	lookups[++j] = lookups[i];
B
Behdad Esfahbod 已提交
319 320 321
      else
        lookups[j].mask |= lookups[i].mask;
    j++;
B
Behdad Esfahbod 已提交
322 323
    *num_lookups = j;
  }
B
Behdad Esfahbod 已提交
324 325 326 327


  /* Set masks in buffer */

B
Minor  
Behdad Esfahbod 已提交
328 329 330 331
  hb_mask_t global_mask = allocator.get_global_mask ();
  if (global_mask)
    c->buffer->set_masks (global_mask, global_mask, 0, (unsigned int) -1);

B
Minor  
Behdad Esfahbod 已提交
332
  for (unsigned int i = 0; i < c->num_features; i++)
B
Behdad Esfahbod 已提交
333 334 335 336 337 338 339
  {
    hb_feature_t *feature = &c->features[i];
    map = allocator.find_feature (feature->tag);
    if (!(feature->start == 0 && feature->end == (unsigned int)-1))
      c->buffer->set_masks (feature->value << map->shift, map->mask, feature->start, feature->end);
  }

B
Minor  
Behdad Esfahbod 已提交
340
  /* complex */
B
Behdad Esfahbod 已提交
341 342 343
}


344 345
static void
hb_ot_substitute_complex (hb_ot_shape_context_t *c)
B
Behdad Esfahbod 已提交
346
{
347
  lookup_map lookups[1000]; /* FIXME */
B
Behdad Esfahbod 已提交
348 349
  unsigned int num_lookups = ARRAY_LENGTH (lookups);

350 351
  if (!hb_ot_layout_has_substitution (c->face))
    return;
B
Behdad Esfahbod 已提交
352

353 354
  c->table_tag = HB_OT_TAG_GSUB;

B
Behdad Esfahbod 已提交
355
  hb_ot_shape_setup_lookups (c, lookups, &num_lookups);
B
Behdad Esfahbod 已提交
356

B
Minor  
Behdad Esfahbod 已提交
357
  for (unsigned int i = 0; i < num_lookups; i++)
358
    hb_ot_layout_substitute_lookup (c->face, c->buffer, lookups[i].index, lookups[i].mask);
B
Behdad Esfahbod 已提交
359

360 361
  c->applied_substitute_complex = TRUE;
  return;
B
Behdad Esfahbod 已提交
362 363
}

364 365
static void
hb_ot_position_complex (hb_ot_shape_context_t *c)
B
Behdad Esfahbod 已提交
366
{
367
  lookup_map lookups[1000]; /* FIXME */
B
Behdad Esfahbod 已提交
368 369
  unsigned int num_lookups = ARRAY_LENGTH (lookups);

370 371
  if (!hb_ot_layout_has_positioning (c->face))
    return;
B
Behdad Esfahbod 已提交
372

373 374
  c->table_tag = HB_OT_TAG_GPOS;

B
Behdad Esfahbod 已提交
375
  hb_ot_shape_setup_lookups (c, lookups, &num_lookups);
B
Behdad Esfahbod 已提交
376

B
Minor  
Behdad Esfahbod 已提交
377
  for (unsigned int i = 0; i < num_lookups; i++)
378
    hb_ot_layout_position_lookup (c->font, c->face, c->buffer, lookups[i].index, lookups[i].mask);
B
Behdad Esfahbod 已提交
379

380
  hb_ot_layout_position_finish (c->font, c->face, c->buffer);
B
Behdad Esfahbod 已提交
381

382 383
  c->applied_position_complex = TRUE;
  return;
B
Behdad Esfahbod 已提交
384
}
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403


/* Main shaper */

/* Prepare */

static inline hb_bool_t
is_variation_selector (hb_codepoint_t unicode)
{
  return unlikely ((unicode >=  0x180B && unicode <=  0x180D) || /* MONGOLIAN FREE VARIATION SELECTOR ONE..THREE */
		   (unicode >=  0xFE00 && unicode <=  0xFE0F) || /* VARIATION SELECTOR-1..16 */
		   (unicode >= 0xE0100 && unicode <= 0xE01EF));  /* VARIATION SELECTOR-17..256 */
}

static void
hb_form_clusters (hb_buffer_t *buffer)
{
  unsigned int count = buffer->len;
  for (unsigned int i = 1; i < count; i++)
404
    if (buffer->unicode->v.get_general_category (buffer->info[i].codepoint) == HB_CATEGORY_NON_SPACING_MARK)
405 406 407
      buffer->info[i].cluster = buffer->info[i - 1].cluster;
}

408
static void
409 410
hb_ensure_native_direction (hb_buffer_t *buffer)
{
411
  hb_direction_t direction = buffer->props.direction;
412 413

  /* TODO vertical */
414 415
  if (HB_DIRECTION_IS_HORIZONTAL (direction) &&
      direction != _hb_script_get_horizontal_direction (buffer->props.script))
416 417
  {
    hb_buffer_reverse_clusters (buffer);
418
    buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction);
419 420 421 422 423 424 425 426 427
  }
}


/* Substitute */

static void
hb_mirror_chars (hb_buffer_t *buffer)
{
428
  hb_unicode_get_mirroring_func_t get_mirroring = buffer->unicode->v.get_mirroring;
429

430
  if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
431 432
    return;

433 434
//  map = allocator.find_feature (HB_TAG ('r','t','l','m'));

435 436
  unsigned int count = buffer->len;
  for (unsigned int i = 0; i < count; i++) {
B
Behdad Esfahbod 已提交
437 438
    hb_codepoint_t codepoint = get_mirroring (buffer->info[i].codepoint);
    if (likely (codepoint == buffer->info[i].codepoint))
439
;//      buffer->info[i].mask |= map->mask;
B
Behdad Esfahbod 已提交
440 441
    else
      buffer->info[i].codepoint = codepoint;
442 443 444 445 446 447 448 449 450 451 452
  }
}

static void
hb_map_glyphs (hb_font_t    *font,
	       hb_face_t    *face,
	       hb_buffer_t  *buffer)
{
  if (unlikely (!buffer->len))
    return;

453
  buffer->clear_output ();
454
  unsigned int count = buffer->len - 1;
455 456 457 458
  for (buffer->i = 0; buffer->i < count;) {
    if (unlikely (is_variation_selector (buffer->info[buffer->i + 1].codepoint))) {
      buffer->add_output_glyph (hb_font_get_glyph (font, face, buffer->info[buffer->i].codepoint, buffer->info[buffer->i + 1].codepoint));
      buffer->i++;
459
    } else {
460
      buffer->add_output_glyph (hb_font_get_glyph (font, face, buffer->info[buffer->i].codepoint, 0));
461 462
    }
  }
463 464
  if (likely (buffer->i < buffer->len))
    buffer->add_output_glyph (hb_font_get_glyph (font, face, buffer->info[buffer->i].codepoint, 0));
465
  buffer->swap ();
466 467 468
}

static void
469
hb_substitute_default (hb_ot_shape_context_t *c)
470
{
471
  hb_map_glyphs (c->font, c->face, c->buffer);
472 473 474
}

static void
475
hb_substitute_complex_fallback (hb_ot_shape_context_t *c HB_UNUSED)
476 477 478 479 480 481 482 483
{
  /* TODO Arabic */
}


/* Position */

static void
484
hb_position_default (hb_ot_shape_context_t *c)
485
{
486
  hb_buffer_clear_positions (c->buffer);
487

488
  unsigned int count = c->buffer->len;
489 490
  for (unsigned int i = 0; i < count; i++) {
    hb_glyph_metrics_t metrics;
491 492 493
    hb_font_get_glyph_metrics (c->font, c->face, c->buffer->info[i].codepoint, &metrics);
    c->buffer->pos[i].x_advance = metrics.x_advance;
    c->buffer->pos[i].y_advance = metrics.y_advance;
494 495 496 497
  }
}

static void
498
hb_position_complex_fallback (hb_ot_shape_context_t *c HB_UNUSED)
499 500 501 502 503
{
  /* TODO Mark pos */
}

static void
504
hb_truetype_kern (hb_ot_shape_context_t *c)
505 506
{
  /* TODO Check for kern=0 */
507
  unsigned int count = c->buffer->len;
508 509
  for (unsigned int i = 1; i < count; i++) {
    hb_position_t kern, kern1, kern2;
510
    kern = hb_font_get_kerning (c->font, c->face, c->buffer->info[i - 1].codepoint, c->buffer->info[i].codepoint);
511 512
    kern1 = kern >> 1;
    kern2 = kern - kern1;
513 514 515
    c->buffer->pos[i - 1].x_advance += kern1;
    c->buffer->pos[i].x_advance += kern2;
    c->buffer->pos[i].x_offset += kern2;
516 517 518 519
  }
}

static void
520
hb_position_complex_fallback_visual (hb_ot_shape_context_t *c)
521
{
522
  hb_truetype_kern (c);
523 524 525 526 527
}


/* Do it! */

528 529
static void
hb_ot_shape_internal (hb_ot_shape_context_t *c)
530
{
531
  hb_form_clusters (c->buffer);
532

B
Behdad Esfahbod 已提交
533
  /* SUBSTITUTE */
B
Minor  
Behdad Esfahbod 已提交
534
  {
535
    c->buffer->clear_masks ();
B
Behdad Esfahbod 已提交
536

B
Minor  
Behdad Esfahbod 已提交
537
    /* Mirroring needs to see the original direction */
538
    hb_mirror_chars (c->buffer);
539

540
    hb_ensure_native_direction (c->buffer);
541

542
    hb_substitute_default (c);
B
Behdad Esfahbod 已提交
543

544
    hb_ot_substitute_complex (c);
545

546 547
    if (!c->applied_substitute_complex)
      hb_substitute_complex_fallback (c);
B
Minor  
Behdad Esfahbod 已提交
548
  }
B
Behdad Esfahbod 已提交
549 550

  /* POSITION */
B
Minor  
Behdad Esfahbod 已提交
551
  {
552
    c->buffer->clear_masks ();
B
Behdad Esfahbod 已提交
553

554
    hb_position_default (c);
555

556
    hb_ot_position_complex (c);
557

558
    hb_bool_t position_fallback = !c->applied_position_complex;
B
Minor  
Behdad Esfahbod 已提交
559
    if (position_fallback)
560
      hb_position_complex_fallback (c);
561

562 563
    if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
      hb_buffer_reverse (c->buffer);
564

B
Minor  
Behdad Esfahbod 已提交
565
    if (position_fallback)
566
      hb_position_complex_fallback_visual (c);
B
Minor  
Behdad Esfahbod 已提交
567
  }
568

569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
  c->buffer->props.direction = c->original_direction;
}

void
hb_ot_shape (hb_font_t    *font,
	     hb_face_t    *face,
	     hb_buffer_t  *buffer,
	     hb_feature_t *features,
	     unsigned int  num_features)
{
  hb_ot_shape_context_t c = {font, face, buffer, features, num_features};

  /* Setup transient context members */
  c.original_direction = buffer->props.direction;

  hb_ot_shape_internal (&c);
585
}
B
Behdad Esfahbod 已提交
586 587 588


HB_END_DECLS