Coverage Report

Created: 2026-10-14 09:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/workdir/UnpackedTarball/harfbuzz/src/hb-draw.hh
Line
Count
Source
1
/*
2
 * Copyright © 2020  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_DRAW_HH
26
#define HB_DRAW_HH
27
28
#include "hb.hh"
29
30
31
/*
32
 * hb_draw_funcs_t
33
 */
34
35
#define HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS \
36
0
  HB_DRAW_FUNC_IMPLEMENT (move_to) \
37
0
  HB_DRAW_FUNC_IMPLEMENT (line_to) \
38
0
  HB_DRAW_FUNC_IMPLEMENT (quadratic_to) \
39
0
  HB_DRAW_FUNC_IMPLEMENT (cubic_to) \
40
0
  HB_DRAW_FUNC_IMPLEMENT (close_path) \
41
0
  HB_DRAW_FUNC_IMPLEMENT (set_budget) \
42
0
  HB_DRAW_FUNC_IMPLEMENT (get_budget) \
43
0
  HB_DRAW_FUNC_IMPLEMENT (get_budget_remaining) \
44
  /* ^--- Add new callbacks here */
45
46
struct hb_draw_funcs_t
47
{
48
  hb_object_header_t header;
49
50
  struct {
51
#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_func_t name;
52
    HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
53
#undef HB_DRAW_FUNC_IMPLEMENT
54
  } func;
55
56
  struct {
57
#define HB_DRAW_FUNC_IMPLEMENT(name) void *name;
58
    HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
59
#undef HB_DRAW_FUNC_IMPLEMENT
60
  } *user_data;
61
62
  struct {
63
#define HB_DRAW_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
64
    HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
65
#undef HB_DRAW_FUNC_IMPLEMENT
66
  } *destroy;
67
68
  void emit_move_to (void *draw_data, hb_draw_state_t &st,
69
         float to_x, float to_y)
70
40.2k
  { func.move_to (this, draw_data, &st,
71
40.2k
      to_x, to_y,
72
40.2k
      !user_data ? nullptr : user_data->move_to); }
73
  void emit_line_to (void *draw_data, hb_draw_state_t &st,
74
         float to_x, float to_y)
75
135k
  { func.line_to (this, draw_data, &st,
76
135k
      to_x, to_y,
77
135k
      !user_data ? nullptr : user_data->line_to); }
78
  void emit_quadratic_to (void *draw_data, hb_draw_state_t &st,
79
        float control_x, float control_y,
80
        float to_x, float to_y)
81
275k
  { func.quadratic_to (this, draw_data, &st,
82
275k
           control_x, control_y,
83
275k
           to_x, to_y,
84
275k
           !user_data ? nullptr : user_data->quadratic_to); }
85
  void emit_cubic_to (void *draw_data, hb_draw_state_t &st,
86
          float control1_x, float control1_y,
87
          float control2_x, float control2_y,
88
          float to_x, float to_y)
89
137k
  { func.cubic_to (this, draw_data, &st,
90
137k
       control1_x, control1_y,
91
137k
       control2_x, control2_y,
92
137k
       to_x, to_y,
93
137k
       !user_data ? nullptr : user_data->cubic_to); }
94
  void emit_close_path (void *draw_data, hb_draw_state_t &st)
95
40.2k
  { func.close_path (this, draw_data, &st,
96
40.2k
         !user_data ? nullptr : user_data->close_path); }
97
98
  bool set_budget (void *draw_data, int64_t budget)
99
0
  {
100
0
    if (budget < 0 && budget != HB_BUDGET_DEFAULT)
101
0
      budget = 0;
102
0
    return func.set_budget (this, draw_data, budget,
103
0
          !user_data ? nullptr : user_data->set_budget);
104
0
  }
105
  int64_t get_budget (void *draw_data)
106
0
  { return func.get_budget (this, draw_data,
107
0
          !user_data ? nullptr : user_data->get_budget); }
108
  int64_t *get_budget_remaining_ptr (void *draw_data)
109
52.5k
  { return func.get_budget_remaining (this, draw_data,
110
52.5k
              !user_data ? nullptr : user_data->get_budget_remaining); }
111
112
113
  void
114
  HB_ALWAYS_INLINE
115
  move_to (void *draw_data, hb_draw_state_t &st,
116
     float to_x, float to_y)
117
20.1k
  {
118
20.1k
    if (unlikely (st.path_open)) close_path (draw_data, st);
119
120
20.1k
    st.current_x = to_x;
121
20.1k
    st.current_y = to_y;
122
20.1k
  }
123
124
  void
125
  HB_ALWAYS_INLINE
126
  line_to (void *draw_data, hb_draw_state_t &st,
127
     float to_x, float to_y)
128
67.7k
  {
129
67.7k
    if (unlikely (!st.path_open)) start_path (draw_data, st);
130
131
67.7k
    emit_line_to (draw_data, st, to_x, to_y);
132
133
67.7k
    st.current_x = to_x;
134
67.7k
    st.current_y = to_y;
135
67.7k
  }
136
137
  void
138
  HB_ALWAYS_INLINE
139
  quadratic_to (void *draw_data, hb_draw_state_t &st,
140
    float control_x, float control_y,
141
    float to_x, float to_y)
142
137k
  {
143
137k
    if (unlikely (!st.path_open)) start_path (draw_data, st);
144
145
137k
    emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y);
146
147
137k
    st.current_x = to_x;
148
137k
    st.current_y = to_y;
149
137k
  }
150
151
  void
152
  HB_ALWAYS_INLINE
153
  cubic_to (void *draw_data, hb_draw_state_t &st,
154
      float control1_x, float control1_y,
155
      float control2_x, float control2_y,
156
      float to_x, float to_y)
157
0
  {
158
0
    if (unlikely (!st.path_open)) start_path (draw_data, st);
159
160
0
    emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y);
161
162
0
    st.current_x = to_x;
163
0
    st.current_y = to_y;
164
0
  }
165
166
  void
167
  HB_ALWAYS_INLINE
168
  close_path (void *draw_data, hb_draw_state_t &st)
169
46.3k
  {
170
46.3k
    if (likely (st.path_open))
171
20.1k
    {
172
20.1k
      if ((st.path_start_x != st.current_x) || (st.path_start_y != st.current_y))
173
0
  emit_line_to (draw_data, st, st.path_start_x, st.path_start_y);
174
20.1k
      emit_close_path (draw_data, st);
175
20.1k
    }
176
46.3k
    st.path_open = false;
177
46.3k
    st.path_start_x = st.current_x = st.path_start_y = st.current_y = 0;
178
46.3k
  }
179
180
  protected:
181
182
  void start_path (void *draw_data, hb_draw_state_t &st)
183
20.1k
  {
184
20.1k
    assert (!st.path_open);
185
20.1k
    emit_move_to (draw_data, st, st.current_x, st.current_y);
186
20.1k
    st.path_open = true;
187
20.1k
    st.path_start_x = st.current_x;
188
20.1k
    st.path_start_y = st.current_y;
189
20.1k
  }
190
};
191
DECLARE_NULL_INSTANCE (hb_draw_funcs_t);
192
193
struct hb_draw_session_t
194
{
195
  hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_)
196
26.2k
    : funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT,
197
26.2k
      local_budget {HB_BUDGET_GLYPH}, budget {funcs->get_budget_remaining_ptr (draw_data)}
198
26.2k
  {
199
26.2k
    if (!budget)
200
26.2k
      budget = &local_budget;
201
26.2k
  }
202
203
26.2k
  ~hb_draw_session_t () { close_path (); }
204
205
  HB_ALWAYS_INLINE
206
  void move_to (float to_x, float to_y)
207
20.1k
  {
208
20.1k
    funcs->move_to (draw_data, st,
209
20.1k
        to_x, to_y);
210
20.1k
  }
211
  HB_ALWAYS_INLINE
212
  void line_to (float to_x, float to_y)
213
67.7k
  {
214
67.7k
    funcs->line_to (draw_data, st,
215
67.7k
        to_x, to_y);
216
67.7k
  }
217
  void
218
  HB_ALWAYS_INLINE
219
  quadratic_to (float control_x, float control_y,
220
    float to_x, float to_y)
221
137k
  {
222
137k
    funcs->quadratic_to (draw_data, st,
223
137k
       control_x, control_y,
224
137k
       to_x, to_y);
225
137k
  }
226
  void
227
  HB_ALWAYS_INLINE
228
  cubic_to (float control1_x, float control1_y,
229
      float control2_x, float control2_y,
230
      float to_x, float to_y)
231
0
  {
232
0
    funcs->cubic_to (draw_data, st,
233
0
         control1_x, control1_y,
234
0
         control2_x, control2_y,
235
0
         to_x, to_y);
236
0
  }
237
  HB_ALWAYS_INLINE
238
  void close_path ()
239
46.3k
  {
240
46.3k
    funcs->close_path (draw_data, st);
241
46.3k
  }
242
243
36.8k
  int64_t &get_budget () { return *budget; }
244
245
  public:
246
  hb_draw_funcs_t *funcs;
247
  void *draw_data;
248
  hb_draw_state_t st;
249
  int64_t local_budget;
250
  int64_t *budget;
251
};
252
253
254
HB_INTERNAL hb_draw_funcs_t *
255
hb_draw_extents_get_funcs ();
256
257
258
#endif /* HB_DRAW_HH */