Coverage Report

Created: 2026-10-22 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/harfbuzz/src/hb-ot-layout-jstf-table.hh
Line
Count
Source
1
/*
2
 * Copyright © 2013  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_LAYOUT_JSTF_TABLE_HH
28
#define HB_OT_LAYOUT_JSTF_TABLE_HH
29
30
#include "hb-open-type.hh"
31
#include "hb-ot-layout-gpos-table.hh"
32
33
34
namespace OT {
35
36
37
/*
38
 * JstfModList -- Justification Modification List Tables
39
 */
40
41
typedef IndexArray JstfModList;
42
43
44
/*
45
 * JstfMax -- Justification Maximum Table
46
 */
47
48
typedef List16OfOffset16To<PosLookup> JstfMax;
49
50
51
/*
52
 * JstfPriority -- Justification Priority Table
53
 */
54
55
struct JstfPriority
56
{
57
  bool sanitize (hb_sanitize_context_t *c) const
58
0
  {
59
0
    TRACE_SANITIZE (this);
60
0
    return_trace (c->check_struct (this) &&
61
0
      shrinkageEnableGSUB.sanitize (c, this) &&
62
0
      shrinkageDisableGSUB.sanitize (c, this) &&
63
0
      shrinkageEnableGPOS.sanitize (c, this) &&
64
0
      shrinkageDisableGPOS.sanitize (c, this) &&
65
0
      shrinkageJstfMax.sanitize (c, this) &&
66
0
      extensionEnableGSUB.sanitize (c, this) &&
67
0
      extensionDisableGSUB.sanitize (c, this) &&
68
0
      extensionEnableGPOS.sanitize (c, this) &&
69
0
      extensionDisableGPOS.sanitize (c, this) &&
70
0
      extensionJstfMax.sanitize (c, this));
71
0
  }
72
73
  protected:
74
  Offset16To<JstfModList>
75
    shrinkageEnableGSUB;  /* Offset to Shrinkage Enable GSUB
76
           * JstfModList table--from beginning of
77
           * JstfPriority table--may be NULL */
78
  Offset16To<JstfModList>
79
    shrinkageDisableGSUB; /* Offset to Shrinkage Disable GSUB
80
           * JstfModList table--from beginning of
81
           * JstfPriority table--may be NULL */
82
  Offset16To<JstfModList>
83
    shrinkageEnableGPOS;  /* Offset to Shrinkage Enable GPOS
84
           * JstfModList table--from beginning of
85
           * JstfPriority table--may be NULL */
86
  Offset16To<JstfModList>
87
    shrinkageDisableGPOS; /* Offset to Shrinkage Disable GPOS
88
           * JstfModList table--from beginning of
89
           * JstfPriority table--may be NULL */
90
  Offset16To<JstfMax>
91
    shrinkageJstfMax; /* Offset to Shrinkage JstfMax table--
92
           * from beginning of JstfPriority table
93
           * --may be NULL */
94
  Offset16To<JstfModList>
95
    extensionEnableGSUB;  /* Offset to Extension Enable GSUB
96
           * JstfModList table--from beginning of
97
           * JstfPriority table--may be NULL */
98
  Offset16To<JstfModList>
99
    extensionDisableGSUB; /* Offset to Extension Disable GSUB
100
           * JstfModList table--from beginning of
101
           * JstfPriority table--may be NULL */
102
  Offset16To<JstfModList>
103
    extensionEnableGPOS;  /* Offset to Extension Enable GPOS
104
           * JstfModList table--from beginning of
105
           * JstfPriority table--may be NULL */
106
  Offset16To<JstfModList>
107
    extensionDisableGPOS; /* Offset to Extension Disable GPOS
108
           * JstfModList table--from beginning of
109
           * JstfPriority table--may be NULL */
110
  Offset16To<JstfMax>
111
    extensionJstfMax; /* Offset to Extension JstfMax table--
112
           * from beginning of JstfPriority table
113
           * --may be NULL */
114
115
  public:
116
  DEFINE_SIZE_STATIC (20);
117
};
118
119
120
/*
121
 * JstfLangSys -- Justification Language System Table
122
 */
123
124
struct JstfLangSys : List16OfOffset16To<JstfPriority>
125
{
126
  bool sanitize (hb_sanitize_context_t *c,
127
     const Record_sanitize_closure_t * = nullptr) const
128
0
  {
129
0
    TRACE_SANITIZE (this);
130
0
    return_trace (List16OfOffset16To<JstfPriority>::sanitize (c));
131
0
  }
132
};
133
134
135
/*
136
 * ExtenderGlyphs -- Extender Glyph Table
137
 */
138
139
template <typename Types>
140
using ExtenderGlyphs = SortedArray16Of<typename Types::HBGlyphID>;
141
142
143
/*
144
 * JstfScript -- The Justification Table
145
 */
146
147
template <typename Types>
148
struct JstfScript
149
{
150
  unsigned int get_lang_sys_count () const
151
  { return langSys.len; }
152
  const Tag& get_lang_sys_tag (unsigned int i) const
153
  { return langSys.get_tag (i); }
154
  unsigned int get_lang_sys_tags (unsigned int start_offset,
155
          unsigned int *lang_sys_count /* IN/OUT */,
156
          hb_tag_t     *lang_sys_tags /* OUT */) const
157
  { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
158
  const JstfLangSys& get_lang_sys (unsigned int i) const
159
  {
160
    if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
161
    return this+langSys[i].offset;
162
  }
163
  bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
164
  { return langSys.find_index (tag, index); }
165
166
  bool has_default_lang_sys () const               { return defaultLangSys != 0; }
167
  const JstfLangSys& get_default_lang_sys () const { return this+defaultLangSys; }
168
169
  bool sanitize (hb_sanitize_context_t *c,
170
     const Record_sanitize_closure_t * = nullptr) const
171
0
  {
172
0
    TRACE_SANITIZE (this);
173
0
    return_trace (extenderGlyphs.sanitize (c, this) &&
174
0
      defaultLangSys.sanitize (c, this) &&
175
0
      langSys.sanitize (c, this));
176
0
  }
177
178
  protected:
179
  typename Types::template LOffsetTo<ExtenderGlyphs<Types>>
180
    extenderGlyphs; /* Offset to ExtenderGlyph table--from beginning
181
         * of JstfScript table-may be NULL */
182
  typename Types::template LOffsetTo<JstfLangSys>
183
    defaultLangSys; /* Offset to DefaultJstfLangSys table--from
184
         * beginning of JstfScript table--may be Null */
185
  RecordArrayOf<JstfLangSys>
186
    langSys;  /* Array of JstfLangSysRecords--listed
187
         * alphabetically by LangSysTag */
188
  public:
189
  DEFINE_SIZE_ARRAY (2 * Types::LOffset::static_size + 2, langSys);
190
};
191
192
template <typename Types>
193
struct JstfScriptRecord
194
{
195
0
  int cmp (hb_tag_t a) const { return tag.cmp (a); }
196
197
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
198
0
  {
199
0
    TRACE_SANITIZE (this);
200
0
    const Record_sanitize_closure_t closure = {tag, base};
201
0
    return_trace (c->check_struct (this) &&
202
0
      offset.sanitize (c, base, &closure));
203
0
  }
204
205
  Tag   tag;    /* 4-byte JstfScript identification tag */
206
  typename Types::template LOffsetTo<JstfScript<Types>>
207
    offset;   /* Offset from beginning of JSTF header */
208
  public:
209
  DEFINE_SIZE_STATIC (4 + Types::LOffset::static_size);
210
};
211
212
template <typename Types>
213
struct JstfScriptList : SortedArray16Of<JstfScriptRecord<Types>>
214
{
215
  const Tag& get_tag (unsigned int i) const
216
0
  { return (*this)[i].tag; }
217
  unsigned int get_tags (unsigned int start_offset,
218
       unsigned int *script_count /* IN/OUT */,
219
       hb_tag_t     *script_tags /* OUT */) const
220
0
  {
221
0
    if (script_count)
222
0
    {
223
0
      + this->as_array ().sub_array (start_offset, script_count)
224
0
      | hb_map (&JstfScriptRecord<Types>::tag)
225
0
      | hb_sink (hb_array (script_tags, *script_count))
226
0
      ;
227
0
    }
228
0
    return this->len;
229
0
  }
230
  const JstfScript<Types>& get_script (const void *base, unsigned int i) const
231
0
  { return base+(*this)[i].offset; }
232
  bool find_index (hb_tag_t tag, unsigned int *index) const
233
0
  {
234
0
    return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
235
0
  }
236
};
237
238
239
/*
240
 * JSTF -- Justification
241
 * https://docs.microsoft.com/en-us/typography/opentype/spec/jstf
242
 */
243
244
struct JSTF
245
{
246
  static constexpr hb_tag_t tableTag = HB_OT_TAG_JSTF;
247
248
  unsigned int get_script_count () const
249
0
  {
250
0
#ifndef HB_NO_BEYOND_64K
251
0
    if (has_script_list2 ()) return get_script_list2 ().len;
252
0
#endif
253
0
    return scriptList.len;
254
0
  }
255
  const Tag& get_script_tag (unsigned int i) const
256
0
  {
257
0
#ifndef HB_NO_BEYOND_64K
258
0
    if (has_script_list2 ()) return get_script_list2 ().get_tag (i);
259
0
#endif
260
0
    return scriptList.get_tag (i);
261
0
  }
262
  unsigned int get_script_tags (unsigned int start_offset,
263
        unsigned int *script_count /* IN/OUT */,
264
        hb_tag_t     *script_tags /* OUT */) const
265
0
  {
266
0
#ifndef HB_NO_BEYOND_64K
267
0
    if (has_script_list2 ())
268
0
      return get_script_list2 ().get_tags (start_offset, script_count, script_tags);
269
0
#endif
270
0
    return scriptList.get_tags (start_offset, script_count, script_tags);
271
0
  }
272
  template <typename Types>
273
  const JstfScript<Types>& get_script (unsigned int i) const;
274
  bool find_script_index (hb_tag_t tag, unsigned int *index) const
275
0
  {
276
0
#ifndef HB_NO_BEYOND_64K
277
0
    if (has_script_list2 ()) return get_script_list2 ().find_index (tag, index);
278
0
#endif
279
0
    return scriptList.find_index (tag, index);
280
0
  }
281
282
  bool sanitize (hb_sanitize_context_t *c) const
283
0
  {
284
0
    TRACE_SANITIZE (this);
285
0
    if (unlikely (!version.sanitize (c) ||
286
0
      !hb_barrier () ||
287
0
      version.major != 1 ||
288
0
      !scriptList.sanitize (c, this)))
289
0
      return_trace (false);
290
0
#ifndef HB_NO_BEYOND_64K
291
0
    if (unlikely (version.minor >= 1 && !get_script_list2 ().sanitize (c, this)))
292
0
      return_trace (false);
293
0
#endif
294
0
    return_trace (true);
295
0
  }
296
297
  private:
298
#ifndef HB_NO_BEYOND_64K
299
  bool has_script_list2 () const
300
  { return version.minor >= 1 && get_script_list2 ().len; }
301
  const JstfScriptList<Layout::MediumTypes>& get_script_list2 () const
302
  { return StructAfter<JstfScriptList<Layout::MediumTypes>> (scriptList); }
303
#endif
304
305
  protected:
306
  FixedVersion<>version;  /* Version of the JSTF table--initially set
307
         * to 0x00010000u */
308
  JstfScriptList<Layout::SmallTypes>
309
    scriptList; /* Array of JstfScripts--listed
310
         * alphabetically by ScriptTag */
311
#ifndef HB_NO_BEYOND_64K
312
/*JstfScriptList<Layout::MediumTypes>
313
    scriptList2;*//* Array of JstfScript2s--listed
314
         * alphabetically by ScriptTag.
315
         * Present only if minorVersion is 1 or greater. */
316
#endif
317
  public:
318
  DEFINE_SIZE_ARRAY (6, scriptList);
319
};
320
321
template <>
322
inline const JstfScript<Layout::SmallTypes>&
323
JSTF::get_script<Layout::SmallTypes> (unsigned int i) const
324
0
{ return scriptList.get_script (this, i); }
325
326
#ifndef HB_NO_BEYOND_64K
327
template <>
328
inline const JstfScript<Layout::MediumTypes>&
329
JSTF::get_script<Layout::MediumTypes> (unsigned int i) const
330
{ return get_script_list2 ().get_script (this, i); }
331
#endif
332
333
334
} /* namespace OT */
335
336
337
#endif /* HB_OT_LAYOUT_JSTF_TABLE_HH */