From e5ff69e15144bab73472e5981a154943842a64b2 Mon Sep 17 00:00:00 2001 From: Michael Fogleman Date: Tue, 23 Feb 2016 16:30:53 -0500 Subject: [PATCH] add doc comments to context functions --- context.go | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/context.go b/context.go index 124363b..7ddea93 100644 --- a/context.go +++ b/context.go @@ -1,3 +1,4 @@ +// Package gg provides a simple API for rendering 2D graphics in pure Go. package gg import ( @@ -54,14 +55,20 @@ type Context struct { stack []*Context } +// NewContext creates a new image.RGBA with the specified width and height +// and prepares a context for rendering onto that image. func NewContext(width, height int) *Context { return NewContextForRGBA(image.NewRGBA(image.Rect(0, 0, width, height))) } +// NewContextForImage copies the specified image into a new image.RGBA +// and prepares a context for rendering onto that image. func NewContextForImage(im image.Image) *Context { return NewContextForRGBA(imageToRGBA(im)) } +// NewContextForRGBA prepares a context for rendering onto the specified image. +// No copy is made. func NewContextForRGBA(im *image.RGBA) *Context { return &Context{ width: im.Bounds().Size().X, @@ -76,22 +83,29 @@ func NewContextForRGBA(im *image.RGBA) *Context { } } +// Image returns the image that has been drawn by this context. func (dc *Context) Image() image.Image { return dc.im } +// Width returns the width of the image in pixels. func (dc *Context) Width() int { return dc.width } +// Height returns the height of the image in pixels. func (dc *Context) Height() int { return dc.height } +// SavePNG encodes the image as a PNG and writes it to disk. func (dc *Context) SavePNG(path string) error { return SavePNG(path, dc.im) } +// SetDash sets the current dash pattern to use. Call with zero arguments to +// disable dashes. The values specify the lengths of each dash, with +// alternating on and off lengths. func (dc *Context) SetDash(dashes ...float64) { dc.dashes = dashes } @@ -142,23 +156,33 @@ func (dc *Context) SetFillRuleEvenOdd() { // Color Setters +// SetColor sets the current color. func (dc *Context) SetColor(c color.Color) { dc.color = c } +// SetHexColor sets the current color using a hex string. The leading pound +// sign (#) is optional. Both 3- and 6-digit variations are supported. 8 digits +// may be provided to set the alpha value as well. func (dc *Context) SetHexColor(x string) { r, g, b, a := parseHexColor(x) dc.SetRGBA255(r, g, b, a) } +// SetRGBA255 sets the current color. r, g, b, a values should be between 0 and +// 255, inclusive. func (dc *Context) SetRGBA255(r, g, b, a int) { dc.color = color.NRGBA{uint8(r), uint8(g), uint8(b), uint8(a)} } +// SetRGB255 sets the current color. r, g, b values should be between 0 and 255, +// inclusive. Alpha will be set to 255 (fully opaque). func (dc *Context) SetRGB255(r, g, b int) { dc.SetRGBA255(r, g, b, 255) } +// SetRGBA sets the current color. r, g, b, a values should be between 0 and 1, +// inclusive. func (dc *Context) SetRGBA(r, g, b, a float64) { dc.color = color.NRGBA{ uint8(r * 255), @@ -168,12 +192,16 @@ func (dc *Context) SetRGBA(r, g, b, a float64) { } } +// SetRGB sets the current color. r, g, b values should be between 0 and 1, +// inclusive. Alpha will be set to 1 (fully opaque). func (dc *Context) SetRGB(r, g, b float64) { dc.SetRGBA(r, g, b, 1) } // Path Manipulation +// MoveTo starts a new subpath within the current path starting at the +// specified point. func (dc *Context) MoveTo(x, y float64) { if dc.hasCurrent { dc.fillPath.Add1(dc.start.Fixed()) @@ -187,6 +215,8 @@ func (dc *Context) MoveTo(x, y float64) { dc.hasCurrent = true } +// LineTo adds a line segment to the current path starting at the current +// point. If there is no current point, it is equivalent to MoveTo(x, y) func (dc *Context) LineTo(x, y float64) { if !dc.hasCurrent { dc.MoveTo(x, y) @@ -199,6 +229,9 @@ func (dc *Context) LineTo(x, y float64) { } } +// QuadraticTo adds a quadratic bezier curve to the current path starting at +// the current point. If there is no current point, it first performs +// MoveTo(x1, y1) func (dc *Context) QuadraticTo(x1, y1, x2, y2 float64) { if !dc.hasCurrent { dc.MoveTo(x1, y1) @@ -212,6 +245,10 @@ func (dc *Context) QuadraticTo(x1, y1, x2, y2 float64) { dc.current = p2 } +// CubicTo adds a cubic bezier curve to the current path starting at the +// current point. If there is no current point, it first performs +// MoveTo(x1, y1). Because freetype/raster does not support cubic beziers, +// this is emulated with many small line segments. func (dc *Context) CubicTo(x1, y1, x2, y2, x3, y3 float64) { if !dc.hasCurrent { dc.MoveTo(x1, y1) @@ -235,6 +272,8 @@ func (dc *Context) CubicTo(x1, y1, x2, y2, x3, y3 float64) { } } +// ClosePath adds a line segment from the current point to the beginning +// of the current subpath. If there is no current point, this is a no-op. func (dc *Context) ClosePath() { if dc.hasCurrent { dc.strokePath.Add1(dc.start.Fixed()) @@ -243,12 +282,16 @@ func (dc *Context) ClosePath() { } } +// ClearPath clears the current path. There is no current point after this +// operation. func (dc *Context) ClearPath() { dc.strokePath.Clear() dc.fillPath.Clear() dc.hasCurrent = false } +// NewSubPath starts a new subpath within the current path. There is no current +// point after this operation. func (dc *Context) NewSubPath() { if dc.hasCurrent { dc.fillPath.Add1(dc.start.Fixed()) @@ -280,6 +323,9 @@ func (dc *Context) joiner() raster.Joiner { return nil } +// StrokePreserve strokes the current path with the current color, line width, +// line cap, line join and dash settings. The path is preserved after this +// operation. func (dc *Context) StrokePreserve() { path := dc.strokePath if len(dc.dashes) > 0 { @@ -293,11 +339,16 @@ func (dc *Context) StrokePreserve() { r.Rasterize(painter) } +// Stroke strokes the current path with the current color, line width, +// line cap, line join and dash settings. The path is cleared after this +// operation. func (dc *Context) Stroke() { dc.StrokePreserve() dc.ClearPath() } +// FillPreserve fills the current path with the current color. Open subpaths +// are implicity closed. The path is preserved after this operation. func (dc *Context) FillPreserve() { path := dc.fillPath if dc.hasCurrent { @@ -313,6 +364,8 @@ func (dc *Context) FillPreserve() { r.Rasterize(painter) } +// Fill fills the current path with the current color. Open subpaths +// are implicity closed. The path is cleared after this operation. func (dc *Context) Fill() { dc.FillPreserve() dc.ClearPath() @@ -320,6 +373,7 @@ func (dc *Context) Fill() { // Convenient Drawing Functions +// Clear fills the entire image with the current color. func (dc *Context) Clear() { src := image.NewUniform(dc.color) draw.Draw(dc.im, dc.im.Bounds(), src, image.ZP, draw.Src) @@ -386,10 +440,15 @@ func (dc *Context) DrawCircle(x, y, r float64) { dc.DrawEllipticalArc(x, y, r, r, 0, 2*math.Pi) } +// DrawImage draws the specified image at the specified point. +// Currently, rotation and scaling transforms are not supported. func (dc *Context) DrawImage(im image.Image, x, y int) { dc.DrawImageAnchored(im, x, y, 0, 0) } +// DrawImageAnchored draws the specified image at the specified anchor point. +// The anchor point is x - w * ax, y - h * ay, where w, h is the size of the +// image. Use ax=0.5, ay=0.5 to center the image at the specified point. func (dc *Context) DrawImageAnchored(im image.Image, x, y int, ax, ay float64) { s := im.Bounds().Size() x -= int(ax * float64(s.X)) @@ -415,10 +474,15 @@ func (dc *Context) LoadFontFace(path string, points float64) { } } +// DrawString draws the specified text at the specified point. +// Currently, rotation and scaling transforms are not supported. func (dc *Context) DrawString(s string, x, y float64) { dc.DrawStringAnchored(s, x, y, 0, 0) } +// DrawStringAnchored draws the specified text at the specified anchor point. +// The anchor point is x - w * ax, y - h * ay, where w, h is the size of the +// text. Use ax=0.5, ay=0.5 to center the text at the specified point. func (dc *Context) DrawStringAnchored(s string, x, y, ax, ay float64) { w, h := dc.MeasureString(s) x -= ax * w @@ -433,6 +497,8 @@ func (dc *Context) DrawStringAnchored(s string, x, y, ax, ay float64) { d.DrawString(s) } +// MeasureString returns the rendered width and height of the specified text +// given the current font face. func (dc *Context) MeasureString(s string) (w, h float64) { d := &font.Drawer{ Face: dc.fontFace, @@ -443,48 +509,67 @@ func (dc *Context) MeasureString(s string) (w, h float64) { // Transformation Matrix Operations +// Identity resets the current transformation matrix to the identity matrix. +// This results in no translating, scaling, rotating, or shearing. func (dc *Context) Identity() { dc.matrix = Identity() } +// Translate updates the current matrix with a translation. func (dc *Context) Translate(x, y float64) { dc.matrix = dc.matrix.Translate(x, y) } +// Scale updates the current matrix with a scaling factor. +// Scaling occurs about the origin. func (dc *Context) Scale(x, y float64) { dc.matrix = dc.matrix.Scale(x, y) } +// ScaleAbout updates the current matrix with a scaling factor. +// Scaling occurs about the specified point. func (dc *Context) ScaleAbout(sx, sy, x, y float64) { dc.Translate(x, y) dc.Scale(sx, sy) dc.Translate(-x, -y) } +// Rotate updates the current matrix with a clockwise rotation. +// Rotation occurs about the origin. Angle is specified in radians. func (dc *Context) Rotate(angle float64) { dc.matrix = dc.matrix.Rotate(angle) } +// RotateAbout updates the current matrix with a clockwise rotation. +// Rotation occurs about the specified point. Angle is specified in radians. func (dc *Context) RotateAbout(angle, x, y float64) { dc.Translate(x, y) dc.Rotate(angle) dc.Translate(-x, -y) } +// Shear updates the current matrix with a shearing angle. +// Shearing occurs about the origin. func (dc *Context) Shear(x, y float64) { dc.matrix = dc.matrix.Shear(x, y) } +// ShearAbout updates the current matrix with a shearing angle. +// Shearing occurs about the specified point. func (dc *Context) ShearAbout(sx, sy, x, y float64) { dc.Translate(x, y) dc.Shear(sx, sy) dc.Translate(-x, -y) } +// TransformPoint multiplies the specified point by the current matrix, +// returning a transformed position. func (dc *Context) TransformPoint(x, y float64) (tx, ty float64) { return dc.matrix.TransformPoint(x, y) } +// InvertY flips the Y axis so that Y grows from bottom to top and Y=0 is at +// the bottom of the image. func (dc *Context) InvertY() { dc.Translate(0, float64(dc.height)) dc.Scale(1, -1) @@ -492,11 +577,14 @@ func (dc *Context) InvertY() { // Stack +// Push saves the current state of the context for later retrieval. These +// can be nested. func (dc *Context) Push() { x := *dc dc.stack = append(dc.stack, &x) } +// Pop pops the last saved context state from the stack. func (dc *Context) Pop() { before := *dc s := dc.stack