[Commit] twin ChangeLog, 1.3, 1.4 Makefile.am, 1.2, 1.3 configure.ac, 1.1.1.1, 1.2 twin.h, 1.3, 1.4 twin_convolve.c, 1.2, 1.3 twin_font.c, NONE, 1.1 twin_glyphs.c, NONE, 1.1 twin_path.c, 1.2, 1.3 twin_poly.c, 1.2, 1.3 twin_vera.c, NONE, 1.1 twinint.h, 1.3, 1.4 xtwin.c, 1.3, 1.4

Keith Packard commit at keithp.com
Thu Sep 23 21:09:14 PDT 2004


Committed by: keithp

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

Modified Files:
	ChangeLog Makefile.am configure.ac twin.h twin_convolve.c 
	twin_path.c twin_poly.c twinint.h xtwin.c 
Added Files:
	twin_font.c twin_glyphs.c twin_vera.c 
Log Message:
2004-09-23  Keith Packard  <keithp at keithp.com>

 	* Makefile.am:
	* configure.ac:
	* twin.h:
	Fix twin_fixed_floor to work for negative values correctly
	Add twin_path_cur_point
	
	* twin_convolve.c: (_twin_path_step), (_around_order), (_angle),
	(_twin_subpath_convolve), (twin_path_convolve):
	fix twin_path_step to actually handle duplicate points.
	Change 'clockwise' to 'around_order' so that all three possible
	results are returned (clockwise, parallel and counterclockwise)
	Handle disjoint strokes

	* twin_font.c: (twin_has_glyph), (twin_path_glyph),
	(twin_glyph_width), (twin_path_string), (twin_path_fglyph),
	(twin_path_ucs4), (_twin_utf8_to_ucs4), (twin_path_utf8):
	Add outline and stroke font support (pick one and remove the other)
	
	* twin_glyphs.c:
	Huge array of stroke fonts from Hershey.  Pick appropriate subset
	and remove extra glyphs (there are a lot here)
	
	* twin_path.c: (_twin_cur_subpath_len), (twin_path_cur_point),
	(twin_path_move), (twin_path_draw), (twin_path_close):
	Eliminate repeated move and close, eliminate duplicate draw.
	
	* twin_poly.c: (_twin_edge_build), (_span_fill), (_twin_edge_fill):
	Add support for 1, 4, 16 and 64 samples.  16 appears to be the
	magic sweet spot.
	
	* twin_ttf/Makefile.am:
	* twin_ttf/Vera.ttf:
	* twin_ttf/twin_ttf.c: (pos), (command), (cpos), (ucs4_to_utf8),
	(glyph), (outline_moveto), (outline_lineto), (outline_conicto),
	(outline_cubicto), (ucs_page), (ucs_first_in_page), (sanitize),
	(facename), (convert_font), (main):
	Convert "real" outline fonts to twin built-ins

	* twin_vera.c:
	Converted version of Bitstream Vera Sans Roman

	* twinint.h:
	* xtwin.c: (main):


Index: ChangeLog
===================================================================
RCS file: /local/src/CVS/twin/ChangeLog,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- ChangeLog	21 Sep 2004 18:28:38 -0000	1.3
+++ ChangeLog	24 Sep 2004 04:09:10 -0000	1.4
@@ -1,3 +1,49 @@
+2004-09-23  Keith Packard  <keithp at keithp.com>
+
+ 	* Makefile.am:
+	* configure.ac:
+	* twin.h:
+	Fix twin_fixed_floor to work for negative values correctly
+	Add twin_path_cur_point
+	
+	* twin_convolve.c: (_twin_path_step), (_around_order), (_angle),
+	(_twin_subpath_convolve), (twin_path_convolve):
+	fix twin_path_step to actually handle duplicate points.
+	Change 'clockwise' to 'around_order' so that all three possible
+	results are returned (clockwise, parallel and counterclockwise)
+	Handle disjoint strokes
+
+	* twin_font.c: (twin_has_glyph), (twin_path_glyph),
+	(twin_glyph_width), (twin_path_string), (twin_path_fglyph),
+	(twin_path_ucs4), (_twin_utf8_to_ucs4), (twin_path_utf8):
+	Add outline and stroke font support (pick one and remove the other)
+	
+	* twin_glyphs.c:
+	Huge array of stroke fonts from Hershey.  Pick appropriate subset
+	and remove extra glyphs (there are a lot here)
+	
+	* twin_path.c: (_twin_cur_subpath_len), (twin_path_cur_point),
+	(twin_path_move), (twin_path_draw), (twin_path_close):
+	Eliminate repeated move and close, eliminate duplicate draw.
+	
+	* twin_poly.c: (_twin_edge_build), (_span_fill), (_twin_edge_fill):
+	Add support for 1, 4, 16 and 64 samples.  16 appears to be the
+	magic sweet spot.
+	
+	* twin_ttf/Makefile.am:
+	* twin_ttf/Vera.ttf:
+	* twin_ttf/twin_ttf.c: (pos), (command), (cpos), (ucs4_to_utf8),
+	(glyph), (outline_moveto), (outline_lineto), (outline_conicto),
+	(outline_cubicto), (ucs_page), (ucs_first_in_page), (sanitize),
+	(facename), (convert_font), (main):
+	Convert "real" outline fonts to twin built-ins
+
+	* twin_vera.c:
+	Converted version of Bitstream Vera Sans Roman
+
+	* twinint.h:
+	* xtwin.c: (main):
+
 2004-09-21  Keith Packard  <keithp at keithp.com>
 
 	* twin.h:

Index: Makefile.am
===================================================================
RCS file: /local/src/CVS/twin/Makefile.am,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- Makefile.am	21 Sep 2004 15:42:56 -0000	1.2
+++ Makefile.am	24 Sep 2004 04:09:10 -0000	1.3
@@ -1,5 +1,6 @@
 CFLAGS=-g
 INCLUDES= @X_CFLAGS@ @WARN_CFLAGS@
+SUBDIRS=twin_ttf
 
 #libtwin_la_SOURCES = \
 #	twin.h \
@@ -18,6 +19,8 @@
 	twin.h \
 	twin_convolve.c \
 	twin_draw.c \
+	twin_glyphs.c \
+	twin_font.c \
 	twin_geom.c \
 	twin_path.c \
 	twin_pixmap.c \
@@ -25,8 +28,9 @@
 	twin_primitive.c \
 	twin_screen.c \
 	twin_spline.c \
+	twin_vera.c \
 	twin_x11.c \
 	twinint.h \
 	xtwin.c
 
-xtwin_LDADD = @X_LIBS@
+xtwin_LDADD = @X_LIBS@ -lm

Index: configure.ac
===================================================================
RCS file: /local/src/CVS/twin/configure.ac,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -d -r1.1.1.1 -r1.2
--- configure.ac	15 Sep 2004 20:43:17 -0000	1.1.1.1
+++ configure.ac	24 Sep 2004 04:09:10 -0000	1.2
@@ -52,5 +52,23 @@
 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
+
+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.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- twin.h	21 Sep 2004 18:28:38 -0000	1.3
+++ twin.h	24 Sep 2004 04:09:10 -0000	1.4
@@ -32,12 +32,14 @@
 typedef uint16_t    twin_a16_t;
 typedef uint16_t    twin_rgb16_t;
 typedef uint32_t    twin_argb32_t;
+typedef uint32_t    twin_ucs4_t;
 typedef int	    twin_bool_t;
 typedef int16_t	    twin_fixed_t;   /* 12.4 format */
 typedef int32_t	    twin_dfixed_t;
 
-#define twin_fixed_floor(f) ((((f) < 0) ? ((f) + 0xf) : (f)) >> 4)
+#define twin_fixed_floor(f) ((f) & ~0xf)
 #define twin_fixed_trunc(f) ((f) >> 4)
+#define twin_fixed_ceil(f)  (((f) + 0xf) & ~0xf)
 
 #define twin_double_to_fixed(d)	((twin_fixed_t) ((d) * 16.0))
 #define twin_fixed_to_double(f)	((double) (f) / 16.0)
@@ -157,6 +159,18 @@
 typedef struct _twin_path twin_path_t;
 
 /*
+ * A font
+ */
+
+typedef struct _twin_font {
+    const struct _twin_charmap  *charmap;
+    const unsigned char		ncharmap;
+    const char			*outlines;
+    const char			ascender, descender, height;
+    const char			*family, *style;
+} twin_font_t;
+
+/*
  * twin_convolve.c
  */
 void
@@ -192,6 +206,30 @@
 	   int		    height);
 
 /*
+ * twin_font.c
+ */
+
+twin_bool_t
+twin_has_glyph (int glyph);
+    
+void
+twin_path_glyph (twin_path_t *path, int glyph);
+ 
+int
+twin_glyph_width (int glyph);
+
+void
+twin_path_string (twin_path_t *path, unsigned char *string);
+
+void
+twin_path_ucs4 (twin_path_t *path, twin_fixed_t scale_x,
+		twin_fixed_t scale_y, twin_ucs4_t ucs4);
+    
+void
+twin_path_utf8 (twin_path_t *path, twin_fixed_t scale_x, twin_fixed_t scale_y, 
+		const char *string);
+
+/*
  * twin_path.c
  */
 
@@ -202,6 +240,9 @@
 twin_path_draw (twin_path_t *path, twin_fixed_t x, twin_fixed_t y);
 
 void
+twin_path_cur_point (twin_path_t *path, twin_fixed_t *xp, twin_fixed_t *yp);
+
+void
 twin_path_circle(twin_path_t *path, twin_fixed_t radius);
 
 void

Index: twin_convolve.c
===================================================================
RCS file: /local/src/CVS/twin/twin_convolve.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- twin_convolve.c	21 Sep 2004 18:28:38 -0000	1.2
+++ twin_convolve.c	24 Sep 2004 04:09:10 -0000	1.3
@@ -74,9 +74,10 @@
 		 int		p,
 		 int		inc)
 {
+    int n = p;
     for (;;)
     {
-	int n = p + inc;
+	n += inc;
 	if (n < 0) n += path->npoints;
 	else if (n >= path->npoints) n -= path->npoints;
 	if (path->points[n].x != path->points[p].x || 
@@ -86,11 +87,11 @@
     return 0;
 }
 
-static twin_bool_t
-_clockwise (twin_point_t    *a1,
-	    twin_point_t    *a2,
-	    twin_point_t    *b1,
-	    twin_point_t    *b2)
+static int
+_around_order (twin_point_t    *a1,
+	       twin_point_t    *a2,
+	       twin_point_t    *b1,
+	       twin_point_t    *b2)
 {
     twin_dfixed_t   adx = (a2->x - a1->x);
     twin_dfixed_t   ady = (a2->y - a1->y);
@@ -98,13 +99,37 @@
     twin_dfixed_t   bdy = (b2->y - b1->y);
     twin_dfixed_t   diff = (ady * bdx - bdy * adx);
 
-    return diff <= 0;
+    if (diff < 0) return -1;
+    if (diff > 0) return 1;
+    return 0;
 }
 
-void
-twin_path_convolve (twin_path_t	*path,
-		    twin_path_t	*stroke,
-		    twin_path_t	*pen)
+#if 0
+#include <stdio.h>
+#include <math.h>
+#define F(x)	twin_fixed_to_double(x)
+#define DBGOUT(x...)	printf(x)
+
+#if 0
+static double
+_angle (twin_point_t *a, twin_point_t *b)
+{
+    twin_fixed_t    dx = b->x - a->x;
+    twin_fixed_t    dy = b->y - a->y;
+    double	    rad;
+
+    rad = atan2 ((double) dy, (double) dx);
+    return rad * 180 / M_PI;
+}
+#endif
+#else
+#define DBGOUT(x...)
+#endif
+
+static void
+_twin_subpath_convolve (twin_path_t	*path,
+			twin_path_t	*stroke,
+			twin_path_t	*pen)
 {
     twin_point_t    *sp   = stroke->points;
     twin_point_t    *pp   = pen->points;
@@ -125,15 +150,31 @@
 
     if (sp[0].x == sp[ns - 1].x && sp[0].y == sp[ns - 1].y)
 	closed = TWIN_TRUE;
+
+    DBGOUT ("convolve: closed(%s)\n", closed ? "true" : "false");
+    DBGOUT ("stroke:\n");
+    for (s = 0; s < ns; s++)
+	DBGOUT ("\ts%02d: %9.4f, %9.4f\n", s, F(sp[s].x), F(sp[s].y));
+    DBGOUT ("pen:\n");
+    for (p = 0; p < np; p++)
+	DBGOUT ("\tp%02d: %9.4f, %9.4f\n", p, F(pp[p].x), F(pp[p].y));
     
     s = 0;
     p = start;
-    twin_path_draw (path, sp[s].x + pp[p].x, sp[s].y + pp[p].y);
+    DBGOUT ("start:  ");
+    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_move (path, sp[s].x + pp[p].x, sp[s].y + pp[p].y);
     
     /* step along the path first */
     inc = 1;
     starget = ns - 1;
-    ptarget = ret;
+    if (closed)
+	ptarget = start;
+    else
+	ptarget = ret;
     for (;;)
     {
 	/*
@@ -149,42 +190,99 @@
 	     * step along pen (forwards or backwards) or stroke as appropriate
 	     */
 	     
-	    if (!_clockwise (&sp[s],&sp[sn],&pp[p],&pp[pn]))
+#if 0
+	    DBGOUT ("\tangles: stroke %9.4f +pen %9.4f -pen %9.4f\n",
+		    _angle (&sp[s], &sp[sn]),
+		    _angle (&pp[p], &pp[pn]),
+		    _angle (&pp[pm], &pp[p]));
+#endif
+	    if (_around_order (&sp[s],&sp[sn],&pp[p],&pp[pn]) > 0)
+	    {
+		DBGOUT ("+pen:   ");
 		p = pn;
-	    else if (_clockwise(&sp[s],&sp[sn],&pp[pm],&pp[p]))
+	    }
+	    else if (_around_order (&sp[s],&sp[sn],&pp[pm],&pp[p]) < 0)
+	    {
+		DBGOUT ("-pen:   ");
 		p = pm;
+	    }
 	    else
+	    {
+		DBGOUT ("stroke: ");
 		s = sn;
+	    }
+	    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_draw (path, sp[s].x + pp[p].x, sp[s].y + pp[p].y);
 	}
 	
+	/* 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_draw (path, sp[s].x + pp[p].x, sp[s].y + pp[p].y);
+	}
 	/*
 	 * Finish this edge
 	 */
 	if (closed)
-	{
 	    twin_path_close (path);
-	    p = ptarget;
-	}
-	else
-	{
-	    /* draw a cap */
-	    while (p != ptarget)
-	    {
-	        if (++p == np) p = 0;
-	        twin_path_draw (path, sp[s].x + pp[p].x, sp[s].y + pp[p].y);
-	    }
-	}
+	
 	if (inc == -1)
 	    break;
 	
-	
 	/* reach the end of the path?  Go back the other way now */
 	inc = -1;
 	starget = 0;
 	ptarget = start;
 	
 	if (closed)
+	{
+	    p = ret;
+	    ptarget = ret;
 	    twin_path_move (path, sp[s].x + pp[p].x, sp[s].y + pp[p].y);
+	}
+	else
+	    ptarget = start;
+    }
+}
+
+void
+twin_path_convolve (twin_path_t	*path,
+		    twin_path_t	*stroke,
+		    twin_path_t	*pen)
+{
+    int		p;
+    int		s;
+
+    p = 0;
+    for (s = 0; s <= stroke->nsublen; s++)
+    {
+	int sublen;
+	int npoints;
+
+	if (s == stroke->nsublen)
+	    sublen = stroke->npoints;
+	else
+	    sublen = stroke->sublen[s];
+	npoints = sublen - p;
+	if (npoints > 1)
+	{
+	    twin_path_t	subpath;
+
+	    subpath.points = stroke->points + p;
+	    subpath.npoints = npoints;
+	    subpath.sublen = 0;
+	    subpath.nsublen = 0;
+	    _twin_subpath_convolve (path, &subpath, pen);
+	    p = sublen;
+	}
     }
 }

--- NEW FILE: twin_font.c ---
(This appears to be a binary file; contents omitted.)

--- NEW FILE: twin_glyphs.c ---
(This appears to be a binary file; contents omitted.)

Index: twin_path.c
===================================================================
RCS file: /local/src/CVS/twin/twin_path.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- twin_path.c	21 Sep 2004 18:28:38 -0000	1.2
+++ twin_path.c	24 Sep 2004 04:09:11 -0000	1.3
@@ -24,17 +24,50 @@
 
 #include "twinint.h"
 
+static int
+_twin_cur_subpath_len (twin_path_t *path)
+{
+    int	start;
+    
+    if (path->nsublen)
+	start = path->sublen[path->nsublen-1];
+    else
+	start = 0;
+    return path->npoints - start;
+}
+
+void
+twin_path_cur_point (twin_path_t *path, twin_fixed_t *x, twin_fixed_t *y)
+{
+    if (!path->npoints)
+	twin_path_move (path, 0, 0);
+    *x = path->points[path->npoints - 1].x;
+    *y = path->points[path->npoints - 1].y;
+}
+
 void 
 twin_path_move (twin_path_t *path, twin_fixed_t x, twin_fixed_t y)
 {
-    if (path->npoints)
+    switch (_twin_cur_subpath_len (path)) {
+    default:
 	twin_path_close (path);
-    twin_path_draw (path, x, y);
+    case 0:
+	twin_path_draw (path, x, y);
+	break;
+    case 1:
+	path->points[path->npoints-1].x = x;
+	path->points[path->npoints-1].y = y;
+	break;
+    }
 }
 
 void
 twin_path_draw (twin_path_t *path, twin_fixed_t x, twin_fixed_t y)
 {
+    if (_twin_cur_subpath_len(path) > 0 &&
+	path->points[path->npoints-1].x == x &&
+	path->points[path->npoints-1].y == y)
+	return;
     if (path->npoints == path->size_points)
     {
 	int		size_points;
@@ -61,6 +94,13 @@
 void
 twin_path_close (twin_path_t *path)
 {
+    switch (_twin_cur_subpath_len(path)) {
+    case 1:
+	path->npoints--;
+    case 0:
+	return;
+    }
+    
     if (path->nsublen == path->size_sublen)
     {
 	int	size_sublen;

Index: twin_poly.c
===================================================================
RCS file: /local/src/CVS/twin/twin_poly.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- twin_poly.c	21 Sep 2004 18:28:38 -0000	1.2
+++ twin_poly.c	24 Sep 2004 04:09:11 -0000	1.3
@@ -24,6 +24,15 @@
 
 #include "twinint.h"
 	    
+#define TWIN_POLY_SHIFT	    2
+#define TWIN_POLY_FIXED_SHIFT	(4 - TWIN_POLY_SHIFT)
+#define TWIN_POLY_SAMPLE    (1 << TWIN_POLY_SHIFT)
+#define TWIN_POLY_MASK	    (TWIN_POLY_SAMPLE - 1)
+#define TWIN_POLY_STEP	    (TWIN_FIXED_ONE >> TWIN_POLY_SHIFT)
+#define TWIN_POLY_START	    (TWIN_POLY_STEP >> 1)
+#define TWIN_POLY_CEIL(c)   (((c) + (TWIN_POLY_STEP-1)) & ~(TWIN_POLY_STEP-1))
+#define TWIN_POLY_COL(x)    (((x) >> TWIN_POLY_FIXED_SHIFT) & TWIN_POLY_MASK)
+
 static int
 _edge_compare_y (const void *a, const void *b)
 {
@@ -121,7 +130,6 @@
 	edges[e].top = y;
 	e++;
     }
-    qsort (edges, e, sizeof (twin_edge_t), _edge_compare_y);
     return e;
 }
     
@@ -131,62 +139,119 @@
 	    twin_fixed_t    left,
 	    twin_fixed_t    right)
 {
-    /* 2x2 oversampling yields slightly uneven alpha values */
+#if TWIN_POLY_SHIFT == 0
+    /* 1x1 */
+    static const twin_a8_t	coverage[1][1] = {
+	{ 0xff },
+    };
+#endif
+#if TWIN_POLY_SHIFT == 1
+    /* 2x2 */
     static const twin_a8_t	coverage[2][2] = {
 	{ 0x40, 0x40 },
 	{ 0x3f, 0x40 },
     };
-    const twin_a8_t *cover = coverage[(y >> 3) & 1];
+#endif
+#if TWIN_POLY_SHIFT == 2
+    /* 4x4 */
+    static const twin_a8_t	coverage[4][4] = {
+	{ 0x10, 0x10, 0x10, 0x10 },
+	{ 0x10, 0x10, 0x10, 0x10 },
+	{ 0x0f, 0x10, 0x10, 0x10 },
+	{ 0x10, 0x10, 0x10, 0x10 },
+    };
+#endif
+#if TWIN_POLY_SHIFT == 3
+    /* 8x8 */
+    static const twin_a8_t	coverage[8][8] = {
+	{ 4, 4, 4, 4, 4, 4, 4, 4 },
+	{ 4, 4, 4, 4, 4, 4, 4, 4 },
+	{ 4, 4, 4, 4, 4, 4, 4, 4 },
+	{ 4, 4, 4, 4, 4, 4, 4, 4 },
+	{ 3, 4, 4, 4, 4, 4, 4, 4 },
+	{ 4, 4, 4, 4, 4, 4, 4, 4 },
+	{ 4, 4, 4, 4, 4, 4, 4, 4 },
+	{ 4, 4, 4, 4, 4, 4, 4, 4 },
+    };
+#endif
+    const twin_a8_t *cover = coverage[(y >> TWIN_POLY_FIXED_SHIFT) & TWIN_POLY_MASK];
     int		    row = twin_fixed_trunc (y);
     twin_a8_t	    *span = pixmap->p.a8 + row * pixmap->stride;
+    twin_a8_t	    *s;
     twin_fixed_t    x;
     twin_a16_t	    a;
     twin_a16_t	    w;
+    int		    col;
     
     /* clip to pixmap */
     if (left < 0)
 	left = 0;
     
-    if (twin_fixed_trunc (right) > pixmap->width)
+    if (right > twin_int_to_fixed (pixmap->width))
 	right = twin_int_to_fixed (pixmap->width);
 
-    left = _twin_fixed_grid_ceil (left);
-    right = _twin_fixed_grid_ceil (right);
+    /* convert to sample grid */
+    left = _twin_fixed_grid_ceil (left) >> TWIN_POLY_FIXED_SHIFT;
+    right = _twin_fixed_grid_ceil (right) >> TWIN_POLY_FIXED_SHIFT;
     
     /* check for empty */
-    if (right < left)
+    if (right <= left)
 	return;
 
     x = left;
     
     /* starting address */
-    span += twin_fixed_trunc(x);
+    s = span + (x >> TWIN_POLY_SHIFT);
     
     /* first pixel */
-    if (x & TWIN_FIXED_HALF)
+    if (x & TWIN_POLY_MASK)
     {
-	a = *span + (twin_a16_t) cover[1];
-	*span++ = twin_sat (a);
-	x += TWIN_FIXED_HALF;
+	w = 0;
+	col = 0;
+	while (x < right && (x & TWIN_POLY_MASK))
+	{
+	    w += cover[col++];
+	    x++;
+	}
+	a = *s + w;
+	*s++ = twin_sat (a);
     }
 
+    w = 0;
+    for (col = 0; col < TWIN_POLY_SAMPLE; col++)
+	w += cover[col];
+
     /* middle pixels */
-    w = cover[0] + cover[1];
-    while (x < right - TWIN_FIXED_HALF)
+    while (x + TWIN_POLY_MASK < right)
     {
-	a = *span + w;
-	*span++ = twin_sat (a);
-	x += TWIN_FIXED_ONE;
+	a = *s + w;
+	*s++ = twin_sat (a);
+	x += TWIN_POLY_SAMPLE;
     }
     
     /* last pixel */
-    if (x < right)
+    if (right & TWIN_POLY_MASK)
     {
-	a = *span + (twin_a16_t) cover[0];
-	*span = twin_sat (a);
+	w = 0;
+	col = 0;
+	while (x < right)
+	{
+	    w += cover[col++];
+	    x++;
+	}
+	a = *s + w;
+	*s = twin_sat (a);
     }
 }
 
+#if 0
+#include <stdio.h>
+#define F(x)	twin_fixed_to_double(x)
+#define DBGOUT(x...)	printf(x)
+#else
+#define DBGOUT(x...)
+#endif
+
 void
 _twin_edge_fill (twin_pixmap_t *pixmap, twin_edge_t *edges, int nedges)
 {
@@ -196,6 +261,7 @@
     twin_fixed_t    x0;
     int		    w;
     
+    qsort (edges, nedges, sizeof (twin_edge_t), _edge_compare_y);
     e = 0;
     y = edges[0].top;
     active = 0;
@@ -211,16 +277,19 @@
 	    *prev = &edges[e];
 	}
 	
+	DBGOUT ("Y %9.4f:", F(y));
 	/* walk this y value marking coverage */
 	w = 0;
 	for (a = active; a; a = a->next)
 	{
+	    DBGOUT (" %9.4f(%d)", F(a->x), a->winding);
 	    if (w == 0)
 		x0 = a->x;
 	    w += a->winding;
 	    if (w == 0)
 		_span_fill (pixmap, y, x0, a->x);
 	}
+	DBGOUT ("\n");
 	
 	/* step down, clipping to pixmap */
 	y += TWIN_POLY_STEP;

--- NEW FILE: twin_vera.c ---
/* Derived from Vera.ttf */

#include "twinint.h"

static const char outlines[] = {
    /* 0x20 ( ) */ 0x14, 
	'e', 
    /* 0x21 (!) */ 0x1a, 
	'm', 0x0a, 0x08, 
	'l', 0x10, 0x08, 
	'l', 0x10, 0x00, 
	'l', 0x0a, 0x00, 
	'l', 0x0a, 0x08, 
	'm', 0x0a, 0x2f, 
	'l', 0x10, 0x2f, 
	'l', 0x10, 0x1a, 
	'l', 0x0f, 0x0f, 
	'l', 0x0a, 0x0f, 
	'l', 0x0a, 0x1a, 
[...5947 lines suppressed...]
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
    }},
};

const twin_font_t twin_Bitstream_Vera_Sans_Roman = {
    charmap, 12,
    outlines,
    0x3b, 0xf1, 0x4b, 
    "Bitstream Vera Sans", "Roman",
};

Index: twinint.h
===================================================================
RCS file: /local/src/CVS/twin/twinint.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- twinint.h	21 Sep 2004 18:28:38 -0000	1.3
+++ twinint.h	24 Sep 2004 04:09:11 -0000	1.4
@@ -242,10 +242,6 @@
     int			winding;
 } twin_edge_t;
 
-#define TWIN_POLY_STEP	    TWIN_FIXED_HALF
-#define TWIN_POLY_START	    (TWIN_POLY_STEP / 2)
-#define TWIN_POLY_CEIL(c)   (((c) + (TWIN_POLY_STEP-1)) & ~(TWIN_POLY_STEP-1))
-
 /*
  * Pixmap must be in a8 format.
  */
@@ -273,4 +269,22 @@
     int		    nsublen;
 };
 
+/*
+ * Glyph stuff
+ */
+
+typedef signed char	twin_gfixed_t;
+
+typedef struct _twin_gpoint { twin_gfixed_t x, y; } twin_gpoint_t;
+
+extern const twin_gpoint_t    *_twin_font[];
+
+#define TWIN_UCS_PAGE_SHIFT 7
+#define TWIN_UCS_PER_PAGE   (1 << TWIN_UCS_PAGE_SHIFT)
+
+typedef struct _twin_charmap {
+    uint16_t	page;
+    uint16_t	offsets[TWIN_UCS_PER_PAGE];
+} twin_charmap_t;
+
 #endif /* _TWININT_H_ */

Index: xtwin.c
===================================================================
RCS file: /local/src/CVS/twin/xtwin.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- xtwin.c	21 Sep 2004 18:28:38 -0000	1.3
+++ xtwin.c	24 Sep 2004 04:09:11 -0000	1.4
@@ -33,38 +33,113 @@
 main (int argc, char **argv)
 {
     Display	    *dpy = XOpenDisplay (0);
-    twin_x11_t	    *x11 = twin_x11_create (dpy, 256, 256);
-    twin_pixmap_t   *red = twin_pixmap_create (TWIN_ARGB32, 100, 100);
+    twin_x11_t	    *x11 = twin_x11_create (dpy, 512, 512);
+    twin_pixmap_t   *red = twin_pixmap_create (TWIN_ARGB32, 512, 512);
     twin_pixmap_t   *blue = twin_pixmap_create (TWIN_ARGB32, 100, 100);
-    twin_pixmap_t   *alpha = twin_pixmap_create (TWIN_A8, 100, 100);
+    twin_pixmap_t   *alpha = twin_pixmap_create (TWIN_A8, 512, 512);
     twin_operand_t  source, mask;
     twin_path_t	    *path;
     twin_path_t	    *pen;
     twin_path_t	    *stroke;
-    XEvent	    ev;
+    XEvent	    ev, motion;
+    twin_bool_t	    had_motion;
     int		    x, y;
+    twin_fixed_t    fx, fy;
+    int		    g;
 
-    twin_fill (red, 0x80800000, TWIN_SOURCE, 0, 0, 100, 100);
-    twin_fill (red, 0xffffff00, TWIN_SOURCE, 25, 25, 50, 50);
+    pen = twin_path_create ();
+    twin_path_circle (pen, D (0.5));
+#define OFF TWIN_FIXED_HALF
+#if 0
+    twin_path_move (pen, D(-1), D(-1));
+    twin_path_draw (pen, D(1), D(-1));
+    twin_path_draw (pen, D(1), D(1));
+    twin_path_draw (pen, D(-1), D(1));
+#endif
+    
+    twin_fill (red, 0x00000000, TWIN_SOURCE, 0, 0, 512, 512);
+    twin_fill (alpha, 0x00000000, TWIN_SOURCE, 0, 0, 512, 512);
+
+    path = twin_path_create ();
+#if 0
+    stroke = twin_path_create();
+
+#define HEIGHT	twin_int_to_fixed(16)
+#define LEFT	(twin_int_to_fixed (3) + OFF)
+    
+    fx = LEFT;
+    fy = HEIGHT + OFF;
+    
+    twin_path_move (stroke, fx, fy);
+    
+    for (g = 0; g < 4000; g++)
+/*    for (g = 1000; g < 2000; g++) */
+/*    for (g = 2000; g < 2500; g++) */
+/*     for (g = 2500; g < 3000; g++) */
+/*    for (g = 3000; g < 4000; g++) */
+    /* really chunky looking */
+/*    for (g = 4000; g < 4327; g++) */
+/*  #define WIDTH	twin_int_to_fixed(60)
+    #define HEIGHT	twin_int_to_fixed(80)
+ */
+    {
+	if (twin_has_glyph (g))
+	{
+	    if (fx + twin_glyph_width (g) > twin_int_to_fixed (500))
+		twin_path_move (stroke, fx = LEFT, fy += HEIGHT);
+	    twin_path_glyph (stroke, g);
+	    fx += twin_glyph_width (g);
+	}
+    }
+
+    twin_path_convolve (path, stroke, pen);
+
+    twin_path_destroy (stroke);
+#else
+    fx = D(3);
+    fy = D(8);
+    for (g = 6; g < 36; g++)
+    {
+	twin_path_move (path, fx, fy);
+	twin_path_utf8 (path, D(g), D(g),
+			"the quick brown fox jumps over the lazy dog.");
+	twin_path_utf8 (path, D(g), D(g),
+			"THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.");
+	fy += D(g);
+    }
+#endif
+    twin_path_fill (alpha, path);
+    
+    twin_path_destroy (path);
+    
+    source.source_kind = TWIN_SOLID;
+    source.u.argb = 0xff000000;
+    mask.source_kind = TWIN_PIXMAP;
+    mask.u.pixmap = alpha;
+    twin_composite (red, 0, 0, &source, 0, 0, &mask, 0, 0, TWIN_OVER,
+		    512, 512);
 
     twin_fill (blue, 0x00000000, TWIN_SOURCE, 0, 0, 100, 100);
     twin_fill (alpha, 0x00000000, TWIN_SOURCE, 0, 0, 100, 100);
 
+#if 1
     path = twin_path_create ();
 
-    pen = twin_path_create ();
-    twin_path_circle (pen, D (3));
-    
     stroke = twin_path_create ();
     
     twin_path_move (stroke, D (10), D (40));
     twin_path_draw (stroke, D (40), D (40));
     twin_path_draw (stroke, D (10), D (10));
+    twin_path_move (stroke, D (10), D (50));
+    twin_path_draw (stroke, D (40), D (50));
 
     twin_path_convolve (path, stroke, pen);
+    twin_path_destroy (stroke);
 
     twin_path_fill (alpha, path);
-    twin_path_empty (path);
+    twin_path_destroy (path);
+
+    path = twin_path_create ();
 
     twin_path_move (path, D (50), D (50));
     twin_path_curve (path, D (70), D (70), D (80), D (70), D (100), D (50));
@@ -77,15 +152,28 @@
     mask.u.pixmap = alpha;
     twin_composite (blue, 0, 0, &source, 0, 0, &mask, 0, 0, TWIN_OVER,
 		    100, 100);
-    
+#endif
+
     twin_pixmap_move (red, 0, 0);
     twin_pixmap_move (blue, 100, 100);
     twin_pixmap_show (red, x11->screen, 0);
     twin_pixmap_show (blue, x11->screen, 0);
+    had_motion = TWIN_FALSE;
     for (;;)
     {
+	if (had_motion)
+	{
+	    x = motion.xmotion.x - 50;
+	    y = motion.xmotion.y - 50;
+	    if (motion.xmotion.state & Button1Mask)
+		twin_pixmap_move (red, x, y);
+	    if (motion.xmotion.state & Button3Mask)
+		twin_pixmap_move (blue, x, y);
+	    had_motion = TWIN_FALSE;
+	}
 	if (twin_screen_damaged (x11->screen))
 	    twin_x11_update (x11);
+	XSync (dpy, False);
 	do {
 	    XNextEvent (dpy, &ev);
 	    switch (ev.type) {
@@ -102,12 +190,8 @@
 		}
 		break;
 	    case MotionNotify:
-		x = ev.xmotion.x - 50;
-		y = ev.xmotion.y - 50;
-		if (ev.xmotion.state & Button1Mask)
-		    twin_pixmap_move (red, x, y);
-		if (ev.xmotion.state & Button3Mask)
-		    twin_pixmap_move (blue, x, y);
+		had_motion = TWIN_TRUE;
+		motion = ev;
 		break;
 	    }
 	} while (QLength (dpy));




More information about the Commit mailing list