diff --git a/f32/f32.go b/f32/f32.go index 54882cb1..1ec4652c 100644 --- a/f32/f32.go +++ b/f32/f32.go @@ -9,7 +9,11 @@ corner with the axes extending right and down. */ package f32 -import "strconv" +import ( + "image" + "math" + "strconv" +) // A Point is a two dimensional point. type Point struct { @@ -167,3 +171,26 @@ func (r Rectangle) Sub(p Point) Rectangle { Point{r.Max.X - p.X, r.Max.Y - p.Y}, } } + +// Round returns the smallest integer rectangle that +// contains r. +func (r Rectangle) Round() image.Rectangle { + return image.Rectangle{ + Min: image.Point{ + X: int(floor(r.Min.X)), + Y: int(floor(r.Min.Y)), + }, + Max: image.Point{ + X: int(ceil(r.Max.X)), + Y: int(ceil(r.Max.Y)), + }, + } +} + +func ceil(v float32) int { + return int(math.Ceil(float64(v))) +} + +func floor(v float32) int { + return int(math.Floor(float64(v))) +} diff --git a/gpu/compute.go b/gpu/compute.go index 625658c7..a4e6fbc2 100644 --- a/gpu/compute.go +++ b/gpu/compute.go @@ -942,7 +942,7 @@ func (g *compute) renderMaterials() error { imgAtlas = op.imgAlloc.atlas quad := g.materialQuad(imgAtlas.size, op.key.transform, op.img, op.imgAlloc.rect.Min) boundsf := quadBounds(quad) - bounds := boundRectF(boundsf) + bounds := boundsf.Round() bounds = bounds.Intersect(op.key.bounds) size := bounds.Size() @@ -1896,7 +1896,7 @@ func (c *collector) collect(root *op.Ops, viewport image.Point, texOps *[]textur // except for their integer offsets can share a transformed image. t := op.state.t.Offset(layout.FPt(op.offset)) t, off := separateTransform(t) - bounds := boundRectF(op.intersect).Sub(off) + bounds := op.intersect.Round().Sub(off) *texOps = append(*texOps, textureOp{ img: op.state.image, off: off, @@ -1963,7 +1963,7 @@ func (g *compute) layer(viewport image.Point, texOps []textureOp) { } } for i, op := range l.ops { - l.rect = l.rect.Union(boundRectF(op.intersect)) + l.rect = l.rect.Union(op.intersect.Round()) l.ops[i].layer = len(c.frame.layers) } c.frame.layers = append(c.frame.layers, l) diff --git a/gpu/gpu.go b/gpu/gpu.go index 8c30a595..213850c5 100644 --- a/gpu/gpu.go +++ b/gpu/gpu.go @@ -758,28 +758,6 @@ func (r *renderer) packStencils(pops *[]*pathOp) { *pops = ops } -// boundRectF returns a bounding image.Rectangle for a f32.Rectangle. -func boundRectF(r f32.Rectangle) image.Rectangle { - return image.Rectangle{ - Min: image.Point{ - X: int(floor(r.Min.X)), - Y: int(floor(r.Min.Y)), - }, - Max: image.Point{ - X: int(ceil(r.Max.X)), - Y: int(ceil(r.Max.Y)), - }, - } -} - -func ceil(v float32) int { - return int(math.Ceil(float64(v))) -} - -func floor(v float32) int { - return int(math.Floor(float64(v))) -} - func (d *drawOps) reset(viewport image.Point) { d.profile = false d.viewport = viewport @@ -983,7 +961,7 @@ loop: d.addClipPath(&state, clipData, k, bnd, off, false) } - bounds := boundRectF(cl) + bounds := cl.Round() mat := state.materialFor(bnd, off, partialTrans, bounds) rect := state.cpath == nil || state.cpath.rect @@ -1045,7 +1023,7 @@ func (d *drawState) materialFor(rect f32.Rectangle, off f32.Point, partTrans f32 m.uvTrans = partTrans.Mul(gradientSpaceTransform(clip, off, d.stop1, d.stop2)) case materialTexture: m.material = materialTexture - dr := boundRectF(rect.Add(off)) + dr := rect.Add(off).Round() sz := d.image.src.Bounds().Size() sr := f32.Rectangle{ Max: f32.Point{ diff --git a/op/clip/clip.go b/op/clip/clip.go index 3ac02fe8..89bb07cc 100644 --- a/op/clip/clip.go +++ b/op/clip/clip.go @@ -157,7 +157,7 @@ func (p *Path) End() PathSpec { return PathSpec{ spec: c, hasSegments: p.hasSegments, - bounds: boundRectF(p.bounds), + bounds: p.bounds.Round(), hash: p.hash.Sum64(), } } @@ -238,28 +238,6 @@ func (p *Path) expand(pt f32.Point) { } } -// boundRectF returns a bounding image.Rectangle for a f32.Rectangle. -func boundRectF(r f32.Rectangle) image.Rectangle { - return image.Rectangle{ - Min: image.Point{ - X: int(floor(r.Min.X)), - Y: int(floor(r.Min.Y)), - }, - Max: image.Point{ - X: int(ceil(r.Max.X)), - Y: int(ceil(r.Max.Y)), - }, - } -} - -func ceil(v float32) int { - return int(math.Ceil(float64(v))) -} - -func floor(v float32) int { - return int(math.Floor(float64(v))) -} - // Quad records a quadratic Bézier from the pen to end // with the control point ctrl. func (p *Path) Quad(ctrl, to f32.Point) {