hb-ot-shape.cc 5.9 KB
Newer Older
B
Behdad Esfahbod 已提交
1 2 3
/*
 * Copyright (C) 2009  Red Hat, Inc.
 *
B
Behdad Esfahbod 已提交
4
 *  This is part of HarfBuzz, a text shaping library.
B
Behdad Esfahbod 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * 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
 */

27
#include "hb-ot-shape-private.hh"
B
Behdad Esfahbod 已提交
28

29
#include "hb-buffer-private.hh"
B
Behdad Esfahbod 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44

#include "hb-ot-layout.h"

hb_tag_t default_features[] = {
  /* GSUB */
  HB_TAG('c','c','m','p'),
  HB_TAG('l','o','c','l'),
  HB_TAG('l','i','g','a'),
  HB_TAG('c','l','i','g'),
  /* GPOS */
  HB_TAG('k','e','r','n'),
  HB_TAG('m','a','r','k'),
  HB_TAG('m','k','m','k'),
};

B
Behdad Esfahbod 已提交
45 46 47 48 49
struct lookup_map {
  unsigned int index;
  hb_mask_t mask;
};

B
Behdad Esfahbod 已提交
50 51 52 53 54

static void
add_feature (hb_face_t    *face,
	     hb_tag_t      table_tag,
	     unsigned int  feature_index,
B
Behdad Esfahbod 已提交
55 56
	     hb_mask_t     mask,
	     lookup_map   *lookups,
B
Behdad Esfahbod 已提交
57 58 59 60
	     unsigned int *num_lookups,
	     unsigned int  room_lookups)
{
  unsigned int i = room_lookups - *num_lookups;
B
Behdad Esfahbod 已提交
61 62 63 64
  lookups += *num_lookups;

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

B
Behdad Esfahbod 已提交
65 66
  hb_ot_layout_feature_get_lookup_indexes (face, table_tag, feature_index, 0,
					   &i,
B
Behdad Esfahbod 已提交
67 68
					   lookup_indices);

B
Behdad Esfahbod 已提交
69
  *num_lookups += i;
B
Behdad Esfahbod 已提交
70 71 72 73 74

  while (i--) {
    lookups[i].mask = mask;
    lookups[i].index = lookup_indices[i];
  }
B
Behdad Esfahbod 已提交
75 76 77 78 79
}

static int
cmp_lookups (const void *p1, const void *p2)
{
B
Behdad Esfahbod 已提交
80 81
  const lookup_map *a = (const lookup_map *) p1;
  const lookup_map *b = (const lookup_map *) p2;
B
Behdad Esfahbod 已提交
82

B
Behdad Esfahbod 已提交
83
  return a->index - b->index;
B
Behdad Esfahbod 已提交
84 85 86
}

static void
B
Behdad Esfahbod 已提交
87
setup_lookups (hb_face_t    *face,
B
Behdad Esfahbod 已提交
88 89 90 91
	       hb_buffer_t  *buffer,
	       hb_feature_t *features,
	       unsigned int  num_features,
	       hb_tag_t      table_tag,
B
Behdad Esfahbod 已提交
92
	       lookup_map   *lookups,
B
Behdad Esfahbod 已提交
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
	       unsigned int *num_lookups)
{
  unsigned int i, j, script_index, language_index, feature_index, room_lookups;

  room_lookups = *num_lookups;
  *num_lookups = 0;

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

  if (hb_ot_layout_language_get_required_feature_index (face, table_tag, script_index, language_index,
							&feature_index))
B
Behdad Esfahbod 已提交
109
    add_feature (face, table_tag, feature_index, 1, lookups, num_lookups, room_lookups);
B
Behdad Esfahbod 已提交
110 111 112 113 114 115

  for (i = 0; i < ARRAY_LENGTH (default_features); i++)
  {
    if (hb_ot_layout_language_find_feature (face, table_tag, script_index, language_index,
					    default_features[i],
					    &feature_index))
B
Behdad Esfahbod 已提交
116
      add_feature (face, table_tag, feature_index, 1, lookups, num_lookups, room_lookups);
B
Behdad Esfahbod 已提交
117 118
  }

B
Behdad Esfahbod 已提交
119 120 121 122 123 124
  /* Clear buffer masks. */
  unsigned int count = buffer->len;
  for (unsigned int i = 0; i < count; i++)
    buffer->info[i].mask = 1;

  unsigned int last_bit_used = 1;
B
Behdad Esfahbod 已提交
125 126
  for (i = 0; i < num_features; i++)
  {
B
Behdad Esfahbod 已提交
127 128 129 130 131 132 133
    unsigned int bits_needed = _hb_bit_storage (features[i].value);
    if (!bits_needed)
      continue;
    unsigned int mask = (1 << (last_bit_used + bits_needed)) - (1 << last_bit_used);
    unsigned int value = features[i].value << last_bit_used;
    last_bit_used += bits_needed;

B
Behdad Esfahbod 已提交
134 135 136
    if (hb_ot_layout_language_find_feature (face, table_tag, script_index, language_index,
					    features[i].tag,
					    &feature_index))
B
Behdad Esfahbod 已提交
137 138 139 140
      add_feature (face, table_tag, feature_index, mask, lookups, num_lookups, room_lookups);

    /* Turn mask on in the buffer, the über-slow way! */
    unsigned int count = buffer->len;
B
Behdad Esfahbod 已提交
141 142
    for (unsigned int j = 0; j < count; j++) {
        unsigned int cluster = buffer->info[j].cluster;
B
Behdad Esfahbod 已提交
143
	if (features[i].start <= cluster && cluster < features[i].end)
B
Behdad Esfahbod 已提交
144
	  buffer->info[j].mask |= value;
B
Behdad Esfahbod 已提交
145
    }
B
Behdad Esfahbod 已提交
146 147
  }

B
Behdad Esfahbod 已提交
148 149 150 151 152
  qsort (lookups, *num_lookups, sizeof (lookups[0]), cmp_lookups);

  if (*num_lookups)
  {
    for (i = 1, j = 0; i < *num_lookups; i++)
B
Behdad Esfahbod 已提交
153
      if (lookups[i].index != lookups[j].index)
B
Behdad Esfahbod 已提交
154
	lookups[++j] = lookups[i];
B
Behdad Esfahbod 已提交
155 156 157
      else
        lookups[j].mask |= lookups[i].mask;
    j++;
B
Behdad Esfahbod 已提交
158 159 160 161 162
    *num_lookups = j;
  }
}


B
Behdad Esfahbod 已提交
163
hb_bool_t
164
_hb_ot_substitute_complex (hb_font_t    *font HB_UNUSED,
B
Behdad Esfahbod 已提交
165 166 167 168 169
			   hb_face_t    *face,
			   hb_buffer_t  *buffer,
			   hb_feature_t *features,
			   unsigned int  num_features)
{
B
Behdad Esfahbod 已提交
170
  lookup_map lookups[1000];
B
Behdad Esfahbod 已提交
171 172 173 174 175 176
  unsigned int num_lookups = ARRAY_LENGTH (lookups);
  unsigned int i;

  if (!hb_ot_layout_has_substitution (face))
    return FALSE;

B
Behdad Esfahbod 已提交
177
  setup_lookups (face, buffer, features, num_features,
B
Behdad Esfahbod 已提交
178 179 180 181
		 HB_OT_TAG_GSUB,
		 lookups, &num_lookups);

  for (i = 0; i < num_lookups; i++)
B
Behdad Esfahbod 已提交
182
    hb_ot_layout_substitute_lookup (face, buffer, lookups[i].index, lookups[i].mask);
B
Behdad Esfahbod 已提交
183

184
  return TRUE;
B
Behdad Esfahbod 已提交
185 186
}

B
Behdad Esfahbod 已提交
187
hb_bool_t
B
Behdad Esfahbod 已提交
188 189 190 191 192 193
_hb_ot_position_complex (hb_font_t    *font,
			 hb_face_t    *face,
			 hb_buffer_t  *buffer,
			 hb_feature_t *features,
			 unsigned int  num_features)
{
B
Behdad Esfahbod 已提交
194
  lookup_map lookups[1000];
B
Behdad Esfahbod 已提交
195 196 197 198 199 200
  unsigned int num_lookups = ARRAY_LENGTH (lookups);
  unsigned int i;

  if (!hb_ot_layout_has_positioning (face))
    return FALSE;

B
Behdad Esfahbod 已提交
201
  setup_lookups (face, buffer, features, num_features,
B
Behdad Esfahbod 已提交
202 203 204 205
		 HB_OT_TAG_GPOS,
		 lookups, &num_lookups);

  for (i = 0; i < num_lookups; i++)
B
Behdad Esfahbod 已提交
206
    hb_ot_layout_position_lookup (font, face, buffer, lookups[i].index, lookups[i].mask);
B
Behdad Esfahbod 已提交
207 208 209

  hb_ot_layout_position_finish (font, face, buffer);

210
  return TRUE;
B
Behdad Esfahbod 已提交
211
}