diff options
author | Keith Packard <keithp@keithp.com> | 2004-10-29 17:33:03 +0000 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2004-10-29 17:33:03 +0000 |
commit | d671e983063b71cddc0a2034e51c1fa05d112dc4 (patch) | |
tree | 6e441500d25ce1bf29999cf5335f156d42bc046c | |
parent | c9e17f96155bed7f32a5dfdf3d5ec7ef902e6ae5 (diff) | |
download | libtwin-d671e983063b71cddc0a2034e51c1fa05d112dc4.tar.gz |
add demoline + demospline
Add cap styles, widget shapes, text alignment and arcs Change
circle/ellipse API.
Capture button events.
Use Lozenge shape for output
Drag lines with the mouse
drag splines with the mouse
move '1' right a bit
Convert dispatch result to boool
was mis-computing delegate and crashing when window->event was NULL
Map X button info to twin mask
draw different stuff.
-rw-r--r-- | ChangeLog | 62 | ||||
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | twin.h | 86 | ||||
-rw-r--r-- | twin_box.c | 5 | ||||
-rw-r--r-- | twin_button.c | 3 | ||||
-rw-r--r-- | twin_calc.c | 9 | ||||
-rw-r--r-- | twin_clock.c | 5 | ||||
-rw-r--r-- | twin_convolve.c | 89 | ||||
-rw-r--r-- | twin_demo.c | 51 | ||||
-rw-r--r-- | twin_demoline.c | 157 | ||||
-rw-r--r-- | twin_demoline.h | 55 | ||||
-rw-r--r-- | twin_demospline.c | 169 | ||||
-rw-r--r-- | twin_demospline.h | 57 | ||||
-rw-r--r-- | twin_draw.c | 8 | ||||
-rw-r--r-- | twin_font.c | 2 | ||||
-rw-r--r-- | twin_glyphs.c | 8 | ||||
-rw-r--r-- | twin_label.c | 19 | ||||
-rw-r--r-- | twin_path.c | 219 | ||||
-rw-r--r-- | twin_toplevel.c | 2 | ||||
-rw-r--r-- | twin_widget.c | 85 | ||||
-rw-r--r-- | twin_window.c | 10 | ||||
-rw-r--r-- | twin_x11.c | 4 | ||||
-rw-r--r-- | twinint.h | 9 | ||||
-rw-r--r-- | xtwin.c | 25 |
24 files changed, 989 insertions, 154 deletions
@@ -1,3 +1,65 @@ +2004-10-29 Keith Packard <keithp@keithp.com> + + * Makefile.am: + add demoline + demospline + + * twin.h: + * twin_box.c: (_twin_box_dispatch): + * twin_clock.c: (twin_clock_hand), (_twin_clock_face): + * twin_convolve.c: (_twin_subpath_convolve): + * twin_demo.c: (twin_line_start), (twin_circletext_start), + * twin_draw.c: (twin_composite): + * twin_font.c: (_twin_text_compute_pen): + * twin_label.c: (_twin_label_paint), (_twin_label_init): + * twin_path.c: (twin_path_circle), (twin_path_ellipse), + (twin_path_arc), (twin_path_rectangle), + (twin_path_rounded_rectangle), (twin_path_lozenge), + (twin_path_tab), (twin_path_set_cap_style), + (twin_path_current_cap_style), (twin_path_create), + (twin_composite_stroke): + (twin_quickbrown_start), (twin_ascii_start), (twin_demo_start): + * twin_widget.c: (_twin_path_shape), (_twin_widget_paint_shape), + (_twin_widget_paint), (_twin_widget_init), + (_twin_path_bevel_shape): + * twinint.h: + Add cap styles, widget shapes, text alignment and arcs + Change circle/ellipse API. + + * twin_button.c: (_twin_button_dispatch): + Capture button events. + + * twin_calc.c: (twin_calc_start): + Use Lozenge shape for output + + * twin_demoline.c: (_twin_demoline_paint), + (_twin_demoline_update_pos), (_twin_demoline_hit), + (_twin_demoline_dispatch), (_twin_demoline_init), + (twin_demoline_create), (twin_demoline_start): + * twin_demoline.h: + Drag lines with the mouse + + * twin_demospline.c: (_twin_demospline_paint), + (_twin_demospline_update_pos), (_twin_demospline_hit), + (_twin_demospline_dispatch), (_twin_demospline_init), + (twin_demospline_create), (twin_demospline_start): + * twin_demospline.h: + drag splines with the mouse + + * twin_glyphs.c: + move '1' right a bit + + * twin_toplevel.c: (_twin_toplevel_event): + Convert dispatch result to boool + + * twin_window.c: (twin_window_create), (twin_window_dispatch): + was mis-computing delegate and crashing when window->event was NULL + + * twin_x11.c: (twin_x11_read_events): + Map X button info to twin mask + + * xtwin.c: (main): + draw different stuff. + 2004-10-27 Keith Packard <keithp@keithp.com> * twin_box.c: (_twin_box_dispatch): diff --git a/Makefile.am b/Makefile.am index 547a2f9..ed2aa9c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -56,6 +56,10 @@ xtwin_SOURCES = \ twin_demo.h \ twin_hello.c \ twin_hello.h \ + twin_demoline.c \ + twin_demoline.h \ + twin_demospline.c \ + twin_demospline.h \ xtwin.c xtwin_LDADD = @X_LIBS@ -lm @@ -62,6 +62,9 @@ typedef int16_t twin_angle_t; /* -2048 .. 2048 for -180 .. 180 */ #define TWIN_ANGLE_22_5 (TWIN_ANGLE_360 >> 4) #define TWIN_ANGLE_11_25 (TWIN_ANGLE_360 >> 5) +#define TWIN_ANGLE_270 (TWIN_ANGLE_180 + TWIN_ANGLE_90) +#define TWIN_ANGLE_0 (0) + #define twin_degrees_to_angle(d) ((twin_angle_t) ((((int32_t) (d)) * TWIN_ANGLE_360 / 360))) /* @@ -227,10 +230,17 @@ typedef struct _twin_matrix { typedef struct _twin_path twin_path_t; +typedef enum _twin_cap { + TwinCapRound, + TwinCapButt, + TwinCapProjecting, +} twin_cap_t; + typedef struct _twin_state { twin_matrix_t matrix; twin_fixed_t font_size; twin_style_t font_style; + twin_cap_t cap_style; } twin_state_t; /* @@ -391,18 +401,28 @@ typedef struct _twin_widget_layout { twin_stretch_t stretch_height; } twin_widget_layout_t; +typedef enum _twin_shape { + TwinShapeRectangle, + TwinShapeRoundedRectangle, + TwinShapeLozenge, + TwinShapeTab, + TwinShapeEllipse, +} twin_shape_t; + struct _twin_widget { twin_window_t *window; twin_widget_t *next; twin_box_t *parent; + twin_dispatch_proc_t dispatch; + twin_rect_t extents; /* current geometry */ twin_widget_t *copy_geom; twin_bool_t paint; twin_bool_t layout; twin_bool_t want_focus; twin_argb32_t background; - twin_rect_t extents; /* current geometry */ twin_widget_layout_t preferred; - twin_dispatch_proc_t dispatch; + twin_shape_t shape; + twin_fixed_t radius; }; struct _twin_box { @@ -417,6 +437,10 @@ typedef struct _twin_toplevel { twin_box_t box; } twin_toplevel_t; +typedef enum _twin_align { + TwinAlignLeft, TwinAlignCenter, TwinAlignRight +} twin_align_t; + typedef struct _twin_label { twin_widget_t widget; char *label; @@ -424,6 +448,7 @@ typedef struct _twin_label { twin_fixed_t font_size; twin_style_t font_style; twin_point_t offset; + twin_align_t align; } twin_label_t; typedef enum _twin_button_signal { @@ -670,13 +695,60 @@ void twin_path_rdraw (twin_path_t *path, twin_fixed_t x, twin_fixed_t y); void -twin_path_circle(twin_path_t *path, twin_fixed_t radius); +twin_path_circle(twin_path_t *path, + twin_fixed_t x, + twin_fixed_t y, + twin_fixed_t radius); void -twin_path_ellipse (twin_path_t *path, +twin_path_ellipse (twin_path_t *path, + twin_fixed_t x, + twin_fixed_t y, twin_fixed_t x_radius, twin_fixed_t y_radius); void +twin_path_arc (twin_path_t *path, + twin_fixed_t x, + twin_fixed_t y, + twin_fixed_t x_radius, + twin_fixed_t y_radius, + twin_angle_t start, + twin_angle_t extent); + +void +twin_path_rectangle (twin_path_t *path, + twin_fixed_t x, + twin_fixed_t y, + twin_fixed_t w, + twin_fixed_t h); + +void +twin_path_rounded_rectangle (twin_path_t *path, + twin_fixed_t x, + twin_fixed_t y, + twin_fixed_t w, + twin_fixed_t h, + twin_fixed_t x_radius, + twin_fixed_t y_radius); + +void +twin_path_lozenge (twin_path_t *path, + twin_fixed_t x, + twin_fixed_t y, + twin_fixed_t w, + twin_fixed_t h); + +void +twin_path_tab (twin_path_t *path, + twin_fixed_t x, + twin_fixed_t y, + twin_fixed_t w, + twin_fixed_t h, + twin_fixed_t x_radius, + twin_fixed_t y_radius); + + +void twin_path_close (twin_path_t *path); void @@ -724,6 +796,12 @@ twin_path_current_font_style (twin_path_t *path); void twin_path_set_font_style (twin_path_t *path, twin_style_t font_style); +void +twin_path_set_cap_style (twin_path_t *path, twin_cap_t cap_style); + +twin_cap_t +twin_path_current_cap_style (twin_path_t *path); + twin_state_t twin_path_save (twin_path_t *path); @@ -236,6 +236,11 @@ _twin_box_dispatch (twin_widget_t *widget, twin_event_t *event) twin_pixmap_t *pixmap = box->widget.window->pixmap; twin_rect_t clip = twin_pixmap_current_clip (pixmap); + if (child->shape != TwinShapeRectangle) + twin_fill (child->window->pixmap, + widget->background, TWIN_SOURCE, + child->extents.left, child->extents.top, + child->extents.right, child->extents.bottom); twin_pixmap_set_clip (pixmap, child->extents); child->paint = TWIN_FALSE; (*child->dispatch) (child, event); diff --git a/twin_button.c b/twin_button.c index b340f10..347daf1 100644 --- a/twin_button.c +++ b/twin_button.c @@ -64,6 +64,7 @@ _twin_button_dispatch (twin_widget_t *widget, twin_event_t *event) _twin_button_set_label_offset (button); if (button->signal) (*button->signal) (button, TwinButtonSignalDown, button->closure); + return TwinDispatchDone; break; case TwinEventMotion: if (button->pressed) @@ -77,6 +78,7 @@ _twin_button_dispatch (twin_widget_t *widget, twin_event_t *event) _twin_button_set_label_offset (button); } } + return TwinDispatchDone; break; case TwinEventButtonUp: button->pressed = TWIN_FALSE; @@ -87,6 +89,7 @@ _twin_button_dispatch (twin_widget_t *widget, twin_event_t *event) if (button->signal) (*button->signal) (button, TwinButtonSignalUp, button->closure); } + return TwinDispatchDone; break; default: break; diff --git a/twin_calc.c b/twin_calc.c index 56af91c..36dfda9 100644 --- a/twin_calc.c +++ b/twin_calc.c @@ -81,10 +81,10 @@ static const char *twin_calc_labels[] = { "+", "-", "*", "/", "=", "CLR" }; -#define TWIN_CALC_VALUE_SIZE twin_int_to_fixed(24) -#define TWIN_CALC_VALUE_STYLE TWIN_TEXT_BOLD +#define TWIN_CALC_VALUE_SIZE twin_int_to_fixed(29) +#define TWIN_CALC_VALUE_STYLE TWIN_TEXT_ROMAN #define TWIN_CALC_VALUE_FG 0xff000000 -#define TWIN_CALC_VALUE_BG 0xc0c0c0c0 +#define TWIN_CALC_VALUE_BG 0x80808080 #define TWIN_CALC_BUTTON_SIZE twin_int_to_fixed(15) #define TWIN_CALC_BUTTON_STYLE TWIN_TEXT_BOLD #define TWIN_CALC_BUTTON_FG 0xff000000 @@ -210,6 +210,8 @@ twin_calc_start (twin_screen_t *screen, const char *name, int x, int y, int w, i TWIN_CALC_VALUE_SIZE, TWIN_CALC_VALUE_STYLE); twin_widget_set (&calc->display->widget, TWIN_CALC_VALUE_BG); + calc->display->align = TwinAlignRight; + calc->display->widget.shape = TwinShapeLozenge; calc->keys = twin_box_create (&calc->toplevel->box, TwinBoxHorz); for (i = 0; i < TWIN_CALC_COLS; i++) { @@ -226,6 +228,7 @@ twin_calc_start (twin_screen_t *screen, const char *name, int x, int y, int w, i TWIN_CALC_BUTTON_BG); calc->buttons[b]->signal = _twin_calc_button_signal; calc->buttons[b]->closure = calc; +/* calc->buttons[b]->label.widget.shape = TwinShapeLozenge; */ if (i || j) calc->buttons[b]->label.widget.copy_geom = &calc->buttons[calc_layout[0][0]]->label.widget; } diff --git a/twin_clock.c b/twin_clock.c index 1e4d02f..7fe5bee 100644 --- a/twin_clock.c +++ b/twin_clock.c @@ -89,7 +89,7 @@ twin_clock_hand (twin_clock_t *clock, m.m[2][1] = 0; twin_path_set_matrix (pen, m); twin_path_set_matrix (path, m); - twin_path_circle (pen, fill_width); + twin_path_circle (pen, 0, 0, fill_width); twin_path_convolve (path, stroke, pen); twin_paint_path (_twin_clock_pixmap(clock), fill_pixel, path); @@ -115,8 +115,7 @@ _twin_clock_face (twin_clock_t *clock) twin_clock_set_transform (clock, path); - twin_path_move (path, 0, 0); - twin_path_circle (path, TWIN_FIXED_ONE); + twin_path_circle (path, 0, 0, TWIN_FIXED_ONE); twin_paint_path (_twin_clock_pixmap(clock), TWIN_CLOCK_BACKGROUND, path); diff --git a/twin_convolve.c b/twin_convolve.c index 99ffcd0..0cb565c 100644 --- a/twin_convolve.c +++ b/twin_convolve.c @@ -75,10 +75,10 @@ _around_order (twin_spoint_t *a1, return 0; } +#define F(x) twin_sfixed_to_double(x) #if 0 #include <stdio.h> #include <math.h> -#define F(x) twin_sfixed_to_double(x) #define DBGOUT(x...) printf(x) static double @@ -95,6 +95,8 @@ _angle (twin_spoint_t *a, twin_spoint_t *b) #define DBGOUT(x...) #endif +#define A(a) ((a) < 0 ? -(a) : (a)) + /* * Convolve one subpath with a convex pen. The result is * a closed path. @@ -104,21 +106,22 @@ _twin_subpath_convolve (twin_path_t *path, twin_path_t *stroke, twin_path_t *pen) { - twin_spoint_t *sp = stroke->points; - twin_spoint_t *pp = pen->points; + twin_spoint_t *sp = stroke->points; + twin_spoint_t *pp = pen->points; int ns = stroke->npoints; int np = pen->npoints; - twin_spoint_t *sp0 = &sp[0]; - twin_spoint_t *sp1 = &sp[1]; + twin_spoint_t *sp0 = &sp[0]; + twin_spoint_t *sp1 = &sp[1]; int start = _twin_path_leftpoint (pen, sp0, sp1); - twin_spoint_t *spn1 = &sp[ns-1]; - twin_spoint_t *spn2 = &sp[ns-2]; + twin_spoint_t *spn1 = &sp[ns-1]; + twin_spoint_t *spn2 = &sp[ns-2]; int ret = _twin_path_leftpoint (pen, spn1, spn2); int p; int s; int starget; int ptarget; int inc; + int first; DBGOUT ("convolve stroke:\n"); for (s = 0; s < ns; s++) @@ -135,6 +138,7 @@ _twin_subpath_convolve (twin_path_t *path, p, F(pp[p].x), F(pp[p].y), F(sp[s].x + pp[p].x), F(sp[s].y + pp[p].y)); _twin_path_smove (path, sp[s].x + pp[p].x, sp[s].y + pp[p].y); + first = path->npoints - 1; /* step along the path first */ inc = 1; @@ -186,15 +190,67 @@ _twin_subpath_convolve (twin_path_t *path, */ /* draw a cap */ - while (p != ptarget) - { - if (++p == np) p = 0; - DBGOUT("cap: "); - DBGOUT ("s%02d (%9.4f, %9.4f), p%02d (%9.4f, %9.4f): %9.4f, %9.4f\n", - s, F(sp[s].x), F(sp[s].y), - p, F(pp[p].x), F(pp[p].y), - F(sp[s].x + pp[p].x), F(sp[s].y + pp[p].y)); - _twin_path_sdraw (path, sp[s].x + pp[p].x, sp[s].y + pp[p].y); + switch (path->state.cap_style) { + int pm; + case TwinCapProjecting: + /* + * This draws a rough projecting cap using the + * pen. + * + * First, project the line forward one pen radius + * by finding the pen location halfway between the + * two normals. + * + * Then, just add that to the normals themselves to + * find the corners of the projecting cap. + * + * The result may have significant error, so overwrite + * the existing corners with the new coordinates to + * avoid a kink. + */ + if (p <= ptarget) + pm = (ptarget + p) >> 1; + else + { + pm = (ptarget + np + p) >> 1; + if (pm >= np) pm -= np; + } + + /* replace last point with corner of cap */ + path->npoints--; + _twin_path_sdraw (path, + sp[s].x + pp[pm].x + pp[p].x, + sp[s].y + pp[pm].y + pp[p].y); + p = ptarget; + if (inc == 1) + { + /* start next line at cap corner */ + _twin_path_sdraw (path, + sp[s].x + pp[pm].x + pp[p].x, + sp[s].y + pp[pm].y + pp[p].y); + } + else + { + /* overwrite initial point */ + path->points[first].x = sp[s].x + pp[pm].x + pp[p].x; + path->points[first].y = sp[s].y + pp[pm].y + pp[p].y; + } + break; + case TwinCapButt: + p = ptarget-1; + /* fall through … */ + case TwinCapRound: + while (p != ptarget) + { + if (++p == np) p = 0; + DBGOUT("cap: "); + DBGOUT ("s%02d (%9.4f, %9.4f), p%02d (%9.4f, %9.4f): %9.4f, %9.4f\n", + s, F(sp[s].x), F(sp[s].y), + p, F(pp[p].x), F(pp[p].y), + F(sp[s].x + pp[p].x), F(sp[s].y + pp[p].y)); + _twin_path_sdraw (path, sp[s].x + pp[p].x, sp[s].y + pp[p].y); + } + break; } if (inc == -1) @@ -205,6 +261,7 @@ _twin_subpath_convolve (twin_path_t *path, ptarget = start; starget = 0; } + twin_path_close (path); } void diff --git a/twin_demo.c b/twin_demo.c index 9a387bb..8e8a37e 100644 --- a/twin_demo.c +++ b/twin_demo.c @@ -78,45 +78,24 @@ twin_line_start (twin_screen_t *screen, int x, int y, int w, int h) twin_window_t *window = twin_window_create (screen, TWIN_ARGB32, TwinWindowApplication, x, y, w, h); - int wid = window->client.right - window->client.left; - int hei = window->client.bottom - window->client.top; twin_pixmap_t *pixmap = window->pixmap; - twin_path_t *path = twin_path_create (); - twin_path_t *pen = twin_path_create (); twin_path_t *stroke = twin_path_create (); - twin_pixmap_t *alpha = twin_pixmap_create (TWIN_A8, w, h); - twin_operand_t source, mask; + twin_fixed_t fy; + twin_path_translate (stroke, D(200), D(200)); twin_fill (pixmap, 0xffffffff, TWIN_SOURCE, - 0, 0, wid, hei); + 0, 0, w, h); twin_window_set_name (window, "line"); - twin_path_circle (pen, D (1)); - - stroke = twin_path_create (); - pen = twin_path_create (); - twin_path_translate (stroke, D(100), D(100)); - -/* twin_path_rotate (stroke, twin_degrees_to_angle (270)); */ - twin_path_rotate (stroke, twin_degrees_to_angle (270)); - twin_path_move (stroke, D(0), D(0)); - twin_path_draw (stroke, D(100), D(0)); - twin_path_set_matrix (pen, twin_path_current_matrix (stroke)); - twin_path_circle (pen, D(20)); - twin_path_convolve (path, stroke, pen); - - twin_fill_path (alpha, path, 0, 0); - twin_path_destroy (path); - twin_path_destroy (pen); + for (fy = 0; fy < 150; fy += 40) + { + twin_path_move (stroke, D(-150), -D(fy)); + twin_path_draw (stroke, D(150), D(fy)); + } + twin_path_set_cap_style (stroke, TwinCapProjecting); + twin_paint_stroke (pixmap, 0xff000000, stroke, D(10)); twin_path_destroy (stroke); - source.source_kind = TWIN_SOLID; - source.u.argb = 0xff000000; - mask.source_kind = TWIN_PIXMAP; - mask.u.pixmap = alpha; - twin_composite (pixmap, 0, 0, - &source, 0, 0, &mask, 0, 0, TWIN_OVER, wid, hei); - twin_pixmap_destroy (alpha); twin_window_show (window); } @@ -140,7 +119,7 @@ twin_circletext_start (twin_screen_t *screen, int x, int y, int w, int h) twin_window_set_name (window, "circletext"); twin_path_set_font_style (path, TWIN_TEXT_UNHINTED); - twin_path_circle (pen, D (1)); + twin_path_circle (pen, 0, 0, D (1)); twin_path_translate (path, D(200), D(200)); twin_path_set_font_size (path, D(15)); @@ -186,7 +165,7 @@ twin_quickbrown_start (twin_screen_t *screen, int x, int y, int w, int h) twin_fill (pixmap, 0xffffffff, TWIN_SOURCE, 0, 0, wid, hei); - twin_path_circle (pen, D (1)); + twin_path_circle (pen, 0, 0, D (1)); fx = D(3); fy = D(8); @@ -233,7 +212,7 @@ twin_ascii_start (twin_screen_t *screen, int x, int y, int w, int h) twin_window_set_name (window, "ASCII"); twin_fill (pixmap, 0xffffffff, TWIN_SOURCE, 0, 0, wid, hei); - twin_path_circle (pen, D (1)); + twin_path_circle (pen, 0, 0, D (1)); fx = D(3); fy = D(8); @@ -328,11 +307,15 @@ twin_jelly_start (twin_screen_t *screen, int x, int y, int w, int h) void twin_demo_start (twin_screen_t *screen, const char *name, int x, int y, int w, int h) { +#if 0 twin_circletext_start (screen, x, y, w, h); +#endif twin_line_start (screen, x += 20, y += 20, w, h); +#if 0 twin_quickbrown_start (screen, x += 20, y += 20, w, h); twin_ascii_start (screen, x += 20, y += 20, w, h); twin_jelly_start (screen, x += 20, y += 20, w, h); +#endif #if 0 #if 0 diff --git a/twin_demoline.c b/twin_demoline.c new file mode 100644 index 0000000..3e3837f --- /dev/null +++ b/twin_demoline.c @@ -0,0 +1,157 @@ +/* + * $Id$ + * + * Copyright © 2004 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include <twin_demoline.h> +#include <twinint.h> +#include <stdio.h> + +#define D(x) twin_double_to_fixed(x) + +#define TWIN_CLOCK_BACKGROUND 0xff3b80ae +#define TWIN_CLOCK_HOUR 0x80808080 +#define TWIN_CLOCK_HOUR_OUT 0x30000000 +#define TWIN_CLOCK_MINUTE 0x80808080 +#define TWIN_CLOCK_MINUTE_OUT 0x30000000 +#define TWIN_CLOCK_SECOND 0x80808080 +#define TWIN_CLOCK_SECOND_OUT 0x30000000 +#define TWIN_CLOCK_TIC 0xffbababa +#define TWIN_CLOCK_NUMBERS 0xffdedede +#define TWIN_CLOCK_WATER 0x60200000 +#define TWIN_CLOCK_WATER_OUT 0x40404040 +#define TWIN_CLOCK_WATER_UNDER 0x60400000 +#define TWIN_CLOCK_BORDER 0xffbababa +#define TWIN_CLOCK_BORDER_WIDTH D(0.01) + +#define _twin_demoline_pixmap(demoline) ((demoline)->widget.window->pixmap) + +void +_twin_demoline_paint (twin_demoline_t *demoline) +{ + twin_path_t *path; + + path = twin_path_create (); + twin_path_set_cap_style (path, demoline->cap_style); + twin_path_move (path, demoline->points[0].x, demoline->points[0].y); + twin_path_draw (path, demoline->points[1].x, demoline->points[1].y); + twin_paint_stroke (_twin_demoline_pixmap(demoline), 0xff000000, path, + demoline->line_width); + twin_path_set_cap_style (path, TwinCapButt); + twin_paint_stroke (_twin_demoline_pixmap(demoline), 0xffff0000, path, + twin_int_to_fixed (2)); + twin_path_destroy (path); +} + +static twin_dispatch_result_t +_twin_demoline_update_pos (twin_demoline_t *demoline, twin_event_t *event) +{ + if (demoline->which < 0) + return TwinDispatchContinue; + demoline->points[demoline->which].x = twin_int_to_fixed (event->u.pointer.x); + demoline->points[demoline->which].y = twin_int_to_fixed (event->u.pointer.y); + _twin_widget_queue_paint (&demoline->widget); + return TwinDispatchDone; +} + +#define twin_fixed_abs(f) ((f) < 0 ? -(f) : (f)) + +static int +_twin_demoline_hit (twin_demoline_t *demoline, twin_fixed_t x, twin_fixed_t y) +{ + int i; + + for (i = 0; i < 2; i++) + if (twin_fixed_abs (x - demoline->points[i].x) < demoline->line_width / 2 && + twin_fixed_abs (y - demoline->points[i].y) < demoline->line_width / 2) + return i; + return -1; +} + +twin_dispatch_result_t +_twin_demoline_dispatch (twin_widget_t *widget, twin_event_t *event) +{ + twin_demoline_t *demoline = (twin_demoline_t *) widget; + + if (_twin_widget_dispatch (widget, event) == TwinDispatchDone) + return TwinDispatchDone; + switch (event->kind) { + case TwinEventPaint: + _twin_demoline_paint (demoline); + break; + case TwinEventButtonDown: + demoline->which = _twin_demoline_hit (demoline, + twin_int_to_fixed (event->u.pointer.x), + twin_int_to_fixed (event->u.pointer.y)); + return _twin_demoline_update_pos (demoline, event); + break; + case TwinEventMotion: + return _twin_demoline_update_pos (demoline, event); + break; + case TwinEventButtonUp: + if (demoline->which < 0) + return TwinDispatchContinue; + _twin_demoline_update_pos (demoline, event); + demoline->which = -1; + return TwinDispatchDone; + break; + default: + break; + } + return TwinDispatchContinue; +} + +void +_twin_demoline_init (twin_demoline_t *demoline, + twin_box_t *parent, + twin_dispatch_proc_t dispatch) +{ + static const twin_widget_layout_t preferred = { 0, 0, 1, 1 }; + _twin_widget_init (&demoline->widget, parent, 0, preferred, dispatch); + twin_widget_set (&demoline->widget, 0xffffffff); + demoline->line_width = twin_int_to_fixed (30); + demoline->cap_style = TwinCapProjecting; + demoline->points[0].x = twin_int_to_fixed (50); + demoline->points[0].y = twin_int_to_fixed (50); + demoline->points[1].x = twin_int_to_fixed (100); + demoline->points[1].y = twin_int_to_fixed (100); +} + +twin_demoline_t * +twin_demoline_create (twin_box_t *parent) +{ + twin_demoline_t *demoline = malloc (sizeof (twin_demoline_t)); + + _twin_demoline_init(demoline, parent, _twin_demoline_dispatch); + return demoline; +} + +void +twin_demoline_start (twin_screen_t *screen, const char *name, int x, int y, int w, int h) +{ + twin_toplevel_t *toplevel = twin_toplevel_create (screen, TWIN_ARGB32, + TwinWindowApplication, + x, y, w, h, name); + twin_demoline_t *demoline = twin_demoline_create (&toplevel->box); + (void) demoline; + twin_toplevel_show (toplevel); +} diff --git a/twin_demoline.h b/twin_demoline.h new file mode 100644 index 0000000..433c7f0 --- /dev/null +++ b/twin_demoline.h @@ -0,0 +1,55 @@ +/* + * $Id$ + * + * Copyright © 2004 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _TWIN_DEMOLINE_H_ +#define _TWIN_DEMOLINE_H_ + +#include <twin.h> + +typedef struct _twin_demoline { + twin_widget_t widget; + twin_point_t points[2]; + int which; + twin_fixed_t line_width; + twin_cap_t cap_style; +} twin_demoline_t; + +void +_twin_demoline_paint (twin_demoline_t *demoline); + +twin_dispatch_result_t +_twin_demoline_dispatch (twin_widget_t *widget, twin_event_t *event); + +void +_twin_demoline_init (twin_demoline_t *demoline, + twin_box_t *parent, + twin_dispatch_proc_t dispatch); + +twin_demoline_t * +twin_demoline_create (twin_box_t *parent); + +void +twin_demoline_start (twin_screen_t *screen, const char *name, int x, int y, int w, int h); + +#endif /* _TWIN_DEMOLINE_H_ */ diff --git a/twin_demospline.c b/twin_demospline.c new file mode 100644 index 0000000..0ae02be --- /dev/null +++ b/twin_demospline.c @@ -0,0 +1,169 @@ +/* + * $Id$ + * + * Copyright © 2004 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include <twin_demospline.h> +#include <twinint.h> +#include <stdio.h> + +#define D(x) twin_double_to_fixed(x) + +#define _twin_demospline_pixmap(demospline) ((demospline)->widget.window->pixmap) + +void +_twin_demospline_paint (twin_demospline_t *demospline) +{ + twin_path_t *path; + int i; + + path = twin_path_create (); + twin_path_set_cap_style (path, demospline->cap_style); + twin_path_move (path, demospline->points[0].x, demospline->points[0].y); + twin_path_curve (path, + demospline->points[1].x, demospline->points[1].y, + demospline->points[2].x, demospline->points[2].y, + demospline->points[3].x, demospline->points[3].y); + twin_paint_stroke (_twin_demospline_pixmap(demospline), 0xff404040, path, + demospline->line_width); + twin_path_set_cap_style (path, TwinCapButt); + twin_paint_stroke (_twin_demospline_pixmap(demospline), 0xffffff00, path, + twin_int_to_fixed (2)); + + twin_path_empty (path); + twin_path_move (path, demospline->points[0].x, demospline->points[0].y); + twin_path_draw (path, demospline->points[1].x, demospline->points[1].y); + twin_paint_stroke (_twin_demospline_pixmap(demospline), 0xc08000c0, path, + twin_int_to_fixed (2)); + twin_path_empty (path); + twin_path_move (path, demospline->points[3].x, demospline->points[3].y); + twin_path_draw (path, demospline->points[2].x, demospline->points[2].y); + twin_paint_stroke (_twin_demospline_pixmap(demospline), 0xc08000c0, path, + twin_int_to_fixed (2)); + twin_path_empty (path); + for (i = 0; i < NPT; i++) + { + twin_path_empty (path); + twin_path_circle (path, demospline->points[i].x, demospline->points[i].y, + twin_int_to_fixed (10)); + twin_paint_path (_twin_demospline_pixmap(demospline), 0x40004020, path); + } + twin_path_destroy (path); +} + +static twin_dispatch_result_t +_twin_demospline_update_pos (twin_demospline_t *demospline, twin_event_t *event) +{ + if (demospline->which < 0) + return TwinDispatchContinue; + demospline->points[demospline->which].x = twin_int_to_fixed (event->u.pointer.x); + demospline->points[demospline->which].y = twin_int_to_fixed (event->u.pointer.y); + _twin_widget_queue_paint (&demospline->widget); + return TwinDispatchDone; +} + +#define twin_fixed_abs(f) ((f) < 0 ? -(f) : (f)) + +static int +_twin_demospline_hit (twin_demospline_t *demospline, twin_fixed_t x, twin_fixed_t y) +{ + int i; + + for (i = 0; i < NPT; i++) + if (twin_fixed_abs (x - demospline->points[i].x) < demospline->line_width / 2 && + twin_fixed_abs (y - demospline->points[i].y) < demospline->line_width / 2) + return i; + return -1; +} + +twin_dispatch_result_t +_twin_demospline_dispatch (twin_widget_t *widget, twin_event_t *event) +{ + twin_demospline_t *demospline = (twin_demospline_t *) widget; + + if (_twin_widget_dispatch (widget, event) == TwinDispatchDone) + return TwinDispatchDone; + switch (event->kind) { + case TwinEventPaint: + _twin_demospline_paint (demospline); + break; + case TwinEventButtonDown: + demospline->which = _twin_demospline_hit (demospline, + twin_int_to_fixed (event->u.pointer.x), + twin_int_to_fixed (event->u.pointer.y)); + return _twin_demospline_update_pos (demospline, event); + break; + case TwinEventMotion: + return _twin_demospline_update_pos (demospline, event); + break; + case TwinEventButtonUp: + if (demospline->which < 0) + return TwinDispatchContinue; + _twin_demospline_update_pos (demospline, event); + demospline->which = -1; + return TwinDispatchDone; + break; + default: + break; + } + return TwinDispatchContinue; +} + +void +_twin_demospline_init (twin_demospline_t *demospline, + twin_box_t *parent, + twin_dispatch_proc_t dispatch) +{ + static const twin_widget_layout_t preferred = { 0, 0, 1, 1 }; + _twin_widget_init (&demospline->widget, parent, 0, preferred, dispatch); + twin_widget_set (&demospline->widget, 0xffffffff); + demospline->line_width = twin_int_to_fixed (100); + demospline->cap_style = TwinCapButt; + demospline->points[0].x = twin_int_to_fixed (100); + demospline->points[0].y = twin_int_to_fixed (100); + demospline->points[1].x = twin_int_to_fixed (300); + demospline->points[1].y = twin_int_to_fixed (300); + demospline->points[2].x = twin_int_to_fixed (100); + demospline->points[2].y = twin_int_to_fixed (300); + demospline->points[3].x = twin_int_to_fixed (300); + demospline->points[3].y = twin_int_to_fixed (100); +} + +twin_demospline_t * +twin_demospline_create (twin_box_t *parent) +{ + twin_demospline_t *demospline = malloc (sizeof (twin_demospline_t)); + + _twin_demospline_init(demospline, parent, _twin_demospline_dispatch); + return demospline; +} + +void +twin_demospline_start (twin_screen_t *screen, const char *name, int x, int y, int w, int h) +{ + twin_toplevel_t *toplevel = twin_toplevel_create (screen, TWIN_ARGB32, + TwinWindowApplication, + x, y, w, h, name); + twin_demospline_t *demospline = twin_demospline_create (&toplevel->box); + (void) demospline; + twin_toplevel_show (toplevel); +} diff --git a/twin_demospline.h b/twin_demospline.h new file mode 100644 index 0000000..87f7ae7 --- /dev/null +++ b/twin_demospline.h @@ -0,0 +1,57 @@ +/* + * $Id$ + * + * Copyright © 2004 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _TWIN_DEMOSPLINE_H_ +#define _TWIN_DEMOSPLINE_H_ + +#include <twin.h> + +#define NPT 4 + +typedef struct _twin_demospline { + twin_widget_t widget; + twin_point_t points[NPT]; + int which; + twin_fixed_t line_width; + twin_cap_t cap_style; +} twin_demospline_t; + +void +_twin_demospline_paint (twin_demospline_t *demospline); + +twin_dispatch_result_t +_twin_demospline_dispatch (twin_widget_t *widget, twin_event_t *event); + +void +_twin_demospline_init (twin_demospline_t *demospline, + twin_box_t *parent, + twin_dispatch_proc_t dispatch); + +twin_demospline_t * +twin_demospline_create (twin_box_t *parent); + +void +twin_demospline_start (twin_screen_t *screen, const char *name, int x, int y, int w, int h); + +#endif /* _TWIN_DEMOLINE_H_ */ diff --git a/twin_draw.c b/twin_draw.c index a4d7fe3..c67f638 100644 --- a/twin_draw.c +++ b/twin_draw.c @@ -274,23 +274,23 @@ twin_composite (twin_pixmap_t *dst, twin_coord_t height) { twin_coord_t iy; - twin_coord_t left, right, top, bottom; + twin_coord_t left, top, right, bottom; twin_coord_t sdx, sdy; twin_source_u s; dst_x += dst->clip.left; dst_y += dst->clip.top; left = dst_x; - right = dst_x + width; top = dst_y; + right = dst_x + width; bottom = dst_y + height; /* clip */ if (left < dst->clip.left) left = dst->clip.left; - if (right > dst->clip.right) - right = dst->clip.right; if (top < dst->clip.top) top = dst->clip.top; + if (right > dst->clip.right) + right = dst->clip.right; if (bottom > dst->clip.bottom) bottom = dst->clip.bottom; diff --git a/twin_font.c b/twin_font.c index 509cc16..aaf22d2 100644 --- a/twin_font.c +++ b/twin_font.c @@ -196,7 +196,7 @@ _twin_text_compute_pen (twin_text_info_t *info) twin_path_t *pen = twin_path_create (); twin_path_set_matrix (pen, info->pen_matrix); - twin_path_circle (pen, TWIN_FIXED_ONE); + twin_path_circle (pen, 0, 0, TWIN_FIXED_ONE); return pen; } diff --git a/twin_glyphs.c b/twin_glyphs.c index d153b54..41c9757 100644 --- a/twin_glyphs.c +++ b/twin_glyphs.c @@ -209,11 +209,11 @@ const signed char _twin_gtable[] = { 'e', /* 0x31 '1' offset 666 */ 0, 28, 42, 0, 2, 3, - 0, 14, 28 /* snap_x */ + 0, 17, 28 /* snap_x */ -21, -15, 0, /* snap_y */ - 'm', 4, -34, - 'c', 8, -35, 12, -38, 14, -42, - 'l', 14, 0, + 'm', 7, -34, + 'c', 11, -35, 15, -38, 17, -42, + 'l', 17, 0, 'e', /* 0x32 '2' offset 691 */ 0, 28, 42, 0, 4, 4, diff --git a/twin_label.c b/twin_label.c index 6d74160..fb43372 100644 --- a/twin_label.c +++ b/twin_label.c @@ -54,13 +54,25 @@ _twin_label_paint (twin_label_t *label) { twin_fixed_t wf = twin_int_to_fixed (w); twin_fixed_t hf = twin_int_to_fixed (h); + twin_fixed_t x, y; twin_path_set_font_size (path, label->font_size); twin_path_set_font_style (path, label->font_style); twin_text_metrics_utf8 (path, label->label, &m); - twin_path_move (path, (wf - m.width) / 2 + label->offset.x, - (hf - (m.ascent + m.descent)) / 2 + m.ascent + label->offset.y); - + y = (hf - (m.ascent + m.descent)) / 2 + m.ascent + label->offset.y; + switch (label->align) { + case TwinAlignLeft: + x = label->font_size / 2; + break; + case TwinAlignCenter: + x = (wf - m.width) / 2; + break; + case TwinAlignRight: + x = wf - label->font_size / 2 - m.width; + break; + } + x += label->offset.x; + twin_path_move (path, x, y); twin_path_utf8 (path, label->label); twin_paint_path (label->widget.window->pixmap, label->foreground, path); twin_path_destroy (path); @@ -126,6 +138,7 @@ _twin_label_init (twin_label_t *label, label->label = NULL; label->offset.x = 0; label->offset.y = 0; + label->align = TwinAlignCenter; twin_label_set (label, value, foreground, font_size, font_style); } diff --git a/twin_path.c b/twin_path.c index d2eade6..a226fff 100644 --- a/twin_path.c +++ b/twin_path.c @@ -192,6 +192,27 @@ twin_path_close (twin_path_t *path) } } +void +twin_path_circle (twin_path_t *path, + twin_fixed_t x, + twin_fixed_t y, + twin_fixed_t radius) +{ + twin_path_ellipse (path, x, y, radius, radius); +} + +void +twin_path_ellipse (twin_path_t *path, + twin_fixed_t x, + twin_fixed_t y, + twin_fixed_t x_radius, + twin_fixed_t y_radius) +{ + twin_path_move (path, x + x_radius, y); + twin_path_arc (path, x, y, x_radius, y_radius, 0, TWIN_ANGLE_360); + twin_path_close (path); +} + #define twin_fixed_abs(f) ((f) < 0 ? -(f) : (f)) static twin_fixed_t @@ -202,90 +223,146 @@ _twin_matrix_max_radius (twin_matrix_t *m) } void -twin_path_circle (twin_path_t *path, twin_fixed_t radius) -{ - int sides; - int n; - twin_spoint_t center; - int i; - twin_matrix_t save; +twin_path_arc (twin_path_t *path, + twin_fixed_t x, + twin_fixed_t y, + twin_fixed_t x_radius, + twin_fixed_t y_radius, + twin_angle_t start, + twin_angle_t extent) +{ + twin_matrix_t save = twin_path_current_matrix (path); twin_fixed_t max_radius; + int32_t sides; + int32_t n; + twin_angle_t a; + twin_angle_t first, last, step, inc; + twin_angle_t epsilon; - save = twin_path_current_matrix (path); - - twin_path_scale (path, radius, radius); - - center = _twin_path_current_spoint (path); + twin_path_translate (path, x, y); + twin_path_scale (path, x_radius, y_radius); - _twin_path_sfinish (path); - max_radius = _twin_matrix_max_radius (&path->state.matrix); - sides = max_radius / twin_sfixed_to_fixed (TWIN_SFIXED_TOLERANCE); - if (sides > 1024) sides = 1024; n = 2; while ((1 << n) < sides) n++; - for (i = 0; i <= (1 << n); i++) - { - twin_angle_t a = (i * TWIN_ANGLE_360) >> n; - twin_fixed_t x = twin_cos (a); - twin_fixed_t y = twin_sin (a); + sides = (1 << n); - _twin_path_sdraw (path, - center.x + _twin_matrix_dx (&path->state.matrix, x, y), - center.y + _twin_matrix_dy (&path->state.matrix, x, y)); + step = TWIN_ANGLE_360 >> n; + inc = step; + epsilon = 1; + if (extent < 0) + { + inc = -inc; + epsilon = -1; } - _twin_path_sfinish (path); + first = (start + inc - epsilon) & ~(step - 1); + last = (start + extent - inc + epsilon) & ~(step - 1); + + if (first != start) + twin_path_draw (path, twin_cos(start), twin_sin(start)); + + for (a = first; a != last; a += inc) + twin_path_draw (path, twin_cos (a), twin_sin (a)); + + if (last != start + extent) + twin_path_draw (path, twin_cos (start+extent), twin_sin(start+extent)); + twin_path_set_matrix (path, save); } void -twin_path_ellipse (twin_path_t *path, - twin_fixed_t x_radius, - twin_fixed_t y_radius) +twin_path_rectangle (twin_path_t *path, + twin_fixed_t x, + twin_fixed_t y, + twin_fixed_t w, + twin_fixed_t h) +{ + twin_path_move (path, x, y); + twin_path_draw (path, x+w, y); + twin_path_draw (path, x+w, y+h); + twin_path_draw (path, x, y+h); + twin_path_close (path); +} + +void +twin_path_rounded_rectangle (twin_path_t *path, + twin_fixed_t x, + twin_fixed_t y, + twin_fixed_t w, + twin_fixed_t h, + twin_fixed_t x_radius, + twin_fixed_t y_radius) +{ + twin_matrix_t save = twin_path_current_matrix (path); + + twin_path_translate (path, x, y); + twin_path_move (path, + 0, y_radius); + twin_path_arc (path, x_radius, y_radius, x_radius, y_radius, + TWIN_ANGLE_180, TWIN_ANGLE_90); + twin_path_draw (path, + w - x_radius, 0); + twin_path_arc (path, w - x_radius, y_radius, x_radius, y_radius, + TWIN_ANGLE_270, TWIN_ANGLE_90); + twin_path_draw (path, + w, h - y_radius); + twin_path_arc (path, w - x_radius, h - y_radius, x_radius, y_radius, + TWIN_ANGLE_0, TWIN_ANGLE_90); + twin_path_draw (path, + x_radius, h); + twin_path_arc (path, x_radius, h - y_radius, x_radius, y_radius, + TWIN_ANGLE_90, TWIN_ANGLE_90); + twin_path_close (path); + twin_path_set_matrix (path, save); +} + +void +twin_path_lozenge (twin_path_t *path, + twin_fixed_t x, + twin_fixed_t y, + twin_fixed_t w, + twin_fixed_t h) { - int sides; - int n; - twin_spoint_t center; - int i; - twin_matrix_t save; - twin_fixed_t max_radius; - - save = twin_path_current_matrix (path); - - twin_path_scale (path, x_radius, y_radius); - - center = _twin_path_current_spoint (path); - - _twin_path_sfinish (path); - - max_radius = _twin_matrix_max_radius (&path->state.matrix); - - sides = max_radius / twin_sfixed_to_fixed (TWIN_SFIXED_TOLERANCE); - - if (sides > 1024) sides = 1024; + twin_fixed_t radius; - n = 2; - while ((1 << n) < sides) - n++; - - for (i = 0; i <= (1 << n); i++) - { - twin_angle_t a = (i * TWIN_ANGLE_360) >> n; - twin_fixed_t x = twin_cos (a); - twin_fixed_t y = twin_sin (a); + if (w > h) + radius = h / 2; + else + radius = w / 2; + twin_path_rounded_rectangle (path, x, y, w, h, radius, radius); +} - _twin_path_sdraw (path, - center.x + _twin_matrix_dx (&path->state.matrix, x, y), - center.y + _twin_matrix_dy (&path->state.matrix, x, y)); - } - - _twin_path_sfinish (path); +void +twin_path_tab (twin_path_t *path, + twin_fixed_t x, + twin_fixed_t y, + twin_fixed_t w, + twin_fixed_t h, + twin_fixed_t x_radius, + twin_fixed_t y_radius) +{ + twin_matrix_t save = twin_path_current_matrix (path); + + twin_path_translate (path, x, y); + twin_path_move (path, + 0, y_radius); + twin_path_arc (path, x_radius, y_radius, x_radius, y_radius, + TWIN_ANGLE_180, TWIN_ANGLE_90); + twin_path_draw (path, + w - x_radius, 0); + twin_path_arc (path, w - x_radius, y_radius, x_radius, y_radius, + TWIN_ANGLE_270, TWIN_ANGLE_90); + twin_path_draw (path, + w, h); + twin_path_draw (path, + 0, h); + twin_path_close (path); twin_path_set_matrix (path, save); } @@ -350,6 +427,18 @@ twin_path_current_font_style (twin_path_t *path) } void +twin_path_set_cap_style (twin_path_t *path, twin_cap_t cap_style) +{ + path->state.cap_style = cap_style; +} + +twin_cap_t +twin_path_current_cap_style (twin_path_t *path) +{ + return path->state.cap_style; +} + +void twin_path_empty (twin_path_t *path) { path->npoints = 0; @@ -424,6 +513,7 @@ twin_path_create (void) twin_matrix_identity (&path->state.matrix); path->state.font_size = TWIN_FIXED_ONE * 15; path->state.font_style = TWIN_TEXT_ROMAN; + path->state.cap_style = TwinCapRound; return path; } @@ -496,7 +586,8 @@ twin_composite_stroke (twin_pixmap_t *dst, m.m[2][0] = 0; m.m[2][1] = 0; twin_path_set_matrix (pen, m); - twin_path_circle (pen, pen_width / 2); + twin_path_set_cap_style (path, twin_path_current_cap_style (stroke)); + twin_path_circle (pen, 0, 0, pen_width / 2); twin_path_convolve (path, stroke, pen); twin_composite_path (dst, src, src_x, src_y, path, operator); twin_path_destroy (path); diff --git a/twin_toplevel.c b/twin_toplevel.c index 42de014..9ce8e7a 100644 --- a/twin_toplevel.c +++ b/twin_toplevel.c @@ -51,7 +51,7 @@ _twin_toplevel_event (twin_window_t *window, { twin_toplevel_t *toplevel = window->client_data; - return (*toplevel->box.widget.dispatch) (&toplevel->box.widget, event); + return (*toplevel->box.widget.dispatch) (&toplevel->box.widget, event) == TwinDispatchDone; } static void diff --git a/twin_widget.c b/twin_widget.c index 372cdcf..34ef0dc 100644 --- a/twin_widget.c +++ b/twin_widget.c @@ -24,14 +24,74 @@ #include "twinint.h" -static void -_twin_widget_paint (twin_widget_t *widget) +static twin_path_t * +_twin_path_shape (twin_shape_t shape, + twin_coord_t left, + twin_coord_t top, + twin_coord_t right, + twin_coord_t bottom, + twin_fixed_t radius) +{ + twin_path_t *path = twin_path_create (); + twin_fixed_t x = twin_int_to_fixed (left); + twin_fixed_t y = twin_int_to_fixed (top); + twin_fixed_t w = twin_int_to_fixed (right - left); + twin_fixed_t h = twin_int_to_fixed (bottom - top); + + if (!path) + return 0; + switch (shape) { + case TwinShapeRectangle: + twin_path_rectangle (path, x, y, w, h); + break; + case TwinShapeRoundedRectangle: + twin_path_rounded_rectangle (path, x, h, w, y, radius, radius); + break; + case TwinShapeLozenge: + twin_path_lozenge (path, x, y, w, h); + break; + case TwinShapeTab: + twin_path_tab (path, x, y, w, h, radius, radius); + break; + case TwinShapeEllipse: + twin_path_ellipse (path, x + w/2, y + h/2, w/2, h/2); + break; + } + return path; +} + +void +_twin_widget_paint_shape (twin_widget_t *widget, + twin_shape_t shape, + twin_coord_t left, + twin_coord_t top, + twin_coord_t right, + twin_coord_t bottom, + twin_fixed_t radius) { twin_pixmap_t *pixmap = widget->window->pixmap; - twin_coord_t w = widget->extents.right - widget->extents.left; - twin_coord_t h = widget->extents.bottom - widget->extents.top; - twin_fill (pixmap, widget->background, TWIN_SOURCE, 0, 0, w, h); + if (shape == TwinShapeRectangle) + twin_fill (pixmap, widget->background, TWIN_SOURCE, + left, top, right, bottom); + else + { + twin_path_t *path = _twin_path_shape (shape, left, top, + right, bottom, radius); + if (path) + { + twin_paint_path (pixmap, widget->background, path); + twin_path_destroy (path); + } + } +} + +static void +_twin_widget_paint (twin_widget_t *widget) +{ + _twin_widget_paint_shape (widget, widget->shape, 0, 0, + _twin_widget_width (widget), + _twin_widget_height (widget), widget->radius); } twin_dispatch_result_t @@ -91,6 +151,8 @@ _twin_widget_init (twin_widget_t *widget, widget->extents.right = widget->extents.bottom = 0; widget->preferred = preferred; widget->dispatch = dispatch; + widget->shape = TwinShapeRectangle; + widget->radius = twin_int_to_fixed (12); } void @@ -129,6 +191,19 @@ _twin_widget_contains (twin_widget_t *widget, 0 <= y && y < _twin_widget_height(widget)); } +static twin_path_t * +_twin_path_bevel_shape (twin_shape_t shape, + twin_bool_t upper, + twin_coord_t left, + twin_coord_t top, + twin_coord_t right, + twin_coord_t bottom, + twin_fixed_t radius, + twin_fixed_t bw) +{ + return 0; +} + void _twin_widget_bevel (twin_widget_t *widget, twin_fixed_t b, diff --git a/twin_window.c b/twin_window.c index 0f489f5..086a8ad 100644 --- a/twin_window.c +++ b/twin_window.c @@ -43,7 +43,7 @@ twin_window_create (twin_screen_t *screen, twin_coord_t height) { twin_window_t *window = malloc (sizeof (twin_window_t)); - twin_coord_t left, right, top, bottom; + twin_coord_t left, top, right, bottom; if (!window) return NULL; window->screen = screen; @@ -66,8 +66,8 @@ twin_window_create (twin_screen_t *screen, width += left + right; height += top + bottom; window->client.left = left; - window->client.right = width - right; window->client.top = top; + window->client.right = width - right; window->client.bottom = height - bottom; window->pixmap = twin_pixmap_create (format, width, height); twin_pixmap_clip (window->pixmap, @@ -334,9 +334,6 @@ twin_window_dispatch (twin_window_t *window, twin_event_t *event) twin_event_t ev = *event; twin_bool_t delegate = TWIN_TRUE; - if (!window->event) - delegate = TWIN_FALSE; - switch (ev.kind) { case TwinEventButtonDown: if (window->client.left <= ev.u.pointer.x && @@ -380,6 +377,9 @@ twin_window_dispatch (twin_window_t *window, twin_event_t *event) default: break; } + if (!window->event) + delegate = TWIN_FALSE; + if (delegate && (*window->event) (window, &ev)) return TWIN_TRUE; @@ -105,6 +105,8 @@ twin_x11_read_events (int file, case ButtonRelease: tev.u.pointer.screen_x = ev.xbutton.x; tev.u.pointer.screen_y = ev.xbutton.y; + tev.u.pointer.button = ((ev.xbutton.state >> 8) | + (1 << (ev.xbutton.button-1))); tev.kind = ((ev.type == ButtonPress) ? TwinEventButtonDown : TwinEventButtonUp); twin_screen_dispatch (tx->screen, &tev); @@ -113,7 +115,7 @@ twin_x11_read_events (int file, tev.u.pointer.screen_x = ev.xmotion.x; tev.u.pointer.screen_y = ev.xmotion.y; tev.kind = TwinEventMotion; - tev.u.pointer.button = ev.xmotion.state; + tev.u.pointer.button = ev.xbutton.state >> 8; twin_screen_dispatch (tx->screen, &tev); break; } @@ -468,6 +468,15 @@ _twin_widget_init (twin_widget_t *widget, twin_widget_layout_t preferred, twin_dispatch_proc_t dispatch); +void +_twin_widget_paint_shape (twin_widget_t *widget, + twin_shape_t shape, + twin_coord_t left, + twin_coord_t top, + twin_coord_t right, + twin_coord_t bottom, + twin_fixed_t radius); + twin_dispatch_result_t _twin_widget_dispatch (twin_widget_t *widget, twin_event_t *event); @@ -34,6 +34,8 @@ #include <twin_demo.h> #include <twin_hello.h> #include <twin_calc.h> +#include <twin_demoline.h> +#include <twin_demospline.h> #define WIDTH 512 #define HEIGHT 512 @@ -47,14 +49,25 @@ main (int argc, char **argv) twin_screen_set_background (x11->screen, twin_make_pattern ()); #if 0 twin_demo_start (x11->screen, "Demo", 100, 100, 400, 400); - twin_text_start (x11->screen, "Gettysburg Address", - 0, 0, 300, 300); - twin_hello_start (x11->screen, "Hello, World", - 0, 0, 200, 200); #endif +#if 0 + twin_text_start (x11->screen, "Gettysburg Address", 0, 0, 300, 300); +#endif +#if 0 + twin_hello_start (x11->screen, "Hello, World", 0, 0, 200, 200); +#endif +#if 1 twin_clock_start (x11->screen, "Clock", 10, 10, 200, 200); - twin_calc_start (x11->screen, "Calculator", - 100, 100, 200, 200); +#endif +#if 1 + twin_calc_start (x11->screen, "Calculator", 100, 100, 200, 200); +#endif +#if 1 + twin_demoline_start (x11->screen, "Demo Line", 0, 0, 400, 400); +#endif +#if 1 + twin_demospline_start (x11->screen, "Demo Spline", 20, 20, 400, 400); +#endif twin_dispatch (); return 0; } |