Coverage Report

Created: 2026-10-22 07:14

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