[Commit] twin ChangeLog, 1.13, 1.14 twin.h, 1.10, 1.11 twin_fixed.c, 1.2, 1.3 twin_font.c, 1.9, 1.10 twin_path.c, 1.7, 1.8 twin_poly.c, 1.6, 1.7 twin_screen.c, 1.3, 1.4 twin_x11.c, 1.2, 1.3 twin_x11.h, 1.1, 1.2 twinint.h, 1.8, 1.9 xtwin.c, 1.12, 1.13

Keith Packard commit at keithp.com
Fri Oct 1 20:07:29 PDT 2004


Committed by: keithp

Update of /local/src/CVS/twin
In directory home.keithp.com:/tmp/cvs-serv4064

Modified Files:
	ChangeLog twin.h twin_fixed.c twin_font.c twin_path.c 
	twin_poly.c twin_screen.c twin_x11.c twin_x11.h twinint.h 
	xtwin.c 
Log Message:
2004-10-01  Keith Packard  <keithp at keithp.com>

	* twin.h:
	* twin_fixed.c:
	* twin_font.c: (twin_text_metrics_ucs4), (twin_path_ucs4),
	(twin_text_metrics_utf8):
	* twin_screen.c: (twin_screen_create), (twin_screen_update):
	* twin_x11.c: (_twin_x11_put_begin), (_twin_x11_put_span),
	* twin_x11.h:
	(twin_x11_create):
	Add put_begin to screen structure so that the backend can batch
	updates.
	Add twin_int_to_fixed.
	Inline twin_fixed_mul and twin_fixed_div using int64_t.
	Add twin_text_metrics_utf8.
	Hard-code the max number of vertices in a glyph.
	Set various ICCCM properties to make X wms happy.

	* twin_path.c: (_twin_matrix_max_radius), (twin_path_circle):
	Use better approximation of ellipse major axis radius when
	drawing circles.
	
	* twin_poly.c: (_twin_edge_fill):
	Compiler warning.

	* twinint.h:
	Delete duplicate twin_over definition
	
	* xtwin.c: (twin_clock_hand), (twin_clock_face), (twin_clock),
	(twin_app_thread), (twin_start_app), (twin_start_clock), (main):
	Allow for multiple clocks, and add watermark.  Note that
	text metrics are quite broken currently.


Index: ChangeLog
===================================================================
RCS file: /local/src/CVS/twin/ChangeLog,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- ChangeLog	30 Sep 2004 17:23:07 -0000	1.13
+++ ChangeLog	2 Oct 2004 03:07:26 -0000	1.14
@@ -1,3 +1,36 @@
+2004-10-01  Keith Packard  <keithp at keithp.com>
+
+	* twin.h:
+	* twin_fixed.c:
+	* twin_font.c: (twin_text_metrics_ucs4), (twin_path_ucs4),
+	(twin_text_metrics_utf8):
+	* twin_screen.c: (twin_screen_create), (twin_screen_update):
+	* twin_x11.c: (_twin_x11_put_begin), (_twin_x11_put_span),
+	* twin_x11.h:
+	(twin_x11_create):
+	Add put_begin to screen structure so that the backend can batch
+	updates.
+	Add twin_int_to_fixed.
+	Inline twin_fixed_mul and twin_fixed_div using int64_t.
+	Add twin_text_metrics_utf8.
+	Hard-code the max number of vertices in a glyph.
+	Set various ICCCM properties to make X wms happy.
+
+	* twin_path.c: (_twin_matrix_max_radius), (twin_path_circle):
+	Use better approximation of ellipse major axis radius when
+	drawing circles.
+	
+	* twin_poly.c: (_twin_edge_fill):
+	Compiler warning.
+
+	* twinint.h:
+	Delete duplicate twin_over definition
+	
+	* xtwin.c: (twin_clock_hand), (twin_clock_face), (twin_clock),
+	(twin_app_thread), (twin_start_app), (twin_start_clock), (main):
+	Allow for multiple clocks, and add watermark.  Note that
+	text metrics are quite broken currently.
+
 2004-09-30  Keith Packard  <keithp at keithp.com>
 
 	* Makefile.am:

Index: twin.h
===================================================================
RCS file: /local/src/CVS/twin/twin.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- twin.h	30 Sep 2004 17:23:07 -0000	1.10
+++ twin.h	2 Oct 2004 03:07:26 -0000	1.11
@@ -106,8 +106,14 @@
 } twin_pixmap_t;
 
 /*
- * A function that paints pixels to the screen
+ * twin_put_begin_t: called before data are drawn to the screen
+ * twin_put_span_t: called for each scanline drawn
  */
+typedef void	(*twin_put_begin_t) (int x,
+				     int y,
+				     int width,
+				     int height,
+				     void *closure);
 typedef void	(*twin_put_span_t) (int x,
 				    int y,
 				    int width,
@@ -139,6 +145,7 @@
     /*
      * Repaint function
      */
+    twin_put_begin_t	put_begin;
     twin_put_span_t	put_span;
     void		*closure;
 } twin_screen_t;
@@ -173,6 +180,8 @@
 #define twin_double_to_fixed(d)    ((twin_fixed_t) ((d) * 65536))
 #define twin_fixed_to_double(f)    ((double) (f) / 65536.0)
 
+#define twin_int_to_fixed(i)	   ((twin_fixed_t) (i) << 16)
+
 /*
  * Place matrices in structures so they can be easily copied
  */
@@ -241,14 +250,22 @@
  * twin_fixed.c
  */
 
+#if 0
 twin_fixed_t
 twin_fixed_mul (twin_fixed_t af, twin_fixed_t bf);
+#else
+#define twin_fixed_mul(a,b)    ((twin_fixed_t) (((int64_t) (a) * (b)) >> 16))
+#endif
 
 twin_fixed_t
 twin_fixed_sqrt (twin_fixed_t a);
 
+#if 0
 twin_fixed_t
 twin_fixed_div (twin_fixed_t a, twin_fixed_t b);
+#else
+#define twin_fixed_div(a,b)	((twin_fixed_t) ((((int64_t) (a)) << 16) / b))
+#endif
 
 /*
  * twin_font.c
@@ -282,6 +299,10 @@
 			twin_ucs4_t	    ucs4, 
 			twin_text_metrics_t *m);
 
+void
+twin_text_metrics_utf8 (twin_path_t	    *path,
+			const char	    *string,
+			twin_text_metrics_t *m);
 /*
  * twin_hull.c
  */
@@ -450,10 +471,11 @@
  */
 
 twin_screen_t *
-twin_screen_create (int		    width,
-		    int		    height, 
-		    twin_put_span_t put_span,
-		    void	    *closure);
+twin_screen_create (int			width,
+		    int			height, 
+		    twin_put_begin_t	put_begin,
+		    twin_put_span_t	put_span,
+		    void		*closure);
 
 void
 twin_screen_destroy (twin_screen_t *screen);

Index: twin_fixed.c
===================================================================
RCS file: /local/src/CVS/twin/twin_fixed.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- twin_fixed.c	28 Sep 2004 05:42:36 -0000	1.2
+++ twin_fixed.c	2 Oct 2004 03:07:26 -0000	1.3
@@ -36,6 +36,7 @@
 #define uint32_hi(i)	((i) >> 16)
 #define uint32_carry16	((1) << 16)
 
+#if 0
 twin_fixed_t
 twin_fixed_mul (twin_fixed_t af, twin_fixed_t bf)
 {
@@ -88,7 +89,9 @@
 	     twin_fixed_to_double (r)));
     return r;
 }
+#endif
 
+#if 0
 twin_fixed_t
 twin_fixed_div (twin_fixed_t a, twin_fixed_t b)
 {
@@ -96,6 +99,7 @@
     q = (twin_fixed_t) ((((int64_t) a) << 16) / b);
     return q;
 }
+#endif
 
 twin_fixed_t
 twin_fixed_sqrt (twin_fixed_t a)

Index: twin_font.c
===================================================================
RCS file: /local/src/CVS/twin/twin_font.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- twin_font.c	30 Sep 2004 17:23:07 -0000	1.9
+++ twin_font.c	2 Oct 2004 03:07:26 -0000	1.10
@@ -209,7 +209,6 @@
 	top = bottom = baseline;
 	right = Scale(p[0].y);
     }
-
     m->left_side_bearing = SNAPI(path, -left);
     m->right_side_bearing = SNAPI(path,right);
     m->width = m->left_side_bearing + m->right_side_bearing;
@@ -234,10 +233,10 @@
     twin_fixed_t	pen_size;
     twin_matrix_t	pen_matrix;
     twin_fixed_t	pen_adjust;
-    twin_gfixed_t    	*snap_x = 0, *snap_y = 0;
+    twin_gfixed_t    	snap_x[TWIN_GLYPH_MAX_POINTS];
+    twin_gfixed_t    	snap_y[TWIN_GLYPH_MAX_POINTS];
     twin_text_metrics_t	metrics;
     int			nsnap_x = 0, nsnap_y = 0;
-    int			npoints;
     
     twin_text_metrics_ucs4 (path, ucs4, &metrics);
     
@@ -245,14 +244,6 @@
     
     if (Hint (path))
     {
-	for (i = 1; p[i].y != -64; i++)
-	    ;
-    
-	npoints = i - 1 + 3;
-	
-	snap_x = malloc ((npoints * 2) * sizeof (twin_gfixed_t));
-	snap_y = snap_x + npoints;
-	
 	nsnap_x = 0;
 	nsnap_y = 0;
     
@@ -336,9 +327,6 @@
     twin_path_destroy (stroke);
     twin_path_destroy (pen);
     
-    if (snap_x)
-	free (snap_x);
-
     w = metrics.width;
 
     _twin_path_smove (path, 
@@ -451,3 +439,40 @@
     return w;
 }
 
+void
+twin_text_metrics_utf8 (twin_path_t	    *path, 
+			const char	    *string,
+			twin_text_metrics_t *m)
+{
+    int			len;
+    twin_ucs4_t		ucs4;
+    twin_fixed_t	w = 0;
+    twin_text_metrics_t	c;
+    twin_bool_t		first = TWIN_TRUE;
+
+    while ((len = _twin_utf8_to_ucs4(string, &ucs4)) > 0)
+    {
+	twin_text_metrics_ucs4 (path, ucs4, &c);
+	if (first)
+	    *m = c;
+	else
+	{
+	    c.left_side_bearing += w;
+	    c.right_side_bearing += w;
+	    c.width += w;
+
+	    if (c.left_side_bearing > m->left_side_bearing)
+		m->left_side_bearing = c.left_side_bearing;
+	    if (c.right_side_bearing > m->right_side_bearing)
+		m->right_side_bearing = c.right_side_bearing;
+	    if (c.width > m->width)
+		m->width = c.width;
+	    if (c.ascent < m->ascent)
+		m->ascent = c.ascent;
+	    if (c.descent > m->descent)
+		m->descent = c.descent;
+	}
+	w = c.width;
+	string += len;
+    }
+}

Index: twin_path.c
===================================================================
RCS file: /local/src/CVS/twin/twin_path.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- twin_path.c	30 Sep 2004 17:23:07 -0000	1.7
+++ twin_path.c	2 Oct 2004 03:07:26 -0000	1.8
@@ -154,6 +154,16 @@
     path->nsublen++;
 }
 
+#define twin_fixed_abs(f)   ((f) < 0 ? -(f) : (f))
+
+static twin_fixed_t
+_twin_matrix_max_radius (twin_matrix_t *m)
+{
+    return (twin_fixed_abs (m->m[0][0]) + twin_fixed_abs (m->m[0][1]) +
+	    twin_fixed_abs (m->m[1][0]) + twin_fixed_abs (m->m[1][1]));
+}
+
+
 void
 twin_path_circle (twin_path_t *path, twin_fixed_t radius)
 {
@@ -162,7 +172,7 @@
     twin_spoint_t   center;
     int		    i;
     twin_matrix_t   save;
-    twin_fixed_t    det;
+    twin_fixed_t    max_radius;
 
     save = twin_path_current_matrix (path);
 
@@ -172,14 +182,12 @@
 
     twin_path_close (path);
     
-    /* The determinant represents the area expansion factor of the
-       transform. In the worst case, this is entirely in one
-       dimension, which is what we assume here. */
-
-    det = _twin_matrix_determinant (&path->state.matrix);
+    max_radius = _twin_matrix_max_radius (&path->state.matrix);
     
-    sides = (4 * det) / twin_sfixed_to_fixed (TWIN_SFIXED_TOLERANCE);
+    sides = max_radius / twin_sfixed_to_fixed (TWIN_SFIXED_TOLERANCE);
     
+    if (sides > 1024) sides = 1024;
+
     n = 2;
     while ((1 << n) < sides)
 	n++;

Index: twin_poly.c
===================================================================
RCS file: /local/src/CVS/twin/twin_poly.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- twin_poly.c	30 Sep 2004 17:23:07 -0000	1.6
+++ twin_poly.c	2 Oct 2004 03:07:26 -0000	1.7
@@ -272,7 +272,7 @@
     twin_edge_t	    *active, *a, *n, **prev;
     int		    e;
     twin_sfixed_t    y;
-    twin_sfixed_t    x0;
+    twin_sfixed_t    x0 = 0;
     int		    w;
     
     qsort (edges, nedges, sizeof (twin_edge_t), _edge_compare_y);

Index: twin_screen.c
===================================================================
RCS file: /local/src/CVS/twin/twin_screen.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- twin_screen.c	30 Sep 2004 17:23:07 -0000	1.3
+++ twin_screen.c	2 Oct 2004 03:07:26 -0000	1.4
@@ -25,10 +25,11 @@
 #include "twinint.h"
 
 twin_screen_t *
-twin_screen_create (int		    width,
-		    int		    height, 
-		    twin_put_span_t put_span,
-		    void	    *closure)
+twin_screen_create (int			width,
+		    int			height, 
+		    twin_put_begin_t	put_begin,
+		    twin_put_span_t	put_span,
+		    void		*closure)
 {
     twin_screen_t   *screen = malloc (sizeof (twin_screen_t));
     if (!screen)
@@ -44,6 +45,7 @@
 #if HAVE_PTHREAD_H
     pthread_mutex_init (&screen->screen_mutex, NULL);
 #endif
+    screen->put_begin = put_begin;
     screen->put_span = put_span;
     screen->closure = closure;
     return screen;
@@ -162,6 +164,8 @@
 	if (!span)
 	    return;
 	
+	if (screen->put_begin)
+	    (*screen->put_begin) (x, y, width, height, screen->closure);
 	while (height--)
 	{
 	    memset (span, 0xff, width * sizeof (twin_argb32_t));

Index: twin_x11.c
===================================================================
RCS file: /local/src/CVS/twin/twin_x11.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- twin_x11.c	30 Sep 2004 17:23:07 -0000	1.2
+++ twin_x11.c	2 Oct 2004 03:07:26 -0000	1.3
@@ -26,6 +26,29 @@
 #include "twinint.h"
 
 static void
+_twin_x11_put_begin (int    x,
+		     int    y,
+		     int    width,
+		     int    height,
+		     void   *closure)
+{
+    twin_x11_t	*tx = closure;
+
+    tx->iy = 0;
+    tx->image = XCreateImage (tx->dpy, tx->visual, tx->depth, ZPixmap,
+			      0, 0, width, height, 32, 0);
+    if (tx->image)
+    {
+	tx->image->data = malloc (4 * width * height);
+	if (!tx->image->data)
+	{
+	    XDestroyImage (tx->image);
+	    tx->image = 0;
+	}
+    }
+}
+
+static void
 _twin_x11_put_span (int		    x,
 		    int		    y,
 		    int		    width,
@@ -33,14 +56,11 @@
 		    void	    *closure)
 {
     twin_x11_t	*tx = closure;
-    XImage	*image;
     int		ix = 0;
     int		iw = width;
 
-    image = XCreateImage (tx->dpy, tx->visual, tx->depth, ZPixmap,
-			  0, 0, width, 1, 32, 0);
-
-    image->data = malloc (4 * width);
+    if (!tx->image)
+	return;
 
     while (iw--)
     {
@@ -48,11 +68,17 @@
 	
 	if (tx->depth == 16)
 	    pixel = twin_argb32_to_rgb16 (pixel);
-	XPutPixel (image, ix, 0, pixel);
+	XPutPixel (tx->image, ix, tx->iy, pixel);
 	ix++;
     }
-    XPutImage (tx->dpy, tx->win, tx->gc, image, 0, 0, x, y, width, 1);
-    XDestroyImage (image);
+    tx->iy++;
+    if (tx->iy == tx->image->height)
+    {
+	XPutImage (tx->dpy, tx->win, tx->gc, tx->image, 0, 0, 
+		   x, y - tx->iy, width, tx->image->height);
+	XDestroyImage (tx->image);
+	tx->image = 0;
+    }
 }
 
 static void *
@@ -111,6 +137,13 @@
     twin_x11_t		    *tx;
     int			    scr = DefaultScreen (dpy);
     XSetWindowAttributes    wa;
+    XTextProperty	    wm_name, icon_name;
+    XSizeHints		    sizeHints;
+    XWMHints		    wmHints;
+    XClassHint		    classHints;
+    Atom		    wm_delete_window;
+    static char		    *argv[] = { "xtwin", 0 };
+    static int		    argc = 1;
 
     tx = malloc (sizeof (twin_x11_t));
     if (!tx)
@@ -128,12 +161,29 @@
 		     ExposureMask|
 		     StructureNotifyMask);
 
+    wm_name.value = (unsigned char *) argv[0];
+    wm_name.encoding = XA_STRING;
+    wm_name.format = 8;
+    wm_name.nitems = strlen (wm_name.value) + 1;
+    icon_name = wm_name;
+
     tx->win = XCreateWindow (dpy, RootWindow (dpy, scr),
 			     0, 0, width, height, 0,
 			     tx->depth, InputOutput,
 			     tx->visual, CWBackPixmap|CWEventMask, &wa);
+    sizeHints.flags = 0;
+    wmHints.flags = InputHint;
+    wmHints.input = True;
+    classHints.res_name = argv[0];
+    classHints.res_class = argv[0];
+    XSetWMProperties (dpy, tx->win,
+		      &wm_name, &icon_name,
+		      argv, argc,
+ 		      &sizeHints, &wmHints, 0);
+    XSetWMProtocols (dpy, tx->win, &wm_delete_window, 1);
+
     tx->gc = XCreateGC (dpy, tx->win, 0, 0);
-    tx->screen = twin_screen_create (width, height,
+    tx->screen = twin_screen_create (width, height, _twin_x11_put_begin,
 				     _twin_x11_put_span, tx);
     twin_screen_register_damaged (tx->screen, twin_x11_screen_damaged, tx);
 

Index: twin_x11.h
===================================================================
RCS file: /local/src/CVS/twin/twin_x11.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- twin_x11.h	30 Sep 2004 17:23:38 -0000	1.1
+++ twin_x11.h	2 Oct 2004 03:07:26 -0000	1.2
@@ -28,6 +28,7 @@
 
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
+#include <X11/Xatom.h>
 #include <pthread.h>
 
 typedef struct _twin_x11 {
@@ -40,6 +41,8 @@
     pthread_t	    damage_thread;
     pthread_cond_t  damage_cond;
     pthread_t	    event_thread;
+    XImage	    *image;
+    int		    iy;
 } twin_x11_t;
 
 /*

Index: twinint.h
===================================================================
RCS file: /local/src/CVS/twin/twinint.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- twinint.h	30 Sep 2004 17:23:07 -0000	1.8
+++ twinint.h	2 Oct 2004 03:07:26 -0000	1.9
@@ -79,11 +79,7 @@
     ((twin_argb32_t) twin_int_mult (twin_get_8(s,i),(m),(t)) << (i))
 
 #define twin_over(s,d,i,m,t)	\
-    ((t) = twin_int_mult(twin_get_8(d,i),(m),(t)) + twin_get_8(s,i),\
-     (twin_argb32_t) twin_sat (t) << (i))
-
-#define twin_over(s,d,i,m,t)	\
-    ((t) = twin_int_mult(twin_get_8(d,i),(m),(t)) + twin_get_8(s,i),\
+    (((t) = twin_int_mult(twin_get_8(d,i),(m),(t)) + twin_get_8(s,i)),\
      (twin_argb32_t) twin_sat (t) << (i))
 
 #define twin_argb32_to_rgb16(s)    ((((s) >> 3) & 0x001f) | \
@@ -344,4 +340,6 @@
 extern const twin_gpoint_t	_twin_glyphs[];
 extern const uint16_t		_twin_glyph_offsets[];
 
+#define TWIN_GLYPH_MAX_POINTS	56
+
 #endif /* _TWININT_H_ */

Index: xtwin.c
===================================================================
RCS file: /local/src/CVS/twin/xtwin.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- xtwin.c	30 Sep 2004 17:23:07 -0000	1.12
+++ xtwin.c	2 Oct 2004 03:07:26 -0000	1.13
@@ -32,26 +32,81 @@
 
 #define D(x) twin_double_to_fixed(x)
 
-#define CLOCK_SIZE 256
-
 #define TWIN_CLOCK_BACKGROUND	0xff3b80ae
-#define TWIN_CLOCK_HOUR		0xffdedede
-#define TWIN_CLOCK_MINUTE	0xffdedede
+#define TWIN_CLOCK_HOUR		0x80808080
+#define TWIN_CLOCK_HOUR_OUT	0xffdedede
+#define TWIN_CLOCK_MINUTE	0x80808080
+#define TWIN_CLOCK_MINUTE_OUT	0xffdedede
 #define TWIN_CLOCK_SECOND	0x80808080
 #define TWIN_CLOCK_TIC		0xffbababa
 #define TWIN_CLOCK_NUMBERS	0xffdedede
+#define TWIN_CLOCK_WATER	0x40404040
+#define TWIN_CLOCK_BORDER	0xffbababa
+#define TWIN_CLOCK_BORDER_WIDTH	D(0.01)
+
+static void
+twin_clock_set_transform (twin_pixmap_t	*clock,
+			  twin_path_t	*path)
+{
+    twin_fixed_t    scale;
+
+    scale = D(1) / 2;
+    scale = twin_fixed_mul (scale, TWIN_FIXED_ONE - TWIN_CLOCK_BORDER_WIDTH * 3);
+    twin_path_scale (path,
+		     clock->width * scale,
+		     clock->height * scale);
+
+    twin_path_translate (path, D(1) + TWIN_CLOCK_BORDER_WIDTH * 3,
+			 D(1) + TWIN_CLOCK_BORDER_WIDTH * 3);
+}
 
 static void
 twin_clock_hand (twin_pixmap_t	*clock, 
 		 twin_angle_t	angle, 
 		 twin_fixed_t	len,
+		 twin_fixed_t	fill_width,
+		 twin_fixed_t	out_width,
+		 twin_argb32_t	fill_pixel,
+		 twin_argb32_t	out_pixel)
+{
+    twin_path_t	    *stroke = twin_path_create ();
+    twin_path_t	    *pen = twin_path_create ();
+    twin_path_t	    *path = twin_path_create ();
+    twin_matrix_t   m;
+
+    twin_clock_set_transform (clock, stroke);
+
+    twin_path_rotate (stroke, angle);
+    twin_path_move (stroke, D(0), D(0));
+    twin_path_draw (stroke, len, D(0));
+
+    m = twin_path_current_matrix (stroke);
+    m.m[2][0] = 0;
+    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_convolve (path, stroke, pen);
+
+    twin_paint_path (clock, fill_pixel, path);
+
+    twin_paint_stroke (clock, out_pixel, path, out_width);
+    
+    twin_path_destroy (path);
+    twin_path_destroy (pen);
+    twin_path_destroy (stroke);
+}
+
+static void
+twin_clock_sec (twin_pixmap_t	*clock, 
+		 twin_angle_t	angle, 
+		 twin_fixed_t	len,
 		 twin_fixed_t	width,
 		 twin_argb32_t	pixel)
 {
     twin_path_t	    *stroke = twin_path_create ();
 
-    twin_path_translate (stroke, D(CLOCK_SIZE) / 2, D(CLOCK_SIZE) / 2);
-    twin_path_scale (stroke, D(CLOCK_SIZE) / 2, D(CLOCK_SIZE) / 2);
+    twin_clock_set_transform (clock, stroke);
 
     twin_path_rotate (stroke, angle);
     twin_path_move (stroke, D(0), D(0));
@@ -74,16 +129,37 @@
     twin_path_t	    *path = twin_path_create ();
     int		    m;
 
-    twin_path_translate (path, D(CLOCK_SIZE) / 2, D(CLOCK_SIZE) / 2);
-    twin_path_scale (path, D(CLOCK_SIZE) / 2, D(CLOCK_SIZE) / 2);
-    twin_path_set_font_size (path, D(0.2));
-    twin_path_set_font_style (path, TWIN_TEXT_UNHINTED);
+    twin_clock_set_transform (clock, path);
 
     twin_path_move (path, 0, 0);
     twin_path_circle (path, TWIN_FIXED_ONE);
     
     twin_paint_path (clock, TWIN_CLOCK_BACKGROUND, path);
 
+    twin_paint_stroke (clock, TWIN_CLOCK_BORDER, path, TWIN_CLOCK_BORDER_WIDTH);
+
+    {
+	twin_state_t	    state = twin_path_save (path);
+	twin_text_metrics_t metrics;
+	twin_fixed_t	    height;
+	static char	    *label = "twin";
+
+	twin_path_empty (path);
+	twin_path_rotate (path, twin_degrees_to_angle (-11));
+	twin_path_set_font_size (path, D(0.5));
+	twin_path_set_font_style (path, TWIN_TEXT_UNHINTED|TWIN_TEXT_OBLIQUE);
+	twin_text_metrics_utf8 (path, label, &metrics);
+	height = metrics.ascent + metrics.descent;
+/*	twin_path_move (path, -metrics.width / 2, height / 2 - metrics.ascent);*/
+	twin_path_move (path, -D(.4), -D(.16));
+	twin_path_utf8 (path, label);
+	twin_paint_path (clock, TWIN_CLOCK_WATER, path);
+	twin_path_restore (path, &state);
+    }
+
+    twin_path_set_font_size (path, D(0.2));
+    twin_path_set_font_style (path, TWIN_TEXT_UNHINTED);
+
     for (m = 1; m <= 60; m++)
     {
 	twin_state_t	state = twin_path_save (path);
@@ -112,22 +188,32 @@
     twin_path_destroy (path);
 }
 
+int nclock;
+
 static void
-twin_clock (twin_screen_t *screen)
+twin_clock (twin_screen_t *screen, int x, int y, int w, int h)
 {
-    twin_pixmap_t   *clock = twin_pixmap_create (TWIN_ARGB32, CLOCK_SIZE, CLOCK_SIZE);
+    twin_pixmap_t   *clock = twin_pixmap_create (TWIN_ARGB32, w, h);
     struct timeval  tv;
     struct tm	    t;
     twin_angle_t    hour_angle, minute_angle, second_angle;
+#if 0
+    int		    i;
+#endif
 
     printf ("twin clock\n");
-    twin_pixmap_move (clock, 0, 0);
+    twin_pixmap_move (clock, x, y);
     twin_pixmap_show (clock, screen, 0);
+    
+#if 0
+    for (i = 0; i < 5; i++)
+#else
     for (;;)
+#endif
     {
 	twin_pixmap_disable_update (clock);
 	twin_fill (clock, 0x00000000, TWIN_SOURCE, 0, 0, 
-		   CLOCK_SIZE, CLOCK_SIZE);
+		   clock->width, clock->height);
 
 	gettimeofday (&tv, NULL);
 
@@ -139,13 +225,63 @@
 	hour_angle = t.tm_hour * TWIN_ANGLE_360 / 12 - TWIN_ANGLE_90 + minute_angle / 12;
 
 	twin_clock_face (clock);
-	twin_clock_hand (clock, hour_angle, D(0.4), D(0.05), 0xffdedede);
-	twin_clock_hand (clock, minute_angle, D(0.8), D(0.03), 0xffdedede);
-	twin_clock_hand (clock, second_angle, D(0.6), D(0.01), 0x80808080);
+	twin_clock_hand (clock, hour_angle, D(0.4), D(0.07), D(0.01),
+			 TWIN_CLOCK_HOUR, TWIN_CLOCK_HOUR_OUT);
+	twin_clock_hand (clock, minute_angle, D(0.8), D(0.05), D(0.01),
+			 TWIN_CLOCK_MINUTE, TWIN_CLOCK_MINUTE_OUT);
+	twin_clock_sec (clock, second_angle, D(0.9), D(0.02),
+			TWIN_CLOCK_SECOND);
 
 	twin_pixmap_enable_update (clock);
+	
+	gettimeofday (&tv, NULL);
+	
 	usleep (1000000 - tv.tv_usec);
     }
+    nclock--;
+}
+
+typedef void (*twin_app_func_t) (twin_screen_t *screen,
+				 int x, int y, int w, int h);
+
+typedef struct _twin_app_args {
+    twin_app_func_t func;
+    twin_screen_t   *screen;
+    int		    x, y, w, h;
+} twin_app_args_t;
+
+static void *
+twin_app_thread (void *closure)
+{
+    twin_app_args_t *a = closure;
+
+    (*a->func) (a->screen, a->x, a->y, a->w, a->h);
+    free (a);
+    return 0;
+}
+
+static void
+twin_start_app (twin_app_func_t func, 
+		twin_screen_t *screen, 
+		int x, int y, int w, int h)
+{
+    twin_app_args_t *a = malloc (sizeof (twin_app_args_t));
+    pthread_t	    thread;
+    
+    a->func = func;
+    a->screen = screen;
+    a->x = x;
+    a->y = y;
+    a->w = w;
+    a->h = h;
+    pthread_create (&thread, NULL, twin_app_thread, a);
+}
+
+static void
+twin_start_clock (twin_screen_t *screen, int x, int y, int w, int h)
+{
+    ++nclock;
+    twin_start_app (twin_clock, screen, x, y, w, h);
 }
 
 int styles[] = {
@@ -475,8 +611,12 @@
     twin_pixmap_show (red, x11->screen, 0);
     twin_pixmap_show (blue, x11->screen, 0);
 #endif
-    twin_clock (x11->screen);
-    sleep (10000);
+    twin_start_clock (x11->screen, 0, 0, 512, 512);
+/*    twin_start_clock (x11->screen, 256, 0, 256, 256);
+    twin_start_clock (x11->screen, 0, 256, 256, 256);
+    twin_start_clock (x11->screen, 256, 256, 256, 256); */
+    while (nclock)
+	sleep (1);
 #if 0
     had_motion = TWIN_FALSE;
     for (;;)




More information about the Commit mailing list