Browse Source

Plan 9 from Bell Labs 2002-12-21

David du Colombier 21 years ago
parent
commit
707bbe5a66

+ 21 - 21
dist/replica/plan9.db

@@ -468,9 +468,9 @@
 386/lib/libbin.a - 664 sys sys 1038443219 2556
 386/lib/libbio.a - 664 sys sys 1038443219 28390
 386/lib/libc.a - 664 sys sys 1039758626 496612
-386/lib/libcontrol.a - 664 sys sys 1039758627 243294
+386/lib/libcontrol.a - 664 sys sys 1040456880 243448
 386/lib/libdisk.a - 664 sys sys 1038443222 43692
-386/lib/libdraw.a - 664 sys sys 1039758627 360966
+386/lib/libdraw.a - 664 sys sys 1040456882 372606
 386/lib/libflate.a - 664 sys sys 1038443223 77880
 386/lib/libframe.a - 664 sys sys 1039758628 65832
 386/lib/libgeometry.a - 664 sys sys 1039758628 50806
@@ -3232,11 +3232,11 @@ sys/include/authsrv.h - 664 sys sys 1014929062 4542
 sys/include/bin.h - 664 sys sys 1014929062 215
 sys/include/bio.h - 664 sys sys 1014929062 1854
 sys/include/bootexec.h - 664 sys sys 1014929062 3144
-sys/include/control.h - 664 sys sys 1016833868 4865
+sys/include/control.h - 664 sys sys 1040451728 4829
 sys/include/ctype.h - 664 sys sys 1014929062 951
 sys/include/cursor.h - 664 sys sys 1014929062 102
 sys/include/disk.h - 664 sys sys 1014929063 1096
-sys/include/draw.h - 664 sys sys 1039752978 13954
+sys/include/draw.h - 664 sys sys 1040442977 15897
 sys/include/event.h - 664 sys sys 1014929063 1426
 sys/include/fcall.h - 664 sys sys 1032058178 3062
 sys/include/flate.h - 664 sys sys 1014929063 1245
@@ -4552,7 +4552,7 @@ sys/man/2/des - 664 sys sys 1032058673 3517
 sys/man/2/dial - 664 sys sys 1015701029 6523
 sys/man/2/dirread - 664 sys sys 1015091519 1901
 sys/man/2/disk - 664 sys sys 1015091519 3188
-sys/man/2/draw - 664 sys sys 984709630 16267
+sys/man/2/draw - 664 sys sys 1040457027 19338
 sys/man/2/dsa - 664 sys sys 1027629169 2072
 sys/man/2/dup - 664 sys sys 950593489 827
 sys/man/2/elgamal - 664 sys sys 1027629189 2152
@@ -4668,7 +4668,7 @@ sys/man/3/arch - 664 sys sys 958419692 1425
 sys/man/3/audio - 664 sys sys 1015024777 2932
 sys/man/3/cap - 664 sys sys 1032632323 2137
 sys/man/3/cons - 664 sys sys 1017251174 8348
-sys/man/3/draw - 664 sys sys 984709635 13692
+sys/man/3/draw - 664 sys sys 1040457030 13813
 sys/man/3/dup - 664 sys sys 1015024778 1099
 sys/man/3/env - 664 sys sys 1015024778 1409
 sys/man/3/ether - 664 sys sys 984709635 2563
@@ -10456,7 +10456,7 @@ sys/src/cmd/wikifs/wdir.c - 664 sys sys 1018211094 876
 sys/src/cmd/wikifs/wiki.h - 664 sys sys 1018323492 1891
 sys/src/cmd/wikifs/wiki2html.c - 664 sys sys 1018211094 815
 sys/src/cmd/wikifs/wiki2text.c - 664 sys sys 1018211094 779
-sys/src/cmd/winwatch.c - 664 sys sys 1016921037 4558
+sys/src/cmd/winwatch.c - 664 sys sys 1040452635 4593
 sys/src/cmd/xd.c - 664 sys sys 944961355 5735
 sys/src/cmd/yacc.c - 664 sys sys 984717754 57876
 sys/src/fs - 20000000775 sys sys 1015110109 0
@@ -11083,20 +11083,20 @@ sys/src/libcontrol - 20000000775 sys sys 1016857569 0
 sys/src/libcontrol/box.c - 664 sys sys 1015095043 3276
 sys/src/libcontrol/button.c - 664 sys sys 1015095044 4508
 sys/src/libcontrol/cache.c - 664 sys sys 1015095044 2621
-sys/src/libcontrol/control.c - 664 sys sys 1020355950 15333
-sys/src/libcontrol/entry.c - 664 sys sys 1015095045 6637
+sys/src/libcontrol/control.c - 664 sys sys 1040447292 15340
+sys/src/libcontrol/entry.c - 664 sys sys 1040447293 6645
 sys/src/libcontrol/group.c - 664 sys sys 1016731563 17710
 sys/src/libcontrol/group.h - 664 sys sys 1015095045 311
-sys/src/libcontrol/keyboard.c - 664 sys sys 1015095046 10886
-sys/src/libcontrol/label.c - 664 sys sys 1015095046 3978
-sys/src/libcontrol/menu.c - 664 sys sys 1015095046 7567
+sys/src/libcontrol/keyboard.c - 664 sys sys 1040447293 10894
+sys/src/libcontrol/label.c - 664 sys sys 1040447294 3986
+sys/src/libcontrol/menu.c - 664 sys sys 1040447294 7575
 sys/src/libcontrol/mkfile - 664 sys sys 1035389777 473
 sys/src/libcontrol/radiobutton.c - 664 sys sys 1015095046 3742
 sys/src/libcontrol/scribble.c - 664 sys sys 1015095047 6071
 sys/src/libcontrol/slider.c - 664 sys sys 1015095047 6411
 sys/src/libcontrol/tabs.c - 644 sys sys 1017166331 5521
-sys/src/libcontrol/text.c - 664 sys sys 1015095048 9062
-sys/src/libcontrol/textbutton.c - 664 sys sys 1015095048 6635
+sys/src/libcontrol/text.c - 664 sys sys 1040447295 9070
+sys/src/libcontrol/textbutton.c - 664 sys sys 1040447296 6643
 sys/src/libdisk - 20000000775 sys sys 969512501 0
 sys/src/libdisk/disk.c - 664 sys sys 1032061278 6662
 sys/src/libdisk/mkfile - 664 sys sys 1035389777 269
@@ -11107,7 +11107,7 @@ sys/src/libdraw - 20000000775 sys sys 1014927873 0
 sys/src/libdraw/alloc.c - 664 sys sys 1014927873 4095
 sys/src/libdraw/allocimagemix.c - 664 sys sys 1014927873 924
 sys/src/libdraw/arith.c - 664 sys sys 1014927873 2846
-sys/src/libdraw/bezier.c - 664 sys sys 944961724 3934
+sys/src/libdraw/bezier.c - 664 sys sys 1040442969 4948
 sys/src/libdraw/border.c - 664 sys sys 984709663 554
 sys/src/libdraw/buildfont.c - 664 sys sys 984709663 2709
 sys/src/libdraw/bytesperline.c - 664 sys sys 1014927873 617
@@ -11117,10 +11117,10 @@ sys/src/libdraw/computil.c - 664 sys sys 1014927873 680
 sys/src/libdraw/creadimage.c - 664 sys sys 1014927874 2252
 sys/src/libdraw/debug.c - 664 sys sys 1014927874 206
 sys/src/libdraw/defont.c - 664 sys sys 944961724 30537
-sys/src/libdraw/draw.c - 664 sys sys 1014927874 919
+sys/src/libdraw/draw.c - 664 sys sys 1040442971 1321
 sys/src/libdraw/drawrepl.c - 664 sys sys 944961725 314
 sys/src/libdraw/egetrect.c - 664 sys sys 1014927874 2612
-sys/src/libdraw/ellipse.c - 664 sys sys 1014927874 1173
+sys/src/libdraw/ellipse.c - 664 sys sys 1040442971 1936
 sys/src/libdraw/emenuhit.c - 664 sys sys 1014927874 7136
 sys/src/libdraw/event.c - 664 sys sys 1014927875 8985
 sys/src/libdraw/font.c - 664 sys sys 1014927875 7542
@@ -11132,7 +11132,7 @@ sys/src/libdraw/icossin.c - 664 sys sys 944961724 2117
 sys/src/libdraw/icossin2.c - 664 sys sys 944961724 4587
 sys/src/libdraw/init.c - 664 sys sys 1018288156 9046
 sys/src/libdraw/keyboard.c - 664 sys sys 1030970091 1703
-sys/src/libdraw/line.c - 664 sys sys 1014927875 526
+sys/src/libdraw/line.c - 664 sys sys 1040442973 731
 sys/src/libdraw/loadimage.c - 664 sys sys 1014927876 983
 sys/src/libdraw/makefile - 664 sys sys 944961725 648
 sys/src/libdraw/menuhit.c - 664 sys sys 1014927876 7263
@@ -11141,15 +11141,15 @@ sys/src/libdraw/mkfont.c - 664 sys sys 944961725 1283
 sys/src/libdraw/mouse.c - 664 sys sys 1030970092 2559
 sys/src/libdraw/newwindow.c - 664 sys sys 1035232036 424
 sys/src/libdraw/openfont.c - 664 sys sys 1014927876 495
-sys/src/libdraw/poly.c - 664 sys sys 1014927876 1311
+sys/src/libdraw/poly.c - 664 sys sys 1040442974 1689
 sys/src/libdraw/readcolmap.c - 664 sys sys 1014927877 745
 sys/src/libdraw/readimage.c - 664 sys sys 1014927877 2292
 sys/src/libdraw/readsubfont.c - 664 sys sys 944961725 1022
 sys/src/libdraw/rectclip.c - 664 sys sys 944961725 571
 sys/src/libdraw/replclipr.c - 664 sys sys 944961725 363
 sys/src/libdraw/rgb.c - 664 sys sys 984709666 1679
-sys/src/libdraw/string.c - 664 sys sys 1014927877 2185
-sys/src/libdraw/stringbg.c - 664 sys sys 944961725 788
+sys/src/libdraw/string.c - 664 sys sys 1040442975 2978
+sys/src/libdraw/stringbg.c - 664 sys sys 1040442975 1611
 sys/src/libdraw/stringsubfont.c - 664 sys sys 944961725 960
 sys/src/libdraw/stringwidth.c - 664 sys sys 1014927877 1587
 sys/src/libdraw/subfont.c - 664 sys sys 984709666 495

+ 21 - 0
dist/replica/plan9.log

@@ -16789,3 +16789,24 @@
 1040310178 0 c sys/src/cmd/ip/imap4d/fetch.c - 664 sys sys 1040309082 11765
 1040367722 0 c 386/bin/ip/imap4d - 775 sys sys 1040366673 232588
 1040367722 1 c 386/bin/upas/marshal - 775 sys sys 1040366675 126814
+1040443322 0 c sys/include/draw.h - 664 sys sys 1040442977 15897
+1040443322 1 c sys/src/libdraw/bezier.c - 664 sys sys 1040442969 4948
+1040443322 2 c sys/src/libdraw/draw.c - 664 sys sys 1040442971 1321
+1040443322 3 c sys/src/libdraw/ellipse.c - 664 sys sys 1040442971 1936
+1040443322 4 c sys/src/libdraw/line.c - 664 sys sys 1040442973 731
+1040443322 5 c sys/src/libdraw/poly.c - 664 sys sys 1040442974 1689
+1040443322 6 c sys/src/libdraw/string.c - 664 sys sys 1040442975 2978
+1040443322 7 c sys/src/libdraw/stringbg.c - 664 sys sys 1040442975 1611
+1040447370 0 c sys/src/libcontrol/control.c - 664 sys sys 1040447292 15340
+1040447370 1 c sys/src/libcontrol/entry.c - 664 sys sys 1040447293 6645
+1040447370 2 c sys/src/libcontrol/keyboard.c - 664 sys sys 1040447293 10894
+1040447370 3 c sys/src/libcontrol/label.c - 664 sys sys 1040447294 3986
+1040447370 4 c sys/src/libcontrol/menu.c - 664 sys sys 1040447294 7575
+1040447370 5 c sys/src/libcontrol/text.c - 664 sys sys 1040447295 9070
+1040447370 6 c sys/src/libcontrol/textbutton.c - 664 sys sys 1040447296 6643
+1040451739 0 c sys/include/control.h - 664 sys sys 1040451728 4829
+1040452670 0 c sys/src/cmd/winwatch.c - 664 sys sys 1040452635 4593
+1040457033 0 c 386/lib/libcontrol.a - 664 sys sys 1040456880 243448
+1040457033 1 c 386/lib/libdraw.a - 664 sys sys 1040456882 372606
+1040457033 2 c sys/man/2/draw - 664 sys sys 1040457027 19338
+1040457033 3 c sys/man/3/draw - 664 sys sys 1040457030 13813

+ 0 - 1
sys/include/control.h

@@ -140,7 +140,6 @@ void		_activategroup(Control*);
 void		_deactivategroup(Control*);
 int		_ctllookup(char *s, char *tab[], int ntab);
 void		_ctlprint(Control *c, char *fmt, ...);
-int		ctlparse(CParse*, char*, int);
 
 /* images */
 CImage*	_getctlimage(char*);

+ 28 - 6
sys/include/draw.h

@@ -81,11 +81,9 @@ enum
 
 #define	ARROW(a, b, c)	(Endarrow|((a)<<5)|((b)<<14)|((c)<<23))
 
-/*
- * Porter-Duff operators
- */
-enum
+typedef enum
 {
+	/* Porter-Duff compositing operators */
 	Clear	= 0,
 
 	SinD	= 8,
@@ -104,7 +102,7 @@ enum
 	DxorS	= DoutS|SoutD,	/* == SxorD */
 
 	Ncomp = 12,
-};
+} Drawop;
 
 /*
  * image channel descriptors 
@@ -398,29 +396,52 @@ extern void		icossin2(int, int, int*, int*);
  * Graphics
  */
 extern void	draw(Image*, Rectangle, Image*, Image*, Point);
+extern void	drawop(Image*, Rectangle, Image*, Image*, Point, Drawop);
 extern void	gendraw(Image*, Rectangle, Image*, Point, Image*, Point);
+extern void	gendrawop(Image*, Rectangle, Image*, Point, Image*, Point, Drawop);
 extern void	line(Image*, Point, Point, int, int, int, Image*, Point);
+extern void	lineop(Image*, Point, Point, int, int, int, Image*, Point, Drawop);
 extern void	poly(Image*, Point*, int, int, int, int, Image*, Point);
+extern void	polyop(Image*, Point*, int, int, int, int, Image*, Point, Drawop);
 extern void	fillpoly(Image*, Point*, int, int, Image*, Point);
+extern void	fillpolyop(Image*, Point*, int, int, Image*, Point, Drawop);
 extern Point	string(Image*, Point, Image*, Point, Font*, char*);
+extern Point	stringop(Image*, Point, Image*, Point, Font*, char*, Drawop);
 extern Point	stringn(Image*, Point, Image*, Point, Font*, char*, int);
+extern Point	stringnop(Image*, Point, Image*, Point, Font*, char*, int, Drawop);
 extern Point	runestring(Image*, Point, Image*, Point, Font*, Rune*);
+extern Point	runestringop(Image*, Point, Image*, Point, Font*, Rune*, Drawop);
 extern Point	runestringn(Image*, Point, Image*, Point, Font*, Rune*, int);
+extern Point	runestringnop(Image*, Point, Image*, Point, Font*, Rune*, int, Drawop);
 extern Point	stringbg(Image*, Point, Image*, Point, Font*, char*, Image*, Point);
+extern Point	stringbgop(Image*, Point, Image*, Point, Font*, char*, Image*, Point, Drawop);
 extern Point	stringnbg(Image*, Point, Image*, Point, Font*, char*, int, Image*, Point);
+extern Point	stringnbgop(Image*, Point, Image*, Point, Font*, char*, int, Image*, Point, Drawop);
 extern Point	runestringbg(Image*, Point, Image*, Point, Font*, Rune*, Image*, Point);
+extern Point	runestringbgop(Image*, Point, Image*, Point, Font*, Rune*, Image*, Point, Drawop);
 extern Point	runestringnbg(Image*, Point, Image*, Point, Font*, Rune*, int, Image*, Point);
-extern Point	_string(Image*, Point, Image*, Point, Font*, char*, Rune*, int, Rectangle, Image*, Point);
+extern Point	runestringnbgop(Image*, Point, Image*, Point, Font*, Rune*, int, Image*, Point, Drawop);
+extern Point	_string(Image*, Point, Image*, Point, Font*, char*, Rune*, int, Rectangle, Image*, Point, Drawop);
 extern Point	stringsubfont(Image*, Point, Image*, Subfont*, char*);
 extern int		bezier(Image*, Point, Point, Point, Point, int, int, int, Image*, Point);
+extern int		bezierop(Image*, Point, Point, Point, Point, int, int, int, Image*, Point, Drawop);
 extern int		bezspline(Image*, Point*, int, int, int, int, Image*, Point);
+extern int		bezsplineop(Image*, Point*, int, int, int, int, Image*, Point, Drawop);
+extern int		bezsplinepts(Point*, int, Point**);
 extern int		fillbezier(Image*, Point, Point, Point, Point, int, Image*, Point);
+extern int		fillbezierop(Image*, Point, Point, Point, Point, int, Image*, Point, Drawop);
 extern int		fillbezspline(Image*, Point*, int, int, Image*, Point);
+extern int		fillbezsplineop(Image*, Point*, int, int, Image*, Point, Drawop);
 extern void	ellipse(Image*, Point, int, int, int, Image*, Point);
+extern void	ellipseop(Image*, Point, int, int, int, Image*, Point, Drawop);
 extern void	fillellipse(Image*, Point, int, int, Image*, Point);
+extern void	fillellipseop(Image*, Point, int, int, Image*, Point, Drawop);
 extern void	arc(Image*, Point, int, int, int, Image*, Point, int, int);
+extern void	arcop(Image*, Point, int, int, int, Image*, Point, int, int, Drawop);
 extern void	fillarc(Image*, Point, int, int, Image*, Point, int, int);
+extern void	fillarcop(Image*, Point, int, int, Image*, Point, int, int, Drawop);
 extern void	border(Image*, Rectangle, int, Image*, Point);
+extern void	borderop(Image*, Rectangle, int, Image*, Point, Drawop);
 
 /*
  * Font management
@@ -472,6 +493,7 @@ extern	Image	*screen;
 extern	Screen	*_screen;
 extern	int	_cursorfd;
 extern	int	_drawdebug;	/* set to 1 to see errors from flushimage */
+extern	void	_setdrawop(Display*, Drawop);
 
 #define	BGSHORT(p)		(((p)[0]<<0) | ((p)[1]<<8))
 #define	BGLONG(p)		((BGSHORT(p)<<0) | (BGSHORT(p+2)<<16))

+ 208 - 171
sys/man/2/draw

@@ -5,16 +5,17 @@ replclipr, line, poly, fillpoly, bezier, bezspline, fillbezier, fillbezspline, e
 fillellipse, arc, fillarc, icossin, icossin2, border, string, stringn,
 runestring, runestringn, stringbg, stringnbg, runestringbg,
 runestringnbg, _string, ARROW, drawsetdebug \- graphics functions
-.SH SYNOPSIS
-.nf
-.B #include <u.h>
-.br
-.B #include <libc.h>
-.br
-.B #include <draw.h>
-.br
+.de PB
 .PP
 .ft L
+.nf
+..
+.SH SYNOPSIS
+.PB
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+.PB
 typedef
 struct Image
 {
@@ -28,168 +29,181 @@ struct Image
 	Screen	*screen;	/* 0 if not a window */
 	Image	*next;	/* next in list of windows */
 } Image;
-.ft
-.PP
-.ta \w'\fLPoint 'u
-.PP
-.B
-void draw(Image *dst, Rectangle r,
-.br
-.B
-		   Image *src, Image *mask, Point p)
-.PP
-.B
-void gendraw(Image *dst, Rectangle r,
-.br
-.B
-		   Image *src, Point sp, Image *mask, Point mp)
-.PP
-.B
-int  drawreplxy(int min, int max, int x)
-.PP
-.B
-Point drawrepl(Rectangle r, Point p)
-.PP
-.B
-void replclipr(Image *i, int repl, Rectangle clipr)
-.PP
-.B
-void line(Image *dst, Point p0, Point p1, int end0, int end1,
-.br
-.B
-		   int radius, Image *src, Point sp)
-.PP
-.B
-void poly(Image *dst, Point *p, int np, int end0, int end1,
-.br
-.B
-		   int radius, Image *src, Point sp)
-.PP
-.B
-void fillpoly(Image *dst, Point *p, int np, int wind,
-.br
-.B
-		   Image *src, Point sp)
-.PP
-.B
-int  bezier(Image *dst, Point p0, Point p1, Point p2, Point p3,
-.br
-.B
-		   int end0, int end1, int radius, Image *src, Point sp)
-.PP
-.B
-int  bezspline(Image *dst, Point *pt, int npt, int end0, int end1,
-.br
-.B
-		   int radius, Image *src, Point sp)
-.PP
-.B
-int  fillbezier(Image *dst, Point p0, Point p1, Point p2, Point p3,
-.br
-.B
-		   int w, Image *src, Point sp)
-.PP
-.B
-int  fillbezspline(Image *dst, Point *pt, int npt, int w,
-.br
-.B
-		   Image *src, Point sp)
-.PP
-.B
-void ellipse(Image *dst, Point c, int a, int b, int thick,
-.br
-.B
-		   Image *src, Point sp)
-.PP
-.B
-void fillellipse(Image *dst, Point c, int a, int b,
-.br
-.B
-		   Image *src, Point sp)
-.PP
-.B
-void arc(Image *dst, Point c, int a, int b, int thick,
-.br
-.B
-		   Image *src, Point sp, int alpha, int phi)
-.PP
-.B
-void fillarc(Image *dst, Point c, int a, int b, Image *src,
-.br
-.B
-		   Point sp, int alpha, int phi)
-.PP
-.B
-int  icossin(int deg, int *cosp, int *sinp)
-.PP
-.B
-int  icossin2(int x, int y, int *cosp, int *sinp)
-.PP
-.B
-void border(Image *dst, Rectangle r, int i, Image *color, Point sp)
-.br
-.PP
-.B
-Point string(Image *dst, Point p, Image *src, Point sp,
-.br
-.B
-		   Font *f, char *s)
-.PP
-.B
-Point stringn(Image *dst, Point p, Image *src, Point sp,
-.br
-.B
-		   Font *f, char *s, int len)
-.PP
-.B
-Point runestring(Image *dst, Point p, Image *src, Point sp,
-.br
-.B
-		   Font *f, Rune *r)
-.PP
-.B
-Point runestringn(Image *dst, Point p, Image *src, Point sp,
-.br
-.B
-		   Font *f, Rune *r, int len)
-.PP
-.B
-Point stringbg(Image *dst, Point p, Image *src, Point sp,
-.br
-.B
-		   Font *f, char *s, Image *bg, Point bgp)
-.PP
-.B
-Point stringnbg(Image *dst, Point p, Image *src, Point sp,
-.br
-.B
-		   Font *f, char *s, int len, Image *bg, Point bgp)
-.PP
-.B
-Point runestringbg(Image *dst, Point p, Image *src, Point sp,
-.br
-.B
-		   Font *f, Rune *r, Image *bg, Point bgp)
-.PP
-.B
-Point runestringnbg(Image *dst, Point p, Image *src, Point sp,
-.br
-.B
-		   Font *f, Rune *r, int len, Image *bg, Point bgp)
-.PP
-.B
-Point _string(Image *dst, Point p, Image *src,
-.br
-.B
-		   Point sp, Font *f, char *s, Rune *r, int len,
+.PB
+typedef enum
+{
+	/* Porter-Duff compositing operators */
+	Clear	= 0,
+.sp 0.1
+	SinD	= 8,
+	DinS	= 4,
+	SoutD	= 2,
+	DoutS	= 1,
+.sp 0.1
+	S		= SinD|SoutD,
+	SoverD	= SinD|SoutD|DoutS,
+	SatopD	= SinD|DoutS,
+	SxorD	= SoutD|DoutS,
+.sp 0.1
+	D		= DinS|DoutS,
+	DoverS	= DinS|DoutS|SoutD,
+	DatopS	= DinS|SoutD,
+	DxorS	= DoutS|SoutD,	/* == SxorD */
+.sp 0.1
+	Ncomp = 12,
+} Drawop;
+.PB
+.PD 0
+.ta +\w'\fL      'u +\w'\fL    'u +6n +4n
+void	draw(Image *dst, Rectangle r, Image *src,
+		Image *mask, Point p)
+.PB
+void	drawop(Image *dst, Rectangle r, Image *src,
+		Image *mask, Point p, Drawop op)
+.PB
+void	gendraw(Image *dst, Rectangle r, Image *src, Point sp,
+		Image *mask, Point mp)
+.PB
+void	gendrawop(Image *dst, Rectangle r, Image *src, Point sp,
+		Image *mask, Point mp, Drawop op)
+.PB
+int	drawreplxy(int min, int max, int x)
+.PB
+Point	drawrepl(Rectangle r, Point p)
+.PB
+void	replclipr(Image *i, int repl, Rectangle clipr)
+.PB
+void	line(Image *dst, Point p0, Point p1, int end0, int end1,
+		int radius, Image *src, Point sp)
+.PB
+void	lineop(Image *dst, Point p0, Point p1, int end0, int end1,
+		int radius, Image *src, Point sp, Drawop op)
+.PB
+void	poly(Image *dst, Point *p, int np, int end0, int end1,
+		int radius, Image *src, Point sp)
+.PB
+void	polyop(Image *dst, Point *p, int np, int end0, int end1,
+		int radius, Image *src, Point sp, Drawop op)
+.PB
+void	fillpoly(Image *dst, Point *p, int np, int wind,
+		Image *src, Point sp)
+.PB
+void	fillpolyop(Image *dst, Point *p, int np, int wind,
+		Image *src, Point sp, Drawop op)
+.PB
+int	bezier(Image *dst, Point p0, Point p1, Point p2, Point p3,
+		int end0, int end1, int radius, Image *src, Point sp)
+.PB
+int	bezierop(Image *dst, Point p0, Point p1, Point p2, Point p3,
+		int end0, int end1, int radius, Image *src, Point sp,
+		Drawop op)
+.PB
+int	bezspline(Image *dst, Point *pt, int npt, int end0, int end1,
+		int radius, Image *src, Point sp)
+.PB
+int	bezsplineop(Image *dst, Point *pt, int npt, int end0, int end1,
+		int radius, Image *src, Point sp, Drawop op)
+.PB
+int	bezsplinepts(Point *pt, int npt, Point **pp)
+.PB
+int	fillbezier(Image *dst, Point p0, Point p1, Point p2, Point p3,
+		int w, Image *src, Point sp)
+.PB
+int	fillbezierop(Image *dst, Point p0, Point p1, Point p2, Point p3,
+		int w, Image *src, Point sp, Drawop op)
+.PB
+int	fillbezspline(Image *dst, Point *pt, int npt, int w,
+		Image *src, Point sp)
+.PB
+int	fillbezsplineop(Image *dst, Point *pt, int npt, int w,
+		Image *src, Point sp, Drawop op)
+.PB
+void	ellipse(Image *dst, Point c, int a, int b, int thick,
+		Image *src, Point sp)
+.PB
+void	ellipseop(Image *dst, Point c, int a, int b, int thick,
+		Image *src, Point sp, Drawop op)
+.PB
+void	fillellipse(Image *dst, Point c, int a, int b,
+		Image *src, Point sp)
+.PB
+void	fillellipseop(Image *dst, Point c, int a, int b,
+		Image *src, Point sp, Drawop op)
+.PB
+void	arc(Image *dst, Point c, int a, int b, int thick,
+		Image *src, Point sp, int alpha, int phi)
+.PB
+void	arcop(Image *dst, Point c, int a, int b, int thick,
+		Image *src, Point sp, int alpha, int phi, Drawop op)
+.PB
+void	fillarc(Image *dst, Point c, int a, int b, Image *src,
+		Point sp, int alpha, int phi)
+.PB
+void	fillarcop(Image *dst, Point c, int a, int b, Image *src,
+		Point sp, int alpha, int phi, Drawop op)
+.PB
+int	icossin(int deg, int *cosp, int *sinp)
+.PB
+int	icossin2(int x, int y, int *cosp, int *sinp)
+.PB
+void	border(Image *dst, Rectangle r, int i, Image *color, Point sp)
 .br
-.B
-		   Rectangle clipr, Image *bg, Point bgp)
-.PP
-.B
+.PB
+Point	string(Image *dst, Point p, Image *src, Point sp,
+		Font *f, char *s)
+.PB
+Point	stringop(Image *dst, Point p, Image *src, Point sp,
+		Font *f, char *s, Drawop op)
+.PB
+Point	stringn(Image *dst, Point p, Image *src, Point sp,
+		Font *f, char *s, int len)
+.PB
+Point	stringnop(Image *dst, Point p, Image *src, Point sp,
+		Font *f, char *s, int len, Drawop op)
+.PB
+Point	runestring(Image *dst, Point p, Image *src, Point sp,
+		Font *f, Rune *r)
+.PB
+Point	runestringop(Image *dst, Point p, Image *src, Point sp,
+		Font *f, Rune *r, Drawop op)
+.PB
+Point	runestringn(Image *dst, Point p, Image *src, Point sp,
+		Font *f, Rune *r, int len)
+.PB
+Point	runestringnop(Image *dst, Point p, Image *src, Point sp,
+		Font *f, Rune *r, int len, Drawop op)
+.PB
+Point	stringbg(Image *dst, Point p, Image *src, Point sp,
+		Font *f, char *s, Image *bg, Point bgp)
+.PB
+Point	stringbgop(Image *dst, Point p, Image *src, Point sp,
+		Font *f, char *s, Image *bg, Point bgp, Drawop op)
+.PB
+Point	stringnbg(Image *dst, Point p, Image *src, Point sp,
+		Font *f, char *s, int len, Image *bg, Point bgp)
+.PB
+Point	stringnbgop(Image *dst, Point p, Image *src, Point sp,
+		Font *f, char *s, int len, Image *bg, Point bgp, Drawop op)
+.PB
+Point	runestringbg(Image *dst, Point p, Image *src, Point sp,
+		Font *f, Rune *r, Image *bg, Point bgp)
+.PB
+Point	runestringbgop(Image *dst, Point p, Image *src, Point sp,
+		Font *f, Rune *r, Image *bg, Point bgp, Drawop op)
+.PB
+Point	runestringnbg(Image *dst, Point p, Image *src, Point sp,
+		Font *f, Rune *r, int len, Image *bg, Point bgp)
+.PB
+Point	runestringnbgop(Image *dst, Point p, Image *src, Point sp,
+		Font *f, Rune *r, int len, Image *bg, Point bgp, Drawop op)
+.PB
+Point	_string(Image *dst, Point p, Image *src,
+		Point sp, Font *f, char *s, Rune *r, int len,
+		Rectangle clipr, Image *bg, Point bgp, Drawop op)
+.PB
 void	drawsetdebug(int on)
-.PP
-.ft L
+.PD
+.PB
 enum
 {
 	/* line ends */
@@ -198,10 +212,8 @@ enum
 	Endarrow	= 2,
 	Endmask		= 0x1F
 };
-
+.PB
 #define ARROW(a, b, c) (Endarrow|((a)<<5)|((b)<<14)|((c)<<23))
-.ft P
-.fi
 .SH DESCRIPTION
 The
 .B Image
@@ -291,6 +303,18 @@ the first image requires far less memory.
 The replication flag may be modified dynamically using
 .I replclipr
 .RI ( q.v. ).
+.PP
+Most of the drawing functions come in two forms:
+a basic form, and an extended form that takes an extra
+.B Drawop
+to specify a Porter-Duff compositing operator to use.
+The basic forms assume the operator is
+.BR SoverD ,
+which suffices for the vast majority of applications.
+The extended forms are named by adding an
+.RB - op
+suffix to the basic form.
+Only the basic forms are listed below.
 .TP
 .BI draw( dst\fP,\fP\ r\fP,\fP\ src\fP,\fP\ mask\fP,\fP\ p )
 .I Draw
@@ -382,6 +406,9 @@ in
 .IR mask )
 over
 .IR dst .
+(In the extended form,
+``over'' is replaced by
+.IR op ).
 .RE
 .IP
 The various
@@ -577,6 +604,16 @@ If the first and last points in
 .I p
 are equal, the spline has periodic end conditions.
 .TP
+\f5bezsplinepts(\f2pt\fP, \f2npt\fP, \f2pp\fP)
+.I Bezsplinepts
+returns in
+.I pp
+a list of points making up the open polygon that
+.I bezspline
+would draw.
+The caller is responsible for freeing
+.IR *pp .
+.TP
 \f5fillbezier(\f2dst\fP, \f2a\fP, \f2b\fP, \f2c\fP, \f2d\fP, \f2wind\fP, \f2src\fP, \f2sp\fP)
 .I Fillbezier
 is to

+ 9 - 0
sys/man/3/draw

@@ -513,6 +513,15 @@ so that the point
 .I log
 corresponds to the upper left corner of the window.
 .HP
+.B O
+.IR op [1]
+.br
+Set the compositing operator to
+.I op
+for the next draw operation.
+(The default is
+.BR SoverD ).
+.HP
 .B p
 .IR dstid [4]
 .IR n [2]

+ 2 - 1
sys/src/cmd/winwatch.c

@@ -127,7 +127,7 @@ drawwin(int i)
 	draw(screen, win[i].r, lightblue, nil, ZP);
 	_string(screen, addpt(win[i].r.min, Pt(2,0)), display->black, ZP,
 		font, win[i].label, nil, strlen(win[i].label), 
-		win[i].r, nil, ZP);
+		win[i].r, nil, ZP, SoverD);
 	border(screen, win[i].r, 1, display->black, ZP);	
 	win[i].dirty = 0;
 }
@@ -218,6 +218,7 @@ click(Mouse m)
 	sprint(buf, "/dev/wsys/%d/wctl", win[i].n);
 	if((fd = open(buf, OWRITE)) < 0)
 		return;
+	write(fd, "unhide\n", 7);
 	write(fd, "top\n", 4);
 	write(fd, "current\n", 8);
 	close(fd);

+ 1 - 1
sys/src/libcontrol/control.c

@@ -381,7 +381,7 @@ ctokenize(char *s, CParse *cp)
 	cp->nargs = tokenize(s, cp->args, nelem(cp->pargs));
 }
 
-int
+static int
 ctlparse(CParse *cp, char *s, int hasreceiver)
 {
 	int i;

+ 1 - 1
sys/src/libcontrol/entry.c

@@ -110,7 +110,7 @@ entryshow(Entry *e)
 	p = entrypoint(e, 0);
 	_string(e->screen, p, e->textcolor->image,
 		ZP, e->font->font, nil, e->text, e->ntext,
-		dr, nil, ZP);
+		dr, nil, ZP, SoverD);
 	if(e->hasfocus){
 		p = entrypoint(e, e->cursor);
 		r.min = p;

+ 1 - 1
sys/src/libcontrol/keyboard.c

@@ -305,7 +305,7 @@ keydraw(Keyboard *k, int state)
 			q = _ctlalignpoint(r, stringnwidth(f, kp, n), f->height, Acenter);
 			_string(im, q, k->textcolor->image,
 				ZP, f, kp, nil, n, r,
-				nil, ZP);
+				nil, ZP, SoverD);
 			x = r.max.x;
 			if(kp[n+1])
 				draw(im, Rect(x, r.min.y, x+1, r.max.y),

+ 1 - 1
sys/src/libcontrol/label.c

@@ -87,7 +87,7 @@ labelshow(Label *l)
 		l->font->font->height, l->align);
 	_string(l->screen, p, l->textcolor->image,
 		ZP, l->font->font, l->text, nil, strlen(l->text),
-		r, nil, ZP);
+		r, nil, ZP, SoverD);
 	flushimage(display, 1);
 }
 

+ 1 - 1
sys/src/libcontrol/menu.c

@@ -128,7 +128,7 @@ menushow(Menu0 *m)
 		q = _ctlalignpoint(r, stringwidth(f, m->line[i]), f->height, m->align%3);
 		_string(m->window, q, c,
 			ZP, f, m->line[i], nil, strlen(m->line[i]),
-			clipr, nil, ZP);
+			clipr, nil, ZP, SoverD);
 		p.y += f->height;
 	}
 //	if(m->pressed)

+ 1 - 1
sys/src/libcontrol/text.c

@@ -158,7 +158,7 @@ textshow(Text *t)
 			f->height, t->align);
 		_string(t->screen, p, t->textcolor->image,
 			ZP, f, nil, text, ntext, tr,
-			nil, ZP);
+			nil, ZP, SoverD);
 		r.min.y += f->height;
 	}
 	flushimage(display, 1);

+ 1 - 1
sys/src/libcontrol/textbutton.c

@@ -146,7 +146,7 @@ textbuttonshow(Textbutton *t)
 		q = _ctlalignpoint(r, stringwidth(f, t->line[i]), f->height, t->align%3);
 		_string(t->screen, q, im,
 			ZP, f, t->line[i], nil, strlen(t->line[i]),
-			clipr, nil, ZP);
+			clipr, nil, ZP, SoverD);
 		p.y += f->height;
 	}
 	if(t->pressed)

+ 42 - 7
sys/src/libdraw/bezier.c

@@ -105,7 +105,7 @@ bezierpts(Plist *l, Point p0, Point p1, Point p2, Point p3)
 }
 
 static void
-bezsplinepts(Plist *l, Point *pt, int npt)
+_bezsplinepts(Plist *l, Point *pt, int npt)
 {
 	Point *p, *ep;
 	Point a, b, c, d;
@@ -144,8 +144,25 @@ bezsplinepts(Plist *l, Point *pt, int npt)
 	appendpt(l, d);
 }
 
+int
+bezsplinepts(Point *pt, int npt, Point **pp)
+{
+	Plist l;
+	l.np = 0;
+	l.p = nil;
+	_bezsplinepts(&l, pt, npt);
+	*pp  = l.p;
+	return l.np;
+}
+
 int
 bezier(Image *dst, Point p0, Point p1, Point p2, Point p3, int end0, int end1, int radius, Image *src, Point sp)
+{
+	return bezierop(dst, p0, p1, p2, p3, end0, end1, radius, src, sp, SoverD);
+}
+
+int
+bezierop(Image *dst, Point p0, Point p1, Point p2, Point p3, int end0, int end1, int radius, Image *src, Point sp, Drawop op)
 {
 	Plist l;
 
@@ -154,7 +171,7 @@ bezier(Image *dst, Point p0, Point p1, Point p2, Point p3, int end0, int end1, i
 	if(l.np == -1)
 		return 0;
 	if(l.np != 0){
-		poly(dst, l.p, l.np, end0, end1, radius, src, sp);
+		polyop(dst, l.p, l.np, end0, end1, radius, src, addpt(subpt(sp, p0), l.p[0]), op);
 		free(l.p);
 	}
 	return 1;
@@ -162,15 +179,21 @@ bezier(Image *dst, Point p0, Point p1, Point p2, Point p3, int end0, int end1, i
 
 int
 bezspline(Image *dst, Point *pt, int npt, int end0, int end1, int radius, Image *src, Point sp)
+{
+	return bezsplineop(dst, pt, npt, end0, end1, radius, src, sp, SoverD);
+}
+
+int
+bezsplineop(Image *dst, Point *pt, int npt, int end0, int end1, int radius, Image *src, Point sp, Drawop op)
 {
 	Plist l;
 
 	l.np = 0;
-	bezsplinepts(&l, pt, npt);
+	_bezsplinepts(&l, pt, npt);
 	if(l.np==-1)
 		return 0;
 	if(l.np != 0){
-		poly(dst, l.p, l.np, end0, end1, radius, src, sp);
+		polyop(dst, l.p, l.np, end0, end1, radius, src, addpt(subpt(sp, pt[0]), l.p[0]), op);
 		free(l.p);
 	}
 	return 1;
@@ -178,6 +201,12 @@ bezspline(Image *dst, Point *pt, int npt, int end0, int end1, int radius, Image
 
 int
 fillbezier(Image *dst, Point p0, Point p1, Point p2, Point p3, int w, Image *src, Point sp)
+{
+	return fillbezierop(dst, p0, p1, p2, p3, w, src, sp, SoverD);
+}
+
+int
+fillbezierop(Image *dst, Point p0, Point p1, Point p2, Point p3, int w, Image *src, Point sp, Drawop op)
 {
 	Plist l;
 
@@ -186,7 +215,7 @@ fillbezier(Image *dst, Point p0, Point p1, Point p2, Point p3, int w, Image *src
 	if(l.np == -1)
 		return 0;
 	if(l.np != 0){
-		fillpoly(dst, l.p, l.np, w, src, sp);
+		fillpolyop(dst, l.p, l.np, w, src, addpt(subpt(sp, p0), l.p[0]), op);
 		free(l.p);
 	}
 	return 1;
@@ -194,15 +223,21 @@ fillbezier(Image *dst, Point p0, Point p1, Point p2, Point p3, int w, Image *src
 
 int
 fillbezspline(Image *dst, Point *pt, int npt, int w, Image *src, Point sp)
+{
+	return fillbezsplineop(dst, pt, npt, w, src, sp, SoverD);
+}
+
+int
+fillbezsplineop(Image *dst, Point *pt, int npt, int w, Image *src, Point sp, Drawop op)
 {
 	Plist l;
 
 	l.np = 0;
-	bezsplinepts(&l, pt, npt);
+	_bezsplinepts(&l, pt, npt);
 	if(l.np == -1)
 		return 0;
 	if(l.np > 0){
-		fillpoly(dst, l.p, l.np, w, src, sp);
+		fillpolyop(dst, l.p, l.np, w, src, addpt(subpt(sp, pt[0]), l.p[0]), op);
 		free(l.p);
 	}
 	return 1;

+ 32 - 6
sys/src/libdraw/draw.c

@@ -2,12 +2,28 @@
 #include <libc.h>
 #include <draw.h>
 
+void
+_setdrawop(Display *d, Drawop op)
+{
+	uchar *a;
+
+	if(op != SoverD){
+		a = bufimage(d, 1+1);
+		if(a == 0)
+			return;
+		a[0] = 'O';
+		a[1] = op;
+	}
+}
+		
 static void
-draw1(Image *dst, Rectangle *r, Image *src, Point *p0, Image *mask, Point *p1)
+draw1(Image *dst, Rectangle *r, Image *src, Point *p0, Image *mask, Point *p1, Drawop op)
 {
 	uchar *a;
 
-	a = bufimage(dst->display, 1+4+4+4+4*4+2*4+2*4+(dst->display->_isnewdisplay?1:0));
+	_setdrawop(dst->display, op);
+
+	a = bufimage(dst->display, 1+4+4+4+4*4+2*4+2*4);
 	if(a == 0)
 		return;
 	if(src == nil)
@@ -26,18 +42,28 @@ draw1(Image *dst, Rectangle *r, Image *src, Point *p0, Image *mask, Point *p1)
 	BPLONG(a+33, p0->y);
 	BPLONG(a+37, p1->x);
 	BPLONG(a+41, p1->y);
-	if(dst->display->_isnewdisplay)
-		a[41] = SoverD;
 }
 
 void
 draw(Image *dst, Rectangle r, Image *src, Image *mask, Point p1)
 {
-	draw1(dst, &r, src, &p1, mask, &p1);
+	draw1(dst, &r, src, &p1, mask, &p1, SoverD);
+}
+
+void
+drawop(Image *dst, Rectangle r, Image *src, Image *mask, Point p1, Drawop op)
+{
+	draw1(dst, &r, src, &p1, mask, &p1, op);
 }
 
 void
 gendraw(Image *dst, Rectangle r, Image *src, Point p0, Image *mask, Point p1)
 {
-	draw1(dst, &r, src, &p0, mask, &p1);
+	draw1(dst, &r, src, &p0, mask, &p1, SoverD);
+}
+
+void
+gendrawop(Image *dst, Rectangle r, Image *src, Point p0, Image *mask, Point p1, Drawop op)
+{
+	draw1(dst, &r, src, &p0, mask, &p1, op);
 }

+ 33 - 5
sys/src/libdraw/ellipse.c

@@ -4,10 +4,12 @@
 
 static
 void
-doellipse(int cmd, Image *dst, Point *c, int xr, int yr, int thick, Image *src, Point *sp, int alpha, int phi)
+doellipse(int cmd, Image *dst, Point *c, int xr, int yr, int thick, Image *src, Point *sp, int alpha, int phi, Drawop op)
 {
 	uchar *a;
 
+	_setdrawop(dst->display, op);
+
 	a = bufimage(dst->display, 1+4+4+2*4+4+4+4+2*4+2*4);
 	if(a == 0){
 		fprint(2, "image ellipse: %r\n");
@@ -30,25 +32,51 @@ doellipse(int cmd, Image *dst, Point *c, int xr, int yr, int thick, Image *src,
 void
 ellipse(Image *dst, Point c, int a, int b, int thick, Image *src, Point sp)
 {
-	doellipse('e', dst, &c, a, b, thick, src, &sp, 0, 0);
+	doellipse('e', dst, &c, a, b, thick, src, &sp, 0, 0, SoverD);
+}
+
+void
+ellipseop(Image *dst, Point c, int a, int b, int thick, Image *src, Point sp, Drawop op)
+{
+	doellipse('e', dst, &c, a, b, thick, src, &sp, 0, 0, op);
 }
 
 void
 fillellipse(Image *dst, Point c, int a, int b, Image *src, Point sp)
 {
-	doellipse('E', dst, &c, a, b, 0, src, &sp, 0, 0);
+	doellipse('E', dst, &c, a, b, 0, src, &sp, 0, 0, SoverD);
+}
+
+void
+fillellipseop(Image *dst, Point c, int a, int b, Image *src, Point sp, Drawop op)
+{
+	doellipse('E', dst, &c, a, b, 0, src, &sp, 0, 0, op);
 }
 
 void
 arc(Image *dst, Point c, int a, int b, int thick, Image *src, Point sp, int alpha, int phi)
 {
 	alpha |= 1<<31;
-	doellipse('e', dst, &c, a, b, thick, src, &sp, alpha, phi);
+	doellipse('e', dst, &c, a, b, thick, src, &sp, alpha, phi, SoverD);
+}
+
+void
+arcop(Image *dst, Point c, int a, int b, int thick, Image *src, Point sp, int alpha, int phi, Drawop op)
+{
+	alpha |= 1<<31;
+	doellipse('e', dst, &c, a, b, thick, src, &sp, alpha, phi, op);
 }
 
 void
 fillarc(Image *dst, Point c, int a, int b, Image *src, Point sp, int alpha, int phi)
 {
 	alpha |= 1<<31;
-	doellipse('E', dst, &c, a, b, 0, src, &sp, alpha, phi);
+	doellipse('E', dst, &c, a, b, 0, src, &sp, alpha, phi, SoverD);
+}
+
+void
+fillarcop(Image *dst, Point c, int a, int b, Image *src, Point sp, int alpha, int phi, Drawop op)
+{
+	alpha |= 1<<31;
+	doellipse('E', dst, &c, a, b, 0, src, &sp, alpha, phi, op);
 }

+ 8 - 0
sys/src/libdraw/line.c

@@ -4,9 +4,17 @@
 
 void
 line(Image *dst, Point p0, Point p1, int end0, int end1, int radius, Image *src, Point sp)
+{
+	lineop(dst, p0, p1, end0, end1, radius, src, sp, SoverD);
+}
+
+void
+lineop(Image *dst, Point p0, Point p1, int end0, int end1, int radius, Image *src, Point sp, Drawop op)
 {
 	uchar *a;
 
+	_setdrawop(dst->display, op);
+
 	a = bufimage(dst->display, 1+4+2*4+2*4+4+4+4+4+2*4);
 	if(a == 0){
 		fprint(2, "image line: %r\n");

+ 18 - 3
sys/src/libdraw/poly.c

@@ -22,7 +22,7 @@ addcoord(uchar *p, int oldx, int newx)
 
 static
 void
-dopoly(int cmd, Image *dst, Point *pp, int np, int end0, int end1, int radius, Image *src, Point *sp)
+dopoly(int cmd, Image *dst, Point *pp, int np, int end0, int end1, int radius, Image *src, Point *sp, Drawop op)
 {
 	uchar *a, *t, *u;
 	int i, ox, oy;
@@ -40,6 +40,9 @@ dopoly(int cmd, Image *dst, Point *pp, int np, int end0, int end1, int radius, I
 		u = addcoord(u, oy, pp[i].y);
 		oy = pp[i].y;
 	}
+
+	_setdrawop(dst->display, op);
+
 	a = bufimage(dst->display, 1+4+2+4+4+4+4+2*4+(u-t));
 	if(a == 0){
 		free(t);
@@ -62,11 +65,23 @@ dopoly(int cmd, Image *dst, Point *pp, int np, int end0, int end1, int radius, I
 void
 poly(Image *dst, Point *p, int np, int end0, int end1, int radius, Image *src, Point sp)
 {
-	dopoly('p', dst, p, np, end0, end1, radius, src, &sp);
+	dopoly('p', dst, p, np, end0, end1, radius, src, &sp, SoverD);
+}
+
+void
+polyop(Image *dst, Point *p, int np, int end0, int end1, int radius, Image *src, Point sp, Drawop op)
+{
+	dopoly('p', dst, p, np, end0, end1, radius, src, &sp, op);
 }
 
 void
 fillpoly(Image *dst, Point *p, int np, int wind, Image *src, Point sp)
 {
-	dopoly('P', dst, p, np, wind, 0, 0, src, &sp);
+	dopoly('P', dst, p, np, wind, 0, 0, src, &sp, SoverD);
+}
+
+void
+fillpolyop(Image *dst, Point *p, int np, int wind, Image *src, Point sp, Drawop op)
+{
+	dopoly('P', dst, p, np, wind, 0, 0, src, &sp, op);
 }

+ 32 - 6
sys/src/libdraw/string.c

@@ -10,29 +10,53 @@ enum
 Point
 string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s)
 {
-	return _string(dst, pt, src, sp, f, s, nil, 1<<24, dst->clipr, nil, ZP);
+	return _string(dst, pt, src, sp, f, s, nil, 1<<24, dst->clipr, nil, ZP, SoverD);
+}
+
+Point
+stringop(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Drawop op)
+{
+	return _string(dst, pt, src, sp, f, s, nil, 1<<24, dst->clipr, nil, ZP, op);
 }
 
 Point
 stringn(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, int len)
 {
-	return _string(dst, pt, src, sp, f, s, nil, len, dst->clipr, nil, ZP);
+	return _string(dst, pt, src, sp, f, s, nil, len, dst->clipr, nil, ZP, SoverD);
+}
+
+Point
+stringnop(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, int len, Drawop op)
+{
+	return _string(dst, pt, src, sp, f, s, nil, len, dst->clipr, nil, ZP, op);
 }
 
 Point
 runestring(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r)
 {
-	return _string(dst, pt, src, sp, f, nil, r, 1<<24, dst->clipr, nil, ZP);
+	return _string(dst, pt, src, sp, f, nil, r, 1<<24, dst->clipr, nil, ZP, SoverD);
+}
+
+Point
+runestringop(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, Drawop op)
+{
+	return _string(dst, pt, src, sp, f, nil, r, 1<<24, dst->clipr, nil, ZP, op);
 }
 
 Point
 runestringn(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, int len)
 {
-	return _string(dst, pt, src, sp, f, nil, r, len, dst->clipr, nil, ZP);
+	return _string(dst, pt, src, sp, f, nil, r, len, dst->clipr, nil, ZP, SoverD);
+}
+
+Point
+runestringnop(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, int len, Drawop op)
+{
+	return _string(dst, pt, src, sp, f, nil, r, len, dst->clipr, nil, ZP, op);
 }
 
 Point
-_string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Rune *r, int len, Rectangle clipr, Image *bg, Point bgp)
+_string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Rune *r, int len, Rectangle clipr, Image *bg, Point bgp, Drawop op)
 {
 	int m, n, wid, max;
 	ushort cbuf[Max], *c, *ec;
@@ -48,7 +72,7 @@ _string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Rune *r, i
 	}else
 		sptr = &s;
 	if(r == nil){
-		r = L"";
+		r = (Rune*) L"";
 		rptr = nil;
 	}else
 		rptr = &r;
@@ -58,6 +82,8 @@ _string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Rune *r, i
 			max = len;
 		n = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname);
 		if(n > 0){
+			_setdrawop(dst->display, op);
+
 			m = 47+2*n;
 			if(bg)
 				m += 4+2*4;

+ 27 - 4
sys/src/libdraw/stringbg.c

@@ -5,24 +5,47 @@
 Point
 stringbg(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Image *bg, Point bgp)
 {
-	return _string(dst, pt, src, sp, f, s, nil, 1<<24, dst->clipr, bg, bgp);
+	return _string(dst, pt, src, sp, f, s, nil, 1<<24, dst->clipr, bg, bgp, SoverD);
+}
+
+Point
+stringbgop(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Image *bg, Point bgp, int op)
+{
+	return _string(dst, pt, src, sp, f, s, nil, 1<<24, dst->clipr, bg, bgp, op);
 }
 
 Point
 stringnbg(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, int len, Image *bg, Point bgp)
 {
-	return _string(dst, pt, src, sp, f, s, nil, len, dst->clipr, bg, bgp);
+	return _string(dst, pt, src, sp, f, s, nil, len, dst->clipr, bg, bgp, SoverD);
+}
+
+Point
+stringnbgop(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, int len, Image *bg, Point bgp, int op)
+{
+	return _string(dst, pt, src, sp, f, s, nil, len, dst->clipr, bg, bgp, op);
 }
 
 Point
 runestringbg(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, Image *bg, Point bgp)
 {
-	return _string(dst, pt, src, sp, f, nil, r, 1<<24, dst->clipr, bg, bgp);
+	return _string(dst, pt, src, sp, f, nil, r, 1<<24, dst->clipr, bg, bgp, SoverD);
+}
+
+Point
+runestringbgop(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, Image *bg, Point bgp, int op)
+{
+	return _string(dst, pt, src, sp, f, nil, r, 1<<24, dst->clipr, bg, bgp, op);
 }
 
 Point
 runestringnbg(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, int len, Image *bg, Point bgp)
 {
-	return _string(dst, pt, src, sp, f, nil, r, len, dst->clipr, bg, bgp);
+	return _string(dst, pt, src, sp, f, nil, r, len, dst->clipr, bg, bgp, SoverD);
 }
 
+Point
+runestringnbgop(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, int len, Image *bg, Point bgp, int op)
+{
+	return _string(dst, pt, src, sp, f, nil, r, len, dst->clipr, bg, bgp, op);
+}