Coverage Report

Created: 2024-05-18 12:36

/src/harfbuzz/src/hb-aat-layout-trak-table.hh
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright © 2018  Ebrahim Byagowi
3
 * Copyright © 2018  Google, Inc.
4
 *
5
 *  This is part of HarfBuzz, a text shaping library.
6
 *
7
 * Permission is hereby granted, without written agreement and without
8
 * license or royalty fees, to use, copy, modify, and distribute this
9
 * software and its documentation for any purpose, provided that the
10
 * above copyright notice and the following two paragraphs appear in
11
 * all copies of this software.
12
 *
13
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16
 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17
 * DAMAGE.
18
 *
19
 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21
 * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
22
 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24
 *
25
 * Google Author(s): Behdad Esfahbod
26
 */
27
28
#ifndef HB_AAT_LAYOUT_TRAK_TABLE_HH
29
#define HB_AAT_LAYOUT_TRAK_TABLE_HH
30
31
#include "hb-aat-layout-common.hh"
32
#include "hb-ot-layout.hh"
33
#include "hb-open-type.hh"
34
35
/*
36
 * trak -- Tracking
37
 * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6trak.html
38
 */
39
#define HB_AAT_TAG_trak HB_TAG('t','r','a','k')
40
41
42
namespace AAT {
43
44
45
struct TrackTableEntry
46
{
47
  friend struct TrackData;
48
49
0
  float get_track_value () const { return track.to_float (); }
50
51
  int get_value (const void *base, unsigned int index,
52
     unsigned int table_size) const
53
0
  { return (base+valuesZ).as_array (table_size)[index]; }
54
55
  public:
56
  bool sanitize (hb_sanitize_context_t *c, const void *base,
57
     unsigned int table_size) const
58
245k
  {
59
245k
    TRACE_SANITIZE (this);
60
245k
    return_trace (likely (c->check_struct (this) &&
61
245k
        (valuesZ.sanitize (c, base, table_size))));
62
245k
  }
63
64
  protected:
65
  F16DOT16  track;    /* Track value for this record. */
66
  NameID  trackNameID;  /* The 'name' table index for this track.
67
         * (a short word or phrase like "loose"
68
         * or "very tight") */
69
  NNOffset16To<UnsizedArrayOf<FWORD>>
70
    valuesZ;  /* Offset from start of tracking table to
71
         * per-size tracking values for this track. */
72
73
  public:
74
  DEFINE_SIZE_STATIC (8);
75
};
76
77
struct TrackData
78
{
79
  float interpolate_at (unsigned int idx,
80
      float target_size,
81
      const TrackTableEntry &trackTableEntry,
82
      const void *base) const
83
0
  {
84
0
    unsigned int sizes = nSizes;
85
0
    hb_array_t<const F16DOT16> size_table ((base+sizeTable).arrayZ, sizes);
86
87
0
    float s0 = size_table[idx].to_float ();
88
0
    float s1 = size_table[idx + 1].to_float ();
89
0
    float t = unlikely (s0 == s1) ? 0.f : (target_size - s0) / (s1 - s0);
90
0
    return t * trackTableEntry.get_value (base, idx + 1, sizes) +
91
0
     (1.f - t) * trackTableEntry.get_value (base, idx, sizes);
92
0
  }
93
94
  int get_tracking (const void *base, float ptem) const
95
0
  {
96
    /*
97
     * Choose track.
98
     */
99
0
    const TrackTableEntry *trackTableEntry = nullptr;
100
0
    unsigned int count = nTracks;
101
0
    for (unsigned int i = 0; i < count; i++)
102
0
    {
103
      /* Note: Seems like the track entries are sorted by values.  But the
104
       * spec doesn't explicitly say that.  It just mentions it in the example. */
105
106
      /* For now we only seek for track entries with zero tracking value */
107
108
0
      if (trackTable[i].get_track_value () == 0.f)
109
0
      {
110
0
  trackTableEntry = &trackTable[i];
111
0
  break;
112
0
      }
113
0
    }
114
0
    if (!trackTableEntry) return 0.;
115
116
    /*
117
     * Choose size.
118
     */
119
0
    unsigned int sizes = nSizes;
120
0
    if (!sizes) return 0.;
121
0
    if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes);
122
123
0
    hb_array_t<const F16DOT16> size_table ((base+sizeTable).arrayZ, sizes);
124
0
    unsigned int size_index;
125
0
    for (size_index = 0; size_index < sizes - 1; size_index++)
126
0
      if (size_table[size_index].to_float () >= ptem)
127
0
  break;
128
129
0
    return roundf (interpolate_at (size_index ? size_index - 1 : 0, ptem,
130
0
           *trackTableEntry, base));
131
0
  }
132
133
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
134
4.14k
  {
135
4.14k
    TRACE_SANITIZE (this);
136
4.14k
    return_trace (likely (c->check_struct (this) &&
137
4.14k
        sizeTable.sanitize (c, base, nSizes) &&
138
4.14k
        trackTable.sanitize (c, nTracks, base, nSizes)));
139
4.14k
  }
140
141
  protected:
142
  HBUINT16  nTracks;  /* Number of separate tracks included in this table. */
143
  HBUINT16  nSizes;   /* Number of point sizes included in this table. */
144
  NNOffset32To<UnsizedArrayOf<F16DOT16>>
145
    sizeTable;  /* Offset from start of the tracking table to
146
         * Array[nSizes] of size values.. */
147
  UnsizedArrayOf<TrackTableEntry>
148
    trackTable; /* Array[nTracks] of TrackTableEntry records. */
149
150
  public:
151
  DEFINE_SIZE_ARRAY (8, trackTable);
152
};
153
154
struct trak
155
{
156
  static constexpr hb_tag_t tableTag = HB_AAT_TAG_trak;
157
158
8.03M
  bool has_data () const { return version.to_int (); }
159
160
  bool apply (hb_aat_apply_context_t *c) const
161
16.0k
  {
162
16.0k
    TRACE_APPLY (this);
163
164
16.0k
    hb_mask_t trak_mask = c->plan->trak_mask;
165
166
16.0k
    const float ptem = c->font->ptem;
167
16.0k
    if (unlikely (ptem <= 0.f))
168
16.0k
      return_trace (false);
169
170
0
    hb_buffer_t *buffer = c->buffer;
171
0
    if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
172
0
    {
173
0
      const TrackData &trackData = this+horizData;
174
0
      int tracking = trackData.get_tracking (this, ptem);
175
0
      hb_position_t offset_to_add = c->font->em_scalef_x (tracking / 2);
176
0
      hb_position_t advance_to_add = c->font->em_scalef_x (tracking);
177
0
      foreach_grapheme (buffer, start, end)
178
0
      {
179
0
  if (!(buffer->info[start].mask & trak_mask)) continue;
180
0
  buffer->pos[start].x_advance += advance_to_add;
181
0
  buffer->pos[start].x_offset += offset_to_add;
182
0
      }
183
0
    }
184
0
    else
185
0
    {
186
0
      const TrackData &trackData = this+vertData;
187
0
      int tracking = trackData.get_tracking (this, ptem);
188
0
      hb_position_t offset_to_add = c->font->em_scalef_y (tracking / 2);
189
0
      hb_position_t advance_to_add = c->font->em_scalef_y (tracking);
190
0
      foreach_grapheme (buffer, start, end)
191
0
      {
192
0
  if (!(buffer->info[start].mask & trak_mask)) continue;
193
0
  buffer->pos[start].y_advance += advance_to_add;
194
0
  buffer->pos[start].y_offset += offset_to_add;
195
0
      }
196
0
    }
197
198
0
    return_trace (true);
199
16.0k
  }
200
201
  bool sanitize (hb_sanitize_context_t *c) const
202
3.76k
  {
203
3.76k
    TRACE_SANITIZE (this);
204
205
3.76k
    return_trace (likely (c->check_struct (this) &&
206
3.76k
        version.major == 1 &&
207
3.76k
        horizData.sanitize (c, this, this) &&
208
3.76k
        vertData.sanitize (c, this, this)));
209
3.76k
  }
210
211
  protected:
212
  FixedVersion<>version;  /* Version of the tracking table
213
         * (0x00010000u for version 1.0). */
214
  HBUINT16  format;   /* Format of the tracking table (set to 0). */
215
  Offset16To<TrackData>
216
    horizData;  /* Offset from start of tracking table to TrackData
217
         * for horizontal text (or 0 if none). */
218
  Offset16To<TrackData>
219
    vertData; /* Offset from start of tracking table to TrackData
220
         * for vertical text (or 0 if none). */
221
  HBUINT16  reserved; /* Reserved. Set to 0. */
222
223
  public:
224
  DEFINE_SIZE_STATIC (12);
225
};
226
227
} /* namespace AAT */
228
229
230
#endif /* HB_AAT_LAYOUT_TRAK_TABLE_HH */