hb-ot-layout-private.hh revision 469524692bd0a258b28e63294c984e677a9c2477
1/*
2 * Copyright © 2007,2008,2009  Red Hat, Inc.
3 * Copyright © 2012,2013  Google, Inc.
4 *
5 *  This is part of HarfBuzz, a text shaping library.
6 *
7 * Permission is hereby granted, without written agreement and without
8 * license or royalty fees, to use, copy, modify, and distribute this
9 * software and its documentation for any purpose, provided that the
10 * above copyright notice and the following two paragraphs appear in
11 * all copies of this software.
12 *
13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17 * DAMAGE.
18 *
19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 *
25 * Red Hat Author(s): Behdad Esfahbod
26 * Google Author(s): Behdad Esfahbod
27 */
28
29#ifndef HB_OT_LAYOUT_PRIVATE_HH
30#define HB_OT_LAYOUT_PRIVATE_HH
31
32#include "hb-private.hh"
33
34#include "hb-ot-layout.h"
35
36#include "hb-font-private.hh"
37#include "hb-buffer-private.hh"
38#include "hb-set-private.hh"
39
40
41/* buffer var allocations, used during the entire shaping process */
42#define unicode_props0()	var2.u8[0]
43#define unicode_props1()	var2.u8[1]
44
45/* buffer var allocations, used during the GSUB/GPOS processing */
46#define glyph_props()		var1.u16[0] /* GDEF glyph properties */
47#define lig_props()		var1.u8[2] /* GSUB/GPOS ligature tracking */
48#define syllable()		var1.u8[3] /* GSUB/GPOS shaping boundaries */
49
50
51enum {
52  MASK0_ZWJ       = 0x20u,
53  MASK0_ZWNJ      = 0x40u,
54  MASK0_IGNORABLE = 0x80u,
55  MASK0_GEN_CAT   = 0x1Fu
56};
57
58inline void
59_hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_unicode_funcs_t *unicode)
60{
61  info->unicode_props0() = ((unsigned int) unicode->general_category (info->codepoint)) |
62			   (unicode->is_default_ignorable (info->codepoint) ? MASK0_IGNORABLE : 0) |
63			   (info->codepoint == 0x200C ? MASK0_ZWNJ : 0) |
64			   (info->codepoint == 0x200D ? MASK0_ZWJ : 0);
65  info->unicode_props1() = unicode->modified_combining_class (info->codepoint);
66}
67
68inline void
69_hb_glyph_info_set_general_category (hb_glyph_info_t *info, hb_unicode_general_category_t gen_cat)
70{
71  info->unicode_props0() = (unsigned int) gen_cat | ((info->unicode_props0()) & ~MASK0_GEN_CAT);
72}
73
74inline hb_unicode_general_category_t
75_hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
76{
77  return (hb_unicode_general_category_t) (info->unicode_props0() & MASK0_GEN_CAT);
78}
79
80inline void
81_hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info, unsigned int modified_class)
82{
83  info->unicode_props1() = modified_class;
84}
85
86inline unsigned int
87_hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
88{
89  return info->unicode_props1();
90}
91
92inline hb_bool_t
93_hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
94{
95  return !!(info->unicode_props0() & MASK0_IGNORABLE);
96}
97
98inline hb_bool_t
99_hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
100{
101  return !!(info->unicode_props0() & MASK0_ZWNJ);
102}
103
104inline hb_bool_t
105_hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
106{
107  return !!(info->unicode_props0() & MASK0_ZWJ);
108}
109
110inline void
111_hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
112{
113  info->unicode_props0() ^= MASK0_ZWNJ | MASK0_ZWJ;
114}
115
116
117/*
118 * GDEF
119 */
120
121typedef enum {
122  /* One bit available here...          = 0x01u */
123
124  /* The following three match LookupFlags::Ignore* numbers. */
125  HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH	= 0x02u,
126  HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE	= 0x04u,
127  HB_OT_LAYOUT_GLYPH_PROPS_MARK		= 0x08u
128
129} hb_ot_layout_glyph_class_mask_t;
130
131
132/*
133 * GSUB/GPOS
134 */
135
136/* lig_id / lig_comp
137 *
138 * When a ligature is formed:
139 *
140 *   - The ligature glyph and any marks in between all the same newly allocated
141 *     lig_id,
142 *   - The ligature glyph will get lig_num_comps set to the number of components
143 *   - The marks get lig_comp > 0, reflecting which component of the ligature
144 *     they were applied to.
145 *   - This is used in GPOS to attach marks to the right component of a ligature
146 *     in MarkLigPos.
147 *
148 * When a multiple-substitution is done:
149 *
150 *   - All resulting glyphs will have lig_id = 0,
151 *   - The resulting glyphs will have lig_comp = 0, 1, 2, ... respectively.
152 *   - This is used in GPOS to attach marks to the first component of a
153 *     multiple substitution in MarkBasePos.
154 *
155 * The numbers are also used in GPOS to do mark-to-mark positioning only
156 * to marks that belong to the same component of a ligature in MarkMarPos.
157 */
158#define IS_LIG_BASE 0x10
159static inline void
160set_lig_props_for_ligature (hb_glyph_info_t &info, unsigned int lig_id, unsigned int lig_num_comps)
161{
162  info.lig_props() = (lig_id << 5) | IS_LIG_BASE | (lig_num_comps & 0x0F);
163}
164static inline void
165set_lig_props_for_mark (hb_glyph_info_t &info, unsigned int lig_id, unsigned int lig_comp)
166{
167  info.lig_props() = (lig_id << 5) | (lig_comp & 0x0F);
168}
169static inline void
170set_lig_props_for_component (hb_glyph_info_t &info, unsigned int comp)
171{
172  set_lig_props_for_mark (info, 0, comp);
173}
174
175static inline unsigned int
176get_lig_id (const hb_glyph_info_t &info)
177{
178  return info.lig_props() >> 5;
179}
180static inline bool
181is_a_ligature (const hb_glyph_info_t &info)
182{
183  return !!(info.lig_props() & IS_LIG_BASE);
184}
185static inline unsigned int
186get_lig_comp (const hb_glyph_info_t &info)
187{
188  if (is_a_ligature (info))
189    return 0;
190  else
191    return info.lig_props() & 0x0F;
192}
193static inline unsigned int
194get_lig_num_comps (const hb_glyph_info_t &info)
195{
196  if ((info.glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE) && is_a_ligature (info))
197    return info.lig_props() & 0x0F;
198  else
199    return 1;
200}
201
202static inline uint8_t allocate_lig_id (hb_buffer_t *buffer) {
203  uint8_t lig_id = buffer->next_serial () & 0x07;
204  if (unlikely (!lig_id))
205    lig_id = allocate_lig_id (buffer); /* in case of overflow */
206  return lig_id;
207}
208
209
210HB_INTERNAL hb_bool_t
211hb_ot_layout_lookup_would_substitute_fast (hb_face_t            *face,
212					   unsigned int          lookup_index,
213					   const hb_codepoint_t *glyphs,
214					   unsigned int          glyphs_length,
215					   hb_bool_t             zero_context);
216
217
218/* Should be called before all the substitute_lookup's are done. */
219HB_INTERNAL void
220hb_ot_layout_substitute_start (hb_font_t    *font,
221			       hb_buffer_t  *buffer);
222
223
224struct hb_ot_layout_lookup_accelerator_t;
225
226namespace OT {
227  struct hb_apply_context_t;
228  struct SubstLookup;
229}
230
231HB_INTERNAL void
232hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
233				const OT::SubstLookup &lookup,
234				const hb_ot_layout_lookup_accelerator_t &accel);
235
236
237/* Should be called after all the substitute_lookup's are done */
238HB_INTERNAL void
239hb_ot_layout_substitute_finish (hb_font_t    *font,
240				hb_buffer_t  *buffer);
241
242
243/* Should be called before all the position_lookup's are done.  Resets positions to zero. */
244HB_INTERNAL void
245hb_ot_layout_position_start (hb_font_t    *font,
246			     hb_buffer_t  *buffer);
247
248/* Should be called after all the position_lookup's are done */
249HB_INTERNAL void
250hb_ot_layout_position_finish (hb_font_t    *font,
251			      hb_buffer_t  *buffer);
252
253
254
255/*
256 * hb_ot_layout_t
257 */
258
259namespace OT {
260  struct GDEF;
261  struct GSUB;
262  struct GPOS;
263}
264
265struct hb_ot_layout_lookup_accelerator_t
266{
267  template <typename TLookup>
268  inline void init (const TLookup &lookup)
269  {
270    digest.init ();
271    lookup.add_coverage (&digest);
272  }
273
274  template <typename TLookup>
275  inline void fini (const TLookup &lookup)
276  {
277  }
278
279  hb_set_digest_t digest;
280};
281
282struct hb_ot_layout_t
283{
284  hb_blob_t *gdef_blob;
285  hb_blob_t *gsub_blob;
286  hb_blob_t *gpos_blob;
287
288  const struct OT::GDEF *gdef;
289  const struct OT::GSUB *gsub;
290  const struct OT::GPOS *gpos;
291
292  unsigned int gsub_lookup_count;
293  unsigned int gpos_lookup_count;
294
295  hb_ot_layout_lookup_accelerator_t *gsub_accels;
296  hb_ot_layout_lookup_accelerator_t *gpos_accels;
297};
298
299
300HB_INTERNAL hb_ot_layout_t *
301_hb_ot_layout_create (hb_face_t *face);
302
303HB_INTERNAL void
304_hb_ot_layout_destroy (hb_ot_layout_t *layout);
305
306
307#define hb_ot_layout_from_face(face) ((hb_ot_layout_t *) face->shaper_data.ot)
308
309
310#endif /* HB_OT_LAYOUT_PRIVATE_HH */
311