blob: d745c1143171c68bd5ea273860645e1011fb9976 [file] [log] [blame]
Ebrahim Byagowif9042382018-11-08 19:17:02 +03301/*
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
41namespace AAT {
42
43using namespace OT;
44
45
46struct ActionSubrecordHeader
47{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +033048 bool sanitize (hb_sanitize_context_t *c) const
Ebrahim Byagowif9042382018-11-08 19:17:02 +033049 {
50 TRACE_SANITIZE (this);
51 return_trace (likely (c->check_struct (this)));
52 }
53
Ebrahim Byagowice114d62019-12-31 15:53:02 +033054 HBUINT16 actionClass; /* The JustClass value associated with this
Ebrahim Byagowif9042382018-11-08 19:17:02 +033055 * ActionSubrecord. */
Ebrahim Byagowice114d62019-12-31 15:53:02 +033056 HBUINT16 actionType; /* The type of postcompensation action. */
57 HBUINT16 actionLength; /* Length of this ActionSubrecord record, which
Ebrahim Byagowif9042382018-11-08 19:17:02 +033058 * must be a multiple of 4. */
59 public:
60 DEFINE_SIZE_STATIC (6);
61};
62
63struct DecompositionAction
64{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +033065 bool sanitize (hb_sanitize_context_t *c) const
Ebrahim Byagowif9042382018-11-08 19:17:02 +033066 {
67 TRACE_SANITIZE (this);
68 return_trace (likely (c->check_struct (this)));
69 }
70
71 ActionSubrecordHeader
72 header;
Ebrahim Byagowice114d62019-12-31 15:53:02 +033073 HBFixed lowerLimit; /* If the distance factor is less than this value,
Ebrahim Byagowif9042382018-11-08 19:17:02 +033074 * then the ligature is decomposed. */
Ebrahim Byagowice114d62019-12-31 15:53:02 +033075 HBFixed upperLimit; /* If the distance factor is greater than this value,
Ebrahim Byagowif9042382018-11-08 19:17:02 +033076 * then the ligature is decomposed. */
Ebrahim Byagowice114d62019-12-31 15:53:02 +033077 HBUINT16 order; /* Numerical order in which this ligature will
Ebrahim Byagowif9042382018-11-08 19:17:02 +033078 * 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. */
Behdad Esfahbod5639e252021-03-31 16:04:43 -060082 Array16Of<HBUINT16>
Ebrahim Byagowif9042382018-11-08 19:17:02 +033083 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
92struct UnconditionalAddGlyphAction
93{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +033094 bool sanitize (hb_sanitize_context_t *c) const
Ebrahim Byagowif9042382018-11-08 19:17:02 +033095 {
96 TRACE_SANITIZE (this);
97 return_trace (c->check_struct (this));
98 }
99
100 protected:
101 ActionSubrecordHeader
102 header;
Behdad Esfahbodc852b862021-09-19 16:30:12 -0400103 HBGlyphID16 addGlyph; /* Glyph that should be added if the distance factor
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330104 * is growing. */
105
106 public:
107 DEFINE_SIZE_STATIC (8);
108};
109
110struct ConditionalAddGlyphAction
111{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330112 bool sanitize (hb_sanitize_context_t *c) const
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330113 {
114 TRACE_SANITIZE (this);
115 return_trace (likely (c->check_struct (this)));
116 }
117
118 protected:
119 ActionSubrecordHeader
120 header;
Ebrahim Byagowice114d62019-12-31 15:53:02 +0330121 HBFixed substThreshold; /* Distance growth factor (in ems) at which
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330122 * this glyph is replaced and the growth factor
123 * recalculated. */
Behdad Esfahbodc852b862021-09-19 16:30:12 -0400124 HBGlyphID16 addGlyph; /* Glyph to be added as kashida. If this value is
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330125 * 0xFFFF, no extra glyph will be added. Note that
126 * generally when a glyph is added, justification
127 * will need to be redone. */
Behdad Esfahbodc852b862021-09-19 16:30:12 -0400128 HBGlyphID16 substGlyph; /* Glyph to be substituted for this glyph if the
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330129 * growth factor equals or exceeds the value of
130 * substThreshold. */
131 public:
132 DEFINE_SIZE_STATIC (14);
133};
134
135struct DuctileGlyphAction
136{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330137 bool sanitize (hb_sanitize_context_t *c) const
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330138 {
139 TRACE_SANITIZE (this);
140 return_trace (likely (c->check_struct (this)));
141 }
142
143 protected:
144 ActionSubrecordHeader
145 header;
Ebrahim Byagowice114d62019-12-31 15:53:02 +0330146 HBUINT32 variationAxis; /* The 4-byte tag identifying the ductile axis.
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330147 * This would normally be 0x64756374 ('duct'),
148 * but you may use any axis the font contains. */
Ebrahim Byagowice114d62019-12-31 15:53:02 +0330149 HBFixed minimumLimit; /* The lowest value for the ductility axis tha
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330150 * still yields an acceptable appearance. Normally
151 * this will be 1.0. */
Ebrahim Byagowice114d62019-12-31 15:53:02 +0330152 HBFixed noStretchValue; /* This is the default value that corresponds to
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330153 * no change in appearance. Normally, this will
154 * be 1.0. */
Ebrahim Byagowice114d62019-12-31 15:53:02 +0330155 HBFixed maximumLimit; /* The highest value for the ductility axis that
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330156 * still yields an acceptable appearance. */
157 public:
158 DEFINE_SIZE_STATIC (22);
159};
160
161struct RepeatedAddGlyphAction
162{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330163 bool sanitize (hb_sanitize_context_t *c) const
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330164 {
165 TRACE_SANITIZE (this);
166 return_trace (likely (c->check_struct (this)));
167 }
168
169 protected:
170 ActionSubrecordHeader
171 header;
Ebrahim Byagowice114d62019-12-31 15:53:02 +0330172 HBUINT16 flags; /* Currently unused; set to 0. */
Behdad Esfahbodc852b862021-09-19 16:30:12 -0400173 HBGlyphID16 glyph; /* Glyph that should be added if the distance factor
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330174 * is growing. */
175 public:
176 DEFINE_SIZE_STATIC (10);
177};
178
179struct ActionSubrecord
180{
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330181 unsigned int get_length () const { return u.header.actionLength; }
Ebrahim Byagowib9895072018-11-08 20:48:54 +0330182
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330183 bool sanitize (hb_sanitize_context_t *c) const
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330184 {
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
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330201 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
216struct PostcompensationActionChain
217{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330218 bool sanitize (hb_sanitize_context_t *c) const
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330219 {
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
242struct 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:
Ebrahim Byagowi08428a12020-04-24 23:45:17 +0430274 HBFixed beforeGrowLimit;/* The ratio by which the advance width of the
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330275 * glyph is permitted to grow on the left or top side. */
Ebrahim Byagowi08428a12020-04-24 23:45:17 +0430276 HBFixed beforeShrinkLimit;
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330277 /* The ratio by which the advance width of the
278 * glyph is permitted to shrink on the left or top side. */
Ebrahim Byagowi08428a12020-04-24 23:45:17 +0430279 HBFixed afterGrowLimit; /* The ratio by which the advance width of the glyph
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330280 * is permitted to shrink on the left or top side. */
Ebrahim Byagowi08428a12020-04-24 23:45:17 +0430281 HBFixed afterShrinkLimit;
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330282 /* 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
292struct WidthDeltaPair
293{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330294 bool sanitize (hb_sanitize_context_t *c) const
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330295 {
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};
Ebrahim Byagowi92588782019-04-30 13:05:10 -0700312
Behdad Esfahbod2520a822021-03-31 15:34:26 -0600313typedef OT::Array32Of<WidthDeltaPair> WidthDeltaCluster;
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330314
315struct 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
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330331 bool sanitize (hb_sanitize_context_t *c, const void *base) const
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330332 {
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
348struct JustificationHeader
349{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330350 bool sanitize (hb_sanitize_context_t *c, const void *base) const
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330351 {
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:
Behdad Esfahbodad28f972021-03-31 12:49:14 -0600361 Offset16To<JustificationCategory>
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330362 justClassTable; /* Offset to the justification category state table. */
Behdad Esfahbodad28f972021-03-31 12:49:14 -0600363 Offset16To<WidthDeltaCluster>
Ebrahim Byagowice114d62019-12-31 15:53:02 +0330364 wdcTable; /* Offset from start of justification table to start
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330365 * of the subtable containing the width delta factors
366 * for the glyphs in your font.
367 *
368 * The width delta clusters table. */
Behdad Esfahbodad28f972021-03-31 12:49:14 -0600369 Offset16To<PostcompensationActionChain>
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330370 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. */
Behdad Esfahbodad28f972021-03-31 12:49:14 -0600374 Lookup<Offset16To<WidthDeltaCluster>>
Ebrahim Byagowice114d62019-12-31 15:53:02 +0330375 lookupTable; /* Lookup table associating glyphs with width delta
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330376 * 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
383struct just
384{
Behdad Esfahbodef006542019-01-22 12:08:57 +0100385 static constexpr hb_tag_t tableTag = HB_AAT_TAG_just;
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330386
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330387 bool sanitize (hb_sanitize_context_t *c) const
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330388 {
389 TRACE_SANITIZE (this);
390
Ebrahim Byagowib9895072018-11-08 20:48:54 +0330391 return_trace (likely (c->check_struct (this) &&
392 version.major == 1 &&
393 horizData.sanitize (c, this, this) &&
394 vertData.sanitize (c, this, this)));
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330395 }
396
397 protected:
398 FixedVersion<>version; /* Version of the justification table
399 * (0x00010000u for version 1.0). */
Ebrahim Byagowice114d62019-12-31 15:53:02 +0330400 HBUINT16 format; /* Format of the justification table (set to 0). */
Behdad Esfahbodad28f972021-03-31 12:49:14 -0600401 Offset16To<JustificationHeader>
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330402 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. */
Behdad Esfahbodad28f972021-03-31 12:49:14 -0600407 Offset16To<JustificationHeader>
Ebrahim Byagowif9042382018-11-08 19:17:02 +0330408 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 */