[Commit] twin ChangeLog, 1.12, 1.13 Makefile.am, 1.6, 1.7 configure.ac, 1.2, 1.3 twin.h, 1.9, 1.10 twin_draw.c, 1.2, 1.3 twin_font.c, 1.8, 1.9 twin_path.c, 1.6, 1.7 twin_pixmap.c, 1.1.1.1, 1.2 twin_poly.c, 1.5, 1.6 twin_screen.c, 1.2, 1.3 twin_x11.c, 1.1.1.1, 1.2 twinint.h, 1.7, 1.8 xtwin.c, 1.11, 1.12

Keith Packard commit at keithp.com
Thu Sep 30 10:23:10 PDT 2004


Committed by: keithp

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

Modified Files:
	ChangeLog Makefile.am configure.ac twin.h twin_draw.c 
	twin_font.c twin_path.c twin_pixmap.c twin_poly.c 
	twin_screen.c twin_x11.c twinint.h xtwin.c 
Log Message:
2004-09-30  Keith Packard  <keithp at keithp.com>

	* Makefile.am:
	* configure.ac:
	* twin.h:
	* twin_draw.c: (twin_composite), (twin_fill):
	* twin_font.c: (_snap), (_twin_pen_size), (twin_text_metrics_ucs4),
	(twin_path_ucs4), (twin_width_utf8):
	Handle unhinted text.
	
	* twin_path.c: (twin_path_close), (twin_path_bounds),
	(twin_composite_path), (twin_paint_path), (twin_composite_stroke),
	(twin_paint_stroke):
	Add helper functions 
	
	* twin_pixmap.c: (twin_pixmap_create), (twin_pixmap_show),
	(twin_pixmap_hide), (twin_pixmap_enable_update),
	(twin_pixmap_disable_update), (twin_pixmap_lock),
	(twin_pixmap_unlock):
	Lock pixmaps during drawing
	
	* twin_poly.c: (_twin_edge_build), (twin_fill_path):
	* twin_screen.c: (twin_screen_create), (twin_screen_lock),
	(twin_screen_unlock), (twin_screen_register_damaged),
	(twin_screen_enable_update), (twin_screen_disable_update),
	(twin_screen_damage), (twin_screen_update):
	Disable screen updates while applications are busy
	
	* twin_x11.c: (twin_x11_damage_thread), (twin_x11_event_thread),
	(twin_x11_screen_damaged), (twin_x11_create), (twin_x11_destroy):
	Add threads to manage events and redisplay

	* twinint.h:
	* xtwin.c: (twin_clock_hand), (twin_clock_minute_angle),
	(twin_clock_face), (twin_clock), (main):
	Paint a clock


Index: ChangeLog
===================================================================
RCS file: /local/src/CVS/twin/ChangeLog,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- ChangeLog	28 Sep 2004 05:42:36 -0000	1.12
+++ ChangeLog	30 Sep 2004 17:23:07 -0000	1.13
@@ -1,3 +1,40 @@
+2004-09-30  Keith Packard  <keithp at keithp.com>
+
+	* Makefile.am:
+	* configure.ac:
+	* twin.h:
+	* twin_draw.c: (twin_composite), (twin_fill):
+	* twin_font.c: (_snap), (_twin_pen_size), (twin_text_metrics_ucs4),
+	(twin_path_ucs4), (twin_width_utf8):
+	Handle unhinted text.
+	
+	* twin_path.c: (twin_path_close), (twin_path_bounds),
+	(twin_composite_path), (twin_paint_path), (twin_composite_stroke),
+	(twin_paint_stroke):
+	Add helper functions 
+	
+	* twin_pixmap.c: (twin_pixmap_create), (twin_pixmap_show),
+	(twin_pixmap_hide), (twin_pixmap_enable_update),
+	(twin_pixmap_disable_update), (twin_pixmap_lock),
+	(twin_pixmap_unlock):
+	Lock pixmaps during drawing
+	
+	* twin_poly.c: (_twin_edge_build), (twin_fill_path):
+	* twin_screen.c: (twin_screen_create), (twin_screen_lock),
+	(twin_screen_unlock), (twin_screen_register_damaged),
+	(twin_screen_enable_update), (twin_screen_disable_update),
+	(twin_screen_damage), (twin_screen_update):
+	Disable screen updates while applications are busy
+	
+	* twin_x11.c: (twin_x11_damage_thread), (twin_x11_event_thread),
+	(twin_x11_screen_damaged), (twin_x11_create), (twin_x11_destroy):
+	Add threads to manage events and redisplay
+
+	* twinint.h:
+	* xtwin.c: (twin_clock_hand), (twin_clock_minute_angle),
+	(twin_clock_face), (twin_clock), (main):
+	Paint a clock
+
 2004-09-27  Keith Packard  <keithp at keithp.com>
 
 	* twin.h:

Index: Makefile.am
===================================================================
RCS file: /local/src/CVS/twin/Makefile.am,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- Makefile.am	27 Sep 2004 21:28:31 -0000	1.6
+++ Makefile.am	30 Sep 2004 17:23:07 -0000	1.7
@@ -1,6 +1,5 @@
 CFLAGS=-g
 INCLUDES= @X_CFLAGS@ @WARN_CFLAGS@
-SUBDIRS=twin_ttf
 
 #libtwin_la_SOURCES = \
 #	twin.h \

Index: configure.ac
===================================================================
RCS file: /local/src/CVS/twin/configure.ac,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- configure.ac	24 Sep 2004 04:09:10 -0000	1.2
+++ configure.ac	30 Sep 2004 17:23:07 -0000	1.3
@@ -29,7 +29,7 @@
 AM_INIT_AUTOMAKE()
 AM_MAINTAINER_MODE
 
-AM_CONFIG_HEADER(config.h)
+AM_CONFIG_HEADER(twin_def.h)
 AC_CONFIG_AUX_DIR(.)
 
 # Check for progs
@@ -52,23 +52,27 @@
 AC_SUBST(X_CFLAGS)
 AC_SUBST(X_LIBS)
 
-AC_ARG_WITH(freetype-config, [  --with-freetype-config=PROG   Use FreeType configuration program PROG], freetype_config=$withval, freetype_config=yes)
-
-if test "$freetype_config" = "yes"; then 
-	AC_PATH_PROG(ft_config,freetype-config,no)
-	if test "$ft_config" = "no"; then
-		AC_MSG_ERROR([You must have freetype installed; see http://www.freetype.org/])
-	fi
-else
-	ft_config="$freetype_config"
-fi
+AC_CHECK_LIB([pthread], [pthread_create])
 
-FREETYPE_CFLAGS="`$ft_config --cflags`"
-FREETYPE_LIBS="`$ft_config --libs`"
+AC_CHECK_HEADERS([pthread.h])
 
-AC_SUBST(FREETYPE_LIBS)
-AC_SUBST(FREETYPE_CFLAGS)
+#
+#AC_ARG_WITH(freetype-config, [  --with-freetype-config=PROG   Use FreeType configuration program PROG], freetype_config=$withval, freetype_config=yes)
+#
+#if test "$freetype_config" = "yes"; then 
+#	AC_PATH_PROG(ft_config,freetype-config,no)
+#	if test "$ft_config" = "no"; then
+#		AC_MSG_ERROR([You must have freetype installed; see http://www.freetype.org/])
+#	fi
+#else
+#	ft_config="$freetype_config"
+#fi
+#
+#FREETYPE_CFLAGS="`$ft_config --cflags`"
+#FREETYPE_LIBS="`$ft_config --libs`"
+#
+#AC_SUBST(FREETYPE_LIBS)
+#AC_SUBST(FREETYPE_CFLAGS)
 
 AC_OUTPUT([Makefile
-	   twin_ttf/Makefile
            twin.pc])

Index: twin.h
===================================================================
RCS file: /local/src/CVS/twin/twin.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- twin.h	28 Sep 2004 05:42:36 -0000	1.9
+++ twin.h	30 Sep 2004 17:23:07 -0000	1.10
@@ -27,6 +27,10 @@
 
 #include <stdlib.h>
 #include <stdint.h>
+#include <twin_def.h>
+#if HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
 
 typedef uint8_t	    twin_a8_t;
 typedef uint16_t    twin_a16_t;
@@ -79,6 +83,7 @@
      * Screen showing these pixels
      */
     struct _twin_screen		*screen;
+    int				disable;
     /*
      * List of displayed pixmaps
      */
@@ -125,6 +130,12 @@
      * Damage
      */
     twin_rect_t		damage;
+    void		(*damaged) (void *);
+    void		*damaged_closure;
+    int			disable;
+#if HAVE_PTHREAD_H
+    pthread_mutex_t	screen_mutex;
+#endif
     /*
      * Repaint function
      */
@@ -314,6 +325,9 @@
 twin_path_empty (twin_path_t *path);
 
 void
+twin_path_bounds (twin_path_t *path, twin_rect_t *rect);
+
+void
 twin_path_append (twin_path_t *dst, twin_path_t *src);
 
 twin_path_t *
@@ -358,6 +372,33 @@
 void
 twin_path_restore (twin_path_t *path, twin_state_t *state);
 
+void
+twin_composite_path (twin_pixmap_t	*dst,
+		     twin_operand_t	*src,
+		     int		src_x,
+		     int		src_y,
+		     twin_path_t	*path,
+		     twin_operator_t	operator);
+void
+twin_paint_path (twin_pixmap_t	*dst,
+		 twin_argb32_t	argb,
+		 twin_path_t	*path);
+
+void
+twin_composite_stroke (twin_pixmap_t	*dst,
+		       twin_operand_t	*src,
+		       int		src_x,
+		       int		src_y,
+		       twin_path_t	*stroke,
+		       twin_fixed_t	pen_width,
+		       twin_operator_t	operator);
+
+void
+twin_paint_stroke (twin_pixmap_t    *dst,
+		   twin_argb32_t    argb,
+		   twin_path_t	    *stroke,
+		   twin_fixed_t	    pen_width);
+
 /*
  * twin_pixmap.c
  */
@@ -377,10 +418,22 @@
 twin_pixmap_hide (twin_pixmap_t *pixmap);
 
 void
+twin_pixmap_enable_update (twin_pixmap_t *pixmap);
+
+void
+twin_pixmap_disable_update (twin_pixmap_t *pixmap);
+
+void
 twin_pixmap_damage (twin_pixmap_t *pixmap,
 		    int x1, int y1, int x2, int y2);
 
 void
+twin_pixmap_lock (twin_pixmap_t *pixmap);
+
+void
+twin_pixmap_unlock (twin_pixmap_t *pixmap);
+
+void
 twin_pixmap_move (twin_pixmap_t *pixmap, int x, int y);
 
 twin_pointer_t
@@ -390,7 +443,7 @@
  * twin_poly.c
  */
 void
-twin_fill_path (twin_pixmap_t *pixmap, twin_path_t *path);
+twin_fill_path (twin_pixmap_t *pixmap, twin_path_t *path, int dx, int dy);
 
 /*
  * twin_screen.c
@@ -406,10 +459,21 @@
 twin_screen_destroy (twin_screen_t *screen);
 
 void
+twin_screen_enable_update (twin_screen_t *screen);
+
+void
+twin_screen_disable_update (twin_screen_t *screen);
+
+void
 twin_screen_damage (twin_screen_t *screen,
 		    int x1, int y1, int x2, int y2);
 		    
 void
+twin_screen_register_damaged (twin_screen_t *screen, 
+			      void (*damaged) (void *),
+			      void *closure);
+
+void
 twin_screen_resize (twin_screen_t *screen, int width, int height);
 
 twin_bool_t
@@ -418,6 +482,13 @@
 void
 twin_screen_update (twin_screen_t *screen);
 
+void
+twin_screen_lock (twin_screen_t *screen);
+
+void
+twin_screen_unlock (twin_screen_t *screen);
+
+
 /*
  * twin_spline.c
  */
@@ -441,34 +512,4 @@
 twin_fixed_t
 twin_tan (twin_angle_t a);
 
-/*
- * twin_x11.c 
- */
-
-#include <X11/Xlib.h>
-
-typedef struct _twin_x11 {
-    twin_screen_t   *screen;
-    Display	    *dpy;
-    Window	    win;
-    GC		    gc;
-    Visual	    *visual;
-    int		    depth;
-} twin_x11_t;
-
-twin_x11_t *
-twin_x11_create (Display *dpy, int width, int height);
-
-void
-twin_x11_destroy (twin_x11_t *tx);
-
-void
-twin_x11_damage (twin_x11_t *tx, XExposeEvent *ev);
-
-void
-twin_x11_configure (twin_x11_t *tx, XConfigureEvent *ev);
-
-void
-twin_x11_update (twin_x11_t *tx);
-
 #endif /* _TWIN_H_ */

Index: twin_draw.c
===================================================================
RCS file: /local/src/CVS/twin/twin_draw.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- twin_draw.c	21 Sep 2004 15:42:56 -0000	1.2
+++ twin_draw.c	30 Sep 2004 17:23:07 -0000	1.3
@@ -256,6 +256,7 @@
     }
 };
 
+    
 #define operand_index(o)    ((o)->source_kind == TWIN_SOLID ? 3 : o->u.pixmap->format)
 
 void
@@ -275,6 +276,7 @@
     int	    iy;
     int	    left, right, top, bottom;
 
+    twin_pixmap_lock (dst);
     if (msk)
     {
 	twin_src_msk_op	op;
@@ -353,6 +355,8 @@
 		   s, right - left);
 	}
     }
+    twin_pixmap_damage (dst, left, top, right, bottom);
+    twin_pixmap_unlock (dst);
 }
 	     
 /*
@@ -386,6 +390,7 @@
     int		    iy;
     int		    left, right, top, bottom;
     
+    twin_pixmap_lock (dst);
     src.c = pixel;
     left = x;
     right = x + width;
@@ -402,4 +407,5 @@
     op = fill[operator][dst->format];
     for (iy = top; iy < bottom; iy++)
 	(*op) (twin_pixmap_pointer (dst, left, iy), src, right - left);
+    twin_pixmap_unlock (dst);
 }

Index: twin_font.c
===================================================================
RCS file: /local/src/CVS/twin/twin_font.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- twin_font.c	28 Sep 2004 05:42:36 -0000	1.8
+++ twin_font.c	30 Sep 2004 17:23:07 -0000	1.9
@@ -38,6 +38,8 @@
 #define ScaleX(x)	Scale(x)
 #define ScaleY(y)	Scale(y)
 
+#define Hint(p)		(((p)->state.font_style & TWIN_TEXT_UNHINTED) == 0)
+
 twin_bool_t
 twin_has_ucs4 (twin_ucs4_t ucs4)
 {
@@ -53,8 +55,8 @@
     return (int) (*a - *b);
 }
 
-#define SNAPI(p)	(((p) + 0x7fff) & ~0xffff)
-#define SNAPH(p)	(((p) + 0x3fff) & ~0x7fff)
+#define SNAPI(path,p)	(Hint(path) ? (((p) + 0x7fff) & ~0xffff) : (p))
+#define SNAPH(path,p)	(Hint(path) ? (((p) + 0x3fff) & ~0x7fff) : (p))
 
 static twin_fixed_t
 _snap (twin_path_t *path, twin_gfixed_t g, twin_gfixed_t *snap, int nsnap)
@@ -70,8 +72,8 @@
 	    twin_fixed_t    before = Scale(snap[s]);
 	    twin_fixed_t    after = Scale(snap[s+1]);
 	    twin_fixed_t    dist = after - before;
-	    twin_fixed_t    snap_before = SNAPI(before);
-	    twin_fixed_t    snap_after = SNAPI(after);
+	    twin_fixed_t    snap_before = SNAPI(path, before);
+	    twin_fixed_t    snap_after = SNAPI(path, after);
 	    twin_fixed_t    move_before = snap_before - before;
 	    twin_fixed_t    move_after = snap_after - after;
 	    twin_fixed_t    dist_before = v - before;
@@ -121,14 +123,14 @@
 {
     twin_fixed_t    pen_size;
     
-    pen_size = SNAPH(path->state.font_size / 24);
-    if (pen_size < TWIN_FIXED_HALF)
+    pen_size = SNAPH(path, path->state.font_size / 24);
+    if (Hint (path) && pen_size < TWIN_FIXED_HALF)
 	pen_size = TWIN_FIXED_HALF;
     
     if (path->state.font_style & TWIN_TEXT_BOLD)
     {
-	twin_fixed_t	pen_add = SNAPH(pen_size >> 1);
-	if (pen_add == 0) 
+	twin_fixed_t	pen_add = SNAPH(path, pen_size >> 1);
+	if (Hint (path) && pen_add == 0) 
 	    pen_add = TWIN_FIXED_HALF;
 	pen_size += pen_add;
     }
@@ -145,7 +147,7 @@
     twin_fixed_t	left, right;
     twin_fixed_t	top, bottom;
     twin_fixed_t	pen_size = _twin_pen_size (path);
-    twin_fixed_t	baseline = SNAPI(Scale(TWIN_FONT_BASELINE));
+    twin_fixed_t	baseline = SNAPI(path, Scale(TWIN_FONT_BASELINE));
     int			i;
     int			skip_xi;
     int			skip_yi;
@@ -169,16 +171,16 @@
 	y = Scale (p[i].y);
 	next_xi = skip_xi;
 	next_yi = skip_yi;
-	if (p[i+1].y != -64 && p[i+1].x != -64)
+	if (Hint (path) && p[i+1].y != -64 && p[i+1].x != -64)
 	{
 	    if (p[i].x == p[i+1].x)
 	    {
-		x = SNAPI(x);
+		x = SNAPI(path, x);
 		skip_xi = i + 2;
 	    }
 	    if (p[i].y == p[i+1].y)
 	    {
-		y = SNAPI(y);
+		y = SNAPI(path, y);
 		skip_yi = i + 2;
 	    }
 	}
@@ -208,13 +210,13 @@
 	right = Scale(p[0].y);
     }
 
-    m->left_side_bearing = SNAPI(-left);
-    m->right_side_bearing = SNAPI(right);
+    m->left_side_bearing = SNAPI(path, -left);
+    m->right_side_bearing = SNAPI(path,right);
     m->width = m->left_side_bearing + m->right_side_bearing;
-    m->ascent = baseline - SNAPI(top);
-    m->descent = SNAPI(bottom) - baseline;
-    m->font_descent = SNAPI(path->state.font_size / 3);
-    m->font_ascent = SNAPI(path->state.font_size) - m->font_descent;
+    m->ascent = baseline - SNAPI(path, top);
+    m->descent = SNAPI(path, bottom) - baseline;
+    m->font_descent = SNAPI(path, path->state.font_size / 3);
+    m->font_ascent = SNAPI(path,path->state.font_size) - m->font_descent;
 }
 
 void
@@ -232,68 +234,74 @@
     twin_fixed_t	pen_size;
     twin_matrix_t	pen_matrix;
     twin_fixed_t	pen_adjust;
-    twin_gfixed_t    	*snap_x, *snap_y;
+    twin_gfixed_t    	*snap_x = 0, *snap_y = 0;
     twin_text_metrics_t	metrics;
-    int			nsnap_x, nsnap_y;
+    int			nsnap_x = 0, nsnap_y = 0;
     int			npoints;
     
     twin_text_metrics_ucs4 (path, ucs4, &metrics);
     
     origin = _twin_path_current_spoint (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;
+    if (Hint (path))
+    {
+	for (i = 1; p[i].y != -64; i++)
+	    ;
     
-    nsnap_x = 0;
-    nsnap_y = 0;
-
-    /* snap left and right boundaries */
+	npoints = i - 1 + 3;
+	
+	snap_x = malloc ((npoints * 2) * sizeof (twin_gfixed_t));
+	snap_y = snap_x + npoints;
+	
+	nsnap_x = 0;
+	nsnap_y = 0;
     
-    nsnap_x = _add_snap (snap_x, nsnap_x, p[0].x);
-    nsnap_x = _add_snap (snap_x, nsnap_x, p[0].y);
+	/* snap left and right boundaries */
+	
+	nsnap_x = _add_snap (snap_x, nsnap_x, p[0].x);
+	nsnap_x = _add_snap (snap_x, nsnap_x, p[0].y);
+	
+	/* snap baseline, x height and cap height  */
+	nsnap_y = _add_snap (snap_y, nsnap_y, 9);
+	nsnap_y = _add_snap (snap_y, nsnap_y, -5);
+	nsnap_y = _add_snap (snap_y, nsnap_y, -12);
+	
+	/*
+	 * Locate horizontal and vertical segments
+	 */
+	for (i = 1; p[i].y != -64 && p[i+1].y != -64; i++)
+	{
+	    if (p[i].x == -64 || p[i+1].x == -64)
+		continue;
+	    if (p[i].x == p[i+1].x)
+		nsnap_x = _add_snap (snap_x, nsnap_x, p[i].x);
+	    if (p[i].y == p[i+1].y)
+		nsnap_y = _add_snap (snap_y, nsnap_y, p[i].y);
+	}
     
-    /* snap baseline, x height and cap height  */
-    nsnap_y = _add_snap (snap_y, nsnap_y, 9);
-    nsnap_y = _add_snap (snap_y, nsnap_y, -5);
-    nsnap_y = _add_snap (snap_y, nsnap_y, -12);
+	qsort (snap_x, nsnap_x, sizeof (twin_gfixed_t), compare_snap);
+	qsort (snap_y, nsnap_y, sizeof (twin_gfixed_t), compare_snap);
     
-    /*
-     * Locate horizontal and vertical segments
-     */
-    for (i = 1; p[i].y != -64 && p[i+1].y != -64; i++)
-    {
-	if (p[i].x == -64 || p[i+1].x == -64)
-	    continue;
-	if (p[i].x == p[i+1].x)
-	    nsnap_x = _add_snap (snap_x, nsnap_x, p[i].x);
-	if (p[i].y == p[i+1].y)
-	    nsnap_y = _add_snap (snap_y, nsnap_y, p[i].y);
+	DBGMSG (("snap_x:"));
+	for (i = 0; i < nsnap_x; i++)
+	    DBGMSG ((" %d", snap_x[i])); 
+	DBGMSG (("\n"));
+	
+	DBGMSG (("snap_y:"));
+	for (i = 0; i < nsnap_y; i++)
+	    DBGMSG ((" %d", snap_y[i])); 
+	DBGMSG (("\n"));
     }
 
-    qsort (snap_x, nsnap_x, sizeof (twin_gfixed_t), compare_snap);
-    qsort (snap_y, nsnap_y, sizeof (twin_gfixed_t), compare_snap);
-
-    DBGMSG (("snap_x:"));
-    for (i = 0; i < nsnap_x; i++)
-	DBGMSG ((" %d", snap_x[i])); 
-    DBGMSG (("\n"));
-    
-    DBGMSG (("snap_y:"));
-    for (i = 0; i < nsnap_y; i++)
-	DBGMSG ((" %d", snap_y[i])); 
-    DBGMSG (("\n"));
-
     stroke = twin_path_create ();
     twin_path_set_matrix (stroke, twin_path_current_matrix (path));
     
     pen_size = _twin_pen_size (path);
 
-    pen_adjust = pen_size & TWIN_FIXED_HALF;
+    if (Hint (path))
+	pen_adjust = pen_size & TWIN_FIXED_HALF;
+    else
+	pen_adjust = 0;
     
     pen = twin_path_create ();
     pen_matrix = twin_path_current_matrix (path);
@@ -328,7 +336,8 @@
     twin_path_destroy (stroke);
     twin_path_destroy (pen);
     
-    free (snap_x);
+    if (snap_x)
+	free (snap_x);
 
     w = metrics.width;
 
@@ -337,7 +346,7 @@
 		      origin.y + _twin_matrix_dy (&path->state.matrix, w, 0));
 }
 
-int
+twin_fixed_t
 twin_width_ucs4 (twin_path_t *path, twin_ucs4_t ucs4)
 {
     twin_text_metrics_t	metrics;
@@ -427,3 +436,18 @@
     }
 }
 
+twin_fixed_t
+twin_width_utf8 (twin_path_t *path, const char *string)
+{
+    int		    len;
+    twin_ucs4_t	    ucs4;
+    twin_fixed_t    w = 0;
+
+    while ((len = _twin_utf8_to_ucs4(string, &ucs4)) > 0)
+    {
+	w += twin_width_ucs4 (path, ucs4);
+	string += len;
+    }
+    return w;
+}
+

Index: twin_path.c
===================================================================
RCS file: /local/src/CVS/twin/twin_path.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- twin_path.c	28 Sep 2004 05:42:36 -0000	1.6
+++ twin_path.c	30 Sep 2004 17:23:07 -0000	1.7
@@ -140,7 +140,7 @@
 	if (path->size_sublen > 0)
 	    size_sublen = path->size_sublen * 2;
 	else
-	    size_sublen = 16;
+	    size_sublen = 1;
 	if (path->sublen)
 	    sublen = realloc (path->sublen, size_sublen * sizeof (int));
 	else
@@ -267,6 +267,32 @@
 }
 
 void
+twin_path_bounds (twin_path_t *path, twin_rect_t *rect)
+{
+    twin_sfixed_t   left = TWIN_SFIXED_MAX;
+    twin_sfixed_t   top = TWIN_SFIXED_MAX;
+    twin_sfixed_t   right = TWIN_SFIXED_MIN;
+    twin_sfixed_t   bottom = TWIN_SFIXED_MIN;
+    int		    i;
+
+    for (i = 0; i < path->npoints; i++)
+    {
+	twin_sfixed_t	x = path->points[i].x;
+	twin_sfixed_t	y = path->points[i].y;
+	if (x < left) left = x;
+	if (x > right) right = x;
+	if (y < top) top = y;
+	if (y > bottom) bottom = y;
+    }
+    if (left >= right || top >= bottom)
+	left = right = top = bottom = 0;
+    rect->left = twin_sfixed_trunc (left);
+    rect->top = twin_sfixed_trunc (top);
+    rect->right = twin_sfixed_trunc (twin_sfixed_ceil (right));
+    rect->bottom = twin_sfixed_trunc (twin_sfixed_ceil (bottom));
+}
+
+void
 twin_path_append (twin_path_t *dst, twin_path_t *src)
 {
     int	    p;
@@ -320,3 +346,84 @@
 	free (path->sublen);
     free (path);
 }
+
+void
+twin_composite_path (twin_pixmap_t	*dst,
+		     twin_operand_t	*src,
+		     int		src_x,
+		     int		src_y,
+		     twin_path_t	*path,
+		     twin_operator_t	operator)
+{
+    twin_rect_t	    bounds;
+    twin_pixmap_t   *mask;
+    twin_operand_t  msk;
+    int		    width, height;
+
+    twin_path_bounds (path, &bounds);
+    if (bounds.left == bounds.right)
+	return;
+    width = bounds.right - bounds.left;
+    height = bounds.bottom - bounds.top;
+    mask = twin_pixmap_create (TWIN_A8, width, height);
+			       
+    if (!mask)
+	return;
+    twin_fill (mask, 0x00000000, TWIN_SOURCE, 0, 0, width, height);
+    twin_fill_path (mask, path, -bounds.left, -bounds.top);
+    msk.source_kind = TWIN_PIXMAP;
+    msk.u.pixmap = mask;
+    twin_composite (dst, bounds.left, bounds.top, 
+		    src, src_x + bounds.left, src_y + bounds.top,
+		    &msk, 0, 0, operator, width, height);
+    twin_pixmap_destroy (mask);
+}
+
+void
+twin_paint_path (twin_pixmap_t	*dst,
+		 twin_argb32_t	argb,
+		 twin_path_t	*path)
+{
+    twin_operand_t  src;
+
+    src.source_kind = TWIN_SOLID;
+    src.u.argb = argb;
+    twin_composite_path (dst, &src, 0, 0, path, TWIN_OVER);
+}
+
+void
+twin_composite_stroke (twin_pixmap_t	*dst,
+		       twin_operand_t	*src,
+		       int		src_x,
+		       int		src_y,
+		       twin_path_t	*stroke,
+		       twin_fixed_t	pen_width,
+		       twin_operator_t	operator)
+{
+    twin_path_t	    *pen = twin_path_create ();
+    twin_path_t	    *path = twin_path_create ();
+    twin_matrix_t   m = twin_path_current_matrix (stroke);
+    
+    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_convolve (path, stroke, pen);
+    twin_composite_path (dst, src, src_x, src_y, path, operator);
+    twin_path_destroy (path);
+    twin_path_destroy (pen);
+}
+
+void
+twin_paint_stroke (twin_pixmap_t    *dst,
+		   twin_argb32_t    argb,
+		   twin_path_t	    *stroke,
+		   twin_fixed_t	    pen_width)
+{
+    twin_operand_t  src;
+
+    src.source_kind = TWIN_SOLID;
+    src.u.argb = argb;
+    twin_composite_stroke (dst, &src, 0, 0, stroke, pen_width, TWIN_OVER);
+}
+

Index: twin_pixmap.c
===================================================================
RCS file: /local/src/CVS/twin/twin_pixmap.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- twin_pixmap.c	15 Sep 2004 20:43:17 -0000	1.1.1.1
+++ twin_pixmap.c	30 Sep 2004 17:23:07 -0000	1.2
@@ -39,6 +39,7 @@
     pixmap->width = width;
     pixmap->height = height;
     pixmap->stride = stride;
+    pixmap->disable = 0;
     pixmap->p.v = pixmap + 1;
     return pixmap;
 }
@@ -57,8 +58,15 @@
 		  twin_pixmap_t	*lower)
 {
     twin_pixmap_t   **higherp;
+    
+    twin_screen_lock (screen);
+
+    if (pixmap->disable)
+	twin_screen_disable_update (screen);
+    
     if (pixmap->screen)
 	twin_pixmap_hide (pixmap);
+    
     pixmap->screen = screen;
     if (lower)
 	higherp = &lower->higher;
@@ -67,6 +75,7 @@
     pixmap->higher = *higherp;
     *higherp = pixmap;
     twin_pixmap_damage (pixmap, 0, 0, pixmap->width, pixmap->height);
+    twin_screen_unlock (screen);
 }
 
 void
@@ -77,12 +86,16 @@
 
     if (!screen)
 	return;
+    twin_screen_lock (screen);
     twin_pixmap_damage (pixmap, 0, 0, pixmap->width, pixmap->height);
     for (higherp = &screen->bottom; *higherp != pixmap; higherp = &(*higherp)->higher)
 	;
     *higherp = pixmap->higher;
     pixmap->screen = 0;
     pixmap->higher = 0;
+    if (pixmap->disable)
+	twin_screen_enable_update (screen);
+    twin_screen_unlock (screen);
 }
 
 twin_pointer_t
@@ -97,6 +110,26 @@
 }
 
 void
+twin_pixmap_enable_update (twin_pixmap_t *pixmap)
+{
+    if (--pixmap->disable == 0)
+    {
+	if (pixmap->screen)
+	    twin_screen_enable_update (pixmap->screen);
+    }
+}
+
+void
+twin_pixmap_disable_update (twin_pixmap_t *pixmap)
+{
+    if (pixmap->disable++ == 0)
+    {
+	if (pixmap->screen)
+	    twin_screen_disable_update (pixmap->screen);
+    }
+}
+
+void
 twin_pixmap_damage (twin_pixmap_t *pixmap,
 		    int x1, int y1, int x2, int y2)
 {
@@ -109,6 +142,20 @@
 }
 
 void
+twin_pixmap_lock (twin_pixmap_t *pixmap)
+{
+    if (pixmap->screen)
+	twin_screen_lock (pixmap->screen);
+}
+
+void
+twin_pixmap_unlock (twin_pixmap_t *pixmap)
+{
+    if (pixmap->screen)
+	twin_screen_unlock (pixmap->screen);
+}
+
+void
 twin_pixmap_move (twin_pixmap_t *pixmap, int x, int y)
 {
     twin_pixmap_damage (pixmap, 0, 0, pixmap->width, pixmap->height);

Index: twin_poly.c
===================================================================
RCS file: /local/src/CVS/twin/twin_poly.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- twin_poly.c	27 Sep 2004 21:28:31 -0000	1.5
+++ twin_poly.c	30 Sep 2004 17:23:07 -0000	1.6
@@ -24,6 +24,17 @@
 
 #include "twinint.h"
 	    
+typedef struct _twin_edge {
+    struct _twin_edge	*next;
+    twin_sfixed_t	top, bot;
+    twin_sfixed_t	x;
+    twin_sfixed_t	e;
+    twin_sfixed_t	dx, dy;
+    twin_sfixed_t	inc_x;
+    twin_sfixed_t	step_x;
+    int			winding;
+} twin_edge_t;
+
 #define TWIN_POLY_SHIFT	    2
 #define TWIN_POLY_FIXED_SHIFT	(4 - TWIN_POLY_SHIFT)
 #define TWIN_POLY_SAMPLE    (1 << TWIN_POLY_SHIFT)
@@ -72,13 +83,14 @@
 #define DBGOUT(x...)
 #endif
 
-int
-_twin_edge_build (twin_spoint_t *vertices, int nvertices, twin_edge_t *edges)
+static int
+_twin_edge_build (twin_spoint_t *vertices, int nvertices, twin_edge_t *edges,
+		  twin_sfixed_t dx, twin_sfixed_t dy)
 {
     int		    v, nv;
     int		    tv, bv;
     int		    e;
-    twin_sfixed_t    y;
+    twin_sfixed_t   y;
 
     e = 0;
     for (v = 0; v < nvertices; v++)
@@ -107,12 +119,12 @@
 	}
 
 	/* snap top to first grid point in pixmap */
-	y = _twin_sfixed_grid_ceil (vertices[tv].y);
+	y = _twin_sfixed_grid_ceil (vertices[tv].y + dy);
 	if (y < TWIN_POLY_START)
 	    y = TWIN_POLY_START;
 	
 	/* skip vertices which don't span a sample row */
-	if (y >= vertices[bv].y)
+	if (y >= vertices[bv].y + dy)
 	    continue;
 
 	/* Compute bresenham terms */
@@ -128,10 +140,10 @@
 	edges[e].step_x = edges[e].inc_x * (edges[e].dx / edges[e].dy);
 	edges[e].dx = edges[e].dx % edges[e].dy;
 
-	edges[e].top = vertices[tv].y;
-	edges[e].bot = vertices[bv].y;
+	edges[e].top = vertices[tv].y + dy;
+	edges[e].bot = vertices[bv].y + dy;
 
-	edges[e].x = vertices[tv].x;
+	edges[e].x = vertices[tv].x + dx;
 	edges[e].e = 0;
 
 	/* step to first grid point */
@@ -254,7 +266,7 @@
     }
 }
 
-void
+static void
 _twin_edge_fill (twin_pixmap_t *pixmap, twin_edge_t *edges, int nedges)
 {
     twin_edge_t	    *active, *a, *n, **prev;
@@ -336,13 +348,15 @@
 }
 
 void
-twin_fill_path (twin_pixmap_t *pixmap, twin_path_t *path)
+twin_fill_path (twin_pixmap_t *pixmap, twin_path_t *path, int dx, int dy)
 {
-    twin_edge_t	*edges;
-    int		nedges, n;
-    int		nalloc;
-    int		s;
-    int		p;
+    twin_edge_t	    *edges;
+    int		    nedges, n;
+    int		    nalloc;
+    int		    s;
+    int		    p;
+    twin_sfixed_t   sdx = twin_int_to_sfixed (dx);
+    twin_sfixed_t   sdy = twin_int_to_sfixed (dy);
 
     nalloc = path->npoints + path->nsublen + 1;
     edges = malloc (sizeof (twin_edge_t) * nalloc);
@@ -360,7 +374,8 @@
 	npoints = sublen - p;
 	if (npoints > 1)
 	{
-	    n = _twin_edge_build (path->points + p, npoints, edges + nedges);
+	    n = _twin_edge_build (path->points + p, npoints, edges + nedges,
+				  sdx, sdy);
 	    p = sublen;
 	    nedges += n;
 	}

Index: twin_screen.c
===================================================================
RCS file: /local/src/CVS/twin/twin_screen.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- twin_screen.c	21 Sep 2004 15:42:57 -0000	1.2
+++ twin_screen.c	30 Sep 2004 17:23:07 -0000	1.3
@@ -38,12 +38,34 @@
     screen->height = height;
     screen->damage.left = screen->damage.right = 0;
     screen->damage.top = screen->damage.bottom = 0;
+    screen->damaged = NULL;
+    screen->damaged_closure = NULL;
+    screen->disable = 0;
+#if HAVE_PTHREAD_H
+    pthread_mutex_init (&screen->screen_mutex, NULL);
+#endif
     screen->put_span = put_span;
     screen->closure = closure;
     return screen;
 }
 
 void
+twin_screen_lock (twin_screen_t *screen)
+{
+#if HAVE_PTHREAD_H
+    pthread_mutex_lock (&screen->screen_mutex);
+#endif
+}
+
+void
+twin_screen_unlock (twin_screen_t *screen)
+{
+#if HAVE_PTHREAD_H
+    pthread_mutex_unlock (&screen->screen_mutex);
+#endif
+}
+
+void
 twin_screen_destroy (twin_screen_t *screen)
 {
     while (screen->bottom)
@@ -52,6 +74,35 @@
 }
 
 void
+twin_screen_register_damaged (twin_screen_t *screen, 
+			      void (*damaged) (void *),
+			      void *closure)
+{
+    screen->damaged = damaged;
+    screen->damaged_closure = closure;
+}
+
+void
+twin_screen_enable_update (twin_screen_t *screen)
+{
+    if (--screen->disable == 0)
+    {
+	if (screen->damage.left < screen->damage.right &&
+	    screen->damage.top < screen->damage.bottom)
+	{
+	    if (screen->damaged)
+		(*screen->damaged) (screen->damaged_closure);
+	}
+    }
+}
+
+void
+twin_screen_disable_update (twin_screen_t *screen)
+{
+    screen->disable++;
+}
+
+void
 twin_screen_damage (twin_screen_t *screen,
 		    int left, int top, int right, int bottom)
 {
@@ -73,6 +124,8 @@
 	if (screen->damage.bottom < bottom)
 	    screen->damage.bottom = bottom;
     }
+    if (screen->damaged && !screen->disable)
+	(*screen->damaged) (screen->damaged_closure);
 }
 
 void
@@ -93,7 +146,8 @@
 void
 twin_screen_update (twin_screen_t *screen)
 {
-    if (screen->damage.left < screen->damage.right &&
+    if (!screen->disable &&
+	screen->damage.left < screen->damage.right &&
 	screen->damage.top < screen->damage.bottom)
     {
 	int		x = screen->damage.left;

Index: twin_x11.c
===================================================================
RCS file: /local/src/CVS/twin/twin_x11.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- twin_x11.c	15 Sep 2004 20:43:17 -0000	1.1.1.1
+++ twin_x11.c	30 Sep 2004 17:23:07 -0000	1.2
@@ -22,8 +22,8 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include "twin_x11.h"
 #include "twinint.h"
-#include <X11/Xutil.h>
 
 static void
 _twin_x11_put_span (int		    x,
@@ -55,6 +55,56 @@
     XDestroyImage (image);
 }
 
+static void *
+twin_x11_damage_thread (void *arg)
+{
+    twin_x11_t	*tx = arg;
+
+    pthread_mutex_lock (&tx->screen->screen_mutex);
+    for (;;)
+    {
+	pthread_cond_wait (&tx->damage_cond, &tx->screen->screen_mutex);
+	if (!tx->win)
+	    break;
+	if (twin_screen_damaged (tx->screen))
+	{
+	    twin_x11_update (tx);
+	    XFlush (tx->dpy);
+	}
+    }
+    pthread_mutex_unlock (&tx->screen->screen_mutex);
+    return 0;
+}
+
+static void *
+twin_x11_event_thread (void *arg)
+{
+    twin_x11_t	*tx = arg;
+    XEvent	ev;
+
+    for (;;)
+    {
+	XNextEvent (tx->dpy, &ev);
+	switch (ev.type) {
+	case Expose:
+	    twin_x11_damage (tx, (XExposeEvent *) &ev);
+	    break;
+	case DestroyNotify:
+	    return 0;
+	}
+    }
+}
+
+static void
+twin_x11_screen_damaged (void *closure)
+{
+    twin_x11_t	*tx = closure;
+
+    pthread_mutex_unlock (&tx->screen->screen_mutex);
+    pthread_cond_broadcast (&tx->damage_cond);
+    pthread_mutex_unlock (&tx->screen->screen_mutex);
+}
+
 twin_x11_t *
 twin_x11_create (Display *dpy, int width, int height)
 {
@@ -85,15 +135,26 @@
     tx->gc = XCreateGC (dpy, tx->win, 0, 0);
     tx->screen = twin_screen_create (width, height,
 				     _twin_x11_put_span, tx);
+    twin_screen_register_damaged (tx->screen, twin_x11_screen_damaged, tx);
+
     XMapWindow (dpy, tx->win);
+
+    pthread_cond_init (&tx->damage_cond, NULL);
+
+    pthread_create (&tx->damage_thread, NULL, twin_x11_damage_thread, tx);
+
+    pthread_create (&tx->event_thread, NULL, twin_x11_event_thread, tx);
+    
     return tx;
 }
 
 void
 twin_x11_destroy (twin_x11_t *tx)
 {
-    twin_screen_destroy (tx->screen);
     XDestroyWindow (tx->dpy, tx->win);
+    tx->win = 0;
+    pthread_cond_broadcast (&tx->damage_cond);
+    twin_screen_destroy (tx->screen);
 }
 
 void

Index: twinint.h
===================================================================
RCS file: /local/src/CVS/twin/twinint.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- twinint.h	28 Sep 2004 05:42:36 -0000	1.7
+++ twinint.h	30 Sep 2004 17:23:07 -0000	1.8
@@ -57,6 +57,8 @@
 #define TWIN_SFIXED_ONE		(0x10)
 #define TWIN_SFIXED_HALF	(0x08)
 #define TWIN_SFIXED_TOLERANCE	(TWIN_SFIXED_ONE >> 2)
+#define TWIN_SFIXED_MIN		(-0x7fff)
+#define TWIN_SFIXED_MAX		(0x7fff)
 
 /*
  * Glyph coordinates are stored in 2.6 fixed point
@@ -285,27 +287,6 @@
  * Polygon stuff
  */
 
-typedef struct _twin_edge {
-    struct _twin_edge	*next;
-    twin_sfixed_t	top, bot;
-    twin_sfixed_t	x;
-    twin_sfixed_t	e;
-    twin_sfixed_t	dx, dy;
-    twin_sfixed_t	inc_x;
-    twin_sfixed_t	step_x;
-    int			winding;
-} twin_edge_t;
-
-/*
- * Pixmap must be in a8 format.
- */
-
-int
-_twin_edge_build (twin_spoint_t *vertices, int nvertices, twin_edge_t *edges);
-
-void
-_twin_edge_fill (twin_pixmap_t *pixmap, twin_edge_t *edges, int nedges);
-
 /*
  * Fixed point helper functions
  */

Index: xtwin.c
===================================================================
RCS file: /local/src/CVS/twin/xtwin.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- xtwin.c	28 Sep 2004 05:42:36 -0000	1.11
+++ xtwin.c	30 Sep 2004 17:23:07 -0000	1.12
@@ -22,13 +22,132 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <X11/Xlib.h>
-#include "twin.h"
+#include "twin_x11.h"
 #include <string.h>
 #include <stdio.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+#include <assert.h>
 
 #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_SECOND	0x80808080
+#define TWIN_CLOCK_TIC		0xffbababa
+#define TWIN_CLOCK_NUMBERS	0xffdedede
+
+static void
+twin_clock_hand (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_path_rotate (stroke, angle);
+    twin_path_move (stroke, D(0), D(0));
+    twin_path_draw (stroke, len, D(0));
+
+    twin_paint_stroke (clock, pixel, stroke, width);
+    
+    twin_path_destroy (stroke);
+}
+
+static twin_angle_t
+twin_clock_minute_angle (int min)
+{
+    return min * TWIN_ANGLE_360 / 60 - TWIN_ANGLE_90;
+}
+
+static void
+twin_clock_face (twin_pixmap_t *clock)
+{
+    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_path_move (path, 0, 0);
+    twin_path_circle (path, TWIN_FIXED_ONE);
+    
+    twin_paint_path (clock, TWIN_CLOCK_BACKGROUND, path);
+
+    for (m = 1; m <= 60; m++)
+    {
+	twin_state_t	state = twin_path_save (path);
+	twin_path_rotate (path, twin_clock_minute_angle (m) + TWIN_ANGLE_90);
+        twin_path_empty (path);
+	if (m % 5 != 0)
+	{
+	    twin_path_move (path, 0, -TWIN_FIXED_ONE);
+	    twin_path_draw (path, 0, -D(0.9));
+	    twin_paint_stroke (clock, TWIN_CLOCK_TIC, path, D(0.01));
+	}
+	else
+	{
+	    char    hour[3];
+	    
+	    twin_fixed_t    w;
+	    sprintf (hour, "%d", m / 5);
+	    w = twin_width_utf8 (path, hour);
+	    twin_path_move (path, -(w/2), -D(0.95));
+	    twin_path_utf8 (path, hour);
+	    twin_paint_path (clock, TWIN_CLOCK_NUMBERS, path);
+	}
+        twin_path_restore (path, &state);
+    }
+    
+    twin_path_destroy (path);
+}
+
+static void
+twin_clock (twin_screen_t *screen)
+{
+    twin_pixmap_t   *clock = twin_pixmap_create (TWIN_ARGB32, CLOCK_SIZE, CLOCK_SIZE);
+    struct timeval  tv;
+    struct tm	    t;
+    twin_angle_t    hour_angle, minute_angle, second_angle;
+
+    printf ("twin clock\n");
+    twin_pixmap_move (clock, 0, 0);
+    twin_pixmap_show (clock, screen, 0);
+    for (;;)
+    {
+	twin_pixmap_disable_update (clock);
+	twin_fill (clock, 0x00000000, TWIN_SOURCE, 0, 0, 
+		   CLOCK_SIZE, CLOCK_SIZE);
+
+	gettimeofday (&tv, NULL);
+
+	localtime_r(&tv.tv_sec, &t);
+
+	second_angle = ((t.tm_sec * 100 + tv.tv_usec / 10000) * 
+			TWIN_ANGLE_360) / 6000 - TWIN_ANGLE_90;
+	minute_angle = twin_clock_minute_angle (t.tm_min) + second_angle / 60;
+	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_pixmap_enable_update (clock);
+	usleep (1000000 - tv.tv_usec);
+    }
+}
+
 int styles[] = {
     TWIN_TEXT_ROMAN,
     TWIN_TEXT_OBLIQUE,
@@ -42,6 +161,7 @@
 int
 main (int argc, char **argv)
 {
+    Status	    status = XInitThreads ();
     Display	    *dpy = XOpenDisplay (0);
     twin_x11_t	    *x11 = twin_x11_create (dpy, WIDTH, HEIGHT);
     twin_pixmap_t   *red = twin_pixmap_create (TWIN_ARGB32, WIDTH, HEIGHT);
@@ -59,12 +179,29 @@
     twin_fixed_t    fx, fy;
     int		    g;
 
+    (void) ev;
+    (void) motion;
+    (void) had_motion;
+    (void) x;
+    (void) y;
+    (void) red;
+    (void) blue;
+    (void) status;
+    (void) alpha;
+    (void) source;
+    (void) mask;
+    (void) source;
+    (void) path;
+    
     extra = 0;
     stroke = 0;
+    pen = 0;
     s = 0;
     fx = 0;
     fy = 0;
     g = 0 ;
+
+#if 0
     pen = twin_path_create ();
     twin_path_circle (pen, D (1));
     
@@ -337,6 +474,10 @@
     twin_pixmap_move (blue, 100, 100);
     twin_pixmap_show (red, x11->screen, 0);
     twin_pixmap_show (blue, x11->screen, 0);
+#endif
+    twin_clock (x11->screen);
+    sleep (10000);
+#if 0
     had_motion = TWIN_FALSE;
     for (;;)
     {
@@ -375,5 +516,7 @@
 	    }
 	} while (QLength (dpy));
     }
+#endif
+    return 0;
 }
 




More information about the Commit mailing list