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-
4588 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- 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,32 @@ 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+
119+ #define D (x ) twin_double_to_fixed(x)
65120static twin_dispatch_result_t _apps_spline_update_pos (apps_spline_t * spline ,
66121 twin_event_t * event )
67122{
68123 if (spline -> which < 0 )
69124 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 );
125+ twin_fixed_t x = twin_int_to_fixed (event -> u .pointer .x );
126+ twin_fixed_t y = twin_int_to_fixed (event -> u .pointer .y );
127+
128+ spline -> points [spline -> which ].x = twin_sfixed_to_fixed (
129+ _twin_matrix_x (& (spline -> inverse_transition ), x , y ));
130+ spline -> points [spline -> which ].y = twin_sfixed_to_fixed (
131+ _twin_matrix_y (& (spline -> inverse_transition ), x , y ));
72132 _twin_widget_queue_paint (& spline -> widget );
73133 return TwinDispatchDone ;
74134}
@@ -80,11 +140,15 @@ static int _apps_spline_hit(apps_spline_t *spline,
80140 twin_fixed_t y )
81141{
82142 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 )
143+ for (i = 0 ; i < spline -> n_points ; i ++ ) {
144+ twin_fixed_t px = twin_sfixed_to_fixed (_twin_matrix_x (
145+ & (spline -> transition ), spline -> points [i ].x , spline -> points [i ].y ));
146+ twin_fixed_t py = twin_sfixed_to_fixed (_twin_matrix_y (
147+ & (spline -> transition ), spline -> points [i ].x , spline -> points [i ].y ));
148+ if (twin_fixed_abs (x - px ) < spline -> line_width / 2 &&
149+ twin_fixed_abs (y - py ) < spline -> line_width / 2 )
87150 return i ;
151+ }
88152 return -1 ;
89153}
90154
@@ -123,28 +187,36 @@ static twin_dispatch_result_t _apps_spline_dispatch(twin_widget_t *widget,
123187
124188static void _apps_spline_init (apps_spline_t * spline ,
125189 twin_box_t * parent ,
126- twin_dispatch_proc_t dispatch )
190+ twin_dispatch_proc_t dispatch ,
191+ int n_points )
127192{
128- static const twin_widget_layout_t preferred = {0 , 0 , 1 , 1 };
193+ static twin_widget_layout_t preferred = {0 , 0 , 1 , 1 };
194+ preferred .height = parent -> widget .window -> screen -> height * 2 / 3 ;
129195 _twin_widget_init (& spline -> widget , parent , 0 , preferred , dispatch );
130196 twin_widget_set (& spline -> widget , 0xffffffff );
131197 spline -> line_width = twin_int_to_fixed (100 );
132198 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 );
199+ twin_matrix_identity (& spline -> transition );
200+ twin_matrix_rotate (& spline -> transition , TWIN_ANGLE_11_25 );
201+ twin_matrix_identity (& spline -> inverse_transition );
202+ twin_matrix_rotate (& spline -> inverse_transition , - TWIN_ANGLE_11_25 );
203+ spline -> points = calloc (n_points , sizeof (twin_point_t ));
204+ spline -> n_points = n_points ;
205+ _init_control_point (spline );
206+ twin_button_t * button =
207+ twin_button_create (parent , "SwitchCurve" , 0xffae0000 , D (10 ),
208+ TwinStyleBold | TwinStyleOblique );
209+ twin_widget_set (& button -> label .widget , 0xc0808080 );
210+ button -> signal = _apps_spline_button_signal ;
211+ button -> closure = spline ;
212+ button -> label .widget .shape = TwinShapeRectangle ;
141213}
142214
143- static apps_spline_t * apps_spline_create (twin_box_t * parent )
215+ static apps_spline_t * apps_spline_create (twin_box_t * parent , int n_points )
144216{
145217 apps_spline_t * spline = malloc (sizeof (apps_spline_t ));
146218
147- _apps_spline_init (spline , parent , _apps_spline_dispatch );
219+ _apps_spline_init (spline , parent , _apps_spline_dispatch , n_points );
148220 return spline ;
149221}
150222
@@ -157,7 +229,7 @@ void apps_spline_start(twin_screen_t *screen,
157229{
158230 twin_toplevel_t * toplevel = twin_toplevel_create (
159231 screen , TWIN_ARGB32 , TwinWindowApplication , x , y , w , h , name );
160- apps_spline_t * spline = apps_spline_create (& toplevel -> box );
232+ apps_spline_t * spline = apps_spline_create (& toplevel -> box , 4 );
161233 (void ) spline ;
162234 twin_toplevel_show (toplevel );
163235}
0 commit comments