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

239 240 241 242 243 244 245 246
static void
hb_ot_shape_setup_lookups_complex (hb_ot_shape_context_t *c,
				   lookup_map            *lookups,
				   unsigned int          *num_lookups)
{
  /* XXX */
}

B
Behdad Esfahbod 已提交
247
static void
B
Behdad Esfahbod 已提交
248 249 250
hb_ot_shape_setup_lookups (hb_ot_shape_context_t *c,
			   lookup_map            *lookups,
			   unsigned int          *num_lookups)
B
Behdad Esfahbod 已提交
251
{
252
  hb_mask_allocator_t allocator;
B
Behdad Esfahbod 已提交
253

254
  switch (c->original_direction) {
B
Behdad Esfahbod 已提交
255
    case HB_DIRECTION_LTR:
B
Behdad Esfahbod 已提交
256 257
      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 已提交
258 259
      break;
    case HB_DIRECTION_RTL:
B
Behdad Esfahbod 已提交
260
      allocator.add_feature (HB_TAG ('r','t','l','a'), 1, true);
261
      allocator.add_feature (HB_TAG ('r','t','l','m'), 1, false);
B
Behdad Esfahbod 已提交
262 263 264 265 266 267 268
      break;
    case HB_DIRECTION_TTB:
    case HB_DIRECTION_BTT:
    default:
      break;
  }

B
Minor  
Behdad Esfahbod 已提交
269
  for (unsigned int i = 0; i < ARRAY_LENGTH (default_features); i++)
B
Behdad Esfahbod 已提交
270 271
    allocator.add_feature (default_features[i], 1, true);

272
  hb_ot_shape_setup_lookups_complex (c, lookups, num_lookups);
B
Behdad Esfahbod 已提交
273

274 275
  for (unsigned int i = 0; i < c->num_features; i++) {
    const hb_feature_t *feature = &c->features[i];
B
Behdad Esfahbod 已提交
276 277
    allocator.add_feature (feature->tag, feature->value, (feature->start == 0 && feature->end == (unsigned int) -1));
  }
B
Behdad Esfahbod 已提交
278 279 280


  /* Compile features */
B
Behdad Esfahbod 已提交
281 282 283 284 285 286 287 288 289 290
  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);

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


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

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

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

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

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

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

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

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


  /* Set masks in buffer */

B
Minor  
Behdad Esfahbod 已提交
329
  for (unsigned int i = 0; i < c->num_features; i++)
B
Behdad Esfahbod 已提交
330 331 332 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);
  }

  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
Behdad Esfahbod 已提交
340 341 342
}


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

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

352 353
  c->table_tag = HB_OT_TAG_GSUB;

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

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

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

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

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

372 373
  c->table_tag = HB_OT_TAG_GPOS;

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

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

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

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


/* 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++)
403
    if (buffer->unicode->v.get_general_category (buffer->info[i].codepoint) == HB_CATEGORY_NON_SPACING_MARK)
404 405 406
      buffer->info[i].cluster = buffer->info[i - 1].cluster;
}

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

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


/* Substitute */

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

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

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

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

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

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

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

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


/* Position */

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

487
  unsigned int count = c->buffer->len;
488 489
  for (unsigned int i = 0; i < count; i++) {
    hb_glyph_metrics_t metrics;
490 491 492
    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;
493 494 495 496
  }
}

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

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

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


/* Do it! */

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

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

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

539
    hb_ensure_native_direction (c->buffer);
540

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

543
    hb_ot_substitute_complex (c);
544

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

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

553
    hb_position_default (c);
554

555
    hb_ot_position_complex (c);
556

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

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

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

568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583
  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);
584
}
B
Behdad Esfahbod 已提交
585 586 587


HB_END_DECLS