15
15
16
16
#define _apps_spline_pixmap (spline ) ((spline)->widget.window->pixmap)
17
17
18
- #define NPT 4
19
-
20
18
typedef struct _apps_spline {
21
19
twin_widget_t widget ;
22
- twin_point_t points [NPT ];
20
+ int n_points ;
21
+ twin_point_t * points ;
23
22
int which ;
24
23
twin_fixed_t line_width ;
25
24
twin_cap_t cap_style ;
25
+ twin_matrix_t transition ;
26
+ twin_matrix_t inverse_transition ;
26
27
} apps_spline_t ;
27
28
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
+
28
66
static void _apps_spline_paint (apps_spline_t * spline )
29
67
{
30
68
twin_path_t * path ;
31
- int i ;
32
-
33
69
path = twin_path_create ();
34
70
twin_path_set_cap_style (path , spline -> cap_style );
71
+ twin_path_set_matrix (path , spline -> transition );
72
+
35
73
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
+ }
39
83
twin_paint_stroke (_apps_spline_pixmap (spline ), 0xff404040 , path ,
40
84
spline -> line_width );
41
85
twin_path_set_cap_style (path , TwinCapButt );
42
86
twin_paint_stroke (_apps_spline_pixmap (spline ), 0xffffff00 , path ,
43
87
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 ));
50
88
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 ++ ) {
57
98
twin_path_empty (path );
58
99
twin_path_circle (path , spline -> points [i ].x , spline -> points [i ].y ,
59
100
twin_int_to_fixed (10 ));
@@ -62,13 +103,31 @@ static void _apps_spline_paint(apps_spline_t *spline)
62
103
twin_path_destroy (path );
63
104
}
64
105
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
+
65
119
static twin_dispatch_result_t _apps_spline_update_pos (apps_spline_t * spline ,
66
120
twin_event_t * event )
67
121
{
68
122
if (spline -> which < 0 )
69
123
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 ));
72
131
_twin_widget_queue_paint (& spline -> widget );
73
132
return TwinDispatchDone ;
74
133
}
@@ -80,11 +139,15 @@ static int _apps_spline_hit(apps_spline_t *spline,
80
139
twin_fixed_t y )
81
140
{
82
141
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 )
87
149
return i ;
150
+ }
88
151
return -1 ;
89
152
}
90
153
@@ -123,28 +186,36 @@ static twin_dispatch_result_t _apps_spline_dispatch(twin_widget_t *widget,
123
186
124
187
static void _apps_spline_init (apps_spline_t * spline ,
125
188
twin_box_t * parent ,
126
- twin_dispatch_proc_t dispatch )
189
+ twin_dispatch_proc_t dispatch ,
190
+ int n_points )
127
191
{
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 ;
129
194
_twin_widget_init (& spline -> widget , parent , 0 , preferred , dispatch );
130
195
twin_widget_set (& spline -> widget , 0xffffffff );
131
196
spline -> line_width = twin_int_to_fixed (100 );
132
197
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 ;
141
212
}
142
213
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 )
144
215
{
145
216
apps_spline_t * spline = malloc (sizeof (apps_spline_t ));
146
217
147
- _apps_spline_init (spline , parent , _apps_spline_dispatch );
218
+ _apps_spline_init (spline , parent , _apps_spline_dispatch , n_points );
148
219
return spline ;
149
220
}
150
221
@@ -157,7 +228,7 @@ void apps_spline_start(twin_screen_t *screen,
157
228
{
158
229
twin_toplevel_t * toplevel = twin_toplevel_create (
159
230
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 );
161
232
(void ) spline ;
162
233
twin_toplevel_show (toplevel );
163
234
}
0 commit comments