refactoring
This commit is contained in:
parent
80f52004a0
commit
805bc68eed
132
context.go
132
context.go
@ -42,17 +42,24 @@ type Context struct {
|
|||||||
path raster.Path
|
path raster.Path
|
||||||
start fixed.Point26_6
|
start fixed.Point26_6
|
||||||
lineWidth float64
|
lineWidth float64
|
||||||
capper raster.Capper
|
lineCap LineCap
|
||||||
joiner raster.Joiner
|
lineJoin LineJoin
|
||||||
fillRule FillRule
|
fillRule FillRule
|
||||||
fontFace font.Face
|
fontFace font.Face
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewContext(width, height int) *Context {
|
func NewContext(width, height int) *Context {
|
||||||
im := image.NewRGBA(image.Rect(0, 0, width, height))
|
return NewContextForRGBA(image.NewRGBA(image.Rect(0, 0, width, height)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewContextForImage(im image.Image) *Context {
|
||||||
|
return NewContextForRGBA(imageToRGBA(im))
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewContextForRGBA(im *image.RGBA) *Context {
|
||||||
return &Context{
|
return &Context{
|
||||||
width: width,
|
width: im.Bounds().Size().X,
|
||||||
height: height,
|
height: im.Bounds().Size().Y,
|
||||||
im: im,
|
im: im,
|
||||||
color: color.Transparent,
|
color: color.Transparent,
|
||||||
lineWidth: 1,
|
lineWidth: 1,
|
||||||
@ -77,11 +84,42 @@ func (dc *Context) WriteToPNG(path string) error {
|
|||||||
return writeToPNG(path, dc.im)
|
return writeToPNG(path, dc.im)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *Context) Paint() {
|
func (dc *Context) SetLineWidth(lineWidth float64) {
|
||||||
draw.Draw(dc.im, dc.im.Bounds(), image.NewUniform(dc.color), image.ZP, draw.Src)
|
dc.lineWidth = lineWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *Context) SetSourceRGBA(r, g, b, a float64) {
|
func (dc *Context) SetLineCap(lineCap LineCap) {
|
||||||
|
dc.lineCap = lineCap
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *Context) SetLineJoin(lineJoin LineJoin) {
|
||||||
|
dc.lineJoin = lineJoin
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *Context) SetFillRule(fillRule FillRule) {
|
||||||
|
dc.fillRule = fillRule
|
||||||
|
}
|
||||||
|
|
||||||
|
// Color Setters
|
||||||
|
|
||||||
|
func (dc *Context) SetColor(c color.Color) {
|
||||||
|
dc.color = c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *Context) SetHexColor(x string) {
|
||||||
|
r, g, b := parseHexColor(x)
|
||||||
|
dc.SetRGB255(r, g, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *Context) SetRGBA255(r, g, b, a int) {
|
||||||
|
dc.color = color.NRGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *Context) SetRGB255(r, g, b int) {
|
||||||
|
dc.SetRGBA255(r, g, b, 255)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *Context) SetRGBA(r, g, b, a float64) {
|
||||||
dc.color = color.NRGBA{
|
dc.color = color.NRGBA{
|
||||||
uint8(r * 255),
|
uint8(r * 255),
|
||||||
uint8(g * 255),
|
uint8(g * 255),
|
||||||
@ -90,37 +128,11 @@ func (dc *Context) SetSourceRGBA(r, g, b, a float64) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *Context) SetSourceRGB(r, g, b float64) {
|
func (dc *Context) SetRGB(r, g, b float64) {
|
||||||
dc.SetSourceRGBA(r, g, b, 1)
|
dc.SetRGBA(r, g, b, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *Context) SetLineWidth(lineWidth float64) {
|
// Path Manipulation
|
||||||
dc.lineWidth = lineWidth
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *Context) SetLineCap(lineCap LineCap) {
|
|
||||||
switch lineCap {
|
|
||||||
case LineCapButt:
|
|
||||||
dc.capper = raster.ButtCapper
|
|
||||||
case LineCapRound:
|
|
||||||
dc.capper = raster.RoundCapper
|
|
||||||
case LineCapSquare:
|
|
||||||
dc.capper = raster.SquareCapper
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *Context) SetLineJoin(lineJoin LineJoin) {
|
|
||||||
switch lineJoin {
|
|
||||||
case LineJoinBevel:
|
|
||||||
dc.joiner = raster.BevelJoiner
|
|
||||||
case LineJoinRound:
|
|
||||||
dc.joiner = raster.RoundJoiner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *Context) SetFillRule(fillRule FillRule) {
|
|
||||||
dc.fillRule = fillRule
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *Context) MoveTo(x, y float64) {
|
func (dc *Context) MoveTo(x, y float64) {
|
||||||
dc.start = fp(x, y)
|
dc.start = fp(x, y)
|
||||||
@ -149,22 +161,40 @@ func (dc *Context) ClosePath() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *Context) NewPath() {
|
func (dc *Context) ClearPath() {
|
||||||
dc.path.Clear()
|
dc.path.Clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Path Drawing
|
||||||
|
|
||||||
func (dc *Context) StrokePreserve() {
|
func (dc *Context) StrokePreserve() {
|
||||||
|
var capper raster.Capper
|
||||||
|
switch dc.lineCap {
|
||||||
|
case LineCapButt:
|
||||||
|
capper = raster.ButtCapper
|
||||||
|
case LineCapRound:
|
||||||
|
capper = raster.RoundCapper
|
||||||
|
case LineCapSquare:
|
||||||
|
capper = raster.SquareCapper
|
||||||
|
}
|
||||||
|
var joiner raster.Joiner
|
||||||
|
switch dc.lineJoin {
|
||||||
|
case LineJoinBevel:
|
||||||
|
joiner = raster.BevelJoiner
|
||||||
|
case LineJoinRound:
|
||||||
|
joiner = raster.RoundJoiner
|
||||||
|
}
|
||||||
painter := raster.NewRGBAPainter(dc.im)
|
painter := raster.NewRGBAPainter(dc.im)
|
||||||
painter.SetColor(dc.color)
|
painter.SetColor(dc.color)
|
||||||
r := raster.NewRasterizer(dc.width, dc.height)
|
r := raster.NewRasterizer(dc.width, dc.height)
|
||||||
r.UseNonZeroWinding = true
|
r.UseNonZeroWinding = true
|
||||||
r.AddStroke(dc.path, fi(dc.lineWidth), dc.capper, dc.joiner)
|
r.AddStroke(dc.path, fi(dc.lineWidth), capper, joiner)
|
||||||
r.Rasterize(painter)
|
r.Rasterize(painter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *Context) Stroke() {
|
func (dc *Context) Stroke() {
|
||||||
dc.StrokePreserve()
|
dc.StrokePreserve()
|
||||||
dc.NewPath()
|
dc.ClearPath()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *Context) FillPreserve() {
|
func (dc *Context) FillPreserve() {
|
||||||
@ -182,17 +212,29 @@ func (dc *Context) FillPreserve() {
|
|||||||
|
|
||||||
func (dc *Context) Fill() {
|
func (dc *Context) Fill() {
|
||||||
dc.FillPreserve()
|
dc.FillPreserve()
|
||||||
dc.NewPath()
|
dc.ClearPath()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenient Drawing Functions
|
// Convenient Drawing Functions
|
||||||
|
|
||||||
|
func (dc *Context) Clear() {
|
||||||
|
draw.Draw(dc.im, dc.im.Bounds(), image.NewUniform(dc.color), image.ZP, draw.Src)
|
||||||
|
}
|
||||||
|
|
||||||
func (dc *Context) DrawLine(x1, y1, x2, y2 float64) {
|
func (dc *Context) DrawLine(x1, y1, x2, y2 float64) {
|
||||||
dc.MoveTo(x1, y1)
|
dc.MoveTo(x1, y1)
|
||||||
dc.LineTo(x2, y2)
|
dc.LineTo(x2, y2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *Context) DrawEllipseArc(x, y, rx, ry, angle1, angle2 float64) {
|
func (dc *Context) DrawRectangle(x, y, w, h float64) {
|
||||||
|
dc.MoveTo(x, y)
|
||||||
|
dc.LineTo(x+w, y)
|
||||||
|
dc.LineTo(x+w, y+h)
|
||||||
|
dc.LineTo(x, y+h)
|
||||||
|
dc.LineTo(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dc *Context) DrawEllipticalArc(x, y, rx, ry, angle1, angle2 float64) {
|
||||||
const n = 16
|
const n = 16
|
||||||
for i := 0; i <= n; i++ {
|
for i := 0; i <= n; i++ {
|
||||||
p1 := float64(i+0) / n
|
p1 := float64(i+0) / n
|
||||||
@ -215,15 +257,15 @@ func (dc *Context) DrawEllipseArc(x, y, rx, ry, angle1, angle2 float64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (dc *Context) DrawEllipse(x, y, rx, ry float64) {
|
func (dc *Context) DrawEllipse(x, y, rx, ry float64) {
|
||||||
dc.DrawEllipseArc(x, y, rx, ry, 0, 2*math.Pi)
|
dc.DrawEllipticalArc(x, y, rx, ry, 0, 2*math.Pi)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *Context) DrawArc(x, y, r, angle1, angle2 float64) {
|
func (dc *Context) DrawArc(x, y, r, angle1, angle2 float64) {
|
||||||
dc.DrawEllipseArc(x, y, r, r, angle1, angle2)
|
dc.DrawEllipticalArc(x, y, r, r, angle1, angle2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dc *Context) DrawCircle(x, y, r float64) {
|
func (dc *Context) DrawCircle(x, y, r float64) {
|
||||||
dc.DrawEllipseArc(x, y, r, r, 0, 2*math.Pi)
|
dc.DrawEllipticalArc(x, y, r, r, 0, 2*math.Pi)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text Functions
|
// Text Functions
|
||||||
|
@ -4,12 +4,12 @@ import "github.com/fogleman/gg"
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
dc := gg.NewContext(1000, 1000)
|
dc := gg.NewContext(1000, 1000)
|
||||||
dc.SetSourceRGB(1, 1, 1)
|
dc.SetRGB(1, 1, 1)
|
||||||
dc.Paint()
|
dc.Clear()
|
||||||
dc.DrawCircle(500, 500, 400)
|
dc.DrawCircle(500, 500, 400)
|
||||||
dc.SetSourceRGBA(0, 0, 0, 0.25)
|
dc.SetRGBA(0, 0, 0, 0.25)
|
||||||
dc.FillPreserve()
|
dc.FillPreserve()
|
||||||
dc.SetSourceRGB(0, 0, 0.5)
|
dc.SetRGB(0, 0, 0.5)
|
||||||
dc.SetLineWidth(8)
|
dc.SetLineWidth(8)
|
||||||
dc.Stroke()
|
dc.Stroke()
|
||||||
dc.WriteToPNG("out.png")
|
dc.WriteToPNG("out.png")
|
||||||
|
@ -4,16 +4,16 @@ import "github.com/fogleman/gg"
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
dc := gg.NewContext(256, 256)
|
dc := gg.NewContext(256, 256)
|
||||||
dc.SetSourceRGBA(1, 0, 0, 0.3)
|
dc.SetRGBA(1, 0, 0, 0.3)
|
||||||
dc.Paint()
|
dc.Clear()
|
||||||
dc.MoveTo(20, 20)
|
dc.MoveTo(20, 20)
|
||||||
dc.LineTo(236, 236)
|
dc.LineTo(236, 236)
|
||||||
dc.LineTo(236, 128)
|
dc.LineTo(236, 128)
|
||||||
dc.LineTo(20, 128)
|
dc.LineTo(20, 128)
|
||||||
dc.QuadraticTo(0, 64, 120, 20)
|
dc.QuadraticTo(0, 64, 120, 20)
|
||||||
dc.SetSourceRGBA(1, 0, 0, 0.8)
|
dc.SetRGBA(1, 0, 0, 0.8)
|
||||||
dc.FillPreserve()
|
dc.FillPreserve()
|
||||||
dc.SetSourceRGB(0, 0, 0)
|
dc.SetRGB(0, 0, 0)
|
||||||
dc.SetLineWidth(8)
|
dc.SetLineWidth(8)
|
||||||
dc.Stroke()
|
dc.Stroke()
|
||||||
dc.WriteToPNG("out.png")
|
dc.WriteToPNG("out.png")
|
||||||
|
@ -10,8 +10,8 @@ func main() {
|
|||||||
const W = 1024
|
const W = 1024
|
||||||
const H = 1024
|
const H = 1024
|
||||||
dc := gg.NewContext(W, H)
|
dc := gg.NewContext(W, H)
|
||||||
dc.SetSourceRGB(0, 0, 0)
|
dc.SetRGB(0, 0, 0)
|
||||||
dc.Paint()
|
dc.Clear()
|
||||||
for i := 0; i < 1000; i++ {
|
for i := 0; i < 1000; i++ {
|
||||||
x1 := rand.Float64() * W
|
x1 := rand.Float64() * W
|
||||||
y1 := rand.Float64() * H
|
y1 := rand.Float64() * H
|
||||||
@ -22,10 +22,10 @@ func main() {
|
|||||||
b := rand.Float64()
|
b := rand.Float64()
|
||||||
a := rand.Float64()*0.5 + 0.5
|
a := rand.Float64()*0.5 + 0.5
|
||||||
w := rand.Float64()*4 + 1
|
w := rand.Float64()*4 + 1
|
||||||
dc.SetSourceRGBA(r, g, b, a)
|
dc.SetRGBA(r, g, b, a)
|
||||||
dc.SetLineWidth(w)
|
dc.SetLineWidth(w)
|
||||||
dc.Stroke()
|
|
||||||
dc.DrawLine(x1, y1, x2, y2)
|
dc.DrawLine(x1, y1, x2, y2)
|
||||||
|
dc.Stroke()
|
||||||
}
|
}
|
||||||
dc.WriteToPNG("out.png")
|
dc.WriteToPNG("out.png")
|
||||||
}
|
}
|
||||||
|
@ -23,17 +23,17 @@ func main() {
|
|||||||
n := 5
|
n := 5
|
||||||
points := Polygon(n, 512, 512, 400)
|
points := Polygon(n, 512, 512, 400)
|
||||||
dc := gg.NewContext(1024, 1024)
|
dc := gg.NewContext(1024, 1024)
|
||||||
dc.SetSourceRGB(1, 1, 1)
|
dc.SetHexColor("fff")
|
||||||
dc.Paint()
|
dc.Clear()
|
||||||
for i := 0; i < n+1; i++ {
|
for i := 0; i < n+1; i++ {
|
||||||
index := (i * 2) % n
|
index := (i * 2) % n
|
||||||
p := points[index]
|
p := points[index]
|
||||||
dc.LineTo(p.X, p.Y)
|
dc.LineTo(p.X, p.Y)
|
||||||
}
|
}
|
||||||
dc.SetSourceRGBA(0, 0.5, 0, 1)
|
dc.SetRGBA(0, 0.5, 0, 1)
|
||||||
dc.SetFillRule(gg.FillRuleEvenOdd)
|
dc.SetFillRule(gg.FillRuleEvenOdd)
|
||||||
dc.FillPreserve()
|
dc.FillPreserve()
|
||||||
dc.SetSourceRGBA(0, 1, 0, 0.5)
|
dc.SetRGBA(0, 1, 0, 0.5)
|
||||||
dc.SetLineWidth(16)
|
dc.SetLineWidth(16)
|
||||||
dc.Stroke()
|
dc.Stroke()
|
||||||
dc.WriteToPNG("out.png")
|
dc.WriteToPNG("out.png")
|
||||||
|
@ -4,9 +4,9 @@ import "github.com/fogleman/gg"
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
dc := gg.NewContext(1000, 1000)
|
dc := gg.NewContext(1000, 1000)
|
||||||
dc.SetSourceRGB(1, 1, 1)
|
dc.SetRGB(1, 1, 1)
|
||||||
dc.Paint()
|
dc.Clear()
|
||||||
dc.SetSourceRGB(0, 0, 0)
|
dc.SetRGB(0, 0, 0)
|
||||||
dc.LoadFontFace("/Library/Fonts/Impact.ttf", 96)
|
dc.LoadFontFace("/Library/Fonts/Impact.ttf", 96)
|
||||||
s := "Hello, world!"
|
s := "Hello, world!"
|
||||||
w := dc.MeasureString(s)
|
w := dc.MeasureString(s)
|
||||||
|
25
util.go
25
util.go
@ -1,10 +1,13 @@
|
|||||||
package gg
|
package gg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
|
"image/draw"
|
||||||
"image/png"
|
"image/png"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/golang/freetype/truetype"
|
"github.com/golang/freetype/truetype"
|
||||||
|
|
||||||
@ -21,6 +24,28 @@ func writeToPNG(path string, im image.Image) error {
|
|||||||
return png.Encode(file, im)
|
return png.Encode(file, im)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func imageToRGBA(src image.Image) *image.RGBA {
|
||||||
|
dst := image.NewRGBA(src.Bounds())
|
||||||
|
draw.Draw(dst, dst.Rect, src, image.ZP, draw.Src)
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseHexColor(x string) (r, g, b int) {
|
||||||
|
x = strings.TrimPrefix(x, "#")
|
||||||
|
if len(x) == 3 {
|
||||||
|
format := "%1x%1x%1x"
|
||||||
|
fmt.Sscanf(x, format, &r, &g, &b)
|
||||||
|
r |= r << 4
|
||||||
|
g |= g << 4
|
||||||
|
b |= b << 4
|
||||||
|
}
|
||||||
|
if len(x) == 6 {
|
||||||
|
format := "%02x%02x%02x"
|
||||||
|
fmt.Sscanf(x, format, &r, &g, &b)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func fp(x, y float64) fixed.Point26_6 {
|
func fp(x, y float64) fixed.Point26_6 {
|
||||||
return fixed.Point26_6{fixed.Int26_6(x * 64), fixed.Int26_6(y * 64)}
|
return fixed.Point26_6{fixed.Int26_6(x * 64), fixed.Int26_6(y * 64)}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user