Draw: module { PATH: con "$Draw"; # predefined colors; pass to Display.color Opaque: con int 16rFFFFFFFF; Transparent: con int 16r00000000; # only useful for Display.newimage Black: con int 16r000000FF; White: con int 16rFFFFFFFF; Red: con int 16rFF0000FF; Green: con int 16r00FF00FF; Blue: con int 16r0000FFFF; Cyan: con int 16r00FFFFFF; Magenta: con int 16rFF00FFFF; Yellow: con int 16rFFFF00FF; Grey: con int 16rEEEEEEFF; Paleyellow: con int 16rFFFFAAFF; Darkyellow: con int 16rEEEE9EFF; Darkgreen: con int 16r448844FF; Palegreen: con int 16rAAFFAAFF; Medgreen: con int 16r88CC88FF; Darkblue: con int 16r000055FF; Palebluegreen: con int 16rAAFFFFFF; Paleblue: con int 16r0000BBFF; Bluegreen: con int 16r008888FF; Greygreen: con int 16r55AAAAFF; Palegreygreen: con int 16r9EEEEEFF; Yellowgreen: con int 16r99994CFF; Medblue: con int 16r000099FF; Greyblue: con int 16r005DBBFF; Palegreyblue: con int 16r4993DDFF; Purpleblue: con int 16r8888CCFF; Notacolor: con int 16rFFFFFF00; Nofill: con Notacolor; # end styles for line Endsquare: con 0; Enddisc: con 1; Endarrow: con 2; # flush control Flushoff: con 0; Flushon: con 1; Flushnow: con 2; # image backing store Refbackup: con 0; Refnone: con 1; # compositing operators SinD: con 1<<3; DinS: con 1<<2; SoutD: con 1<<1; DoutS: con 1<<0; S: con SinD|SoutD; SoverD: con SinD|SoutD|DoutS; SatopD: con SinD|DoutS; SxorD: con SoutD|DoutS; D: con DinS|DoutS; DoverS: con DinS|DoutS|SoutD; DatopS: con DinS|SoutD; DxorS: con DoutS|SoutD; Clear: con 0; # Image channels descriptor Chans: adt { desc: int; # descriptor packed into an int # interpret standard channel string mk: fn(s: string): Chans; # standard printable form text: fn(c: self Chans): string; # equality eq: fn(c: self Chans, d: Chans): int; # bits per pixel depth: fn(c: self Chans): int; }; CRed, CGreen, CBlue, CGrey, CAlpha, CMap, CIgnore: con iota; GREY1: con Chans((CGrey<<4) | 1); GREY2: con Chans((CGrey<<4) | 2); GREY4: con Chans((CGrey<<4) | 4); GREY8: con Chans((CGrey<<4) | 8); CMAP8: con Chans((CMap<<4) | 8); RGB15: con Chans(((CIgnore<<4)|1)<<24 | ((CRed<<4)|5)<<16 | ((CGreen<<4)|5)<<8 | ((CBlue<<4)|5)); RGB16: con Chans(((CRed<<4)|5)<<16 | ((CGreen<<4)|6)<<8 | ((CBlue<<4)|5)); RGB24: con Chans(((CRed<<4)|8)<<16 | ((CGreen<<4)|8)<<8 | ((CBlue<<4)|8)); RGBA32: con Chans((((CRed<<4)|8)<<24 | ((CGreen<<4)|8)<<16 | ((CBlue<<4)|8))<<8 | ((CAlpha<<4)|8)); ARGB32: con Chans(((CAlpha<<4)|8)<<24 | ((CRed<<4)|8)<<16 | ((CGreen<<4)|8)<<8 | ((CBlue<<4)|8)); # stupid VGAs XRGB32: con Chans(((CIgnore<<4)|8)<<24 | ((CRed<<4)|8)<<16 | ((CGreen<<4)|8)<<8 | ((CBlue<<4)|8)); # stupid VGAs # Coordinate of a pixel on display Point: adt { x: int; y: int; # arithmetic add: fn(p: self Point, q: Point): Point; sub: fn(p: self Point, q: Point): Point; mul: fn(p: self Point, i: int): Point; div: fn(p: self Point, i: int): Point; # equality eq: fn(p: self Point, q: Point): int; # inside rectangle in: fn(p: self Point, r: Rect): int; }; # Rectangle of pixels on the display; min <= max Rect: adt { min: Point; # upper left corner max: Point; # lower right corner # make sure min <= max canon: fn(r: self Rect): Rect; # extent dx: fn(r: self Rect): int; dy: fn(r: self Rect): int; size: fn(r: self Rect): Point; # equality eq: fn(r: self Rect, s: Rect): int; # intersection and clipping Xrect: fn(r: self Rect, s: Rect): int; inrect: fn(r: self Rect, s: Rect): int; clip: fn(r: self Rect, s: Rect): (Rect, int); contains: fn(r: self Rect, p: Point): int; combine: fn(r: self Rect, s: Rect): Rect; # arithmetic addpt: fn(r: self Rect, p: Point): Rect; subpt: fn(r: self Rect, p: Point): Rect; inset: fn(r: self Rect, n: int): Rect; }; # a picture; if made by Screen.newwindow, a window. always attached to a Display Image: adt { # these data are local copies, but repl and clipr # are monitored by the runtime and may be modified as desired. r: Rect; # rectangle in data area, local coords clipr: Rect; # clipping region depth: int; # number of bits per pixel chans: Chans; repl: int; # whether data area replicates to tile the plane display: ref Display; # where Image resides screen: ref Screen; # nil if not window iname: string; # graphics operators drawop: fn(dst: self ref Image, r: Rect, src: ref Image, matte: ref Image, p: Point, op: int); draw: fn(dst: self ref Image, r: Rect, src: ref Image, matte: ref Image, p: Point); gendrawop: fn(dst: self ref Image, r: Rect, src: ref Image, p0: Point, matte: ref Image, p1: Point, op: int); gendraw: fn(dst: self ref Image, r: Rect, src: ref Image, p0: Point, matte: ref Image, p1: Point); lineop: fn(dst: self ref Image, p0,p1: Point, end0,end1,radius: int, src: ref Image, sp: Point, op: int); line: fn(dst: self ref Image, p0,p1: Point, end0,end1,radius: int, src: ref Image, sp: Point); polyop: fn(dst: self ref Image, p: array of Point, end0,end1,radius: int, src: ref Image, sp: Point, op: int); poly: fn(dst: self ref Image, p: array of Point, end0,end1,radius: int, src: ref Image, sp: Point); bezsplineop: fn(dst: self ref Image, p: array of Point, end0,end1,radius: int, src: ref Image, sp: Point, op: int); bezspline: fn(dst: self ref Image, p: array of Point, end0,end1,radius: int, src: ref Image, sp: Point); fillpolyop: fn(dst: self ref Image, p: array of Point, wind: int, src: ref Image, sp: Point, op: int); fillpoly: fn(dst: self ref Image, p: array of Point, wind: int, src: ref Image, sp: Point); fillbezsplineop: fn(dst: self ref Image, p: array of Point, wind: int, src: ref Image, sp: Point, op: int); fillbezspline: fn(dst: self ref Image, p: array of Point, wind: int, src: ref Image, sp: Point); ellipseop: fn(dst: self ref Image, c: Point, a, b, thick: int, src: ref Image, sp: Point, op: int); ellipse: fn(dst: self ref Image, c: Point, a, b, thick: int, src: ref Image, sp: Point); fillellipseop: fn(dst: self ref Image, c: Point, a, b: int, src: ref Image, sp: Point, op: int); fillellipse: fn(dst: self ref Image, c: Point, a, b: int, src: ref Image, sp: Point); arcop: fn(dst: self ref Image, c: Point, a, b, thick: int, src: ref Image, sp: Point, alpha, phi: int, op: int); arc: fn(dst: self ref Image, c: Point, a, b, thick: int, src: ref Image, sp: Point, alpha, phi: int); fillarcop: fn(dst: self ref Image, c: Point, a, b: int, src: ref Image, sp: Point, alpha, phi: int, op: int); fillarc: fn(dst: self ref Image, c: Point, a, b: int, src: ref Image, sp: Point, alpha, phi: int); bezierop: fn(dst: self ref Image, a,b,c,d: Point, end0,end1,radius: int, src: ref Image, sp: Point, op: int); bezier: fn(dst: self ref Image, a,b,c,d: Point, end0,end1,radius: int, src: ref Image, sp: Point); fillbezierop: fn(dst: self ref Image, a,b,c,d: Point, wind:int, src: ref Image, sp: Point, op: int); fillbezier: fn(dst: self ref Image, a,b,c,d: Point, wind:int, src: ref Image, sp: Point); textop: fn(dst: self ref Image, p: Point, src: ref Image, sp: Point, font: ref Font, str: string, op: int): Point; text: fn(dst: self ref Image, p: Point, src: ref Image, sp: Point, font: ref Font, str: string): Point; textbgop: fn(dst: self ref Image, p: Point, src: ref Image, sp: Point, font: ref Font, str: string, bg: ref Image, bgp: Point, op: int): Point; textbg: fn(dst: self ref Image, p: Point, src: ref Image, sp: Point, font: ref Font, str: string, bg: ref Image, bgp: Point): Point; border: fn(dst: self ref Image, r: Rect, i: int, src: ref Image, sp: Point); arrow: fn(a,b,c: int): int; # direct access to pixels readpixels: fn(src: self ref Image, r: Rect, data: array of byte): int; writepixels: fn(dst: self ref Image, r: Rect, data: array of byte): int; # publishing name: fn(src: self ref Image, name: string, in: int): int; # windowing top: fn(win: self ref Image); bottom: fn(win: self ref Image); flush: fn(win: self ref Image, func: int); origin: fn(win: self ref Image, log, scr: Point): int; }; # a frame buffer, holding a connection to /dev/draw Display: adt { image: ref Image; # holds the contents of the display white: ref Image; black: ref Image; opaque: ref Image; transparent: ref Image; # allocate and start refresh slave allocate: fn(dev: string): ref Display; startrefresh: fn(d: self ref Display); # attach to existing Screen publicscreen: fn(d: self ref Display, id: int): ref Screen; getwindow: fn(d: self ref Display, winname: string, screen: ref Screen, image: ref Image, backup: int): (ref Screen, ref Image); # image creation newimage: fn(d: self ref Display, r: Rect, chans: Chans, repl, color: int): ref Image; color: fn(d: self ref Display, color: int): ref Image; colormix: fn(d: self ref Display, c1: int, c2: int): ref Image; rgb: fn(d: self ref Display, r, g, b: int): ref Image; # attach to named Image namedimage: fn(d: self ref Display, name: string): ref Image; # I/O to files open: fn(d: self ref Display, name: string): ref Image; readimage: fn(d: self ref Display, fd: ref Sys->FD): ref Image; writeimage: fn(d: self ref Display, fd: ref Sys->FD, i: ref Image): int; # color map rgb2cmap: fn(d: self ref Display, r, g, b: int): int; cmap2rgb: fn(d: self ref Display, c: int): (int, int, int); cmap2rgba: fn(d: self ref Display, c: int): int; }; # a mapping between characters and pictures; always attached to a Display Font: adt { name: string; # *default* or a file name (this may change) height: int; # interline spacing of font ascent: int; # distance from baseline to top display: ref Display; # where Font resides # read from file or construct from local description open: fn(d: ref Display, name: string): ref Font; build: fn(d: ref Display, name, desc: string): ref Font; # string extents width: fn(f: self ref Font, str: string): int; bbox: fn(f: self ref Font, str: string): Rect; }; # a collection of windows; always attached to a Display Screen: adt { id: int; # for export when public image: ref Image; # root of window tree fill: ref Image; # picture to use when repainting display: ref Display; # where Screen resides # create; see also Display.publicscreen allocate: fn(image, fill: ref Image, public: int): ref Screen; # allocate a new window newwindow: fn(screen: self ref Screen, r: Rect, backing: int, color: int): ref Image; # raise or lower a group of windows top: fn(screen: self ref Screen, wins: array of ref Image); bottom: fn(screen: self ref Screen, wins: array of ref Image); }; # the state of a pointer device, e.g. a mouse or stylus Pointer: adt { buttons: int; # bits 1 2 4 ... represent state of buttons left to right; 1 means pressed xy: Point; # position msec: int; # millisecond time stamp }; # graphics context Context: adt { display: ref Display; # frame buffer on which windows reside screen: ref Screen; # place to make windows (mux only) wm: chan of (string, chan of (string, ref Wmcontext)); # connect to window manager }; # connection to window manager for one or more windows (as Images) Wmcontext: adt { kbd: chan of int; # incoming characters from keyboard ptr: chan of ref Pointer; # incoming stream of mouse positions ctl: chan of string; # commands from wm to application wctl: chan of string; # commands from application to wm images: chan of ref Image; # exchange of images connfd: ref Sys->FD; # connection control ctxt: ref Context; }; # functions that don't fit well in any adt setalpha: fn(c: int, a: int): int; bytesperline: fn(r: Rect, d: int): int; icossin: fn(deg: int): (int, int); icossin2: fn(p: Point): (int, int); };