Imported Upstream version 1.7.6
[platform/upstream/harfbuzz.git] / src / hb-ot-glyf-table.hh
1 /*
2  * Copyright © 2015  Google, Inc.
3  *
4  *  This is part of HarfBuzz, a text shaping 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  * Google Author(s): Behdad Esfahbod
25  */
26
27 #ifndef HB_OT_GLYF_TABLE_HH
28 #define HB_OT_GLYF_TABLE_HH
29
30 #include "hb-open-type-private.hh"
31 #include "hb-ot-head-table.hh"
32 #include "hb-subset-glyf.hh"
33 #include "hb-subset-plan.hh"
34 #include "hb-subset-private.hh"
35
36 namespace OT {
37
38
39 /*
40  * loca -- Index to Location
41  */
42
43 #define HB_OT_TAG_loca HB_TAG('l','o','c','a')
44
45
46 struct loca
47 {
48   friend struct glyf;
49
50   static const hb_tag_t tableTag = HB_OT_TAG_loca;
51
52   inline bool sanitize (hb_sanitize_context_t *c) const
53   {
54     TRACE_SANITIZE (this);
55     return_trace (true);
56   }
57
58   protected:
59   HBUINT8               dataX[VAR];             /* Location data. */
60   DEFINE_SIZE_ARRAY (0, dataX);
61 };
62
63
64 /*
65  * glyf -- TrueType Glyph Data
66  */
67
68 #define HB_OT_TAG_glyf HB_TAG('g','l','y','f')
69
70
71 struct glyf
72 {
73   static const hb_tag_t tableTag = HB_OT_TAG_glyf;
74
75   inline bool sanitize (hb_sanitize_context_t *c) const
76   {
77     TRACE_SANITIZE (this);
78     /* We don't check for anything specific here.  The users of the
79      * struct do all the hard work... */
80     return_trace (true);
81   }
82
83   inline bool subset (hb_subset_plan_t *plan) const
84   {
85     hb_blob_t *glyf_prime = nullptr;
86     hb_blob_t *loca_prime = nullptr;
87
88     bool success = true;
89     bool use_short_loca = false;
90     if (hb_subset_glyf_and_loca (plan, &use_short_loca, &glyf_prime, &loca_prime)) {
91       success = success && hb_subset_plan_add_table (plan, HB_OT_TAG_glyf, glyf_prime);
92       success = success && hb_subset_plan_add_table (plan, HB_OT_TAG_loca, loca_prime);
93       success = success && _add_head_and_set_loca_version (plan->source, use_short_loca, plan->dest);
94     } else {
95       success = false;
96     }
97     hb_blob_destroy (loca_prime);
98     hb_blob_destroy (glyf_prime);
99
100     return success;
101   }
102
103   static bool
104   _add_head_and_set_loca_version (hb_face_t *source, bool use_short_loca, hb_face_t *dest)
105   {
106     hb_blob_t *head_blob = OT::Sanitizer<OT::head>().sanitize (hb_face_reference_table (source, HB_OT_TAG_head));
107     hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
108     hb_blob_destroy (head_blob);
109
110     if (unlikely (!head_prime_blob))
111       return false;
112
113     OT::head *head_prime = (OT::head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
114     head_prime->indexToLocFormat.set (use_short_loca ? 0 : 1);
115     bool success = hb_subset_face_add_table (dest, HB_OT_TAG_head, head_prime_blob);
116
117     hb_blob_destroy (head_prime_blob);
118     return success;
119   }
120
121   struct GlyphHeader
122   {
123     HBINT16             numberOfContours;       /* If the number of contours is
124                                                  * greater than or equal to zero,
125                                                  * this is a simple glyph; if negative,
126                                                  * this is a composite glyph. */
127     FWORD               xMin;                   /* Minimum x for coordinate data. */
128     FWORD               yMin;                   /* Minimum y for coordinate data. */
129     FWORD               xMax;                   /* Maximum x for coordinate data. */
130     FWORD               yMax;                   /* Maximum y for coordinate data. */
131
132     DEFINE_SIZE_STATIC (10);
133   };
134
135   struct CompositeGlyphHeader
136   {
137     static const uint16_t ARG_1_AND_2_ARE_WORDS =      0x0001;
138     static const uint16_t ARGS_ARE_XY_VALUES =         0x0002;
139     static const uint16_t ROUND_XY_TO_GRID =           0x0004;
140     static const uint16_t WE_HAVE_A_SCALE =            0x0008;
141     static const uint16_t MORE_COMPONENTS =            0x0020;
142     static const uint16_t WE_HAVE_AN_X_AND_Y_SCALE =   0x0040;
143     static const uint16_t WE_HAVE_A_TWO_BY_TWO =       0x0080;
144     static const uint16_t WE_HAVE_INSTRUCTIONS =       0x0100;
145     static const uint16_t USE_MY_METRICS =             0x0200;
146     static const uint16_t OVERLAP_COMPOUND =           0x0400;
147     static const uint16_t SCALED_COMPONENT_OFFSET =    0x0800;
148     static const uint16_t UNSCALED_COMPONENT_OFFSET =  0x1000;
149
150     HBUINT16 flags;
151     HBUINT16 glyphIndex;
152
153     inline unsigned int get_size (void) const
154     {
155       unsigned int size = min_size;
156       if (flags & ARG_1_AND_2_ARE_WORDS) {
157         // arg1 and 2 are int16
158         size += 4;
159       } else {
160         // arg1 and 2 are int8
161         size += 2;
162       }
163       if (flags & WE_HAVE_A_SCALE) {
164         // One x 16 bit (scale)
165         size += 2;
166       } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
167         // Two x 16 bit (xscale, yscale)
168         size += 4;
169       } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
170         // Four x 16 bit (xscale, scale01, scale10, yscale)
171         size += 8;
172       }
173       return size;
174     }
175
176     struct Iterator
177     {
178       const char *glyph_start;
179       const char *glyph_end;
180       const CompositeGlyphHeader *current;
181
182       inline bool move_to_next ()
183       {
184         if (current->flags & CompositeGlyphHeader::MORE_COMPONENTS)
185         {
186           const CompositeGlyphHeader *possible =
187             &StructAfter<CompositeGlyphHeader, CompositeGlyphHeader> (*current);
188           if (!in_range (possible))
189             return false;
190           current = possible;
191           return true;
192         }
193         return false;
194       }
195
196       inline bool in_range (const CompositeGlyphHeader *composite) const
197       {
198         return (const char *) composite >= glyph_start
199           && ((const char *) composite + CompositeGlyphHeader::min_size) <= glyph_end
200           && ((const char *) composite + composite->get_size()) <= glyph_end;
201       }
202     };
203
204     static inline bool get_iterator (const char * glyph_data,
205                                      unsigned int length,
206                                      CompositeGlyphHeader::Iterator *iterator /* OUT */)
207     {
208       if (length < GlyphHeader::static_size)
209         return false; /* Empty glyph; zero extents. */
210
211       const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyph_data, 0);
212       if (glyph_header.numberOfContours < 0)
213       {
214         const CompositeGlyphHeader *possible =
215           &StructAfter<CompositeGlyphHeader, GlyphHeader> (glyph_header);
216
217         iterator->glyph_start = glyph_data;
218         iterator->glyph_end = (const char *) glyph_data + length;
219         if (!iterator->in_range (possible))
220           return false;
221         iterator->current = possible;
222         return true;
223       }
224
225       return false;
226     }
227
228     DEFINE_SIZE_MIN (4);
229   };
230
231   struct accelerator_t
232   {
233     inline void init (hb_face_t *face)
234     {
235       hb_blob_t *head_blob = Sanitizer<head>().sanitize (face->reference_table (HB_OT_TAG_head));
236       const head *head_table = Sanitizer<head>::lock_instance (head_blob);
237       if ((unsigned int) head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0)
238       {
239         /* Unknown format.  Leave num_glyphs=0, that takes care of disabling us. */
240         hb_blob_destroy (head_blob);
241         return;
242       }
243       short_offset = 0 == head_table->indexToLocFormat;
244       hb_blob_destroy (head_blob);
245
246       loca_blob = Sanitizer<loca>().sanitize (face->reference_table (HB_OT_TAG_loca));
247       loca_table = Sanitizer<loca>::lock_instance (loca_blob);
248       glyf_blob = Sanitizer<glyf>().sanitize (face->reference_table (HB_OT_TAG_glyf));
249       glyf_table = Sanitizer<glyf>::lock_instance (glyf_blob);
250
251       num_glyphs = MAX (1u, hb_blob_get_length (loca_blob) / (short_offset ? 2 : 4)) - 1;
252       glyf_len = hb_blob_get_length (glyf_blob);
253     }
254
255     inline void fini (void)
256     {
257       hb_blob_destroy (loca_blob);
258       hb_blob_destroy (glyf_blob);
259     }
260
261     /*
262      * Returns true if the referenced glyph is a valid glyph and a composite glyph.
263      * If true is returned a pointer to the composite glyph will be written into
264      * composite.
265      */
266     inline bool get_composite (hb_codepoint_t glyph,
267                                CompositeGlyphHeader::Iterator *composite /* OUT */) const
268     {
269       unsigned int start_offset, end_offset;
270       if (!get_offsets (glyph, &start_offset, &end_offset))
271         return false; /* glyph not found */
272
273       return CompositeGlyphHeader::get_iterator ((const char*) this->glyf_table + start_offset,
274                                                  end_offset - start_offset,
275                                                  composite);
276     }
277
278     /* based on FontTools _g_l_y_f.py::trim */
279     inline bool remove_padding(unsigned int start_offset,
280                                unsigned int *end_offset) const
281     {
282       static const int FLAG_X_SHORT = 0x02;
283       static const int FLAG_Y_SHORT = 0x04;
284       static const int FLAG_REPEAT = 0x08;
285       static const int FLAG_X_SAME = 0x10;
286       static const int FLAG_Y_SAME = 0x20;
287
288       if (*end_offset - start_offset < GlyphHeader::static_size)
289         return true;
290
291       const char *glyph = ((const char *) glyf_table) + start_offset;
292       const char * const glyph_end = glyph + (*end_offset - start_offset);
293       const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyph, 0);
294       int16_t num_contours = (int16_t) glyph_header.numberOfContours;
295
296       if (num_contours < 0)
297         /* Trimming for composites not implemented.
298          * If removing hints it falls out of that. */
299         return true;
300       else if (num_contours > 0)
301       {
302         /* simple glyph w/contours, possibly trimmable */
303         glyph += GlyphHeader::static_size + 2 * num_contours;
304
305         if (unlikely (glyph + 2 >= glyph_end)) return false;
306         uint16_t nCoordinates = (uint16_t) StructAtOffset<HBUINT16>(glyph - 2, 0) + 1;
307         uint16_t nInstructions = (uint16_t) StructAtOffset<HBUINT16>(glyph, 0);
308
309         glyph += 2 + nInstructions;
310         if (unlikely (glyph + 2 >= glyph_end)) return false;
311
312         unsigned int coordBytes = 0;
313         unsigned int coordsWithFlags = 0;
314         while (glyph < glyph_end)
315         {
316           uint8_t flag = (uint8_t) *glyph;
317           glyph++;
318
319           unsigned int repeat = 1;
320           if (flag & FLAG_REPEAT)
321           {
322             if (glyph >= glyph_end)
323             {
324               DEBUG_MSG(SUBSET, nullptr, "Bad flag");
325               return false;
326             }
327             repeat = ((uint8_t) *glyph) + 1;
328             glyph++;
329           }
330
331           unsigned int xBytes, yBytes;
332           xBytes = yBytes = 0;
333           if (flag & FLAG_X_SHORT)
334             xBytes = 1;
335           else if ((flag & FLAG_X_SAME) == 0)
336             xBytes = 2;
337
338           if (flag & FLAG_Y_SHORT)
339             yBytes = 1;
340           else if ((flag & FLAG_Y_SAME) == 0)
341             yBytes = 2;
342
343           coordBytes += (xBytes + yBytes) * repeat;
344           coordsWithFlags += repeat;
345           if (coordsWithFlags >= nCoordinates)
346             break;
347         }
348
349         if (coordsWithFlags != nCoordinates)
350         {
351           DEBUG_MSG(SUBSET, nullptr, "Expect %d coords to have flags, got flags for %d", nCoordinates, coordsWithFlags);
352           return false;
353         }
354         glyph += coordBytes;
355
356         if (glyph < glyph_end)
357           *end_offset -= glyph_end - glyph;
358       }
359       return true;
360     }
361
362     inline bool get_offsets (hb_codepoint_t  glyph,
363                              unsigned int   *start_offset /* OUT */,
364                              unsigned int   *end_offset   /* OUT */) const
365     {
366       if (unlikely (glyph >= num_glyphs))
367         return false;
368
369       if (short_offset)
370       {
371         const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataX;
372         *start_offset = 2 * offsets[glyph];
373         *end_offset   = 2 * offsets[glyph + 1];
374       }
375       else
376       {
377         const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataX;
378
379         *start_offset = offsets[glyph];
380         *end_offset   = offsets[glyph + 1];
381       }
382
383       if (*start_offset > *end_offset || *end_offset > glyf_len)
384         return false;
385
386       return true;
387     }
388
389     inline bool get_instruction_offsets(unsigned int start_offset,
390                                         unsigned int end_offset,
391                                         unsigned int *instruction_start /* OUT */,
392                                         unsigned int *instruction_end /* OUT */) const
393     {
394       if (end_offset - start_offset < GlyphHeader::static_size)
395       {
396         *instruction_start = 0;
397         *instruction_end = 0;
398         return true; /* Empty glyph; no instructions. */
399       }
400       const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table, start_offset);
401       int16_t num_contours = (int16_t) glyph_header.numberOfContours;
402       if (num_contours < 0)
403       {
404         CompositeGlyphHeader::Iterator composite_it;
405         if (unlikely (!CompositeGlyphHeader::get_iterator (
406             (const char*) this->glyf_table + start_offset,
407              end_offset - start_offset, &composite_it))) return false;
408         const CompositeGlyphHeader *last;
409         do {
410           last = composite_it.current;
411         } while (composite_it.move_to_next());
412
413         if ( (uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS)
414           *instruction_start = ((char *) last - (char *) glyf_table->dataX) + last->get_size();
415         else
416           *instruction_start = end_offset;
417         *instruction_end = end_offset;
418         if (unlikely (*instruction_start > *instruction_end))
419         {
420           DEBUG_MSG(SUBSET, nullptr, "Invalid instruction offset, %d is outside [%d, %d]", *instruction_start, start_offset, end_offset);
421           return false;
422         }
423       }
424       else
425       {
426         unsigned int instruction_length_offset = start_offset + GlyphHeader::static_size + 2 * num_contours;
427         const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (glyf_table, instruction_length_offset);
428         *instruction_start = instruction_length_offset + 2;
429         *instruction_end = *instruction_start + (uint16_t) instruction_length;
430       }
431       return true;
432     }
433
434     inline bool get_extents (hb_codepoint_t glyph,
435                              hb_glyph_extents_t *extents) const
436     {
437       unsigned int start_offset, end_offset;
438       if (!get_offsets (glyph, &start_offset, &end_offset))
439         return false;
440
441       if (end_offset - start_offset < GlyphHeader::static_size)
442         return true; /* Empty glyph; zero extents. */
443
444       const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table, start_offset);
445
446       extents->x_bearing = MIN (glyph_header.xMin, glyph_header.xMax);
447       extents->y_bearing = MAX (glyph_header.yMin, glyph_header.yMax);
448       extents->width     = MAX (glyph_header.xMin, glyph_header.xMax) - extents->x_bearing;
449       extents->height    = MIN (glyph_header.yMin, glyph_header.yMax) - extents->y_bearing;
450
451       return true;
452     }
453
454     private:
455     bool short_offset;
456     unsigned int num_glyphs;
457     const loca *loca_table;
458     const glyf *glyf_table;
459     hb_blob_t *loca_blob;
460     hb_blob_t *glyf_blob;
461     unsigned int glyf_len;
462   };
463
464   protected:
465   HBUINT8               dataX[VAR];             /* Glyphs data. */
466
467   DEFINE_SIZE_ARRAY (0, dataX);
468 };
469
470 } /* namespace OT */
471
472
473 #endif /* HB_OT_GLYF_TABLE_HH */