예제 #1
0
파일: taprep.c 프로젝트: MechanisM/entypo
static FT_Error
TA_table_build_prep(FT_Byte** prep,
                    FT_ULong* prep_len,
                    FONT* font)
{
  TA_LatinAxis vaxis;
  TA_LatinBlue blue_adjustment = NULL;
  FT_UInt i;

  FT_UInt buf_len = 0;
  FT_UInt len;
  FT_Byte* buf;
  FT_Byte* buf_p;


  if (font->loader->hints.metrics->clazz->script == TA_SCRIPT_NONE)
    vaxis = NULL;
  else
  {
    vaxis = &((TA_LatinMetrics)font->loader->hints.metrics)->axis[1];

    for (i = 0; i < vaxis->blue_count; i++)
    {
      if (vaxis->blues[i].flags & TA_LATIN_BLUE_ADJUSTMENT)
      {
        blue_adjustment = &vaxis->blues[i];
        break;
      }
    }
  }

  if (font->hinting_limit)
    buf_len += sizeof (PREP(hinting_limit_a))
               + 2
               + sizeof (PREP(hinting_limit_b));

  buf_len += sizeof (PREP(store_0x10000));

  if (blue_adjustment)
    buf_len += sizeof (PREP(align_top_a))
               + 1
               + sizeof (PREP(align_top_b))
               + (font->increase_x_height ? sizeof (PREP(align_top_c1))
                                          : sizeof (PREP(align_top_c2)))
               + sizeof (PREP(align_top_d))
               + sizeof (PREP(loop_cvt_a))
               + 2
               + sizeof (PREP(loop_cvt_b))
               + 2
               + sizeof (PREP(loop_cvt_c))
               + 2
               + sizeof (PREP(loop_cvt_d));

  buf_len += sizeof (PREP(compute_extra_light_a))
             + 1
             + sizeof (PREP(compute_extra_light_b));

  if (CVT_BLUES_SIZE(font))
    buf_len += sizeof (PREP(round_blues_a))
               + 2
               + sizeof (PREP(round_blues_b));

  buf_len += sizeof (PREP(set_dropout_mode));
  buf_len += sizeof (PREP(reset_component_counter));

  /* buffer length must be a multiple of four */
  len = (buf_len + 3) & ~3;
  buf = (FT_Byte*)malloc(len);
  if (!buf)
    return FT_Err_Out_Of_Memory;

  /* pad end of buffer with zeros */
  buf[len - 1] = 0x00;
  buf[len - 2] = 0x00;
  buf[len - 3] = 0x00;

  /* copy cvt program into buffer and fill in the missing variables */
  buf_p = buf;

  if (font->hinting_limit)
  {
    COPY_PREP(hinting_limit_a);
    *(buf_p++) = HIGH(font->hinting_limit);
    *(buf_p++) = LOW(font->hinting_limit);
    COPY_PREP(hinting_limit_b);
  }

  COPY_PREP(store_0x10000);

  if (blue_adjustment)
  {
    COPY_PREP(align_top_a);
    *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
                                 + blue_adjustment - vaxis->blues);
    COPY_PREP(align_top_b);
    if (font->increase_x_height)
      COPY_PREP(align_top_c1);
    else
      COPY_PREP(align_top_c2);
    COPY_PREP(align_top_d);

    COPY_PREP(loop_cvt_a);
    *(buf_p++) = (unsigned char)CVT_VERT_WIDTHS_OFFSET(font);
    *(buf_p++) = (unsigned char)(CVT_VERT_WIDTHS_OFFSET(font)
                                 + CVT_VERT_WIDTHS_SIZE(font) - 1);
    COPY_PREP(loop_cvt_b);
    *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
    *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
                                 + CVT_BLUES_SIZE(font) - 1);
    COPY_PREP(loop_cvt_c);
    *(buf_p++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(font);
    *(buf_p++) = (unsigned char)(CVT_BLUE_SHOOTS_OFFSET(font)
                                 + CVT_BLUES_SIZE(font) - 1);
    COPY_PREP(loop_cvt_d);
  }

  COPY_PREP(compute_extra_light_a);
  *(buf_p++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(font);
  COPY_PREP(compute_extra_light_b);

  if (CVT_BLUES_SIZE(font))
  {
    COPY_PREP(round_blues_a);
    *(buf_p++) = (unsigned char)CVT_BLUE_REFS_OFFSET(font);
    *(buf_p++) = (unsigned char)(CVT_BLUE_REFS_OFFSET(font)
                                 + CVT_BLUES_SIZE(font) - 1);
    COPY_PREP(round_blues_b);
  }

  COPY_PREP(set_dropout_mode);
  COPY_PREP(reset_component_counter);

  *prep = buf;
  *prep_len = buf_len;

  return FT_Err_Ok;
}
예제 #2
0
static void
TA_hints_recorder(TA_Action action,
                  TA_GlyphHints hints,
                  TA_Dimension dim,
                  void* arg1,
                  TA_Edge arg2,
                  TA_Edge arg3,
                  TA_Edge lower_bound,
                  TA_Edge upper_bound)
{
  TA_AxisHints axis = &hints->axis[dim];
  TA_Edge edges = axis->edges;
  TA_Segment segments = axis->segments;
  TA_Point points = hints->points;

  Recorder* recorder = (Recorder*)hints->user;
  FONT* font = recorder->font;
  FT_UInt* wraps = recorder->wrap_around_segments;
  FT_Byte* p = recorder->hints_record.buf;

  FT_UInt* ip;
  FT_UInt* limit;


  if (dim == TA_DIMENSION_HORZ)
    return;

  /* we collect point hints for later processing */
  switch (action)
  {
  case ta_ip_before:
    {
      TA_Point point = (TA_Point)arg1;


      ip = recorder->ip_before_points;
      limit = ip + recorder->num_strong_points;
      for (; ip < limit; ip++)
      {
        if (*ip == MISSING)
        {
          *ip = point - points;
          break;
        }
      }
    }
    return;

  case ta_ip_after:
    {
      TA_Point point = (TA_Point)arg1;


      ip = recorder->ip_after_points;
      limit = ip + recorder->num_strong_points;
      for (; ip < limit; ip++)
      {
        if (*ip == MISSING)
        {
          *ip = point - points;
          break;
        }
      }
    }
    return;

  case ta_ip_on:
    {
      TA_Point point = (TA_Point)arg1;
      TA_Edge edge = arg2;


      ip = recorder->ip_on_point_array
           + recorder->num_strong_points
             * (edge - edges);
      limit = ip + recorder->num_strong_points;
      for (; ip < limit; ip++)
      {
        if (*ip == MISSING)
        {
          *ip = point - points;
          break;
        }
      }
    }
    return;

  case ta_ip_between:
    {
      TA_Point point = (TA_Point)arg1;
      TA_Edge before = arg2;
      TA_Edge after = arg3;


      /* note that `recorder->num_segments' has been used for allocation, */
      /* but `axis->num_edges' is used for accessing this array */
      ip = recorder->ip_between_point_array
           + recorder->num_strong_points * axis->num_edges
             * (before - edges)
           + recorder->num_strong_points
             * (after - edges);
      limit = ip + recorder->num_strong_points;
      for (; ip < limit; ip++)
      {
        if (*ip == MISSING)
        {
          *ip = point - points;
          break;
        }
      }
    }
    return;

  case ta_bound:
    /* we ignore the BOUND action since we signal this information */
    /* with the proper function number */
    return;

  default:
    break;
  }

  /* some enum values correspond to four or eight bytecode functions; */
  /* if the value is n, the function numbers are n, ..., n+7, */
  /* to be differentiated with flags */

  switch (action)
  {
  case ta_link:
    {
      TA_Edge base_edge = (TA_Edge)arg1;
      TA_Edge stem_edge = arg2;


      *(p++) = 0;
      *(p++) = (FT_Byte)action + ACTION_OFFSET
               + ((stem_edge->flags & TA_EDGE_SERIF) != 0)
               + 2 * ((base_edge->flags & TA_EDGE_ROUND) != 0);

      *(p++) = HIGH(base_edge->first - segments);
      *(p++) = LOW(base_edge->first - segments);
      *(p++) = HIGH(stem_edge->first - segments);
      *(p++) = LOW(stem_edge->first - segments);

      p = TA_hints_recorder_handle_segments(p, axis, stem_edge, wraps);
    }
    break;

  case ta_anchor:
    {
      TA_Edge edge = (TA_Edge)arg1;
      TA_Edge edge2 = arg2;


      *(p++) = 0;
      *(p++) = (FT_Byte)action + ACTION_OFFSET
               + ((edge2->flags & TA_EDGE_SERIF) != 0)
               + 2 * ((edge->flags & TA_EDGE_ROUND) != 0);

      *(p++) = HIGH(edge->first - segments);
      *(p++) = LOW(edge->first - segments);
      *(p++) = HIGH(edge2->first - segments);
      *(p++) = LOW(edge2->first - segments);

      p = TA_hints_recorder_handle_segments(p, axis, edge, wraps);
    }
    break;

  case ta_adjust:
    {
      TA_Edge edge = (TA_Edge)arg1;
      TA_Edge edge2 = arg2;
      TA_Edge edge_minus_one = lower_bound;


      *(p++) = 0;
      *(p++) = (FT_Byte)action + ACTION_OFFSET
               + ((edge2->flags & TA_EDGE_SERIF) != 0)
               + 2 * ((edge->flags & TA_EDGE_ROUND) != 0)
               + 4 * (edge_minus_one != NULL);

      *(p++) = HIGH(edge->first - segments);
      *(p++) = LOW(edge->first - segments);
      *(p++) = HIGH(edge2->first - segments);
      *(p++) = LOW(edge2->first - segments);

      if (edge_minus_one)
      {
        *(p++) = HIGH(edge_minus_one->first - segments);
        *(p++) = LOW(edge_minus_one->first - segments);
      }

      p = TA_hints_recorder_handle_segments(p, axis, edge, wraps);
    }
    break;

  case ta_blue_anchor:
    {
      TA_Edge edge = (TA_Edge)arg1;
      TA_Edge blue = arg2;


      *(p++) = 0;
      *(p++) = (FT_Byte)action + ACTION_OFFSET;

      *(p++) = HIGH(blue->first - segments);
      *(p++) = LOW(blue->first - segments);

      if (edge->best_blue_is_shoot)
      {
        *(p++) = HIGH(CVT_BLUE_SHOOTS_OFFSET(font) + edge->best_blue_idx);
        *(p++) = LOW(CVT_BLUE_SHOOTS_OFFSET(font) + edge->best_blue_idx);
      }
      else
      {
        *(p++) = HIGH(CVT_BLUE_REFS_OFFSET(font) + edge->best_blue_idx);
        *(p++) = LOW(CVT_BLUE_REFS_OFFSET(font) + edge->best_blue_idx);
      }

      *(p++) = HIGH(edge->first - segments);
      *(p++) = LOW(edge->first - segments);

      p = TA_hints_recorder_handle_segments(p, axis, edge, wraps);
    }
    break;

  case ta_stem:
    {
      TA_Edge edge = (TA_Edge)arg1;
      TA_Edge edge2 = arg2;
      TA_Edge edge_minus_one = lower_bound;


      *(p++) = 0;
      *(p++) = (FT_Byte)action + ACTION_OFFSET
               + ((edge2->flags & TA_EDGE_SERIF) != 0)
               + 2 * ((edge->flags & TA_EDGE_ROUND) != 0)
               + 4 * (edge_minus_one != NULL);

      *(p++) = HIGH(edge->first - segments);
      *(p++) = LOW(edge->first - segments);
      *(p++) = HIGH(edge2->first - segments);
      *(p++) = LOW(edge2->first - segments);

      if (edge_minus_one)
      {
        *(p++) = HIGH(edge_minus_one->first - segments);
        *(p++) = LOW(edge_minus_one->first - segments);
      }

      p = TA_hints_recorder_handle_segments(p, axis, edge, wraps);
      p = TA_hints_recorder_handle_segments(p, axis, edge2, wraps);
    }
    break;

  case ta_blue:
    {
      TA_Edge edge = (TA_Edge)arg1;


      *(p++) = 0;
      *(p++) = (FT_Byte)action + ACTION_OFFSET;

      if (edge->best_blue_is_shoot)
      {
        *(p++) = HIGH(CVT_BLUE_SHOOTS_OFFSET(font) + edge->best_blue_idx);
        *(p++) = LOW(CVT_BLUE_SHOOTS_OFFSET(font) + edge->best_blue_idx);
      }
      else
      {
        *(p++) = HIGH(CVT_BLUE_REFS_OFFSET(font) + edge->best_blue_idx);
        *(p++) = LOW(CVT_BLUE_REFS_OFFSET(font) + edge->best_blue_idx);
      }

      *(p++) = HIGH(edge->first - segments);
      *(p++) = LOW(edge->first - segments);

      p = TA_hints_recorder_handle_segments(p, axis, edge, wraps);
    }
    break;

  case ta_serif:
    {
      TA_Edge serif = (TA_Edge)arg1;
      TA_Edge base = serif->serif;


      *(p++) = 0;
      *(p++) = (FT_Byte)action + ACTION_OFFSET
               + (lower_bound != NULL)
               + 2 * (upper_bound != NULL);

      *(p++) = HIGH(serif->first - segments);
      *(p++) = LOW(serif->first - segments);
      *(p++) = HIGH(base->first - segments);
      *(p++) = LOW(base->first - segments);

      if (lower_bound)
      {
        *(p++) = HIGH(lower_bound->first - segments);
        *(p++) = LOW(lower_bound->first - segments);
      }
      if (upper_bound)
      {
        *(p++) = HIGH(upper_bound->first - segments);
        *(p++) = LOW(upper_bound->first - segments);
      }

      p = TA_hints_recorder_handle_segments(p, axis, serif, wraps);
    }
    break;

  case ta_serif_anchor:
  case ta_serif_link2:
    {
      TA_Edge edge = (TA_Edge)arg1;


      *(p++) = 0;
      *(p++) = (FT_Byte)action + ACTION_OFFSET
               + (lower_bound != NULL)
               + 2 * (upper_bound != NULL);

      *(p++) = HIGH(edge->first - segments);
      *(p++) = LOW(edge->first - segments);

      if (lower_bound)
      {
        *(p++) = HIGH(lower_bound->first - segments);
        *(p++) = LOW(lower_bound->first - segments);
      }
      if (upper_bound)
      {
        *(p++) = HIGH(upper_bound->first - segments);
        *(p++) = LOW(upper_bound->first - segments);
      }

      p = TA_hints_recorder_handle_segments(p, axis, edge, wraps);
    }
    break;

  case ta_serif_link1:
    {
      TA_Edge edge = (TA_Edge)arg1;
      TA_Edge before = arg2;
      TA_Edge after = arg3;


      *(p++) = 0;
      *(p++) = (FT_Byte)action + ACTION_OFFSET
               + (lower_bound != NULL)
               + 2 * (upper_bound != NULL);

      *(p++) = HIGH(before->first - segments);
      *(p++) = LOW(before->first - segments);
      *(p++) = HIGH(edge->first - segments);
      *(p++) = LOW(edge->first - segments);
      *(p++) = HIGH(after->first - segments);
      *(p++) = LOW(after->first - segments);

      if (lower_bound)
      {
        *(p++) = HIGH(lower_bound->first - segments);
        *(p++) = LOW(lower_bound->first - segments);
      }
      if (upper_bound)
      {
        *(p++) = HIGH(upper_bound->first - segments);
        *(p++) = LOW(upper_bound->first - segments);
      }

      p = TA_hints_recorder_handle_segments(p, axis, edge, wraps);
    }
    break;

  default:
    /* there are more cases in the enumeration */
    /* which are handled with flags */
    break;
  }

  recorder->hints_record.num_actions++;
  recorder->hints_record.buf = p;
}
예제 #3
0
static FT_Error
TA_table_build_prep(FT_Byte** prep,
                    FT_ULong* prep_len,
                    SFNT* sfnt,
                    FONT* font)
{
  SFNT_Table* glyf_table = &font->tables[sfnt->glyf_idx];
  glyf_Data* data = (glyf_Data*)glyf_table->data;
  /* XXX: make this work for more than 256 styles */
  FT_Byte num_used_styles = (FT_Byte)data->num_used_styles;

  FT_Int i;

  FT_Byte* buf = NULL;
  FT_Byte* buf_new;
  FT_UInt buf_len;
  FT_UInt buf_new_len;

  FT_UInt len;
  FT_Byte* bufp = NULL;


  if (font->x_height_snapping_exceptions)
  {
    bufp = TA_sfnt_build_number_set(sfnt, &buf,
                                    font->x_height_snapping_exceptions);
    if (!bufp)
      return FT_Err_Out_Of_Memory;
  }

  buf_len = (FT_UInt)(bufp - buf);
  buf_new_len = buf_len;

  if (font->hinting_limit)
    buf_new_len += sizeof (PREP(hinting_limit_a))
                   + 2
                   + sizeof (PREP(hinting_limit_b));

  buf_new_len += sizeof (PREP(store_funits_to_pixels));

  if (font->x_height_snapping_exceptions)
    buf_new_len += sizeof (PREP(test_exception_a));

  buf_new_len += sizeof (PREP(align_top_a))
                 + (num_used_styles > 6 ? num_used_styles + 3
                                        : num_used_styles + 2)
                 + sizeof (PREP(align_top_b));
  buf_new_len += sizeof (PREP(loop_cvt_a))
                 + (num_used_styles > 3 ? 2 * num_used_styles + 3
                                        : 2 * num_used_styles + 2)
                 + sizeof (PREP(loop_cvt_b))
                 + (num_used_styles > 3 ? 2 * num_used_styles + 3
                                        : 2 * num_used_styles + 2)
                 + sizeof (PREP(loop_cvt_c));

  if (font->x_height_snapping_exceptions)
    buf_new_len += sizeof (PREP(test_exception_b));

  buf_new_len += sizeof (PREP(store_vwidth_data_a))
                 + 1
                 + sizeof (PREP(store_vwidth_data_b))
                 + (num_used_styles > 6 ? 2 * (num_used_styles + 1) + 2
                                        : 2 * (num_used_styles + 1) + 1)
                 + sizeof (PREP(store_vwidth_data_c))
                 + 1
                 + sizeof (PREP(store_vwidth_data_d))
                 + (num_used_styles > 6 ? 2 * (num_used_styles + 1) + 2
                                        : 2 * (num_used_styles + 1) + 1)
                 + sizeof (PREP(store_vwidth_data_e));
  buf_new_len += sizeof (PREP(set_smooth_or_strong_a))
                 + 1
                 + sizeof (PREP(set_smooth_or_strong_b))
                 + 1
                 + sizeof (PREP(set_smooth_or_strong_c))
                 + 1
                 + sizeof (PREP(set_smooth_or_strong_d));
  buf_new_len += (num_used_styles > 3 ? 2 * num_used_styles + 3
                                      : 2 * num_used_styles + 2)
                 + sizeof (PREP(round_blues));
  buf_new_len += sizeof (PREP(set_dropout_mode));
  buf_new_len += sizeof (PREP(reset_component_counter));
  if (font->control_data_head)
    buf_new_len += sizeof (PREP(adjust_delta_exceptions));
  buf_new_len += sizeof (PREP(set_default_cvs_values));

  /* buffer length must be a multiple of four */
  len = (buf_new_len + 3) & ~3U;
  buf_new = (FT_Byte*)realloc(buf, len);
  if (!buf_new)
  {
    free(buf);
    return FT_Err_Out_Of_Memory;
  }
  buf = buf_new;

  /* pad end of buffer with zeros */
  buf[len - 1] = 0x00;
  buf[len - 2] = 0x00;
  buf[len - 3] = 0x00;

  /* copy remaining cvt program into buffer */
  /* and fill in the missing variables */
  bufp = buf + buf_len;

  if (font->hinting_limit)
  {
    COPY_PREP(hinting_limit_a);
    *(bufp++) = HIGH(font->hinting_limit);
    *(bufp++) = LOW(font->hinting_limit);
    COPY_PREP(hinting_limit_b);
  }

  COPY_PREP(store_funits_to_pixels);

  if (font->x_height_snapping_exceptions)
    COPY_PREP(test_exception_a);

  COPY_PREP(align_top_a);
  if (num_used_styles > 6)
  {
    BCI(NPUSHB);
    BCI(num_used_styles + 2);
  }
  else
    BCI(PUSHB_1 - 1 + num_used_styles + 2);
  /* XXX: make this work for offsets > 255 */
  for (i = TA_STYLE_MAX - 1; i >= 0; i--)
  {
    if (data->style_ids[i] == 0xFFFFU)
      continue;

    *(bufp++) = CVT_X_HEIGHT_BLUE_OFFSET(i) >= 0xFFFFU
                  ? 0
                  : (unsigned char)CVT_X_HEIGHT_BLUE_OFFSET(i);
  }
  *(bufp++) = num_used_styles;
  COPY_PREP(align_top_b);

  COPY_PREP(loop_cvt_a);
  if (num_used_styles > 3)
  {
    BCI(NPUSHB);
    BCI(2 * num_used_styles + 2);
  }
  else
    BCI(PUSHB_1 - 1 + 2 * num_used_styles + 2);
  /* XXX: make this work for offsets > 255 */
  for (i = TA_STYLE_MAX - 1; i >= 0; i--)
  {
    if (data->style_ids[i] == 0xFFFFU)
      continue;

    /* don't loop over artificial blue zones */
    *(bufp++) = (unsigned char)CVT_VERT_STANDARD_WIDTH_OFFSET(i);
    *(bufp++) = (unsigned char)(
                  1
                  + CVT_VERT_WIDTHS_SIZE(i)
                  + (CVT_BLUES_SIZE(i) > 1 ? CVT_BLUES_SIZE(i) - 2 : 0));
  }
  *(bufp++) = num_used_styles;
  COPY_PREP(loop_cvt_b);
  if (num_used_styles > 3)
  {
    BCI(NPUSHB);
    BCI(2 * num_used_styles + 2);
  }
  else
    BCI(PUSHB_1 - 1 + 2 * num_used_styles + 2);
  /* XXX: make this work for offsets > 255 */
  for (i = TA_STYLE_MAX - 1; i >= 0; i--)
  {
    if (data->style_ids[i] == 0xFFFFU)
      continue;

    /* don't loop over artificial blue zones */
    *(bufp++) = (unsigned char)CVT_BLUE_SHOOTS_OFFSET(i);
    *(bufp++) = (unsigned char)(
                  CVT_BLUES_SIZE(i) > 1 ? CVT_BLUES_SIZE(i) - 2 : 0);
  }
  *(bufp++) = num_used_styles;
  COPY_PREP(loop_cvt_c);

  if (font->x_height_snapping_exceptions)
    COPY_PREP(test_exception_b);

  COPY_PREP(store_vwidth_data_a);
  *(bufp++) = (unsigned char)CVT_VWIDTH_OFFSET_DATA(0);
  COPY_PREP(store_vwidth_data_b);
  if (num_used_styles > 6)
  {
    BCI(NPUSHW);
    BCI(num_used_styles + 2);
  }
  else
    BCI(PUSHW_1 - 1 + num_used_styles + 2);
  for (i = TA_STYLE_MAX - 1; i >= 0; i--)
  {
    if (data->style_ids[i] == 0xFFFFU)
      continue;

    *(bufp++) = HIGH(CVT_VERT_WIDTHS_OFFSET(i) * 64);
    *(bufp++) = LOW(CVT_VERT_WIDTHS_OFFSET(i) * 64);
  }
  *(bufp++) = HIGH(num_used_styles);
  *(bufp++) = LOW(num_used_styles);
  COPY_PREP(store_vwidth_data_c);
  *(bufp++) = (unsigned char)CVT_VWIDTH_SIZE_DATA(0);
  COPY_PREP(store_vwidth_data_d);
  if (num_used_styles > 6)
  {
    BCI(NPUSHW);
    BCI(num_used_styles + 2);
  }
  else
    BCI(PUSHW_1 - 1 + num_used_styles + 2);
  for (i = TA_STYLE_MAX - 1; i >= 0; i--)
  {
    if (data->style_ids[i] == 0xFFFFU)
      continue;

    *(bufp++) = HIGH(CVT_VERT_WIDTHS_SIZE(i) * 64);
    *(bufp++) = LOW(CVT_VERT_WIDTHS_SIZE(i) * 64);
  }
  *(bufp++) = HIGH(num_used_styles);
  *(bufp++) = LOW(num_used_styles);
  COPY_PREP(store_vwidth_data_e);

  COPY_PREP(set_smooth_or_strong_a);
  *(bufp++) = font->gray_strong_stem_width ? 100 : 0;
  COPY_PREP(set_smooth_or_strong_b);
  *(bufp++) = font->gdi_cleartype_strong_stem_width ? 100 : 0;
  COPY_PREP(set_smooth_or_strong_c);
  *(bufp++) = font->dw_cleartype_strong_stem_width ? 100 : 0;
  COPY_PREP(set_smooth_or_strong_d);

  if (num_used_styles > 3)
  {
    BCI(NPUSHB);
    BCI(2 * num_used_styles + 2);
  }
  else
    BCI(PUSHB_1 - 1 + 2 * num_used_styles + 2);
  /* XXX: make this work for offsets > 255 */
  for (i = TA_STYLE_MAX - 1; i >= 0; i--)
  {
    if (data->style_ids[i] == 0xFFFFU)
      continue;

    *(bufp++) = (unsigned char)CVT_BLUE_REFS_OFFSET(i);
    *(bufp++) = (unsigned char)CVT_BLUES_SIZE(i);
  }
  *(bufp++) = num_used_styles;
  COPY_PREP(round_blues);

  COPY_PREP(set_dropout_mode);
  COPY_PREP(reset_component_counter);
  if (font->control_data_head)
    COPY_PREP(adjust_delta_exceptions);
  COPY_PREP(set_default_cvs_values);

  *prep = buf;
  *prep_len = buf_new_len;

  return FT_Err_Ok;
}