aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2004-10-29 17:33:03 +0000
committerKeith Packard <keithp@keithp.com>2004-10-29 17:33:03 +0000
commitd671e983063b71cddc0a2034e51c1fa05d112dc4 (patch)
tree6e441500d25ce1bf29999cf5335f156d42bc046c
parentc9e17f96155bed7f32a5dfdf3d5ec7ef902e6ae5 (diff)
downloadlibtwin-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--ChangeLog62
-rw-r--r--Makefile.am4
-rw-r--r--twin.h86
-rw-r--r--twin_box.c5
-rw-r--r--twin_button.c3
-rw-r--r--twin_calc.c9
-rw-r--r--twin_clock.c5
-rw-r--r--twin_convolve.c89
-rw-r--r--twin_demo.c51
-rw-r--r--twin_demoline.c157
-rw-r--r--twin_demoline.h55
-rw-r--r--twin_demospline.c169
-rw-r--r--twin_demospline.h57
-rw-r--r--twin_draw.c8
-rw-r--r--twin_font.c2
-rw-r--r--twin_glyphs.c8
-rw-r--r--twin_label.c19
-rw-r--r--twin_path.c219
-rw-r--r--twin_toplevel.c2
-rw-r--r--twin_widget.c85
-rw-r--r--twin_window.c10
-rw-r--r--twin_x11.c4
-rw-r--r--twinint.h9
-rw-r--r--xtwin.c25
24 files changed, 989 insertions, 154 deletions
diff --git a/ChangeLog b/ChangeLog
index e4ab423..4ba1917 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/twin.h b/twin.h
index f425c5f..c99a1f7 100644
--- a/twin.h
+++ b/twin.h
@@ -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);
diff --git a/twin_box.c b/twin_box.c
index c181bf8..2ebf63b 100644
--- a/twin_box.c
+++ b/twin_box.c
@@ -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;
diff --git a/twin_x11.c b/twin_x11.c
index cc06441..603e21d 100644
--- a/twin_x11.c
+++ b/twin_x11.c
@@ -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;
}
diff --git a/twinint.h b/twinint.h
index c970d0b..42cecf1 100644
--- a/twinint.h
+++ b/twinint.h
@@ -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);
diff --git a/xtwin.c b/xtwin.c
index 98e8c6c..06f4485 100644
--- a/xtwin.c
+++ b/xtwin.c
@@ -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;
}