1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 // This file is available under and governed by the GNU General Public 26 // License version 2 only, as published by the Free Software Foundation. 27 // However, the following notice accompanied the original version of this 28 // file: 29 // 30 /* 31 * Copyright © 2009,2010 Red Hat, Inc. 32 * Copyright © 2010,2011,2012,2013 Google, Inc. 33 * 34 * This is part of HarfBuzz, a text shaping library. 35 * 36 * Permission is hereby granted, without written agreement and without 37 * license or royalty fees, to use, copy, modify, and distribute this 38 * software and its documentation for any purpose, provided that the 39 * above copyright notice and the following two paragraphs appear in 40 * all copies of this software. 41 * 42 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 43 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 44 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 45 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 46 * DAMAGE. 47 * 48 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 49 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 50 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 51 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 52 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 53 * 54 * Red Hat Author(s): Behdad Esfahbod 55 * Google Author(s): Behdad Esfahbod 56 */ 57 58 #ifndef HB_OT_MAP_PRIVATE_HH 59 #define HB_OT_MAP_PRIVATE_HH 60 61 #include "hb-buffer-private.hh" 62 63 64 struct hb_ot_shape_plan_t; 65 66 static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS}; 67 68 struct hb_ot_map_t 69 { 70 friend struct hb_ot_map_builder_t; 71 72 public: 73 74 struct feature_map_t { 75 hb_tag_t tag; /* should be first for our bsearch to work */ 76 unsigned int index[2]; /* GSUB/GPOS */ 77 unsigned int stage[2]; /* GSUB/GPOS */ 78 unsigned int shift; 79 hb_mask_t mask; 80 hb_mask_t _1_mask; /* mask for value=1, for quick access */ 81 unsigned int needs_fallback : 1; 82 unsigned int auto_zwj : 1; 83 84 static int cmp (const feature_map_t *a, const feature_map_t *b) 85 { return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0; } 86 }; 87 88 struct lookup_map_t { 89 unsigned short index; 90 unsigned short auto_zwj : 1; 91 hb_mask_t mask; 92 93 static int cmp (const lookup_map_t *a, const lookup_map_t *b) 94 { return a->index < b->index ? -1 : a->index > b->index ? 1 : 0; } 95 }; 96 97 typedef void (*pause_func_t) (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer); 98 99 struct stage_map_t { 100 unsigned int last_lookup; /* Cumulative */ 101 pause_func_t pause_func; 102 }; 103 104 105 hb_ot_map_t (void) { memset (this, 0, sizeof (*this)); } 106 107 inline hb_mask_t get_global_mask (void) const { return global_mask; } 108 109 inline hb_mask_t get_mask (hb_tag_t feature_tag, unsigned int *shift = NULL) const { 110 const feature_map_t *map = features.bsearch (&feature_tag); 111 if (shift) *shift = map ? map->shift : 0; 112 return map ? map->mask : 0; 113 } 114 115 inline bool needs_fallback (hb_tag_t feature_tag) const { 116 const feature_map_t *map = features.bsearch (&feature_tag); 117 return map ? map->needs_fallback : false; 118 } 119 120 inline hb_mask_t get_1_mask (hb_tag_t feature_tag) const { 121 const feature_map_t *map = features.bsearch (&feature_tag); 122 return map ? map->_1_mask : 0; 123 } 124 125 inline unsigned int get_feature_index (unsigned int table_index, hb_tag_t feature_tag) const { 126 const feature_map_t *map = features.bsearch (&feature_tag); 127 return map ? map->index[table_index] : HB_OT_LAYOUT_NO_FEATURE_INDEX; 128 } 129 130 inline unsigned int get_feature_stage (unsigned int table_index, hb_tag_t feature_tag) const { 131 const feature_map_t *map = features.bsearch (&feature_tag); 132 return map ? map->stage[table_index] : (unsigned int) -1; 133 } 134 135 inline void get_stage_lookups (unsigned int table_index, unsigned int stage, 136 const struct lookup_map_t **plookups, unsigned int *lookup_count) const { 137 if (unlikely (stage == (unsigned int) -1)) { 138 *plookups = NULL; 139 *lookup_count = 0; 140 return; 141 } 142 assert (stage <= stages[table_index].len); 143 unsigned int start = stage ? stages[table_index][stage - 1].last_lookup : 0; 144 unsigned int end = stage < stages[table_index].len ? stages[table_index][stage].last_lookup : lookups[table_index].len; 145 *plookups = &lookups[table_index][start]; 146 *lookup_count = end - start; 147 } 148 149 HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const; 150 template <typename Proxy> 151 HB_INTERNAL inline void apply (const Proxy &proxy, 152 const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const; 153 HB_INTERNAL void substitute (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const; 154 HB_INTERNAL void position (const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const; 155 156 inline void finish (void) { 157 features.finish (); 158 for (unsigned int table_index = 0; table_index < 2; table_index++) 159 { 160 lookups[table_index].finish (); 161 stages[table_index].finish (); 162 } 163 } 164 165 public: 166 hb_tag_t chosen_script[2]; 167 bool found_script[2]; 168 169 private: 170 171 HB_INTERNAL void add_lookups (hb_face_t *face, 172 unsigned int table_index, 173 unsigned int feature_index, 174 hb_mask_t mask, 175 bool auto_zwj); 176 177 hb_mask_t global_mask; 178 179 hb_prealloced_array_t<feature_map_t, 8> features; 180 hb_prealloced_array_t<lookup_map_t, 32> lookups[2]; /* GSUB/GPOS */ 181 hb_prealloced_array_t<stage_map_t, 4> stages[2]; /* GSUB/GPOS */ 182 }; 183 184 enum hb_ot_map_feature_flags_t { 185 F_NONE = 0x0000u, 186 F_GLOBAL = 0x0001u, /* Feature applies to all characters; results in no mask allocated for it. */ 187 F_HAS_FALLBACK = 0x0002u, /* Has fallback implementation, so include mask bit even if feature not found. */ 188 F_MANUAL_ZWJ = 0x0004u, /* Don't skip over ZWJ when matching. */ 189 F_GLOBAL_SEARCH = 0x0008u /* If feature not found in LangSys, look for it in global feature list and pick one. */ 190 }; 191 /* Macro version for where const is desired. */ 192 #define F_COMBINE(l,r) (hb_ot_map_feature_flags_t ((unsigned int) (l) | (unsigned int) (r))) 193 static inline hb_ot_map_feature_flags_t 194 operator | (hb_ot_map_feature_flags_t l, hb_ot_map_feature_flags_t r) 195 { return hb_ot_map_feature_flags_t ((unsigned int) l | (unsigned int) r); } 196 static inline hb_ot_map_feature_flags_t 197 operator & (hb_ot_map_feature_flags_t l, hb_ot_map_feature_flags_t r) 198 { return hb_ot_map_feature_flags_t ((unsigned int) l & (unsigned int) r); } 199 static inline hb_ot_map_feature_flags_t 200 operator ~ (hb_ot_map_feature_flags_t r) 201 { return hb_ot_map_feature_flags_t (~(unsigned int) r); } 202 static inline hb_ot_map_feature_flags_t& 203 operator |= (hb_ot_map_feature_flags_t &l, hb_ot_map_feature_flags_t r) 204 { l = l | r; return l; } 205 static inline hb_ot_map_feature_flags_t& 206 operator &= (hb_ot_map_feature_flags_t& l, hb_ot_map_feature_flags_t r) 207 { l = l & r; return l; } 208 209 210 struct hb_ot_map_builder_t 211 { 212 public: 213 214 HB_INTERNAL hb_ot_map_builder_t (hb_face_t *face_, 215 const hb_segment_properties_t *props_); 216 217 HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value, 218 hb_ot_map_feature_flags_t flags); 219 220 inline void add_global_bool_feature (hb_tag_t tag) 221 { add_feature (tag, 1, F_GLOBAL); } 222 223 inline void add_gsub_pause (hb_ot_map_t::pause_func_t pause_func) 224 { add_pause (0, pause_func); } 225 inline void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func) 226 { add_pause (1, pause_func); } 227 228 HB_INTERNAL void compile (struct hb_ot_map_t &m); 229 230 inline void finish (void) { 231 feature_infos.finish (); 232 for (unsigned int table_index = 0; table_index < 2; table_index++) 233 { 234 stages[table_index].finish (); 235 } 236 } 237 238 private: 239 240 struct feature_info_t { 241 hb_tag_t tag; 242 unsigned int seq; /* sequence#, used for stable sorting only */ 243 unsigned int max_value; 244 hb_ot_map_feature_flags_t flags; 245 unsigned int default_value; /* for non-global features, what should the unset glyphs take */ 246 unsigned int stage[2]; /* GSUB/GPOS */ 247 248 static int cmp (const feature_info_t *a, const feature_info_t *b) 249 { return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : (a->seq < b->seq ? -1 : 1); } 250 }; 251 252 struct stage_info_t { 253 unsigned int index; 254 hb_ot_map_t::pause_func_t pause_func; 255 }; 256 257 HB_INTERNAL void add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func); 258 259 public: 260 261 hb_face_t *face; 262 hb_segment_properties_t props; 263 264 hb_tag_t chosen_script[2]; 265 bool found_script[2]; 266 unsigned int script_index[2], language_index[2]; 267 268 private: 269 270 unsigned int current_stage[2]; /* GSUB/GPOS */ 271 hb_prealloced_array_t<feature_info_t, 32> feature_infos; 272 hb_prealloced_array_t<stage_info_t, 8> stages[2]; /* GSUB/GPOS */ 273 }; 274 275 276 277 #endif /* HB_OT_MAP_PRIVATE_HH */