hb-ot-layout.cc revision 590d55cbb9e21ef74dfd88eee51fd0a763958cd2
1/* 2 * Copyright (C) 2007,2008 Red Hat, Inc. 3 * 4 * This is part of HarfBuzz, an OpenType Layout engine library. 5 * 6 * Permission is hereby granted, without written agreement and without 7 * license or royalty fees, to use, copy, modify, and distribute this 8 * software and its documentation for any purpose, provided that the 9 * above copyright notice and the following two paragraphs appear in 10 * all copies of this software. 11 * 12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16 * DAMAGE. 17 * 18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23 * 24 * Red Hat Author(s): Behdad Esfahbod 25 */ 26 27#define HB_OT_LAYOUT_CC 28 29#include "hb-ot-layout.h" 30#include "hb-ot-layout-private.h" 31 32#include "hb-ot-layout-open-private.h" 33#include "hb-ot-layout-gdef-private.h" 34#include "hb-ot-layout-gsub-private.h" 35 36#include <stdlib.h> 37#include <string.h> 38 39 40struct _HB_OT_Layout { 41 const GDEF *gdef; 42 const GSUB *gsub; 43//const GPOS *gpos; 44 45 struct { 46 unsigned char *klasses; 47 unsigned int len; 48 } new_gdef; 49 50}; 51 52HB_OT_Layout * 53hb_ot_layout_create (const char *font_data, 54 int face_index) 55{ 56 HB_OT_Layout *layout = (HB_OT_Layout *) calloc (1, sizeof (HB_OT_Layout)); 57 58 const OpenTypeFontFile &font = OpenTypeFontFile::get_for_data (font_data); 59 const OpenTypeFontFace &face = font.get_face (face_index); 60 61 layout->gdef = &GDEF::get_for_data (font.get_table_data (face.get_table (GDEF::Tag))); 62 layout->gsub = &GSUB::get_for_data (font.get_table_data (face.get_table (GSUB::Tag))); 63//layout->gpos = &GPOS::get_for_data (font.get_table_data (face.get_table (GPOS::Tag))); 64 65 return layout; 66} 67 68void 69hb_ot_layout_destroy (HB_OT_Layout *layout) 70{ 71 free (layout); 72} 73 74/* 75 * GDEF 76 */ 77 78hb_bool_t 79hb_ot_layout_has_font_glyph_classes (HB_OT_Layout *layout) 80{ 81 return layout->gdef->has_glyph_classes (); 82} 83 84static hb_bool_t 85_hb_ot_layout_has_new_glyph_classes (HB_OT_Layout *layout) 86{ 87 return layout->new_gdef.len > 0; 88} 89 90static hb_ot_layout_glyph_properties_t 91_hb_ot_layout_get_glyph_properties (HB_OT_Layout *layout, 92 hb_glyph_t glyph) 93{ 94 hb_ot_layout_class_t klass; 95 96 /* TODO old harfbuzz doesn't always parse mark attachments as it says it was 97 * introduced without a version bump, so it may not be safe */ 98 klass = layout->gdef->get_mark_attachment_type (glyph); 99 if (klass) 100 return klass << 8; 101 102 klass = layout->gdef->get_glyph_class (glyph); 103 104 if (!klass && glyph < layout->new_gdef.len) 105 klass = layout->new_gdef.klasses[glyph]; 106 107 switch (klass) { 108 default: 109 case GDEF::UnclassifiedGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED; 110 case GDEF::BaseGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH; 111 case GDEF::LigatureGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE; 112 case GDEF::MarkGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_MARK; 113 case GDEF::ComponentGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT; 114 } 115} 116 117#if 0 118static bool 119_hb_ot_layout_check_glyph_properties (HB_OT_Layout *layout, 120 HB_GlyphItem gitem, 121 HB_UShort flags, 122 HB_UShort* property) 123{ 124 HB_Error error; 125 126 if ( gdef ) 127 { 128 HB_UShort basic_glyph_class; 129 HB_UShort desired_attachment_class; 130 131 if ( gitem->gproperties == HB_GLYPH_PROPERTIES_UNKNOWN ) 132 { 133 error = HB_GDEF_Get_Glyph_Property( gdef, gitem->gindex, &gitem->gproperties ); 134 if ( error ) 135 return error; 136 } 137 138 *property = gitem->gproperties; 139 140 /* If the glyph was found in the MarkAttachmentClass table, 141 * then that class value is the high byte of the result, 142 * otherwise the low byte contains the basic type of the glyph 143 * as defined by the GlyphClassDef table. 144 */ 145 if ( *property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) 146 basic_glyph_class = HB_GDEF_MARK; 147 else 148 basic_glyph_class = *property; 149 150 /* Return Not_Covered, if, for example, basic_glyph_class 151 * is HB_GDEF_LIGATURE and LookFlags includes HB_LOOKUP_FLAG_IGNORE_LIGATURES 152 */ 153 if ( flags & basic_glyph_class ) 154 return HB_Err_Not_Covered; 155 156 /* The high byte of LookupFlags has the meaning 157 * "ignore marks of attachment type different than 158 * the attachment type specified." 159 */ 160 desired_attachment_class = flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS; 161 if ( desired_attachment_class ) 162 { 163 if ( basic_glyph_class == HB_GDEF_MARK && 164 *property != desired_attachment_class ) 165 return HB_Err_Not_Covered; 166 } 167 } else { 168 *property = 0; 169 } 170 171 return HB_Err_Ok; 172} 173#endif 174 175 176hb_ot_layout_glyph_class_t 177hb_ot_layout_get_glyph_class (HB_OT_Layout *layout, 178 hb_glyph_t glyph) 179{ 180 hb_ot_layout_glyph_properties_t properties; 181 hb_ot_layout_class_t klass; 182 183 properties = _hb_ot_layout_get_glyph_properties (layout, glyph); 184 185 if (properties & 0xFF) 186 return HB_OT_LAYOUT_GLYPH_CLASS_MARK; 187 188 return (hb_ot_layout_glyph_class_t) properties; 189} 190 191void 192hb_ot_layout_set_glyph_class (HB_OT_Layout *layout, 193 hb_glyph_t glyph, 194 hb_ot_layout_glyph_class_t klass) 195{ 196 /* TODO optimize this, similar to old harfbuzz code for example */ 197 198 hb_ot_layout_class_t gdef_klass; 199 int len = layout->new_gdef.len; 200 201 if (glyph >= len) { 202 int new_len; 203 unsigned char *new_klasses; 204 205 new_len = len == 0 ? 120 : 2 * len; 206 if (new_len > 65535) 207 new_len = 65535; 208 new_klasses = (unsigned char *) realloc (layout->new_gdef.klasses, new_len * sizeof (unsigned char)); 209 210 if (G_UNLIKELY (!new_klasses)) 211 return; 212 213 memset (new_klasses + len, 0, new_len - len); 214 215 layout->new_gdef.klasses = new_klasses; 216 layout->new_gdef.len = new_len; 217 } 218 219 switch (klass) { 220 default: 221 case HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED: gdef_klass = GDEF::UnclassifiedGlyph; break; 222 case HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH: gdef_klass = GDEF::BaseGlyph; break; 223 case HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE: gdef_klass = GDEF::LigatureGlyph; break; 224 case HB_OT_LAYOUT_GLYPH_CLASS_MARK: gdef_klass = GDEF::MarkGlyph; break; 225 case HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT: gdef_klass = GDEF::ComponentGlyph; break; 226 } 227 228 layout->new_gdef.klasses[glyph] = gdef_klass; 229 return; 230} 231 232void 233hb_ot_layout_build_glyph_classes (HB_OT_Layout *layout, 234 uint16_t num_total_glyphs, 235 hb_glyph_t *glyphs, 236 unsigned char *klasses, 237 uint16_t count) 238{ 239 int i; 240 241 if (G_UNLIKELY (!count || !glyphs || !klasses)) 242 return; 243 244 if (layout->new_gdef.len == 0) { 245 layout->new_gdef.klasses = (unsigned char *) calloc (num_total_glyphs, sizeof (unsigned char)); 246 layout->new_gdef.len = count; 247 } 248 249 for (i = 0; i < count; i++) 250 hb_ot_layout_set_glyph_class (layout, glyphs[i], (hb_ot_layout_glyph_class_t) klasses[i]); 251} 252