gfx/harfbuzz/src/hb-ot-shape-fallback.cc

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/harfbuzz/src/hb-ot-shape-fallback.cc	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,479 @@
     1.4 +/*
     1.5 + * Copyright © 2011,2012  Google, Inc.
     1.6 + *
     1.7 + *  This is part of HarfBuzz, a text shaping library.
     1.8 + *
     1.9 + * Permission is hereby granted, without written agreement and without
    1.10 + * license or royalty fees, to use, copy, modify, and distribute this
    1.11 + * software and its documentation for any purpose, provided that the
    1.12 + * above copyright notice and the following two paragraphs appear in
    1.13 + * all copies of this software.
    1.14 + *
    1.15 + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
    1.16 + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
    1.17 + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
    1.18 + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
    1.19 + * DAMAGE.
    1.20 + *
    1.21 + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
    1.22 + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
    1.23 + * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
    1.24 + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
    1.25 + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
    1.26 + *
    1.27 + * Google Author(s): Behdad Esfahbod
    1.28 + */
    1.29 +
    1.30 +#include "hb-ot-shape-fallback-private.hh"
    1.31 +#include "hb-ot-layout-gsubgpos-private.hh"
    1.32 +
    1.33 +static unsigned int
    1.34 +recategorize_combining_class (hb_codepoint_t u,
    1.35 +			      unsigned int klass)
    1.36 +{
    1.37 +  if (klass >= 200)
    1.38 +    return klass;
    1.39 +
    1.40 +  /* Thai / Lao need some per-character work. */
    1.41 +  if ((u & ~0xFF) == 0x0E00)
    1.42 +  {
    1.43 +    if (unlikely (klass == 0))
    1.44 +    {
    1.45 +      switch (u)
    1.46 +      {
    1.47 +        case 0x0E31:
    1.48 +        case 0x0E34:
    1.49 +        case 0x0E35:
    1.50 +        case 0x0E36:
    1.51 +        case 0x0E37:
    1.52 +        case 0x0E47:
    1.53 +        case 0x0E4C:
    1.54 +        case 0x0E4D:
    1.55 +        case 0x0E4E:
    1.56 +	  klass = HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
    1.57 +	  break;
    1.58 +
    1.59 +        case 0x0EB1:
    1.60 +        case 0x0EB4:
    1.61 +        case 0x0EB5:
    1.62 +        case 0x0EB6:
    1.63 +        case 0x0EB7:
    1.64 +        case 0x0EBB:
    1.65 +        case 0x0ECC:
    1.66 +        case 0x0ECD:
    1.67 +	  klass = HB_UNICODE_COMBINING_CLASS_ABOVE;
    1.68 +	  break;
    1.69 +
    1.70 +        case 0x0EBC:
    1.71 +	  klass = HB_UNICODE_COMBINING_CLASS_BELOW;
    1.72 +	  break;
    1.73 +      }
    1.74 +    } else {
    1.75 +      /* Thai virama is below-right */
    1.76 +      if (u == 0x0E3A)
    1.77 +	klass = HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT;
    1.78 +    }
    1.79 +  }
    1.80 +
    1.81 +  switch (klass)
    1.82 +  {
    1.83 +
    1.84 +    /* Hebrew */
    1.85 +
    1.86 +    case HB_MODIFIED_COMBINING_CLASS_CCC10: /* sheva */
    1.87 +    case HB_MODIFIED_COMBINING_CLASS_CCC11: /* hataf segol */
    1.88 +    case HB_MODIFIED_COMBINING_CLASS_CCC12: /* hataf patah */
    1.89 +    case HB_MODIFIED_COMBINING_CLASS_CCC13: /* hataf qamats */
    1.90 +    case HB_MODIFIED_COMBINING_CLASS_CCC14: /* hiriq */
    1.91 +    case HB_MODIFIED_COMBINING_CLASS_CCC15: /* tsere */
    1.92 +    case HB_MODIFIED_COMBINING_CLASS_CCC16: /* segol */
    1.93 +    case HB_MODIFIED_COMBINING_CLASS_CCC17: /* patah */
    1.94 +    case HB_MODIFIED_COMBINING_CLASS_CCC18: /* qamats */
    1.95 +    case HB_MODIFIED_COMBINING_CLASS_CCC20: /* qubuts */
    1.96 +    case HB_MODIFIED_COMBINING_CLASS_CCC22: /* meteg */
    1.97 +      return HB_UNICODE_COMBINING_CLASS_BELOW;
    1.98 +
    1.99 +    case HB_MODIFIED_COMBINING_CLASS_CCC23: /* rafe */
   1.100 +      return HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE;
   1.101 +
   1.102 +    case HB_MODIFIED_COMBINING_CLASS_CCC24: /* shin dot */
   1.103 +      return HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
   1.104 +
   1.105 +    case HB_MODIFIED_COMBINING_CLASS_CCC25: /* sin dot */
   1.106 +    case HB_MODIFIED_COMBINING_CLASS_CCC19: /* holam */
   1.107 +      return HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT;
   1.108 +
   1.109 +    case HB_MODIFIED_COMBINING_CLASS_CCC26: /* point varika */
   1.110 +      return HB_UNICODE_COMBINING_CLASS_ABOVE;
   1.111 +
   1.112 +    case HB_MODIFIED_COMBINING_CLASS_CCC21: /* dagesh */
   1.113 +      break;
   1.114 +
   1.115 +
   1.116 +    /* Arabic and Syriac */
   1.117 +
   1.118 +    case HB_MODIFIED_COMBINING_CLASS_CCC27: /* fathatan */
   1.119 +    case HB_MODIFIED_COMBINING_CLASS_CCC28: /* dammatan */
   1.120 +    case HB_MODIFIED_COMBINING_CLASS_CCC30: /* fatha */
   1.121 +    case HB_MODIFIED_COMBINING_CLASS_CCC31: /* damma */
   1.122 +    case HB_MODIFIED_COMBINING_CLASS_CCC33: /* shadda */
   1.123 +    case HB_MODIFIED_COMBINING_CLASS_CCC34: /* sukun */
   1.124 +    case HB_MODIFIED_COMBINING_CLASS_CCC35: /* superscript alef */
   1.125 +    case HB_MODIFIED_COMBINING_CLASS_CCC36: /* superscript alaph */
   1.126 +      return HB_UNICODE_COMBINING_CLASS_ABOVE;
   1.127 +
   1.128 +    case HB_MODIFIED_COMBINING_CLASS_CCC29: /* kasratan */
   1.129 +    case HB_MODIFIED_COMBINING_CLASS_CCC32: /* kasra */
   1.130 +      return HB_UNICODE_COMBINING_CLASS_BELOW;
   1.131 +
   1.132 +
   1.133 +    /* Thai */
   1.134 +
   1.135 +    case HB_MODIFIED_COMBINING_CLASS_CCC103: /* sara u / sara uu */
   1.136 +      return HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT;
   1.137 +
   1.138 +    case HB_MODIFIED_COMBINING_CLASS_CCC107: /* mai */
   1.139 +      return HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT;
   1.140 +
   1.141 +
   1.142 +    /* Lao */
   1.143 +
   1.144 +    case HB_MODIFIED_COMBINING_CLASS_CCC118: /* sign u / sign uu */
   1.145 +      return HB_UNICODE_COMBINING_CLASS_BELOW;
   1.146 +
   1.147 +    case HB_MODIFIED_COMBINING_CLASS_CCC122: /* mai */
   1.148 +      return HB_UNICODE_COMBINING_CLASS_ABOVE;
   1.149 +
   1.150 +
   1.151 +    /* Tibetan */
   1.152 +
   1.153 +    case HB_MODIFIED_COMBINING_CLASS_CCC129: /* sign aa */
   1.154 +      return HB_UNICODE_COMBINING_CLASS_BELOW;
   1.155 +
   1.156 +    case HB_MODIFIED_COMBINING_CLASS_CCC130: /* sign i*/
   1.157 +      return HB_UNICODE_COMBINING_CLASS_ABOVE;
   1.158 +
   1.159 +    case HB_MODIFIED_COMBINING_CLASS_CCC132: /* sign u */
   1.160 +      return HB_UNICODE_COMBINING_CLASS_BELOW;
   1.161 +
   1.162 +  }
   1.163 +
   1.164 +  return klass;
   1.165 +}
   1.166 +
   1.167 +void
   1.168 +_hb_ot_shape_fallback_position_recategorize_marks (const hb_ot_shape_plan_t *plan HB_UNUSED,
   1.169 +						   hb_font_t *font HB_UNUSED,
   1.170 +						   hb_buffer_t  *buffer)
   1.171 +{
   1.172 +  unsigned int count = buffer->len;
   1.173 +  for (unsigned int i = 0; i < count; i++)
   1.174 +    if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) {
   1.175 +      unsigned int combining_class = _hb_glyph_info_get_modified_combining_class (&buffer->info[i]);
   1.176 +      combining_class = recategorize_combining_class (buffer->info[i].codepoint, combining_class);
   1.177 +      _hb_glyph_info_set_modified_combining_class (&buffer->info[i], combining_class);
   1.178 +    }
   1.179 +}
   1.180 +
   1.181 +
   1.182 +static void
   1.183 +zero_mark_advances (hb_buffer_t *buffer,
   1.184 +		    unsigned int start,
   1.185 +		    unsigned int end)
   1.186 +{
   1.187 +  for (unsigned int i = start; i < end; i++)
   1.188 +    if (_hb_glyph_info_get_general_category (&buffer->info[i]) == HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
   1.189 +    {
   1.190 +      buffer->pos[i].x_advance = 0;
   1.191 +      buffer->pos[i].y_advance = 0;
   1.192 +    }
   1.193 +}
   1.194 +
   1.195 +static inline void
   1.196 +position_mark (const hb_ot_shape_plan_t *plan,
   1.197 +	       hb_font_t *font,
   1.198 +	       hb_buffer_t  *buffer,
   1.199 +	       hb_glyph_extents_t &base_extents,
   1.200 +	       unsigned int i,
   1.201 +	       unsigned int combining_class)
   1.202 +{
   1.203 +  hb_glyph_extents_t mark_extents;
   1.204 +  if (!font->get_glyph_extents (buffer->info[i].codepoint,
   1.205 +				&mark_extents))
   1.206 +    return;
   1.207 +
   1.208 +  hb_position_t y_gap = font->y_scale / 16;
   1.209 +
   1.210 +  hb_glyph_position_t &pos = buffer->pos[i];
   1.211 +  pos.x_offset = pos.y_offset = 0;
   1.212 +
   1.213 +
   1.214 +  /* We dont position LEFT and RIGHT marks. */
   1.215 +
   1.216 +  /* X positioning */
   1.217 +  switch (combining_class)
   1.218 +  {
   1.219 +    case HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW:
   1.220 +    case HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE:
   1.221 +      if (buffer->props.direction == HB_DIRECTION_LTR) {
   1.222 +	pos.x_offset += base_extents.x_bearing - mark_extents.width / 2 - mark_extents.x_bearing;
   1.223 +        break;
   1.224 +      } else if (buffer->props.direction == HB_DIRECTION_RTL) {
   1.225 +	pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width / 2 - mark_extents.x_bearing;
   1.226 +        break;
   1.227 +      }
   1.228 +      /* Fall through */
   1.229 +
   1.230 +    default:
   1.231 +    case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
   1.232 +    case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE:
   1.233 +    case HB_UNICODE_COMBINING_CLASS_BELOW:
   1.234 +    case HB_UNICODE_COMBINING_CLASS_ABOVE:
   1.235 +      /* Center align. */
   1.236 +      pos.x_offset += base_extents.x_bearing + (base_extents.width - mark_extents.width) / 2 - mark_extents.x_bearing;
   1.237 +      break;
   1.238 +
   1.239 +    case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT:
   1.240 +    case HB_UNICODE_COMBINING_CLASS_BELOW_LEFT:
   1.241 +    case HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT:
   1.242 +      /* Left align. */
   1.243 +      pos.x_offset += base_extents.x_bearing - mark_extents.x_bearing;
   1.244 +      break;
   1.245 +
   1.246 +    case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT:
   1.247 +    case HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT:
   1.248 +    case HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT:
   1.249 +      /* Right align. */
   1.250 +      pos.x_offset += base_extents.x_bearing + base_extents.width - mark_extents.width - mark_extents.x_bearing;
   1.251 +      break;
   1.252 +  }
   1.253 +
   1.254 +  /* Y positioning */
   1.255 +  switch (combining_class)
   1.256 +  {
   1.257 +    case HB_UNICODE_COMBINING_CLASS_DOUBLE_BELOW:
   1.258 +    case HB_UNICODE_COMBINING_CLASS_BELOW_LEFT:
   1.259 +    case HB_UNICODE_COMBINING_CLASS_BELOW:
   1.260 +    case HB_UNICODE_COMBINING_CLASS_BELOW_RIGHT:
   1.261 +      /* Add gap, fall-through. */
   1.262 +      base_extents.height -= y_gap;
   1.263 +
   1.264 +    case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW_LEFT:
   1.265 +    case HB_UNICODE_COMBINING_CLASS_ATTACHED_BELOW:
   1.266 +      pos.y_offset = base_extents.y_bearing + base_extents.height - mark_extents.y_bearing;
   1.267 +      /* Never shift up "below" marks. */
   1.268 +      if ((y_gap > 0) == (pos.y_offset > 0))
   1.269 +      {
   1.270 +	base_extents.height -= pos.y_offset;
   1.271 +	pos.y_offset = 0;
   1.272 +      }
   1.273 +      base_extents.height += mark_extents.height;
   1.274 +      break;
   1.275 +
   1.276 +    case HB_UNICODE_COMBINING_CLASS_DOUBLE_ABOVE:
   1.277 +    case HB_UNICODE_COMBINING_CLASS_ABOVE_LEFT:
   1.278 +    case HB_UNICODE_COMBINING_CLASS_ABOVE:
   1.279 +    case HB_UNICODE_COMBINING_CLASS_ABOVE_RIGHT:
   1.280 +      /* Add gap, fall-through. */
   1.281 +      base_extents.y_bearing += y_gap;
   1.282 +      base_extents.height -= y_gap;
   1.283 +
   1.284 +    case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE:
   1.285 +    case HB_UNICODE_COMBINING_CLASS_ATTACHED_ABOVE_RIGHT:
   1.286 +      pos.y_offset = base_extents.y_bearing - (mark_extents.y_bearing + mark_extents.height);
   1.287 +      /* Don't shift down "above" marks too much. */
   1.288 +      if ((y_gap > 0) != (pos.y_offset > 0))
   1.289 +      {
   1.290 +	unsigned int correction = -pos.y_offset / 2;
   1.291 +	base_extents.y_bearing += correction;
   1.292 +	base_extents.height -= correction;
   1.293 +	pos.y_offset += correction;
   1.294 +      }
   1.295 +      base_extents.y_bearing -= mark_extents.height;
   1.296 +      base_extents.height += mark_extents.height;
   1.297 +      break;
   1.298 +  }
   1.299 +}
   1.300 +
   1.301 +static inline void
   1.302 +position_around_base (const hb_ot_shape_plan_t *plan,
   1.303 +		      hb_font_t *font,
   1.304 +		      hb_buffer_t  *buffer,
   1.305 +		      unsigned int base,
   1.306 +		      unsigned int end)
   1.307 +{
   1.308 +  hb_direction_t horiz_dir = HB_DIRECTION_INVALID;
   1.309 +  hb_glyph_extents_t base_extents;
   1.310 +  if (!font->get_glyph_extents (buffer->info[base].codepoint,
   1.311 +				&base_extents))
   1.312 +  {
   1.313 +    /* If extents don't work, zero marks and go home. */
   1.314 +    zero_mark_advances (buffer, base + 1, end);
   1.315 +    return;
   1.316 +  }
   1.317 +  base_extents.x_bearing += buffer->pos[base].x_offset;
   1.318 +  base_extents.y_bearing += buffer->pos[base].y_offset;
   1.319 +
   1.320 +  unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[base]);
   1.321 +  unsigned int num_lig_components = _hb_glyph_info_get_lig_num_comps (&buffer->info[base]);
   1.322 +
   1.323 +  hb_position_t x_offset = 0, y_offset = 0;
   1.324 +  if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) {
   1.325 +    x_offset -= buffer->pos[base].x_advance;
   1.326 +    y_offset -= buffer->pos[base].y_advance;
   1.327 +  }
   1.328 +
   1.329 +  hb_glyph_extents_t component_extents = base_extents;
   1.330 +  unsigned int last_lig_component = (unsigned int) -1;
   1.331 +  unsigned int last_combining_class = 255;
   1.332 +  hb_glyph_extents_t cluster_extents = base_extents; /* Initialization is just to shut gcc up. */
   1.333 +  for (unsigned int i = base + 1; i < end; i++)
   1.334 +    if (_hb_glyph_info_get_modified_combining_class (&buffer->info[i]))
   1.335 +    {
   1.336 +      if (num_lig_components > 1) {
   1.337 +	unsigned int this_lig_id = _hb_glyph_info_get_lig_id (&buffer->info[i]);
   1.338 +	unsigned int this_lig_component = _hb_glyph_info_get_lig_comp (&buffer->info[i]) - 1;
   1.339 +	/* Conditions for attaching to the last component. */
   1.340 +	if (!lig_id || lig_id != this_lig_id || this_lig_component >= num_lig_components)
   1.341 +	  this_lig_component = num_lig_components - 1;
   1.342 +	if (last_lig_component != this_lig_component)
   1.343 +	{
   1.344 +	  last_lig_component = this_lig_component;
   1.345 +	  last_combining_class = 255;
   1.346 +	  component_extents = base_extents;
   1.347 +	  if (unlikely (horiz_dir == HB_DIRECTION_INVALID)) {
   1.348 +	    if (HB_DIRECTION_IS_HORIZONTAL (plan->props.direction))
   1.349 +	      horiz_dir = plan->props.direction;
   1.350 +	    else
   1.351 +	      horiz_dir = hb_script_get_horizontal_direction (plan->props.script);
   1.352 +	  }
   1.353 +	  if (horiz_dir == HB_DIRECTION_LTR)
   1.354 +	    component_extents.x_bearing += (this_lig_component * component_extents.width) / num_lig_components;
   1.355 +	  else
   1.356 +	    component_extents.x_bearing += ((num_lig_components - 1 - this_lig_component) * component_extents.width) / num_lig_components;
   1.357 +	  component_extents.width /= num_lig_components;
   1.358 +	}
   1.359 +      }
   1.360 +
   1.361 +      unsigned int this_combining_class = _hb_glyph_info_get_modified_combining_class (&buffer->info[i]);
   1.362 +      if (last_combining_class != this_combining_class)
   1.363 +      {
   1.364 +	last_combining_class = this_combining_class;
   1.365 +        cluster_extents = component_extents;
   1.366 +      }
   1.367 +
   1.368 +      position_mark (plan, font, buffer, cluster_extents, i, this_combining_class);
   1.369 +
   1.370 +      buffer->pos[i].x_advance = 0;
   1.371 +      buffer->pos[i].y_advance = 0;
   1.372 +      buffer->pos[i].x_offset += x_offset;
   1.373 +      buffer->pos[i].y_offset += y_offset;
   1.374 +
   1.375 +    } else {
   1.376 +      if (HB_DIRECTION_IS_FORWARD (buffer->props.direction)) {
   1.377 +	x_offset -= buffer->pos[i].x_advance;
   1.378 +	y_offset -= buffer->pos[i].y_advance;
   1.379 +      } else {
   1.380 +	x_offset += buffer->pos[i].x_advance;
   1.381 +	y_offset += buffer->pos[i].y_advance;
   1.382 +      }
   1.383 +    }
   1.384 +}
   1.385 +
   1.386 +static inline void
   1.387 +position_cluster (const hb_ot_shape_plan_t *plan,
   1.388 +		  hb_font_t *font,
   1.389 +		  hb_buffer_t  *buffer,
   1.390 +		  unsigned int start,
   1.391 +		  unsigned int end)
   1.392 +{
   1.393 +  if (end - start < 2)
   1.394 +    return;
   1.395 +
   1.396 +  /* Find the base glyph */
   1.397 +  for (unsigned int i = start; i < end; i++)
   1.398 +    if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[i])))
   1.399 +    {
   1.400 +      /* Find mark glyphs */
   1.401 +      unsigned int j;
   1.402 +      for (j = i + 1; j < end; j++)
   1.403 +	if (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&buffer->info[j])))
   1.404 +	  break;
   1.405 +
   1.406 +      position_around_base (plan, font, buffer, i, j);
   1.407 +
   1.408 +      i = j - 1;
   1.409 +    }
   1.410 +}
   1.411 +
   1.412 +void
   1.413 +_hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan,
   1.414 +				hb_font_t *font,
   1.415 +				hb_buffer_t  *buffer)
   1.416 +{
   1.417 +  unsigned int start = 0;
   1.418 +  unsigned int last_cluster = buffer->info[0].cluster;
   1.419 +  unsigned int count = buffer->len;
   1.420 +  for (unsigned int i = 1; i < count; i++)
   1.421 +    if (buffer->info[i].cluster != last_cluster) {
   1.422 +      position_cluster (plan, font, buffer, start, i);
   1.423 +      start = i;
   1.424 +      last_cluster = buffer->info[i].cluster;
   1.425 +    }
   1.426 +  position_cluster (plan, font, buffer, start, count);
   1.427 +}
   1.428 +
   1.429 +
   1.430 +/* Performs old-style TrueType kerning. */
   1.431 +void
   1.432 +_hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
   1.433 +			    hb_font_t *font,
   1.434 +			    hb_buffer_t  *buffer)
   1.435 +{
   1.436 +  if (!plan->has_kern) return;
   1.437 +
   1.438 +  unsigned int count = buffer->len;
   1.439 +
   1.440 +  OT::hb_apply_context_t c (1, font, buffer);
   1.441 +  c.set_lookup_mask (plan->kern_mask);
   1.442 +  c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
   1.443 +
   1.444 +  hb_glyph_info_t *info = buffer->info;
   1.445 +  hb_glyph_position_t *pos = buffer->pos;
   1.446 +
   1.447 +  for (unsigned int idx = 0; idx < count;)
   1.448 +  {
   1.449 +    OT::hb_apply_context_t::skipping_forward_iterator_t skippy_iter (&c, idx, 1);
   1.450 +    if (!skippy_iter.next ())
   1.451 +    {
   1.452 +      idx++;
   1.453 +      continue;
   1.454 +    }
   1.455 +
   1.456 +    hb_position_t x_kern, y_kern;
   1.457 +    font->get_glyph_kerning_for_direction (info[idx].codepoint,
   1.458 +					   info[skippy_iter.idx].codepoint,
   1.459 +					   buffer->props.direction,
   1.460 +					   &x_kern, &y_kern);
   1.461 +
   1.462 +    if (x_kern)
   1.463 +    {
   1.464 +      hb_position_t kern1 = x_kern >> 1;
   1.465 +      hb_position_t kern2 = x_kern - kern1;
   1.466 +      pos[idx].x_advance += kern1;
   1.467 +      pos[skippy_iter.idx].x_advance += kern2;
   1.468 +      pos[skippy_iter.idx].x_offset += kern2;
   1.469 +    }
   1.470 +
   1.471 +    if (y_kern)
   1.472 +    {
   1.473 +      hb_position_t kern1 = y_kern >> 1;
   1.474 +      hb_position_t kern2 = y_kern - kern1;
   1.475 +      pos[idx].y_advance += kern1;
   1.476 +      pos[skippy_iter.idx].y_advance += kern2;
   1.477 +      pos[skippy_iter.idx].y_offset += kern2;
   1.478 +    }
   1.479 +
   1.480 +    idx = skippy_iter.idx;
   1.481 +  }
   1.482 +}

mercurial