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-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
598
  { func.move_to (this, draw_data, &st,
71
598
      to_x, to_y,
72
598
      !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
2.54k
  { func.line_to (this, draw_data, &st,
76
2.54k
      to_x, to_y,
77
2.54k
      !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
634
  { func.quadratic_to (this, draw_data, &st,
82
634
           control_x, control_y,
83
634
           to_x, to_y,
84
634
           !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
317
  { func.cubic_to (this, draw_data, &st,
90
317
       control1_x, control1_y,
91
317
       control2_x, control2_y,
92
317
       to_x, to_y,
93
317
       !user_data ? nullptr : user_data->cubic_to); }
94
  void emit_close_path (void *draw_data, hb_draw_state_t &st)
95
598
  { func.close_path (this, draw_data, &st,
96
598
         !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
664
  { return func.get_budget_remaining (this, draw_data,
110
664
              !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
299
  {
118
299
    if (unlikely (st.path_open)) close_path (draw_data, st);
119
120
299
    st.current_x = to_x;
121
299
    st.current_y = to_y;
122
299
  }
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
1.27k
  {
129
1.27k
    if (unlikely (!st.path_open)) start_path (draw_data, st);
130
131
1.27k
    emit_line_to (draw_data, st, to_x, to_y);
132
133
1.27k
    st.current_x = to_x;
134
1.27k
    st.current_y = to_y;
135
1.27k
  }
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
317
  {
143
317
    if (unlikely (!st.path_open)) start_path (draw_data, st);
144
145
317
    emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y);
146
147
317
    st.current_x = to_x;
148
317
    st.current_y = to_y;
149
317
  }
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
631
  {
170
631
    if (likely (st.path_open))
171
299
    {
172
299
      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
299
      emit_close_path (draw_data, st);
175
299
    }
176
631
    st.path_open = false;
177
631
    st.path_start_x = st.current_x = st.path_start_y = st.current_y = 0;
178
631
  }
179
180
  protected:
181
182
  void start_path (void *draw_data, hb_draw_state_t &st)
183
299
  {
184
299
    assert (!st.path_open);
185
299
    emit_move_to (draw_data, st, st.current_x, st.current_y);
186
299
    st.path_open = true;
187
299
    st.path_start_x = st.current_x;
188
299
    st.path_start_y = st.current_y;
189
299
  }
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
332
    : funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT,
197
332
      local_budget {HB_BUDGET_GLYPH}, budget {funcs->get_budget_remaining_ptr (draw_data)}
198
332
  {
199
332
    if (!budget)
200
332
      budget = &local_budget;
201
332
  }
202
203
332
  ~hb_draw_session_t () { close_path (); }
204
205
  HB_ALWAYS_INLINE
206
  void move_to (float to_x, float to_y)
207
299
  {
208
299
    funcs->move_to (draw_data, st,
209
299
        to_x, to_y);
210
299
  }
211
  HB_ALWAYS_INLINE
212
  void line_to (float to_x, float to_y)
213
1.27k
  {
214
1.27k
    funcs->line_to (draw_data, st,
215
1.27k
        to_x, to_y);
216
1.27k
  }
217
  void
218
  HB_ALWAYS_INLINE
219
  quadratic_to (float control_x, float control_y,
220
    float to_x, float to_y)
221
317
  {
222
317
    funcs->quadratic_to (draw_data, st,
223
317
       control_x, control_y,
224
317
       to_x, to_y);
225
317
  }
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
631
  {
240
631
    funcs->close_path (draw_data, st);
241
631
  }
242
243
334
  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 */