0bf9bd29126232709d53a57455a6ab60cfced31c
[platform/upstream/harfbuzz.git] / src / hb-aat-layout-just-table.hh
1 /*
2  * Copyright © 2018  Ebrahim Byagowi
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
25 #ifndef HB_AAT_LAYOUT_JUST_TABLE_HH
26 #define HB_AAT_LAYOUT_JUST_TABLE_HH
27
28 #include "hb-aat-layout-common.hh"
29 #include "hb-ot-layout.hh"
30 #include "hb-open-type.hh"
31
32 #include "hb-aat-layout-morx-table.hh"
33
34 /*
35  * just -- Justification
36  * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6just.html
37  */
38 #define HB_AAT_TAG_just HB_TAG('j','u','s','t')
39
40
41 namespace AAT {
42
43 using namespace OT;
44
45
46 struct ActionSubrecordHeader
47 {
48   bool sanitize (hb_sanitize_context_t *c) const
49   {
50     TRACE_SANITIZE (this);
51     return_trace (likely (c->check_struct (this)));
52   }
53
54   HBUINT16      actionClass;    /* The JustClass value associated with this
55                                  * ActionSubrecord. */
56   HBUINT16      actionType;     /* The type of postcompensation action. */
57   HBUINT16      actionLength;   /* Length of this ActionSubrecord record, which
58                                  * must be a multiple of 4. */
59   public:
60   DEFINE_SIZE_STATIC (6);
61 };
62
63 struct DecompositionAction
64 {
65   bool sanitize (hb_sanitize_context_t *c) const
66   {
67     TRACE_SANITIZE (this);
68     return_trace (likely (c->check_struct (this)));
69   }
70
71   ActionSubrecordHeader
72                 header;
73   HBFixed       lowerLimit;     /* If the distance factor is less than this value,
74                                  * then the ligature is decomposed. */
75   HBFixed       upperLimit;     /* If the distance factor is greater than this value,
76                                  * then the ligature is decomposed. */
77   HBUINT16      order;          /* Numerical order in which this ligature will
78                                  * be decomposed; you may want infrequent ligatures
79                                  * to decompose before more frequent ones. The ligatures
80                                  * on the line of text will decompose in increasing
81                                  * value of this field. */
82   Array16Of<HBUINT16>
83                 decomposedglyphs;
84                                 /* Number of 16-bit glyph indexes that follow;
85                                  * the ligature will be decomposed into these glyphs.
86                                  *
87                                  * Array of decomposed glyphs. */
88   public:
89   DEFINE_SIZE_ARRAY (18, decomposedglyphs);
90 };
91
92 struct UnconditionalAddGlyphAction
93 {
94   bool sanitize (hb_sanitize_context_t *c) const
95   {
96     TRACE_SANITIZE (this);
97     return_trace (c->check_struct (this));
98   }
99
100   protected:
101   ActionSubrecordHeader
102                 header;
103   HBGlyphID16   addGlyph;       /* Glyph that should be added if the distance factor
104                                  * is growing. */
105
106   public:
107   DEFINE_SIZE_STATIC (8);
108 };
109
110 struct ConditionalAddGlyphAction
111 {
112   bool sanitize (hb_sanitize_context_t *c) const
113   {
114     TRACE_SANITIZE (this);
115     return_trace (likely (c->check_struct (this)));
116   }
117
118   protected:
119   ActionSubrecordHeader
120                 header;
121   HBFixed       substThreshold; /* Distance growth factor (in ems) at which
122                                  * this glyph is replaced and the growth factor
123                                  * recalculated. */
124   HBGlyphID16   addGlyph;       /* Glyph to be added as kashida. If this value is
125                                  * 0xFFFF, no extra glyph will be added. Note that
126                                  * generally when a glyph is added, justification
127                                  * will need to be redone. */
128   HBGlyphID16   substGlyph;     /* Glyph to be substituted for this glyph if the
129                                  * growth factor equals or exceeds the value of
130                                  * substThreshold. */
131   public:
132   DEFINE_SIZE_STATIC (14);
133 };
134
135 struct DuctileGlyphAction
136 {
137   bool sanitize (hb_sanitize_context_t *c) const
138   {
139     TRACE_SANITIZE (this);
140     return_trace (likely (c->check_struct (this)));
141   }
142
143   protected:
144   ActionSubrecordHeader
145                 header;
146   HBUINT32      variationAxis;  /* The 4-byte tag identifying the ductile axis.
147                                  * This would normally be 0x64756374 ('duct'),
148                                  * but you may use any axis the font contains. */
149   HBFixed       minimumLimit;   /* The lowest value for the ductility axis that
150                                  * still yields an acceptable appearance. Normally
151                                  * this will be 1.0. */
152   HBFixed       noStretchValue; /* This is the default value that corresponds to
153                                  * no change in appearance. Normally, this will
154                                  * be 1.0. */
155   HBFixed       maximumLimit;   /* The highest value for the ductility axis that
156                                  * still yields an acceptable appearance. */
157   public:
158   DEFINE_SIZE_STATIC (22);
159 };
160
161 struct RepeatedAddGlyphAction
162 {
163   bool sanitize (hb_sanitize_context_t *c) const
164   {
165     TRACE_SANITIZE (this);
166     return_trace (likely (c->check_struct (this)));
167   }
168
169   protected:
170   ActionSubrecordHeader
171                 header;
172   HBUINT16      flags;          /* Currently unused; set to 0. */
173   HBGlyphID16   glyph;          /* Glyph that should be added if the distance factor
174                                  * is growing. */
175   public:
176   DEFINE_SIZE_STATIC (10);
177 };
178
179 struct ActionSubrecord
180 {
181   unsigned int get_length () const { return u.header.actionLength; }
182
183   bool sanitize (hb_sanitize_context_t *c) const
184   {
185     TRACE_SANITIZE (this);
186     if (unlikely (!c->check_struct (this)))
187       return_trace (false);
188
189     switch (u.header.actionType)
190     {
191     case 0:  return_trace (u.decompositionAction.sanitize (c));
192     case 1:  return_trace (u.unconditionalAddGlyphAction.sanitize (c));
193     case 2:  return_trace (u.conditionalAddGlyphAction.sanitize (c));
194     // case 3: return_trace (u.stretchGlyphAction.sanitize (c));
195     case 4:  return_trace (u.decompositionAction.sanitize (c));
196     case 5:  return_trace (u.decompositionAction.sanitize (c));
197     default: return_trace (true);
198     }
199   }
200
201   protected:
202   union {
203   ActionSubrecordHeader         header;
204   DecompositionAction           decompositionAction;
205   UnconditionalAddGlyphAction   unconditionalAddGlyphAction;
206   ConditionalAddGlyphAction     conditionalAddGlyphAction;
207   /* StretchGlyphAction stretchGlyphAction; -- Not supported by CoreText */
208   DuctileGlyphAction            ductileGlyphAction;
209   RepeatedAddGlyphAction        repeatedAddGlyphAction;
210   } u;                          /* Data. The format of this data depends on
211                                  * the value of the actionType field. */
212   public:
213   DEFINE_SIZE_UNION (6, header);
214 };
215
216 struct PostcompensationActionChain
217 {
218   bool sanitize (hb_sanitize_context_t *c) const
219   {
220     TRACE_SANITIZE (this);
221     if (unlikely (!c->check_struct (this)))
222       return_trace (false);
223
224     unsigned int offset = min_size;
225     for (unsigned int i = 0; i < count; i++)
226     {
227       const ActionSubrecord& subrecord = StructAtOffset<ActionSubrecord> (this, offset);
228       if (unlikely (!subrecord.sanitize (c))) return_trace (false);
229       offset += subrecord.get_length ();
230     }
231
232     return_trace (true);
233   }
234
235   protected:
236   HBUINT32      count;
237
238   public:
239   DEFINE_SIZE_STATIC (4);
240 };
241
242 struct JustWidthDeltaEntry
243 {
244   enum Flags
245   {
246     Reserved1           =0xE000,/* Reserved. You should set these bits to zero. */
247     UnlimiteGap         =0x1000,/* The glyph can take unlimited gap. When this
248                                  * glyph participates in the justification process,
249                                  * it and any other glyphs on the line having this
250                                  * bit set absorb all the remaining gap. */
251     Reserved2           =0x0FF0,/* Reserved. You should set these bits to zero. */
252     Priority            =0x000F /* The justification priority of the glyph. */
253   };
254
255   enum Priority
256   {
257     Kashida             = 0,    /* Kashida priority. This is the highest priority
258                                  * during justification. */
259     Whitespace          = 1,    /* Whitespace priority. Any whitespace glyphs (as
260                                  * identified in the glyph properties table) will
261                                  * get this priority. */
262     InterCharacter      = 2,    /* Inter-character priority. Give this to any
263                                  * remaining glyphs. */
264     NullPriority        = 3     /* Null priority. You should set this priority for
265                                  * glyphs that only participate in justification
266                                  * after the above priorities. Normally all glyphs
267                                  * have one of the previous three values. If you
268                                  * don't want a glyph to participate in justification,
269                                  * and you don't want to set its factors to zero,
270                                  * you may instead assign it to the null priority. */
271   };
272
273   protected:
274   HBFixed       beforeGrowLimit;/* The ratio by which the advance width of the
275                                  * glyph is permitted to grow on the left or top side. */
276   HBFixed       beforeShrinkLimit;
277                                 /* The ratio by which the advance width of the
278                                  * glyph is permitted to shrink on the left or top side. */
279   HBFixed       afterGrowLimit; /* The ratio by which the advance width of the glyph
280                                  * is permitted to shrink on the left or top side. */
281   HBFixed       afterShrinkLimit;
282                                 /* The ratio by which the advance width of the glyph
283                                  * is at most permitted to shrink on the right or
284                                  * bottom side. */
285   HBUINT16      growFlags;      /* Flags controlling the grow case. */
286   HBUINT16      shrinkFlags;    /* Flags controlling the shrink case. */
287
288   public:
289   DEFINE_SIZE_STATIC (20);
290 };
291
292 struct WidthDeltaPair
293 {
294   bool sanitize (hb_sanitize_context_t *c) const
295   {
296     TRACE_SANITIZE (this);
297     return_trace (likely (c->check_struct (this)));
298   }
299
300   protected:
301   HBUINT32      justClass;      /* The justification category associated
302                                  * with the wdRecord field. Only 7 bits of
303                                  * this field are used. (The other bits are
304                                  * used as padding to guarantee longword
305                                  * alignment of the following record). */
306   JustWidthDeltaEntry
307                 wdRecord;       /* The actual width delta record. */
308
309   public:
310   DEFINE_SIZE_STATIC (24);
311 };
312
313 typedef OT::Array32Of<WidthDeltaPair> WidthDeltaCluster;
314
315 struct JustificationCategory
316 {
317   typedef void EntryData;
318
319   enum Flags
320   {
321     SetMark             =0x8000,/* If set, make the current glyph the marked
322                                  * glyph. */
323     DontAdvance         =0x4000,/* If set, don't advance to the next glyph before
324                                  * going to the new state. */
325     MarkCategory        =0x3F80,/* The justification category for the marked
326                                  * glyph if nonzero. */
327     CurrentCategory     =0x007F /* The justification category for the current
328                                  * glyph if nonzero. */
329   };
330
331   bool sanitize (hb_sanitize_context_t *c, const void *base) const
332   {
333     TRACE_SANITIZE (this);
334     return_trace (likely (c->check_struct (this) &&
335                           morphHeader.sanitize (c) &&
336                           stHeader.sanitize (c)));
337   }
338
339   protected:
340   ChainSubtable<ObsoleteTypes>
341                 morphHeader;    /* Metamorphosis-style subtable header. */
342   StateTable<ObsoleteTypes, EntryData>
343                 stHeader;       /* The justification insertion state table header */
344   public:
345   DEFINE_SIZE_STATIC (30);
346 };
347
348 struct JustificationHeader
349 {
350   bool sanitize (hb_sanitize_context_t *c, const void *base) const
351   {
352     TRACE_SANITIZE (this);
353     return_trace (likely (c->check_struct (this) &&
354                           justClassTable.sanitize (c, base, base) &&
355                           wdcTable.sanitize (c, base) &&
356                           pcTable.sanitize (c, base) &&
357                           lookupTable.sanitize (c, base)));
358   }
359
360   protected:
361   Offset16To<JustificationCategory>
362                 justClassTable; /* Offset to the justification category state table. */
363   Offset16To<WidthDeltaCluster>
364                 wdcTable;       /* Offset from start of justification table to start
365                                  * of the subtable containing the width delta factors
366                                  * for the glyphs in your font.
367                                  *
368                                  * The width delta clusters table. */
369   Offset16To<PostcompensationActionChain>
370                 pcTable;        /* Offset from start of justification table to start
371                                  * of postcompensation subtable (set to zero if none).
372                                  *
373                                  * The postcompensation subtable, if present in the font. */
374   Lookup<Offset16To<WidthDeltaCluster>>
375                 lookupTable;    /* Lookup table associating glyphs with width delta
376                                  * clusters. See the description of Width Delta Clusters
377                                  * table for details on how to interpret the lookup values. */
378
379   public:
380   DEFINE_SIZE_MIN (8);
381 };
382
383 struct just
384 {
385   static constexpr hb_tag_t tableTag = HB_AAT_TAG_just;
386
387   bool sanitize (hb_sanitize_context_t *c) const
388   {
389     TRACE_SANITIZE (this);
390
391     return_trace (likely (c->check_struct (this) &&
392                           version.major == 1 &&
393                           horizData.sanitize (c, this, this) &&
394                           vertData.sanitize (c, this, this)));
395   }
396
397   protected:
398   FixedVersion<>version;        /* Version of the justification table
399                                  * (0x00010000u for version 1.0). */
400   HBUINT16      format;         /* Format of the justification table (set to 0). */
401   Offset16To<JustificationHeader>
402                 horizData;      /* Byte offset from the start of the justification table
403                                  * to the header for tables that contain justification
404                                  * information for horizontal text.
405                                  * If you are not including this information,
406                                  * store 0. */
407   Offset16To<JustificationHeader>
408                 vertData;       /* ditto, vertical */
409
410   public:
411   DEFINE_SIZE_STATIC (10);
412 };
413
414 } /* namespace AAT */
415
416
417 #endif /* HB_AAT_LAYOUT_JUST_TABLE_HH */