Coverage Report

Created: 2026-03-31 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/harfbuzz/src/OT/glyf/path-builder.hh
Line
Count
Source
1
#ifndef OT_GLYF_PATH_BUILDER_HH
2
#define OT_GLYF_PATH_BUILDER_HH
3
4
5
#include "../../hb.hh"
6
7
8
namespace OT {
9
namespace glyf_impl {
10
11
12
struct path_builder_t
13
{
14
  hb_font_t *font;
15
  hb_draw_session_t *draw_session;
16
17
  struct optional_point_t
18
  {
19
18.2M
    optional_point_t () {}
20
69.6M
    optional_point_t (float x_, float y_) : has_data (true), x (x_), y (y_) {}
21
125M
    operator bool () const { return has_data; }
22
23
    bool has_data = false;
24
    float x;
25
    float y;
26
27
    optional_point_t mid (optional_point_t p)
28
15.9M
    { return optional_point_t ((x + p.x) * 0.5f, (y + p.y) * 0.5f); }
29
  } first_oncurve, first_offcurve, first_offcurve2, last_offcurve, last_offcurve2;
30
31
  path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_) :
32
2.17M
    font (font_), draw_session (&draw_session_) {}
33
34
  /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
35
     See also:
36
     * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
37
     * https://stackoverflow.com/a/20772557
38
     *
39
     * Cubic support added. */
40
  HB_ALWAYS_INLINE
41
  void consume_point (const contour_point_t &point)
42
53.6M
  {
43
53.6M
    bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
44
#ifdef HB_NO_CUBIC_GLYF
45
    constexpr bool is_cubic = false;
46
#else
47
53.6M
    bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC);
48
53.6M
#endif
49
53.6M
    optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y));
50
53.6M
    if (unlikely (!first_oncurve))
51
2.19M
    {
52
2.19M
      if (is_on_curve)
53
1.04M
      {
54
1.04M
  first_oncurve = p;
55
1.04M
  draw_session->move_to (p.x, p.y);
56
1.04M
      }
57
1.14M
      else
58
1.14M
      {
59
1.14M
  if (is_cubic && !first_offcurve2)
60
32.6k
  {
61
32.6k
    first_offcurve2 = first_offcurve;
62
32.6k
    first_offcurve = p;
63
32.6k
  }
64
1.11M
  else if (first_offcurve)
65
365k
  {
66
365k
    optional_point_t mid = first_offcurve.mid (p);
67
365k
    first_oncurve = mid;
68
365k
    last_offcurve = p;
69
365k
    draw_session->move_to (mid.x, mid.y);
70
365k
  }
71
750k
  else
72
750k
    first_offcurve = p;
73
1.14M
      }
74
2.19M
    }
75
51.4M
    else
76
51.4M
    {
77
51.4M
      if (last_offcurve)
78
20.4M
      {
79
20.4M
  if (is_on_curve)
80
1.04M
  {
81
1.04M
    if (last_offcurve2)
82
107k
    {
83
107k
      draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
84
107k
            last_offcurve.x, last_offcurve.y,
85
107k
            p.x, p.y);
86
107k
      last_offcurve2 = optional_point_t ();
87
107k
    }
88
941k
    else
89
941k
      draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
90
941k
               p.x, p.y);
91
1.04M
    last_offcurve = optional_point_t ();
92
1.04M
  }
93
19.3M
  else
94
19.3M
  {
95
19.3M
    if (is_cubic && !last_offcurve2)
96
4.15M
    {
97
4.15M
      last_offcurve2 = last_offcurve;
98
4.15M
      last_offcurve = p;
99
4.15M
    }
100
15.2M
    else
101
15.2M
    {
102
15.2M
      optional_point_t mid = last_offcurve.mid (p);
103
104
15.2M
      if (is_cubic)
105
3.98M
      {
106
3.98M
        draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
107
3.98M
              last_offcurve.x, last_offcurve.y,
108
3.98M
              mid.x, mid.y);
109
3.98M
        last_offcurve2 = optional_point_t ();
110
3.98M
      }
111
11.2M
      else
112
11.2M
        draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
113
11.2M
           mid.x, mid.y);
114
15.2M
      last_offcurve = p;
115
15.2M
    }
116
19.3M
  }
117
20.4M
      }
118
31.0M
      else
119
31.0M
      {
120
31.0M
  if (is_on_curve)
121
29.9M
    draw_session->line_to (p.x, p.y);
122
1.12M
  else
123
1.12M
    last_offcurve = p;
124
31.0M
      }
125
51.4M
    }
126
127
53.6M
  }
128
129
  void contour_end ()
130
1.82M
  {
131
1.82M
    if (first_offcurve && last_offcurve)
132
344k
    {
133
344k
      optional_point_t mid = last_offcurve.mid (first_offcurve2 ?
134
228k
            first_offcurve2 :
135
344k
            first_offcurve);
136
344k
      if (last_offcurve2)
137
53.6k
  draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
138
53.6k
        last_offcurve.x, last_offcurve.y,
139
53.6k
        mid.x, mid.y);
140
290k
      else
141
290k
  draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
142
290k
           mid.x, mid.y);
143
344k
      last_offcurve = optional_point_t ();
144
344k
    }
145
    /* now check the rest */
146
147
1.82M
    if (first_offcurve && first_oncurve)
148
367k
    {
149
367k
      if (first_offcurve2)
150
231k
  draw_session->cubic_to (first_offcurve2.x, first_offcurve2.y,
151
231k
        first_offcurve.x, first_offcurve.y,
152
231k
        first_oncurve.x, first_oncurve.y);
153
135k
      else
154
135k
  draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
155
135k
           first_oncurve.x, first_oncurve.y);
156
367k
    }
157
1.45M
    else if (last_offcurve && first_oncurve)
158
97.2k
    {
159
97.2k
      if (last_offcurve2)
160
17.0k
  draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
161
17.0k
        last_offcurve.x, last_offcurve.y,
162
17.0k
        first_oncurve.x, first_oncurve.y);
163
80.1k
      else
164
80.1k
  draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
165
80.1k
           first_oncurve.x, first_oncurve.y);
166
97.2k
    }
167
1.35M
    else if (first_oncurve)
168
950k
      draw_session->line_to (first_oncurve.x, first_oncurve.y);
169
407k
    else if (first_offcurve)
170
407k
    {
171
407k
      float x = first_offcurve.x, y = first_offcurve.y;
172
407k
      draw_session->move_to (x, y);
173
407k
      draw_session->quadratic_to (x, y, x, y);
174
407k
    }
175
176
    /* Getting ready for the next contour */
177
1.82M
    first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
178
1.82M
    draw_session->close_path ();
179
1.82M
  }
180
181
934k
  void points_end () {}
182
183
2.13M
  bool is_consuming_contour_points () { return true; }
184
934k
  contour_point_t *get_phantoms_sink () { return nullptr; }
185
};
186
187
188
} /* namespace glyf_impl */
189
} /* namespace OT */
190
191
192
#endif /* OT_GLYF_PATH_BUILDER_HH */