Skip to content

Commit 16f7f9e

Browse files
authored
Merge pull request #74 from ndsl7109256/path
Support path function to fulfill TinyVG rendering
2 parents 1d990a9 + ff4847d commit 16f7f9e

File tree

8 files changed

+545
-45
lines changed

8 files changed

+545
-45
lines changed

apps/multi.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,57 @@ static void apps_jelly_start(twin_screen_t *screen, int x, int y, int w, int h)
220220
twin_window_show(window);
221221
}
222222

223+
static void draw_flower(twin_path_t *path,
224+
twin_fixed_t radius,
225+
int number_of_petals)
226+
{
227+
const twin_angle_t angle_shift = TWIN_ANGLE_360 / number_of_petals;
228+
const twin_angle_t angle_start = angle_shift / 2;
229+
twin_fixed_t s, c;
230+
twin_sincos(-angle_start, &s, &c);
231+
twin_fixed_t p_x = twin_fixed_mul(radius, c);
232+
twin_fixed_t p_y = twin_fixed_mul(radius, s);
233+
twin_path_move(path, p_x, p_y);
234+
235+
for (twin_angle_t a = angle_start; a <= TWIN_ANGLE_360; a += angle_shift) {
236+
twin_sincos(a, &s, &c);
237+
twin_fixed_t c_x = twin_fixed_mul(radius, c);
238+
twin_fixed_t c_y = twin_fixed_mul(radius, s);
239+
twin_fixed_t rx = radius;
240+
twin_fixed_t ry = radius * 3;
241+
twin_path_arc_ellipse(path, 1, 1, rx, ry, p_x, p_y, c_x, c_y,
242+
a - angle_start);
243+
p_x = c_x;
244+
p_y = c_y;
245+
}
246+
247+
twin_path_close(path);
248+
}
249+
250+
static void apps_flower_start(twin_screen_t *screen, int x, int y, int w, int h)
251+
{
252+
twin_window_t *window = twin_window_create(
253+
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h);
254+
twin_pixmap_t *pixmap = window->pixmap;
255+
twin_path_t *stroke = twin_path_create();
256+
twin_path_t *path = twin_path_create();
257+
twin_path_translate(path, D(200), D(200));
258+
twin_path_scale(path, D(10), D(10));
259+
twin_path_translate(stroke, D(200), D(200));
260+
twin_fill(pixmap, 0xffffffff, TWIN_SOURCE, 0, 0, w, h);
261+
twin_window_set_name(window, "Flower");
262+
twin_path_move(stroke, D(-200), D(0));
263+
twin_path_draw(stroke, D(200), D(0));
264+
twin_path_move(stroke, D(0), D(200));
265+
twin_path_draw(stroke, D(0), D(-200));
266+
twin_path_set_cap_style(stroke, TwinCapProjecting);
267+
twin_paint_stroke(pixmap, 0xffcc9999, stroke, D(10));
268+
draw_flower(path, D(3), 5);
269+
twin_paint_path(pixmap, 0xffe2d2d2, path);
270+
twin_path_destroy(stroke);
271+
twin_window_show(window);
272+
}
273+
223274
void apps_multi_start(twin_screen_t *screen,
224275
const char *name,
225276
int x,
@@ -233,4 +284,5 @@ void apps_multi_start(twin_screen_t *screen,
233284
apps_quickbrown_start(screen, x += 20, y += 20, w, h);
234285
apps_ascii_start(screen, x += 20, y += 20, w, h);
235286
apps_jelly_start(screen, x += 20, y += 20, w / 2, h);
287+
apps_flower_start(screen, x += 20, y += 20, w, h);
236288
}

apps/spline.c

Lines changed: 110 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,45 +15,86 @@
1515

1616
#define _apps_spline_pixmap(spline) ((spline)->widget.window->pixmap)
1717

18-
#define NPT 4
19-
2018
typedef struct _apps_spline {
2119
twin_widget_t widget;
22-
twin_point_t points[NPT];
20+
int n_points;
21+
twin_point_t *points;
2322
int which;
2423
twin_fixed_t line_width;
2524
twin_cap_t cap_style;
25+
twin_matrix_t transition;
26+
twin_matrix_t inverse_transition;
2627
} apps_spline_t;
2728

29+
static void _init_control_point(apps_spline_t *spline)
30+
{
31+
const int init_point_quad[3][2] = {
32+
{100, 100},
33+
{200, 100},
34+
{300, 100},
35+
};
36+
const int init_point_cubic[4][2] = {
37+
{100, 100},
38+
{300, 300},
39+
{100, 300},
40+
{300, 100},
41+
};
42+
const int(*init_point)[2];
43+
if (spline->n_points == 4) {
44+
init_point = init_point_cubic;
45+
} else if (spline->n_points == 3) {
46+
init_point = init_point_quad;
47+
}
48+
for (int i = 0; i < spline->n_points; i++) {
49+
spline->points[i].x = twin_int_to_fixed(init_point[i][0]);
50+
spline->points[i].y = twin_int_to_fixed(init_point[i][1]);
51+
}
52+
}
53+
54+
static void _draw_aux_line(twin_path_t *path,
55+
apps_spline_t *spline,
56+
int idx1,
57+
int idx2)
58+
{
59+
twin_path_move(path, spline->points[idx1].x, spline->points[idx1].y);
60+
twin_path_draw(path, spline->points[idx2].x, spline->points[idx2].y);
61+
twin_paint_stroke(_apps_spline_pixmap(spline), 0xc08000c0, path,
62+
twin_int_to_fixed(2));
63+
twin_path_empty(path);
64+
}
65+
2866
static void _apps_spline_paint(apps_spline_t *spline)
2967
{
3068
twin_path_t *path;
31-
int i;
32-
3369
path = twin_path_create();
3470
twin_path_set_cap_style(path, spline->cap_style);
71+
twin_path_set_matrix(path, spline->transition);
72+
3573
twin_path_move(path, spline->points[0].x, spline->points[0].y);
36-
twin_path_curve(path, spline->points[1].x, spline->points[1].y,
37-
spline->points[2].x, spline->points[2].y,
38-
spline->points[3].x, spline->points[3].y);
74+
if (spline->n_points == 4) {
75+
twin_path_curve(path, spline->points[1].x, spline->points[1].y,
76+
spline->points[2].x, spline->points[2].y,
77+
spline->points[3].x, spline->points[3].y);
78+
} else if (spline->n_points == 3) {
79+
twin_path_quadratic_curve(path, spline->points[1].x,
80+
spline->points[1].y, spline->points[2].x,
81+
spline->points[2].y);
82+
}
3983
twin_paint_stroke(_apps_spline_pixmap(spline), 0xff404040, path,
4084
spline->line_width);
4185
twin_path_set_cap_style(path, TwinCapButt);
4286
twin_paint_stroke(_apps_spline_pixmap(spline), 0xffffff00, path,
4387
twin_int_to_fixed(2));
44-
45-
twin_path_empty(path);
46-
twin_path_move(path, spline->points[0].x, spline->points[0].y);
47-
twin_path_draw(path, spline->points[1].x, spline->points[1].y);
48-
twin_paint_stroke(_apps_spline_pixmap(spline), 0xc08000c0, path,
49-
twin_int_to_fixed(2));
5088
twin_path_empty(path);
51-
twin_path_move(path, spline->points[3].x, spline->points[3].y);
52-
twin_path_draw(path, spline->points[2].x, spline->points[2].y);
53-
twin_paint_stroke(_apps_spline_pixmap(spline), 0xc08000c0, path,
54-
twin_int_to_fixed(2));
55-
twin_path_empty(path);
56-
for (i = 0; i < NPT; i++) {
89+
if (spline->n_points == 4) {
90+
_draw_aux_line(path, spline, 0, 1);
91+
_draw_aux_line(path, spline, 3, 2);
92+
} else if (spline->n_points == 3) {
93+
_draw_aux_line(path, spline, 0, 1);
94+
_draw_aux_line(path, spline, 1, 2);
95+
}
96+
97+
for (int i = 0; i < spline->n_points; i++) {
5798
twin_path_empty(path);
5899
twin_path_circle(path, spline->points[i].x, spline->points[i].y,
59100
twin_int_to_fixed(10));
@@ -62,13 +103,31 @@ static void _apps_spline_paint(apps_spline_t *spline)
62103
twin_path_destroy(path);
63104
}
64105

106+
static void _apps_spline_button_signal(maybe_unused twin_button_t *button,
107+
twin_button_signal_t signal,
108+
void *closure)
109+
{
110+
if (signal != TwinButtonSignalDown)
111+
return;
112+
113+
apps_spline_t *spline = closure;
114+
spline->n_points = (spline->n_points == 3) ? 4 : 3;
115+
_init_control_point(spline);
116+
_twin_widget_queue_paint(&spline->widget);
117+
}
118+
65119
static twin_dispatch_result_t _apps_spline_update_pos(apps_spline_t *spline,
66120
twin_event_t *event)
67121
{
68122
if (spline->which < 0)
69123
return TwinDispatchContinue;
70-
spline->points[spline->which].x = twin_int_to_fixed(event->u.pointer.x);
71-
spline->points[spline->which].y = twin_int_to_fixed(event->u.pointer.y);
124+
twin_fixed_t x = twin_int_to_fixed(event->u.pointer.x);
125+
twin_fixed_t y = twin_int_to_fixed(event->u.pointer.y);
126+
127+
spline->points[spline->which].x = twin_sfixed_to_fixed(
128+
_twin_matrix_x(&(spline->inverse_transition), x, y));
129+
spline->points[spline->which].y = twin_sfixed_to_fixed(
130+
_twin_matrix_y(&(spline->inverse_transition), x, y));
72131
_twin_widget_queue_paint(&spline->widget);
73132
return TwinDispatchDone;
74133
}
@@ -80,11 +139,15 @@ static int _apps_spline_hit(apps_spline_t *spline,
80139
twin_fixed_t y)
81140
{
82141
int i;
83-
84-
for (i = 0; i < NPT; i++)
85-
if (twin_fixed_abs(x - spline->points[i].x) < spline->line_width / 2 &&
86-
twin_fixed_abs(y - spline->points[i].y) < spline->line_width / 2)
142+
for (i = 0; i < spline->n_points; i++) {
143+
twin_fixed_t px = twin_sfixed_to_fixed(_twin_matrix_x(
144+
&(spline->transition), spline->points[i].x, spline->points[i].y));
145+
twin_fixed_t py = twin_sfixed_to_fixed(_twin_matrix_y(
146+
&(spline->transition), spline->points[i].x, spline->points[i].y));
147+
if (twin_fixed_abs(x - px) < spline->line_width / 2 &&
148+
twin_fixed_abs(y - py) < spline->line_width / 2)
87149
return i;
150+
}
88151
return -1;
89152
}
90153

@@ -123,28 +186,36 @@ static twin_dispatch_result_t _apps_spline_dispatch(twin_widget_t *widget,
123186

124187
static void _apps_spline_init(apps_spline_t *spline,
125188
twin_box_t *parent,
126-
twin_dispatch_proc_t dispatch)
189+
twin_dispatch_proc_t dispatch,
190+
int n_points)
127191
{
128-
static const twin_widget_layout_t preferred = {0, 0, 1, 1};
192+
static twin_widget_layout_t preferred = {0, 0, 1, 1};
193+
preferred.height = parent->widget.window->screen->height * 2 / 3;
129194
_twin_widget_init(&spline->widget, parent, 0, preferred, dispatch);
130195
twin_widget_set(&spline->widget, 0xffffffff);
131196
spline->line_width = twin_int_to_fixed(100);
132197
spline->cap_style = TwinCapRound;
133-
spline->points[0].x = twin_int_to_fixed(100);
134-
spline->points[0].y = twin_int_to_fixed(100);
135-
spline->points[1].x = twin_int_to_fixed(300);
136-
spline->points[1].y = twin_int_to_fixed(300);
137-
spline->points[2].x = twin_int_to_fixed(100);
138-
spline->points[2].y = twin_int_to_fixed(300);
139-
spline->points[3].x = twin_int_to_fixed(300);
140-
spline->points[3].y = twin_int_to_fixed(100);
198+
twin_matrix_identity(&spline->transition);
199+
twin_matrix_rotate(&spline->transition, TWIN_ANGLE_11_25);
200+
twin_matrix_identity(&spline->inverse_transition);
201+
twin_matrix_rotate(&spline->inverse_transition, -TWIN_ANGLE_11_25);
202+
spline->points = calloc(n_points, sizeof(twin_point_t));
203+
spline->n_points = n_points;
204+
_init_control_point(spline);
205+
twin_button_t *button =
206+
twin_button_create(parent, "SwitchCurve", 0xffae0000, D(10),
207+
TwinStyleBold | TwinStyleOblique);
208+
twin_widget_set(&button->label.widget, 0xc0808080);
209+
button->signal = _apps_spline_button_signal;
210+
button->closure = spline;
211+
button->label.widget.shape = TwinShapeRectangle;
141212
}
142213

143-
static apps_spline_t *apps_spline_create(twin_box_t *parent)
214+
static apps_spline_t *apps_spline_create(twin_box_t *parent, int n_points)
144215
{
145216
apps_spline_t *spline = malloc(sizeof(apps_spline_t));
146217

147-
_apps_spline_init(spline, parent, _apps_spline_dispatch);
218+
_apps_spline_init(spline, parent, _apps_spline_dispatch, n_points);
148219
return spline;
149220
}
150221

@@ -157,7 +228,7 @@ void apps_spline_start(twin_screen_t *screen,
157228
{
158229
twin_toplevel_t *toplevel = twin_toplevel_create(
159230
screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h, name);
160-
apps_spline_t *spline = apps_spline_create(&toplevel->box);
231+
apps_spline_t *spline = apps_spline_create(&toplevel->box, 4);
161232
(void) spline;
162233
twin_toplevel_show(toplevel);
163234
}

include/twin.h

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ void twin_event_enqueue(const twin_event_t *event);
659659
*/
660660

661661
#define twin_fixed_mul(a, b) ((twin_fixed_t) (((int64_t) (a) * (b)) >> 16))
662-
#define twin_fixed_div(a, b) ((twin_fixed_t) ((((int64_t) (a)) << 16) / b))
662+
#define twin_fixed_div(a, b) ((twin_fixed_t) ((((int64_t) (a)) << 16) / (b)))
663663

664664
twin_fixed_t twin_fixed_sqrt(twin_fixed_t a);
665665

@@ -789,6 +789,7 @@ void twin_path_ellipse(twin_path_t *path,
789789
twin_fixed_t y,
790790
twin_fixed_t x_radius,
791791
twin_fixed_t y_radius);
792+
792793
void twin_path_arc(twin_path_t *path,
793794
twin_fixed_t x,
794795
twin_fixed_t y,
@@ -797,6 +798,26 @@ void twin_path_arc(twin_path_t *path,
797798
twin_angle_t start,
798799
twin_angle_t extent);
799800

801+
void twin_path_arc_ellipse(twin_path_t *path,
802+
bool large_arc,
803+
bool sweep,
804+
twin_fixed_t radius_x,
805+
twin_fixed_t radius_y,
806+
twin_fixed_t cur_x,
807+
twin_fixed_t cur_y,
808+
twin_fixed_t target_x,
809+
twin_fixed_t target_y,
810+
twin_angle_t rotation);
811+
812+
void twin_path_arc_circle(twin_path_t *path,
813+
bool large_arc,
814+
bool sweep,
815+
twin_fixed_t radius,
816+
twin_fixed_t cur_x,
817+
twin_fixed_t cur_y,
818+
twin_fixed_t target_x,
819+
twin_fixed_t target_y);
820+
800821
void twin_path_rectangle(twin_path_t *path,
801822
twin_fixed_t x,
802823
twin_fixed_t y,
@@ -1050,6 +1071,12 @@ void twin_path_curve(twin_path_t *path,
10501071
twin_fixed_t x3,
10511072
twin_fixed_t y3);
10521073

1074+
void twin_path_quadratic_curve(twin_path_t *path,
1075+
twin_fixed_t x1,
1076+
twin_fixed_t y1,
1077+
twin_fixed_t x2,
1078+
twin_fixed_t y2);
1079+
10531080
/*
10541081
* timeout.c
10551082
*/
@@ -1087,6 +1114,10 @@ twin_fixed_t twin_tan(twin_angle_t a);
10871114

10881115
void twin_sincos(twin_angle_t a, twin_fixed_t *sin, twin_fixed_t *cos);
10891116

1117+
twin_angle_t twin_atan2(twin_fixed_t y, twin_fixed_t x);
1118+
1119+
twin_angle_t twin_acos(twin_fixed_t x);
1120+
10901121
/*
10911122
* widget.c
10921123
*/

0 commit comments

Comments
 (0)