Coverage Report

Created: 2026-09-28 10:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/workdir/UnpackedTarball/harfbuzz/src/hb-kern.hh
Line
Count
Source
1
/*
2
 * Copyright © 2017  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_KERN_HH
28
#define HB_KERN_HH
29
30
#include "hb-open-type.hh"
31
#include "hb-aat-layout-common.hh"
32
#include "hb-ot-layout-gpos-table.hh"
33
34
35
namespace OT {
36
37
38
template <typename Driver>
39
struct hb_kern_machine_t
40
{
41
  hb_kern_machine_t (const Driver &driver_,
42
         bool crossStream_ = false) :
43
399k
           driver (driver_),
44
399k
           crossStream (crossStream_) {}
Unexecuted instantiation: OT::hb_kern_machine_t<AAT::KerxSubTableFormat0<AAT::KerxSubTableHeader>::accelerator_t>::hb_kern_machine_t(AAT::KerxSubTableFormat0<AAT::KerxSubTableHeader>::accelerator_t const&, bool)
Unexecuted instantiation: OT::hb_kern_machine_t<AAT::KerxSubTableFormat2<AAT::KerxSubTableHeader>::accelerator_t>::hb_kern_machine_t(AAT::KerxSubTableFormat2<AAT::KerxSubTableHeader>::accelerator_t const&, bool)
Unexecuted instantiation: OT::hb_kern_machine_t<AAT::KerxSubTableFormat6<AAT::KerxSubTableHeader>::accelerator_t>::hb_kern_machine_t(AAT::KerxSubTableFormat6<AAT::KerxSubTableHeader>::accelerator_t const&, bool)
OT::hb_kern_machine_t<AAT::KerxSubTableFormat0<OT::KernOTSubTableHeader>::accelerator_t>::hb_kern_machine_t(AAT::KerxSubTableFormat0<OT::KernOTSubTableHeader>::accelerator_t const&, bool)
Line
Count
Source
43
399k
           driver (driver_),
44
399k
           crossStream (crossStream_) {}
Unexecuted instantiation: OT::hb_kern_machine_t<AAT::KerxSubTableFormat2<OT::KernOTSubTableHeader>::accelerator_t>::hb_kern_machine_t(AAT::KerxSubTableFormat2<OT::KernOTSubTableHeader>::accelerator_t const&, bool)
Unexecuted instantiation: OT::hb_kern_machine_t<OT::KernSubTableFormat3<OT::KernOTSubTableHeader> >::hb_kern_machine_t(OT::KernSubTableFormat3<OT::KernOTSubTableHeader> const&, bool)
Unexecuted instantiation: OT::hb_kern_machine_t<AAT::KerxSubTableFormat0<OT::KernAATSubTableHeader>::accelerator_t>::hb_kern_machine_t(AAT::KerxSubTableFormat0<OT::KernAATSubTableHeader>::accelerator_t const&, bool)
Unexecuted instantiation: OT::hb_kern_machine_t<AAT::KerxSubTableFormat2<OT::KernAATSubTableHeader>::accelerator_t>::hb_kern_machine_t(AAT::KerxSubTableFormat2<OT::KernAATSubTableHeader>::accelerator_t const&, bool)
Unexecuted instantiation: OT::hb_kern_machine_t<OT::KernSubTableFormat3<OT::KernAATSubTableHeader> >::hb_kern_machine_t(OT::KernSubTableFormat3<OT::KernAATSubTableHeader> const&, bool)
Unexecuted instantiation: OT::hb_kern_machine_t<hb_ot_shape_fallback_kern_driver_t>::hb_kern_machine_t(hb_ot_shape_fallback_kern_driver_t const&, bool)
45
46
  void kern (hb_font_t   *font,
47
       hb_buffer_t *buffer,
48
       hb_mask_t    kern_mask,
49
       bool         scale = true) const
50
399k
  {
51
399k
    if (!buffer->message (font, "start kern"))
52
0
      return;
53
54
399k
    buffer->unsafe_to_concat ();
55
399k
    OT::hb_ot_apply_context_t c (1, font, buffer, hb_blob_get_empty ());
56
399k
    c.set_lookup_mask (kern_mask);
57
399k
    c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
58
399k
    auto &skippy_iter = c.iter_input;
59
60
399k
    bool horizontal = HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction);
61
399k
    unsigned int count = buffer->len;
62
399k
    hb_glyph_info_t *info = buffer->info;
63
399k
    hb_glyph_position_t *pos = buffer->pos;
64
1.68M
    for (unsigned int idx = 0; idx < count;)
65
1.28M
    {
66
1.28M
      if (!(info[idx].mask & kern_mask))
67
0
      {
68
0
  idx++;
69
0
  continue;
70
0
      }
71
72
1.28M
      skippy_iter.reset_fast (idx);
73
1.28M
      unsigned unsafe_to;
74
1.28M
      if (unlikely (!skippy_iter.next (&unsafe_to)))
75
399k
      {
76
399k
  idx = unsafe_to;
77
399k
  continue;
78
399k
      }
79
80
881k
      unsigned int i = idx;
81
881k
      unsigned int j = skippy_iter.idx;
82
83
881k
      hb_position_t kern = driver.get_kerning (info[i].codepoint,
84
881k
                 info[j].codepoint);
85
86
87
881k
      if (likely (!kern))
88
850k
  goto skip;
89
90
31.3k
      if (horizontal)
91
31.3k
      {
92
31.3k
  if (scale)
93
31.3k
    kern = font->em_scale_x (kern);
94
31.3k
  if (crossStream)
95
0
  {
96
0
    pos[j].y_offset = kern;
97
0
    buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
98
0
  }
99
31.3k
  else
100
31.3k
  {
101
31.3k
    hb_position_t kern1 = kern >> 1;
102
31.3k
    hb_position_t kern2 = kern - kern1;
103
31.3k
    pos[i].x_advance = hb_saturate_add (pos[i].x_advance, kern1);
104
31.3k
    pos[j].x_advance = hb_saturate_add (pos[j].x_advance, kern2);
105
31.3k
    pos[j].x_offset = hb_saturate_add (pos[j].x_offset, kern2);
106
31.3k
  }
107
31.3k
      }
108
0
      else
109
0
      {
110
0
  if (scale)
111
0
    kern = font->em_scale_y (kern);
112
0
  if (crossStream)
113
0
  {
114
0
    pos[j].x_offset = kern;
115
0
    buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
116
0
  }
117
0
  else
118
0
  {
119
0
    hb_position_t kern1 = kern >> 1;
120
0
    hb_position_t kern2 = kern - kern1;
121
0
    pos[i].y_advance = hb_saturate_add (pos[i].y_advance, kern1);
122
0
    pos[j].y_advance = hb_saturate_add (pos[j].y_advance, kern2);
123
0
    pos[j].y_offset = hb_saturate_add (pos[j].y_offset, kern2);
124
0
  }
125
0
      }
126
127
31.3k
      buffer->unsafe_to_break (i, j + 1);
128
129
881k
    skip:
130
881k
      idx = skippy_iter.idx;
131
881k
    }
132
133
399k
    (void) buffer->message (font, "end kern");
134
399k
  }
Unexecuted instantiation: OT::hb_kern_machine_t<AAT::KerxSubTableFormat0<AAT::KerxSubTableHeader>::accelerator_t>::kern(hb_font_t*, hb_buffer_t*, unsigned int, bool) const
Unexecuted instantiation: OT::hb_kern_machine_t<AAT::KerxSubTableFormat2<AAT::KerxSubTableHeader>::accelerator_t>::kern(hb_font_t*, hb_buffer_t*, unsigned int, bool) const
Unexecuted instantiation: OT::hb_kern_machine_t<AAT::KerxSubTableFormat6<AAT::KerxSubTableHeader>::accelerator_t>::kern(hb_font_t*, hb_buffer_t*, unsigned int, bool) const
OT::hb_kern_machine_t<AAT::KerxSubTableFormat0<OT::KernOTSubTableHeader>::accelerator_t>::kern(hb_font_t*, hb_buffer_t*, unsigned int, bool) const
Line
Count
Source
50
399k
  {
51
399k
    if (!buffer->message (font, "start kern"))
52
0
      return;
53
54
399k
    buffer->unsafe_to_concat ();
55
399k
    OT::hb_ot_apply_context_t c (1, font, buffer, hb_blob_get_empty ());
56
399k
    c.set_lookup_mask (kern_mask);
57
399k
    c.set_lookup_props (OT::LookupFlag::IgnoreMarks);
58
399k
    auto &skippy_iter = c.iter_input;
59
60
399k
    bool horizontal = HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction);
61
399k
    unsigned int count = buffer->len;
62
399k
    hb_glyph_info_t *info = buffer->info;
63
399k
    hb_glyph_position_t *pos = buffer->pos;
64
1.68M
    for (unsigned int idx = 0; idx < count;)
65
1.28M
    {
66
1.28M
      if (!(info[idx].mask & kern_mask))
67
0
      {
68
0
  idx++;
69
0
  continue;
70
0
      }
71
72
1.28M
      skippy_iter.reset_fast (idx);
73
1.28M
      unsigned unsafe_to;
74
1.28M
      if (unlikely (!skippy_iter.next (&unsafe_to)))
75
399k
      {
76
399k
  idx = unsafe_to;
77
399k
  continue;
78
399k
      }
79
80
881k
      unsigned int i = idx;
81
881k
      unsigned int j = skippy_iter.idx;
82
83
881k
      hb_position_t kern = driver.get_kerning (info[i].codepoint,
84
881k
                 info[j].codepoint);
85
86
87
881k
      if (likely (!kern))
88
850k
  goto skip;
89
90
31.3k
      if (horizontal)
91
31.3k
      {
92
31.3k
  if (scale)
93
31.3k
    kern = font->em_scale_x (kern);
94
31.3k
  if (crossStream)
95
0
  {
96
0
    pos[j].y_offset = kern;
97
0
    buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
98
0
  }
99
31.3k
  else
100
31.3k
  {
101
31.3k
    hb_position_t kern1 = kern >> 1;
102
31.3k
    hb_position_t kern2 = kern - kern1;
103
31.3k
    pos[i].x_advance = hb_saturate_add (pos[i].x_advance, kern1);
104
31.3k
    pos[j].x_advance = hb_saturate_add (pos[j].x_advance, kern2);
105
31.3k
    pos[j].x_offset = hb_saturate_add (pos[j].x_offset, kern2);
106
31.3k
  }
107
31.3k
      }
108
0
      else
109
0
      {
110
0
  if (scale)
111
0
    kern = font->em_scale_y (kern);
112
0
  if (crossStream)
113
0
  {
114
0
    pos[j].x_offset = kern;
115
0
    buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
116
0
  }
117
0
  else
118
0
  {
119
0
    hb_position_t kern1 = kern >> 1;
120
0
    hb_position_t kern2 = kern - kern1;
121
0
    pos[i].y_advance = hb_saturate_add (pos[i].y_advance, kern1);
122
0
    pos[j].y_advance = hb_saturate_add (pos[j].y_advance, kern2);
123
0
    pos[j].y_offset = hb_saturate_add (pos[j].y_offset, kern2);
124
0
  }
125
0
      }
126
127
31.3k
      buffer->unsafe_to_break (i, j + 1);
128
129
881k
    skip:
130
881k
      idx = skippy_iter.idx;
131
881k
    }
132
133
399k
    (void) buffer->message (font, "end kern");
134
399k
  }
Unexecuted instantiation: OT::hb_kern_machine_t<AAT::KerxSubTableFormat2<OT::KernOTSubTableHeader>::accelerator_t>::kern(hb_font_t*, hb_buffer_t*, unsigned int, bool) const
Unexecuted instantiation: OT::hb_kern_machine_t<OT::KernSubTableFormat3<OT::KernOTSubTableHeader> >::kern(hb_font_t*, hb_buffer_t*, unsigned int, bool) const
Unexecuted instantiation: OT::hb_kern_machine_t<AAT::KerxSubTableFormat0<OT::KernAATSubTableHeader>::accelerator_t>::kern(hb_font_t*, hb_buffer_t*, unsigned int, bool) const
Unexecuted instantiation: OT::hb_kern_machine_t<AAT::KerxSubTableFormat2<OT::KernAATSubTableHeader>::accelerator_t>::kern(hb_font_t*, hb_buffer_t*, unsigned int, bool) const
Unexecuted instantiation: OT::hb_kern_machine_t<OT::KernSubTableFormat3<OT::KernAATSubTableHeader> >::kern(hb_font_t*, hb_buffer_t*, unsigned int, bool) const
Unexecuted instantiation: OT::hb_kern_machine_t<hb_ot_shape_fallback_kern_driver_t>::kern(hb_font_t*, hb_buffer_t*, unsigned int, bool) const
135
136
  const Driver &driver;
137
  bool crossStream;
138
};
139
140
141
} /* namespace OT */
142
143
144
#endif /* HB_KERN_HH */