1515
1616#define _apps_spline_pixmap (spline ) ((spline)->widget.window->pixmap)
1717
18- #define NPT 4
19-
2018typedef 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+
2866static 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+
65119static 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
124187static 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}
0 commit comments