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#ifdef HB_EXPERIMENTAL_API
31struct hb_draw_funcs_t
32{
33 hb_object_header_t header;
34
35 hb_draw_move_to_func_t move_to;
36 hb_draw_line_to_func_t line_to;
37 hb_draw_quadratic_to_func_t quadratic_to;
38 bool is_quadratic_to_set;
39 hb_draw_cubic_to_func_t cubic_to;
40 hb_draw_close_path_func_t close_path;
41};
42
43struct draw_helper_t
44{
45 draw_helper_t (const hb_draw_funcs_t *funcs_, void *user_data_)
46 {
47 funcs = funcs_;
48 user_data = user_data_;
49 path_open = false;
50 path_start_x = current_x = path_start_y = current_y = 0;
51 }
52 ~draw_helper_t () { end_path (); }
53
54 void move_to (hb_position_t x, hb_position_t y)
55 {
56 if (path_open) end_path ();
57 current_x = path_start_x = x;
58 current_y = path_start_y = y;
59 }
60
61 void line_to (hb_position_t x, hb_position_t y)
62 {
63 if (equal_to_current (x, y)) return;
64 if (!path_open) start_path ();
65 funcs->line_to (x, y, user_data);
66 current_x = x;
67 current_y = y;
68 }
69
70 void
71 quadratic_to (hb_position_t control_x, hb_position_t control_y,
72 hb_position_t to_x, hb_position_t to_y)
73 {
74 if (equal_to_current (control_x, control_y) && equal_to_current (to_x, to_y))
75 return;
76 if (!path_open) start_path ();
77 if (funcs->is_quadratic_to_set)
78 funcs->quadratic_to (control_x, control_y, to_x, to_y, user_data);
79 else
80 funcs->cubic_to (roundf ((current_x + 2.f * control_x) / 3.f),
81 roundf ((current_y + 2.f * control_y) / 3.f),
82 roundf ((to_x + 2.f * control_x) / 3.f),
83 roundf ((to_y + 2.f * control_y) / 3.f),
84 to_x, to_y, user_data);
85 current_x = to_x;
86 current_y = to_y;
87 }
88
89 void
90 cubic_to (hb_position_t control1_x, hb_position_t control1_y,
91 hb_position_t control2_x, hb_position_t control2_y,
92 hb_position_t to_x, hb_position_t to_y)
93 {
94 if (equal_to_current (control1_x, control1_y) &&
95 equal_to_current (control2_x, control2_y) &&
96 equal_to_current (to_x, to_y))
97 return;
98 if (!path_open) start_path ();
99 funcs->cubic_to (control1_x, control1_y, control2_x, control2_y, to_x, to_y, user_data);
100 current_x = to_x;
101 current_y = to_y;
102 }
103
104 void end_path ()
105 {
106 if (path_open)
107 {
108 if ((path_start_x != current_x) || (path_start_y != current_y))
109 funcs->line_to (path_start_x, path_start_y, user_data);
110 funcs->close_path (user_data);
111 }
112 path_open = false;
113 path_start_x = current_x = path_start_y = current_y = 0;
114 }
115
116 protected:
117 bool equal_to_current (hb_position_t x, hb_position_t y)
118 { return current_x == x && current_y == y; }
119
120 void start_path ()
121 {
122 if (path_open) end_path ();
123 path_open = true;
124 funcs->move_to (path_start_x, path_start_y, user_data);
125 }
126
127 hb_position_t path_start_x;
128 hb_position_t path_start_y;
129
130 hb_position_t current_x;
131 hb_position_t current_y;
132
133 bool path_open;
134 const hb_draw_funcs_t *funcs;
135 void *user_data;
136};
137#endif
138
139#endif /* HB_DRAW_HH */
140