--- /dev/null
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+include $(GOROOT)/src/Make.$(GOARCH)
+
+TARG=draw
+GOFILES=\
+ arith.go\
+ color.go\
+ draw.go\
+ event.go\
+
+include $(GOROOT)/src/Make.pkg
--- /dev/null
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package draw
+
+// A Point is an X, Y coordinate pair.
+type Point struct {
+ X, Y int;
+}
+
+// ZP is the zero Point.
+var ZP Point
+
+// A Rectangle contains the Points with Min.X <= X < Max.X, Min.Y <= Y < Max.Y.
+type Rectangle struct {
+ Min, Max Point;
+}
+
+// ZR is the zero Rectangle.
+var ZR Rectangle
+
+// Pt is shorthand for Point{X, Y}.
+func Pt(X, Y int) Point {
+ return Point{X, Y}
+}
+
+// Rect is shorthand for Rectangle{Pt(x0, y0), Pt(x1, y1)}.
+func Rect(x0, y0, x1, y1 int) Rectangle {
+ return Rectangle{Point{x0,y0}, Point{x1,y1}}
+}
+
+// Rpt is shorthand for Rectangle{min, max}.
+func Rpt(min, max Point) Rectangle {
+ return Rectangle{min, max}
+}
+
+// Add returns the sum of p and q: Pt(p.X+q.X, p.Y+q.Y).
+func (p Point) Add(q Point) Point {
+ return Point{p.X+q.X, p.Y+q.Y}
+}
+
+// Sub returns the difference of p and q: Pt(p.X-q.X, p.Y-q.Y).
+func (p Point) Sub(q Point) Point {
+ return Point{p.X-q.X, p.Y-q.Y}
+}
+
+// Mul returns p scaled by k: Pt(p.X*k p.Y*k).
+func (p Point) Mul(k int) Point {
+ return Point{p.X*k, p.Y*k}
+}
+
+// Div returns p divided by k: Pt(p.X/k, p.Y/k).
+func (p Point) Div(k int) Point {
+ return Point{p.X/k, p.Y/k}
+}
+
+// Eq returns true if p and q are equal.
+func (p Point) Eq(q Point) bool {
+ return p.X == q.X && p.Y == q.Y
+}
+
+// Inset returns the rectangle r inset by n: Rect(r.Min.X+n, r.Min.Y+n, r.Max.X-n, r.Max.Y-n).
+func (r Rectangle) Inset(n int) Rectangle {
+ return Rectangle{Point{r.Min.X+n, r.Min.Y+n}, Point{r.Max.X-n, r.Max.Y-n}}
+}
+
+// Add returns the rectangle r translated by p: Rpt(r.Min.Add(p), r.Max.Add(p)).
+func (r Rectangle) Add(p Point) Rectangle {
+ return Rectangle{r.Min.Add(p), r.Max.Add(p)}
+}
+
+// Sub returns the rectangle r translated by -p: Rpt(r.Min.Sub(p), r.Max.Sub(p)).
+func (r Rectangle) Sub(p Point) Rectangle {
+ return Rectangle{r.Min.Sub(p), r.Max.Sub(p)}
+}
+
+// Canon returns a canonical version of r: the returned rectangle
+// has Min.X <= Max.X and Min.Y <= Max.Y.
+func (r Rectangle) Canon() Rectangle {
+ if r.Max.X < r.Min.X {
+ r.Max.X = r.Min.X
+ }
+ if r.Max.Y < r.Min.Y {
+ r.Max.Y = r.Min.Y
+ }
+ return r;
+}
+
+// Overlaps returns true if r and r1 cross; that is, it returns true if they share any point.
+func (r Rectangle) Overlaps(r1 Rectangle) bool {
+ return r.Min.X < r1.Max.X && r1.Min.X < r.Max.X
+ && r.Min.Y < r1.Max.Y && r1.Min.Y < r.Max.Y
+}
+
+// Empty retruns true if r contains no points.
+func (r Rectangle) Empty() bool {
+ return r.Max.X <= r.Min.X || r.Max.Y <= r.Min.Y
+}
+
+// InRect returns true if all the points in r are also in r1.
+func (r Rectangle) In(r1 Rectangle) bool {
+ if r.Empty() {
+ return true
+ }
+ if r1.Empty() {
+ return false
+ }
+ return r1.Min.X <= r.Min.X && r.Max.X <= r1.Max.X
+ && r1.Min.Y <= r.Min.Y && r.Max.Y <= r1.Max.Y
+}
+
+// Combine returns the smallest rectangle containing all points from r and from r1.
+func (r Rectangle) Combine(r1 Rectangle) Rectangle {
+ if r.Empty() {
+ return r1
+ }
+ if r1.Empty() {
+ return r
+ }
+ if r.Min.X > r1.Min.X {
+ r.Min.X = r1.Min.X
+ }
+ if r.Min.Y > r1.Min.Y {
+ r.Min.Y = r1.Min.Y
+ }
+ if r.Max.X < r1.Max.X {
+ r.Max.X = r1.Max.X
+ }
+ if r.Max.Y < r1.Max.Y {
+ r.Max.Y = r1.Max.Y
+ }
+ return r
+}
+
+// Clip returns the largest rectangle containing only points shared by r and r1.
+func (r Rectangle) Clip(r1 Rectangle) Rectangle {
+ if r.Empty() {
+ return r
+ }
+ if r1.Empty() {
+ return r1
+ }
+ if r.Min.X < r1.Min.X {
+ r.Min.X = r1.Min.X
+ }
+ if r.Min.Y < r1.Min.Y {
+ r.Min.Y = r1.Min.Y
+ }
+ if r.Max.X > r1.Max.X {
+ r.Max.X = r1.Max.X
+ }
+ if r.Max.Y > r1.Max.Y {
+ r.Max.Y = r1.Max.Y
+ }
+ return r;
+}
+
+// Dx returns the width of the rectangle r: r.Max.X - r.Min.X.
+func (r Rectangle) Dx() int {
+ return r.Max.X - r.Min.X
+}
+
+// Dy returns the width of the rectangle r: r.Max.Y - r.Min.Y.
+func (r Rectangle) Dy() int {
+ return r.Max.Y - r.Min.Y
+}
+
--- /dev/null
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package draw
+
+import "image"
+
+// A Color represents a color with 8-bit R, G, B, and A values,
+// packed into a uint32—0xRRGGBBAA—so that comparison
+// is defined on colors.
+// Color implements image.Color.
+// Color also implements image.Image: it is a
+// 10⁹x10⁹-pixel image of uniform color.
+type Color uint32
+
+// Check that Color implements image.Color and image.Image
+var _ image.Color = Black
+var _ image.Image = Black
+
+var (
+ Opaque Color = 0xFFFFFFFF;
+ Transparent Color = 0x00000000;
+ Black Color = 0x000000FF;
+ White Color = 0xFFFFFFFF;
+ Red Color = 0xFF0000FF;
+ Green Color = 0x00FF00FF;
+ Blue Color = 0x0000FFFF;
+ Cyan Color = 0x00FFFFFF;
+ Magenta Color = 0xFF00FFFF;
+ Yellow Color = 0xFFFF00FF;
+ PaleYellow Color = 0xFFFFAAFF;
+ DarkYellow Color = 0xEEEE9EFF;
+ DarkGreen Color = 0x448844FF;
+ PaleGreen Color = 0xAAFFAAFF;
+ MedGreen Color = 0x88CC88FF;
+ DarkBlue Color = 0x000055FF;
+ PaleBlueGreen Color = 0xAAFFFFFF;
+ PaleBlue Color = 0x0000BBFF;
+ BlueGreen Color = 0x008888FF;
+ GreyGreen Color = 0x55AAAAFF;
+ PaleGreyGreen Color = 0x9EEEEEFF;
+ YellowGreen Color = 0x99994CFF;
+ MedBlue Color = 0x000099FF;
+ GreyBlue Color = 0x005DBBFF;
+ PaleGreyBlue Color = 0x4993DDFF;
+ PurpleBlue Color = 0x8888CCFF;
+)
+
+func (c Color) RGBA() (r, g, b, a uint32) {
+ x := uint32(c);
+ r, g, b, a = x>>24, (x>>16)&0xFF, (x>>8)&0xFF, x&0xFF;
+ r |= r<<8;
+ r |= r<<16;
+ g |= g<<8;
+ g |= g<<16;
+ b |= b<<8;
+ b |= b<<16;
+ a |= a<<8;
+ a |= a<<16;
+ return;
+}
+
+// SetAlpha returns the color obtained by changing
+// c's alpha value to a and scaling r, g, and b appropriately.
+func (c Color) SetAlpha(a uint8) Color {
+ r, g, b, oa := c>>24, (c>>16)&0xFF, (c>>8)&0xFF, c&0xFF;
+ if oa == 0 {
+ return 0
+ }
+ r = r*Color(a)/oa;
+ if r < 0 {
+ r = 0;
+ }
+ if r > 0xFF {
+ r = 0xFF;
+ }
+ g = g*Color(a)/oa;
+ if g < 0 {
+ g = 0;
+ }
+ if g > 0xFF {
+ g = 0xFF;
+ }
+ b = b*Color(a)/oa;
+ if b < 0 {
+ b = 0;
+ }
+ if b > 0xFF {
+ b = 0xFF;
+ }
+ return r<<24 | g<<16 | b<<8 | Color(a);
+}
+
+func (c Color) Width() int {
+ return 1e9;
+}
+
+func (c Color) Height() int {
+ return 1e9;
+}
+
+func (c Color) At(x, y int) image.Color {
+ return c;
+}
+
+func toColor(color image.Color) image.Color {
+ if c, ok := color.(Color); ok {
+ return c;
+ }
+ r, g, b, a := color.RGBA();
+ return Color(r>>24<<24 | g>>24<<16 | b>>24<<8 | a>>24);
+}
+
+func (c Color) ColorModel() image.ColorModel {
+ return image.ColorModelFunc(toColor);
+}
--- /dev/null
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package draw provides basic graphics and drawing primitives,
+// in the style of the Plan 9 graphics library
+// (see http://plan9.bell-labs.com/magic/man2html/2/draw)
+// and the X Render extension.
+package draw
+
+// BUG(rsc): This is a toy library and not ready for production use.
+
+import "image"
+
+// A draw.Image is an image.Image with a Set method to change a single pixel.
+type Image interface {
+ image.Image;
+ Set(x, y int, c image.Color);
+}
+
+// Draw aligns r.Min in dst with pt in src and mask
+// and then replaces the rectangle r in dst with the
+// result of the Porter-Duff compositing operation
+// ``(src in mask) over dst.'' If mask is nil, the operation
+// simplifies to ``src over dst.''
+// The implementation is simple and slow.
+func Draw(dst Image, r Rectangle, src, mask image.Image, pt Point) {
+ // Plenty of room for optimizations here.
+
+ dx, dy := src.Width(), src.Height();
+ if mask != nil {
+ if dx > mask.Width() {
+ dx = mask.Width();
+ }
+ if dy > mask.Width() {
+ dy = mask.Width();
+ }
+ }
+ dx -= pt.X;
+ dy -= pt.Y;
+ if r.Dx() > dx {
+ r.Max.X = r.Min.X + dx;
+ }
+ if r.Dy() > dy {
+ r.Max.Y = r.Min.Y + dy;
+ }
+
+ x0, x1, dx := r.Min.X, r.Max.X, 1;
+ y0, y1, dy := r.Min.Y, r.Max.Y, 1;
+ if image.Image(dst) == src && r.Overlaps(r.Add(pt.Sub(r.Min))) {
+ // Rectangles overlap: process backward?
+ if pt.Y < r.Min.Y || pt.Y == r.Min.Y && pt.X < r.Min.X {
+ x0, x1, dx = x1-1, x0-1, -1;
+ y0, y1, dy = y1-1, y0-1, -1;
+ }
+ }
+
+ var out *image.RGBA64Color;
+ for y := y0; y != y1; y+=dy {
+ for x := x0; x != x1; x+=dx {
+ sx := pt.X + x - r.Min.X;
+ sy := pt.Y + y - r.Min.Y;
+ if mask == nil {
+ dst.Set(x, y, src.At(sx, sy));
+ continue;
+ }
+ _, _, _, ma := mask.At(sx, sy).RGBA();
+ switch ma {
+ case 0:
+ continue;
+ case 0xFFFFFFFF:
+ dst.Set(x, y, src.At(sx, sy));
+ default:
+ dr, dg, db, da := dst.At(x, y).RGBA();
+ dr >>= 16;
+ dg >>= 16;
+ db >>= 16;
+ da >>= 16;
+ sr, sg, sb, sa := src.At(sx, sy).RGBA();
+ sr >>= 16;
+ sg >>= 16;
+ sb >>= 16;
+ sa >>= 16;
+ ma >>= 16;
+ const M = 1<<16 - 1;
+ a := sa*ma/M;
+ dr = (dr*(M-a) + sr*ma) / M;
+ dg = (dg*(M-a) + sg*ma) / M;
+ db = (db*(M-a) + sb*ma) / M;
+ da = (da*(M-a) + sa*ma) / M;
+ if out == nil {
+ out = new(image.RGBA64Color);
+ }
+ out.R = uint16(dr);
+ out.G = uint16(dg);
+ out.B = uint16(db);
+ out.A = uint16(da);
+ dst.Set(x, y, out);
+ }
+ }
+ }
+}
+
+// Border aligns r.Min in dst with sp in src and then replaces pixels
+// in a w-pixel border around r in dst with the result of the Porter-Duff compositing
+// operation ``src over dst.'' If w is positive, the border extends w pixels inside r.
+// If w is negative, the border extends w pixels outside r.
+func Border(dst Image, r Rectangle, w int, src image.Image, sp Point) {
+ i := w;
+ if i > 0 {
+ // inside r
+ Draw(dst, Rect(r.Min.X, r.Min.Y, r.Max.X, r.Min.Y+i), src, nil, sp); // top
+ Draw(dst, Rect(r.Min.X, r.Min.Y+i, r.Min.X+i, r.Max.Y-i), src, nil, sp.Add(Pt(0, i))); // left
+ Draw(dst, Rect(r.Max.X-i, r.Min.Y+i, r.Max.X, r.Max.Y-i), src, nil, sp.Add(Pt(r.Dx()-i, i))); // right
+ Draw(dst, Rect(r.Min.X, r.Max.Y-i, r.Max.X, r.Max.Y), src, nil, sp.Add(Pt(0, r.Dy()-i))); // bottom
+ return;
+ }
+
+ // outside r;
+ i = -i;
+ Draw(dst, Rect(r.Min.X-i, r.Min.Y-i, r.Max.X+i, r.Min.Y), src, nil, sp.Add(Pt(-i, -i))); // top
+ Draw(dst, Rect(r.Min.X-i, r.Min.Y, r.Min.X, r.Max.Y), src, nil, sp.Add(Pt(-i, 0))); // left
+ Draw(dst, Rect(r.Max.X, r.Min.Y, r.Max.X+i, r.Max.Y), src, nil, sp.Add(Pt(r.Dx(), 0))); // right
+ Draw(dst, Rect(r.Min.X-i, r.Max.Y, r.Max.X+i, r.Max.Y+i), src, nil, sp.Add(Pt(-i, 0))); // bottom
+}
--- /dev/null
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package draw
+
+// A Context represents a single graphics window.
+type Context interface {
+ // Screen returns an editable Image of window.
+ Screen() Image;
+
+ // FlushImage flushes changes made to Screen() back to screen.
+ FlushImage();
+
+ // KeyboardChan returns a channel carrying keystrokes.
+ // An event is sent each time a key is pressed or released.
+ // The value k represents key k being pressed.
+ // The value -k represents key k being released.
+ // The specific set of key values is not specified,
+ // but ordinary character represent themselves.
+ KeyboardChan() <-chan int;
+
+ // MouseChan returns a channel carrying mouse events.
+ // A new event is sent each time the mouse moves or a
+ // button is pressed or released.
+ MouseChan() <-chan Mouse;
+
+ // ResizeChan returns a channel carrying resize events.
+ // An event is sent each time the window is resized;
+ // the client should respond by calling Screen() to obtain
+ // the new screen image.
+ // The value sent on the channel is always ``true'' and can be ignored.
+ ResizeChan() <-chan bool;
+
+ // QuitChan returns a channel carrying quit requests.
+ // After reading a value from the quit channel, the application
+ // should exit.
+ QuitChan() <-chan bool;
+}
+
+// A Mouse represents the state of the mouse.
+type Mouse struct {
+ Buttons int; // bit mask of buttons: 1<<0 is left, 1<<1 middle, 1<<2 right
+ Point; // location of cursor
+ Nsec int64; // time stamp
+}
+