Line data Source code
1 : /*
2 : * Copyright © 1998-2004 David Turner and Werner Lemberg
3 : * Copyright © 2004,2007,2009,2010 Red Hat, Inc.
4 : * Copyright © 2011,2012 Google, Inc.
5 : *
6 : * This is part of HarfBuzz, a text shaping library.
7 : *
8 : * Permission is hereby granted, without written agreement and without
9 : * license or royalty fees, to use, copy, modify, and distribute this
10 : * software and its documentation for any purpose, provided that the
11 : * above copyright notice and the following two paragraphs appear in
12 : * all copies of this software.
13 : *
14 : * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
15 : * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
16 : * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
17 : * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18 : * DAMAGE.
19 : *
20 : * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
21 : * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
22 : * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
23 : * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
24 : * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25 : *
26 : * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
27 : * Google Author(s): Behdad Esfahbod
28 : */
29 :
30 : #ifndef HB_BUFFER_PRIVATE_HH
31 : #define HB_BUFFER_PRIVATE_HH
32 :
33 : #include "hb-private.hh"
34 : #include "hb-object-private.hh"
35 : #include "hb-unicode-private.hh"
36 :
37 :
38 : #ifndef HB_BUFFER_MAX_EXPANSION_FACTOR
39 : #define HB_BUFFER_MAX_EXPANSION_FACTOR 32
40 : #endif
41 : #ifndef HB_BUFFER_MAX_LEN_MIN
42 : #define HB_BUFFER_MAX_LEN_MIN 8192
43 : #endif
44 : #ifndef HB_BUFFER_MAX_LEN_DEFAULT
45 : #define HB_BUFFER_MAX_LEN_DEFAULT 0x3FFFFFFF /* Shaping more than a billion chars? Let us know! */
46 : #endif
47 :
48 : ASSERT_STATIC (sizeof (hb_glyph_info_t) == 20);
49 : ASSERT_STATIC (sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t));
50 :
51 34 : HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
52 : HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
53 :
54 : enum hb_buffer_scratch_flags_t {
55 : HB_BUFFER_SCRATCH_FLAG_DEFAULT = 0x00000000u,
56 : HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII = 0x00000001u,
57 : HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u,
58 : HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u,
59 : HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u,
60 : /* Reserved for complex shapers' internal use. */
61 : HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u,
62 : HB_BUFFER_SCRATCH_FLAG_COMPLEX1 = 0x02000000u,
63 : HB_BUFFER_SCRATCH_FLAG_COMPLEX2 = 0x04000000u,
64 : HB_BUFFER_SCRATCH_FLAG_COMPLEX3 = 0x08000000u,
65 : };
66 208 : HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
67 :
68 :
69 : /*
70 : * hb_buffer_t
71 : */
72 :
73 : struct hb_buffer_t {
74 : hb_object_header_t header;
75 : ASSERT_POD ();
76 :
77 : /* Information about how the text in the buffer should be treated */
78 : hb_unicode_funcs_t *unicode; /* Unicode functions */
79 : hb_buffer_flags_t flags; /* BOT / EOT / etc. */
80 : hb_buffer_cluster_level_t cluster_level;
81 : hb_codepoint_t replacement; /* U+FFFD or something else. */
82 : hb_buffer_scratch_flags_t scratch_flags; /* Have space-flallback, etc. */
83 : unsigned int max_len; /* Maximum allowed len. */
84 :
85 : /* Buffer contents */
86 : hb_buffer_content_type_t content_type;
87 : hb_segment_properties_t props; /* Script, language, direction */
88 :
89 : bool in_error; /* Allocation failed */
90 : bool have_output; /* Whether we have an output buffer going on */
91 : bool have_positions; /* Whether we have positions */
92 :
93 : unsigned int idx; /* Cursor into ->info and ->pos arrays */
94 : unsigned int len; /* Length of ->info and ->pos arrays */
95 : unsigned int out_len; /* Length of ->out array if have_output */
96 :
97 : unsigned int allocated; /* Length of allocated arrays */
98 : hb_glyph_info_t *info;
99 : hb_glyph_info_t *out_info;
100 : hb_glyph_position_t *pos;
101 :
102 9153 : inline hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
103 : inline hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; }
104 :
105 185 : inline hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; }
106 : inline hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; }
107 :
108 231 : inline hb_glyph_info_t &prev (void) { return out_info[out_len ? out_len - 1 : 0]; }
109 : inline hb_glyph_info_t prev (void) const { return out_info[out_len ? out_len - 1 : 0]; }
110 :
111 36 : inline bool has_separate_output (void) const { return info != out_info; }
112 :
113 : unsigned int serial;
114 :
115 : /* Text before / after the main buffer contents.
116 : * Always in Unicode, and ordered outward.
117 : * Index 0 is for "pre-context", 1 for "post-context". */
118 : static const unsigned int CONTEXT_LENGTH = 5;
119 : hb_codepoint_t context[2][CONTEXT_LENGTH];
120 : unsigned int context_len[2];
121 :
122 : /* Debugging API */
123 : hb_buffer_message_func_t message_func;
124 : void *message_data;
125 : hb_destroy_func_t message_destroy;
126 :
127 : /* Internal debugging. */
128 : /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */
129 : #ifndef HB_NDEBUG
130 : uint8_t allocated_var_bits;
131 : #endif
132 170 : inline void allocate_var (unsigned int start, unsigned int count)
133 : {
134 : #ifndef HB_NDEBUG
135 170 : unsigned int end = start + count;
136 170 : assert (end <= 8);
137 170 : unsigned int bits = (1u<<end) - (1u<<start);
138 170 : assert (0 == (allocated_var_bits & bits));
139 170 : allocated_var_bits |= bits;
140 : #endif
141 170 : }
142 170 : inline void deallocate_var (unsigned int start, unsigned int count)
143 : {
144 : #ifndef HB_NDEBUG
145 170 : unsigned int end = start + count;
146 170 : assert (end <= 8);
147 170 : unsigned int bits = (1u<<end) - (1u<<start);
148 170 : assert (bits == (allocated_var_bits & bits));
149 170 : allocated_var_bits &= ~bits;
150 : #endif
151 170 : }
152 238 : inline void assert_var (unsigned int start, unsigned int count)
153 : {
154 : #ifndef HB_NDEBUG
155 238 : unsigned int end = start + count;
156 238 : assert (end <= 8);
157 238 : unsigned int bits = (1u<<end) - (1u<<start);
158 238 : assert (bits == (allocated_var_bits & bits));
159 : #endif
160 238 : }
161 104 : inline void deallocate_var_all (void)
162 : {
163 : #ifndef HB_NDEBUG
164 104 : allocated_var_bits = 0;
165 : #endif
166 104 : }
167 :
168 :
169 : /* Methods */
170 :
171 : HB_INTERNAL void reset (void);
172 : HB_INTERNAL void clear (void);
173 :
174 1 : inline unsigned int backtrack_len (void) const
175 1 : { return have_output? out_len : idx; }
176 0 : inline unsigned int lookahead_len (void) const
177 0 : { return len - idx; }
178 0 : inline unsigned int next_serial (void) { return serial++; }
179 :
180 : HB_INTERNAL void add (hb_codepoint_t codepoint,
181 : unsigned int cluster);
182 : HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info);
183 :
184 : HB_INTERNAL void reverse_range (unsigned int start, unsigned int end);
185 : HB_INTERNAL void reverse (void);
186 : HB_INTERNAL void reverse_clusters (void);
187 : HB_INTERNAL void guess_segment_properties (void);
188 :
189 : HB_INTERNAL void swap_buffers (void);
190 : HB_INTERNAL void remove_output (void);
191 : HB_INTERNAL void clear_output (void);
192 : HB_INTERNAL void clear_positions (void);
193 :
194 : HB_INTERNAL void replace_glyphs (unsigned int num_in,
195 : unsigned int num_out,
196 : const hb_codepoint_t *glyph_data);
197 :
198 : HB_INTERNAL void replace_glyph (hb_codepoint_t glyph_index);
199 : /* Makes a copy of the glyph at idx to output and replace glyph_index */
200 : HB_INTERNAL void output_glyph (hb_codepoint_t glyph_index);
201 : HB_INTERNAL void output_info (const hb_glyph_info_t &glyph_info);
202 : /* Copies glyph at idx to output but doesn't advance idx */
203 : HB_INTERNAL void copy_glyph (void);
204 : HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */
205 : /* Copies glyph at idx to output and advance idx.
206 : * If there's no output, just advance idx. */
207 : inline void
208 4315 : next_glyph (void)
209 : {
210 4315 : if (have_output)
211 : {
212 2277 : if (unlikely (out_info != info || out_len != idx)) {
213 0 : if (unlikely (!make_room_for (1, 1))) return;
214 0 : out_info[out_len] = info[idx];
215 : }
216 2277 : out_len++;
217 : }
218 :
219 4315 : idx++;
220 : }
221 :
222 : /* Advance idx without copying to output. */
223 0 : inline void skip_glyph (void) { idx++; }
224 :
225 34 : inline void reset_masks (hb_mask_t mask)
226 : {
227 299 : for (unsigned int j = 0; j < len; j++)
228 265 : info[j].mask = mask;
229 34 : }
230 : inline void add_masks (hb_mask_t mask)
231 : {
232 : for (unsigned int j = 0; j < len; j++)
233 : info[j].mask |= mask;
234 : }
235 : HB_INTERNAL void set_masks (hb_mask_t value,
236 : hb_mask_t mask,
237 : unsigned int cluster_start,
238 : unsigned int cluster_end);
239 :
240 0 : HB_INTERNAL void merge_clusters (unsigned int start,
241 : unsigned int end)
242 : {
243 0 : if (end - start < 2)
244 0 : return;
245 0 : merge_clusters_impl (start, end);
246 : }
247 : HB_INTERNAL void merge_clusters_impl (unsigned int start,
248 : unsigned int end);
249 : HB_INTERNAL void merge_out_clusters (unsigned int start,
250 : unsigned int end);
251 : /* Merge clusters for deleting current glyph, and skip it. */
252 : HB_INTERNAL void delete_glyph (void);
253 :
254 : /* Internal methods */
255 : HB_INTERNAL bool enlarge (unsigned int size);
256 :
257 299 : inline bool ensure (unsigned int size)
258 299 : { return likely (!size || size < allocated) ? true : enlarge (size); }
259 :
260 : inline bool ensure_inplace (unsigned int size)
261 : { return likely (!size || size < allocated); }
262 :
263 : HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out);
264 : HB_INTERNAL bool shift_forward (unsigned int count);
265 :
266 : typedef long scratch_buffer_t;
267 : HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size);
268 :
269 34 : inline void clear_context (unsigned int side) { context_len[side] = 0; }
270 :
271 : HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *));
272 :
273 988 : inline bool messaging (void) { return unlikely (message_func); }
274 988 : inline bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4)
275 : {
276 988 : if (!messaging ())
277 988 : return true;
278 : va_list ap;
279 0 : va_start (ap, fmt);
280 0 : bool ret = message_impl (font, fmt, ap);
281 0 : va_end (ap);
282 0 : return ret;
283 : }
284 : HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0);
285 : };
286 :
287 :
288 : #define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
289 : b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
290 : sizeof (b->info[0].var))
291 : #define HB_BUFFER_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var ())
292 : #define HB_BUFFER_DEALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
293 : #define HB_BUFFER_ASSERT_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, assert_var, var ())
294 :
295 :
296 : #endif /* HB_BUFFER_PRIVATE_HH */
|