hb-ot-layout.cc 7.0 KB
Newer Older
B
Behdad Esfahbod 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
/*
 * Copyright (C) 2007,2008  Red Hat, Inc.
 *
 *  This is part of HarfBuzz, an OpenType Layout engine library.
 *
 * 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
 */

#define HB_OT_LAYOUT_CC

#include "hb-ot-layout.h"
#include "hb-ot-layout-private.h"

#include "hb-ot-layout-open-private.h"
#include "hb-ot-layout-gdef-private.h"
#include "hb-ot-layout-gsub-private.h"

#include <stdlib.h>
B
Behdad Esfahbod 已提交
37 38
#include <string.h>

B
Behdad Esfahbod 已提交
39

B
Behdad Esfahbod 已提交
40 41 42 43 44 45 46 47 48 49 50 51
struct _HB_OT_Layout {
  const GDEF *gdef;
  const GSUB *gsub;
//const GPOS *gpos;

  struct {
    unsigned char *klasses;
    unsigned int len;
  } new_gdef;

};

B
Behdad Esfahbod 已提交
52 53 54 55 56 57
HB_OT_Layout *
hb_ot_layout_create (const char *font_data,
                     int         face_index)
{
  HB_OT_Layout *layout = (HB_OT_Layout *) calloc (1, sizeof (HB_OT_Layout));

B
Behdad Esfahbod 已提交
58 59
  const OpenTypeFontFile &font = OpenTypeFontFile::get_for_data (font_data);
  const OpenTypeFontFace &face = font.get_face (face_index);
B
Behdad Esfahbod 已提交
60

B
Behdad Esfahbod 已提交
61 62 63
  layout->gdef = &GDEF::get_for_data (font.get_table_data (face.get_table (GDEF::Tag)));
  layout->gsub = &GSUB::get_for_data (font.get_table_data (face.get_table (GSUB::Tag)));
//layout->gpos = &GPOS::get_for_data (font.get_table_data (face.get_table (GPOS::Tag)));
B
Behdad Esfahbod 已提交
64 65 66 67 68 69 70 71 72 73

  return layout;
}

void
hb_ot_layout_destroy (HB_OT_Layout *layout)
{
  free (layout);
}

B
Behdad Esfahbod 已提交
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
/*
 * GDEF
 */

hb_bool_t
hb_ot_layout_has_font_glyph_classes (HB_OT_Layout *layout)
{
  return layout->gdef->has_glyph_classes ();
}

static hb_bool_t
_hb_ot_layout_has_new_glyph_classes (HB_OT_Layout *layout)
{
  return layout->new_gdef.len > 0;
}

B
Behdad Esfahbod 已提交
90
static hb_ot_layout_glyph_properties_t
B
Behdad Esfahbod 已提交
91 92
_hb_ot_layout_get_glyph_properties (HB_OT_Layout *layout,
				    hb_glyph_t    glyph)
B
Behdad Esfahbod 已提交
93
{
B
Behdad Esfahbod 已提交
94 95 96 97 98 99 100 101 102
  hb_ot_layout_class_t klass;

  /* TODO old harfbuzz doesn't always parse mark attachments as it says it was
   * introduced without a version bump, so it may not be safe */
  klass = layout->gdef->get_mark_attachment_type (glyph);
  if (klass)
    return klass << 8;

  klass = layout->gdef->get_glyph_class (glyph);
B
Behdad Esfahbod 已提交
103

B
Behdad Esfahbod 已提交
104 105 106 107 108 109 110 111 112 113 114
  if (!klass && glyph < layout->new_gdef.len)
    klass = layout->new_gdef.klasses[glyph];

  switch (klass) {
  default:
  case GDEF::UnclassifiedGlyph:	return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED;
  case GDEF::BaseGlyph:		return HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH;
  case GDEF::LigatureGlyph:	return HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE;
  case GDEF::MarkGlyph:		return HB_OT_LAYOUT_GLYPH_CLASS_MARK;
  case GDEF::ComponentGlyph:	return HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT;
  }
B
Behdad Esfahbod 已提交
115
}
B
Behdad Esfahbod 已提交
116

B
Behdad Esfahbod 已提交
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
#if 0
static bool
_hb_ot_layout_check_glyph_properties (HB_OT_Layout *layout,
				      HB_GlyphItem  gitem,
				      HB_UShort     flags,
				      HB_UShort*    property)
{
  HB_Error  error;

  if ( gdef )
  {
    HB_UShort basic_glyph_class;
    HB_UShort desired_attachment_class;

    if ( gitem->gproperties == HB_GLYPH_PROPERTIES_UNKNOWN )
    {
      error = HB_GDEF_Get_Glyph_Property( gdef, gitem->gindex, &gitem->gproperties );
      if ( error )
	return error;
    }

    *property = gitem->gproperties;

    /* If the glyph was found in the MarkAttachmentClass table,
     * then that class value is the high byte of the result,
     * otherwise the low byte contains the basic type of the glyph
     * as defined by the GlyphClassDef table.
     */
    if ( *property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS  )
      basic_glyph_class = HB_GDEF_MARK;
    else
      basic_glyph_class = *property;

    /* Return Not_Covered, if, for example, basic_glyph_class
     * is HB_GDEF_LIGATURE and LookFlags includes HB_LOOKUP_FLAG_IGNORE_LIGATURES
     */
    if ( flags & basic_glyph_class )
      return HB_Err_Not_Covered;

    /* The high byte of LookupFlags has the meaning
     * "ignore marks of attachment type different than
     * the attachment type specified."
     */
    desired_attachment_class = flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS;
    if ( desired_attachment_class )
    {
      if ( basic_glyph_class == HB_GDEF_MARK &&
	   *property != desired_attachment_class )
	return HB_Err_Not_Covered;
    }
  } else {
      *property = 0;
  }

  return HB_Err_Ok;
}
#endif


B
Behdad Esfahbod 已提交
176
hb_ot_layout_glyph_class_t
B
Behdad Esfahbod 已提交
177 178
hb_ot_layout_get_glyph_class (HB_OT_Layout *layout,
			      hb_glyph_t    glyph)
B
Behdad Esfahbod 已提交
179
{
B
Behdad Esfahbod 已提交
180 181
  hb_ot_layout_glyph_properties_t properties;
  hb_ot_layout_class_t klass;
B
Behdad Esfahbod 已提交
182

B
Behdad Esfahbod 已提交
183 184 185 186 187 188
  properties = _hb_ot_layout_get_glyph_properties (layout, glyph);

  if (properties & 0xFF)
    return HB_OT_LAYOUT_GLYPH_CLASS_MARK;

  return (hb_ot_layout_glyph_class_t) properties;
B
Behdad Esfahbod 已提交
189 190
}

B
Behdad Esfahbod 已提交
191 192
void
hb_ot_layout_set_glyph_class (HB_OT_Layout               *layout,
B
Behdad Esfahbod 已提交
193
			      hb_glyph_t                  glyph,
B
Behdad Esfahbod 已提交
194 195 196 197 198 199 200 201 202
			      hb_ot_layout_glyph_class_t  klass)
{
  /* TODO optimize this, similar to old harfbuzz code for example */

  hb_ot_layout_class_t gdef_klass;
  int len = layout->new_gdef.len;

  if (glyph >= len) {
    int new_len;
B
Behdad Esfahbod 已提交
203
    unsigned char *new_klasses;
B
Behdad Esfahbod 已提交
204 205 206 207

    new_len = len == 0 ? 120 : 2 * len;
    if (new_len > 65535)
      new_len = 65535;
B
Behdad Esfahbod 已提交
208
    new_klasses = (unsigned char *) realloc (layout->new_gdef.klasses, new_len * sizeof (unsigned char));
B
Behdad Esfahbod 已提交
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230

    if (G_UNLIKELY (!new_klasses))
      return;
      
    memset (new_klasses + len, 0, new_len - len);

    layout->new_gdef.klasses = new_klasses;
    layout->new_gdef.len = new_len;
  }

  switch (klass) {
  default:
  case HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED:	gdef_klass = GDEF::UnclassifiedGlyph;	break;
  case HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH:	gdef_klass = GDEF::BaseGlyph;		break;
  case HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE:	gdef_klass = GDEF::LigatureGlyph;	break;
  case HB_OT_LAYOUT_GLYPH_CLASS_MARK:		gdef_klass = GDEF::MarkGlyph;		break;
  case HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT:	gdef_klass = GDEF::ComponentGlyph;	break;
  }

  layout->new_gdef.klasses[glyph] = gdef_klass;
  return;
}
B
Behdad Esfahbod 已提交
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251

void
hb_ot_layout_build_glyph_classes (HB_OT_Layout  *layout,
				  uint16_t       num_total_glyphs,
				  hb_glyph_t    *glyphs,
				  unsigned char *klasses,
				  uint16_t       count)
{
  int i;

  if (G_UNLIKELY (!count || !glyphs || !klasses))
    return;

  if (layout->new_gdef.len == 0) {
    layout->new_gdef.klasses = (unsigned char *) calloc (num_total_glyphs, sizeof (unsigned char));
    layout->new_gdef.len = count;
  }

  for (i = 0; i < count; i++)
    hb_ot_layout_set_glyph_class (layout, glyphs[i], (hb_ot_layout_glyph_class_t) klasses[i]);
}