Coverage Report

Created: 2024-05-20 07:14

/src/skia/third_party/externals/harfbuzz/src/hb-aat-layout-just-table.hh
Line
Count
Source (jump to first uncovered line)
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
0
  {
50
0
    TRACE_SANITIZE (this);
51
0
    return_trace (c->check_struct (this));
52
0
  }
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
0
  {
67
0
    TRACE_SANITIZE (this);
68
0
    return_trace (c->check_struct (this));
69
0
  }
70
71
  ActionSubrecordHeader
72
    header;
73
  F16DOT16  lowerLimit; /* If the distance factor is less than this value,
74
         * then the ligature is decomposed. */
75
  F16DOT16  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
0
  {
96
0
    TRACE_SANITIZE (this);
97
0
    return_trace (c->check_struct (this));
98
0
  }
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
0
  {
114
0
    TRACE_SANITIZE (this);
115
0
    return_trace (c->check_struct (this));
116
0
  }
117
118
  protected:
119
  ActionSubrecordHeader
120
    header;
121
  F16DOT16  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
0
  {
139
0
    TRACE_SANITIZE (this);
140
0
    return_trace (c->check_struct (this));
141
0
  }
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
  F16DOT16  minimumLimit; /* The lowest value for the ductility axis that
150
         * still yields an acceptable appearance. Normally
151
         * this will be 1.0. */
152
  F16DOT16  noStretchValue; /* This is the default value that corresponds to
153
         * no change in appearance. Normally, this will
154
         * be 1.0. */
155
  F16DOT16  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
0
  {
165
0
    TRACE_SANITIZE (this);
166
0
    return_trace (c->check_struct (this));
167
0
  }
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
0
  unsigned int get_length () const { return u.header.actionLength; }
182
183
  bool sanitize (hb_sanitize_context_t *c) const
184
0
  {
185
0
    TRACE_SANITIZE (this);
186
0
    if (unlikely (!c->check_struct (this)))
187
0
      return_trace (false);
188
0
    hb_barrier ();
189
0
190
0
    switch (u.header.actionType)
191
0
    {
192
0
    case 0:  return_trace (u.decompositionAction.sanitize (c));
193
0
    case 1:  return_trace (u.unconditionalAddGlyphAction.sanitize (c));
194
0
    case 2:  return_trace (u.conditionalAddGlyphAction.sanitize (c));
195
0
    // case 3: return_trace (u.stretchGlyphAction.sanitize (c));
196
0
    case 4:  return_trace (u.decompositionAction.sanitize (c));
197
0
    case 5:  return_trace (u.decompositionAction.sanitize (c));
198
0
    default: return_trace (true);
199
0
    }
200
0
  }
201
202
  protected:
203
  union {
204
  ActionSubrecordHeader   header;
205
  DecompositionAction   decompositionAction;
206
  UnconditionalAddGlyphAction unconditionalAddGlyphAction;
207
  ConditionalAddGlyphAction conditionalAddGlyphAction;
208
  /* StretchGlyphAction stretchGlyphAction; -- Not supported by CoreText */
209
  DuctileGlyphAction    ductileGlyphAction;
210
  RepeatedAddGlyphAction  repeatedAddGlyphAction;
211
  } u;        /* Data. The format of this data depends on
212
         * the value of the actionType field. */
213
  public:
214
  DEFINE_SIZE_UNION (6, header);
215
};
216
217
struct PostcompensationActionChain
218
{
219
  bool sanitize (hb_sanitize_context_t *c) const
220
0
  {
221
0
    TRACE_SANITIZE (this);
222
0
    if (unlikely (!c->check_struct (this)))
223
0
      return_trace (false);
224
0
    hb_barrier ();
225
0
226
0
    unsigned int offset = min_size;
227
0
    for (unsigned int i = 0; i < count; i++)
228
0
    {
229
0
      const ActionSubrecord& subrecord = StructAtOffset<ActionSubrecord> (this, offset);
230
0
      if (unlikely (!subrecord.sanitize (c))) return_trace (false);
231
0
      offset += subrecord.get_length ();
232
0
    }
233
0
234
0
    return_trace (true);
235
0
  }
236
237
  protected:
238
  HBUINT32  count;
239
240
  public:
241
  DEFINE_SIZE_STATIC (4);
242
};
243
244
struct JustWidthDeltaEntry
245
{
246
  enum Flags
247
  {
248
    Reserved1   =0xE000,/* Reserved. You should set these bits to zero. */
249
    UnlimiteGap   =0x1000,/* The glyph can take unlimited gap. When this
250
         * glyph participates in the justification process,
251
         * it and any other glyphs on the line having this
252
         * bit set absorb all the remaining gap. */
253
    Reserved2   =0x0FF0,/* Reserved. You should set these bits to zero. */
254
    Priority    =0x000F /* The justification priority of the glyph. */
255
  };
256
257
  enum Priority
258
  {
259
    Kashida   = 0,  /* Kashida priority. This is the highest priority
260
         * during justification. */
261
    Whitespace    = 1,  /* Whitespace priority. Any whitespace glyphs (as
262
         * identified in the glyph properties table) will
263
         * get this priority. */
264
    InterCharacter  = 2,  /* Inter-character priority. Give this to any
265
         * remaining glyphs. */
266
    NullPriority  = 3 /* Null priority. You should set this priority for
267
         * glyphs that only participate in justification
268
         * after the above priorities. Normally all glyphs
269
         * have one of the previous three values. If you
270
         * don't want a glyph to participate in justification,
271
         * and you don't want to set its factors to zero,
272
         * you may instead assign it to the null priority. */
273
  };
274
275
  protected:
276
  F16DOT16  beforeGrowLimit;/* The ratio by which the advance width of the
277
         * glyph is permitted to grow on the left or top side. */
278
  F16DOT16  beforeShrinkLimit;
279
        /* The ratio by which the advance width of the
280
         * glyph is permitted to shrink on the left or top side. */
281
  F16DOT16  afterGrowLimit; /* The ratio by which the advance width of the glyph
282
         * is permitted to shrink on the left or top side. */
283
  F16DOT16  afterShrinkLimit;
284
        /* The ratio by which the advance width of the glyph
285
         * is at most permitted to shrink on the right or
286
         * bottom side. */
287
  HBUINT16  growFlags;  /* Flags controlling the grow case. */
288
  HBUINT16  shrinkFlags;  /* Flags controlling the shrink case. */
289
290
  public:
291
  DEFINE_SIZE_STATIC (20);
292
};
293
294
struct WidthDeltaPair
295
{
296
  bool sanitize (hb_sanitize_context_t *c) const
297
0
  {
298
0
    TRACE_SANITIZE (this);
299
0
    return_trace (c->check_struct (this));
300
0
  }
301
302
  protected:
303
  HBUINT32  justClass;  /* The justification category associated
304
         * with the wdRecord field. Only 7 bits of
305
         * this field are used. (The other bits are
306
         * used as padding to guarantee longword
307
         * alignment of the following record). */
308
  JustWidthDeltaEntry
309
    wdRecord; /* The actual width delta record. */
310
311
  public:
312
  DEFINE_SIZE_STATIC (24);
313
};
314
315
typedef OT::Array32Of<WidthDeltaPair> WidthDeltaCluster;
316
317
struct JustificationCategory
318
{
319
  typedef void EntryData;
320
321
  enum Flags
322
  {
323
    SetMark   =0x8000,/* If set, make the current glyph the marked
324
         * glyph. */
325
    DontAdvance   =0x4000,/* If set, don't advance to the next glyph before
326
         * going to the new state. */
327
    MarkCategory  =0x3F80,/* The justification category for the marked
328
         * glyph if nonzero. */
329
    CurrentCategory =0x007F /* The justification category for the current
330
         * glyph if nonzero. */
331
  };
332
333
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
334
0
  {
335
0
    TRACE_SANITIZE (this);
336
0
    return_trace (likely (c->check_struct (this) &&
337
0
        morphHeader.sanitize (c) &&
338
0
        stHeader.sanitize (c)));
339
0
  }
340
341
  protected:
342
  ChainSubtable<ObsoleteTypes>
343
    morphHeader;  /* Metamorphosis-style subtable header. */
344
  StateTable<ObsoleteTypes, EntryData>
345
    stHeader; /* The justification insertion state table header */
346
  public:
347
  DEFINE_SIZE_STATIC (30);
348
};
349
350
struct JustificationHeader
351
{
352
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
353
0
  {
354
0
    TRACE_SANITIZE (this);
355
0
    return_trace (likely (c->check_struct (this) &&
356
0
        justClassTable.sanitize (c, base, base) &&
357
0
        wdcTable.sanitize (c, base) &&
358
0
        pcTable.sanitize (c, base) &&
359
0
        lookupTable.sanitize (c, base)));
360
0
  }
361
362
  protected:
363
  Offset16To<JustificationCategory>
364
    justClassTable; /* Offset to the justification category state table. */
365
  Offset16To<WidthDeltaCluster>
366
    wdcTable; /* Offset from start of justification table to start
367
         * of the subtable containing the width delta factors
368
         * for the glyphs in your font.
369
         *
370
         * The width delta clusters table. */
371
  Offset16To<PostcompensationActionChain>
372
    pcTable;  /* Offset from start of justification table to start
373
         * of postcompensation subtable (set to zero if none).
374
         *
375
         * The postcompensation subtable, if present in the font. */
376
  Lookup<Offset16To<WidthDeltaCluster>>
377
    lookupTable;  /* Lookup table associating glyphs with width delta
378
         * clusters. See the description of Width Delta Clusters
379
         * table for details on how to interpret the lookup values. */
380
381
  public:
382
  DEFINE_SIZE_MIN (8);
383
};
384
385
struct just
386
{
387
  static constexpr hb_tag_t tableTag = HB_AAT_TAG_just;
388
389
  bool sanitize (hb_sanitize_context_t *c) const
390
0
  {
391
0
    TRACE_SANITIZE (this);
392
0
393
0
    return_trace (likely (c->check_struct (this) &&
394
0
        hb_barrier () &&
395
0
        version.major == 1 &&
396
0
        horizData.sanitize (c, this, this) &&
397
0
        vertData.sanitize (c, this, this)));
398
0
  }
399
400
  protected:
401
  FixedVersion<>version;  /* Version of the justification table
402
         * (0x00010000u for version 1.0). */
403
  HBUINT16  format;   /* Format of the justification table (set to 0). */
404
  Offset16To<JustificationHeader>
405
    horizData;  /* Byte offset from the start of the justification table
406
         * to the header for tables that contain justification
407
         * information for horizontal text.
408
         * If you are not including this information,
409
         * store 0. */
410
  Offset16To<JustificationHeader>
411
    vertData; /* ditto, vertical */
412
413
  public:
414
  DEFINE_SIZE_STATIC (10);
415
};
416
417
} /* namespace AAT */
418
419
420
#endif /* HB_AAT_LAYOUT_JUST_TABLE_HH */