f32,gpu,op/clip: add f32.Rectangle method for converting to image.Rectangle

Creating an image.Rectangle from a f32.Rectangle is used by two packages in Gio
and about to be used for a third. Add a Round method to f32.Rectangle to avoid
duplicating the implementation.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2022-03-30 12:00:45 +02:00
parent 920e6dd004
commit 1f11a5a17b
4 changed files with 34 additions and 51 deletions
+28 -1
View File
@@ -9,7 +9,11 @@ corner with the axes extending right and down.
*/ */
package f32 package f32
import "strconv" import (
"image"
"math"
"strconv"
)
// A Point is a two dimensional point. // A Point is a two dimensional point.
type Point struct { 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}, 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)))
}
+3 -3
View File
@@ -942,7 +942,7 @@ func (g *compute) renderMaterials() error {
imgAtlas = op.imgAlloc.atlas imgAtlas = op.imgAlloc.atlas
quad := g.materialQuad(imgAtlas.size, op.key.transform, op.img, op.imgAlloc.rect.Min) quad := g.materialQuad(imgAtlas.size, op.key.transform, op.img, op.imgAlloc.rect.Min)
boundsf := quadBounds(quad) boundsf := quadBounds(quad)
bounds := boundRectF(boundsf) bounds := boundsf.Round()
bounds = bounds.Intersect(op.key.bounds) bounds = bounds.Intersect(op.key.bounds)
size := bounds.Size() 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. // except for their integer offsets can share a transformed image.
t := op.state.t.Offset(layout.FPt(op.offset)) t := op.state.t.Offset(layout.FPt(op.offset))
t, off := separateTransform(t) t, off := separateTransform(t)
bounds := boundRectF(op.intersect).Sub(off) bounds := op.intersect.Round().Sub(off)
*texOps = append(*texOps, textureOp{ *texOps = append(*texOps, textureOp{
img: op.state.image, img: op.state.image,
off: off, off: off,
@@ -1963,7 +1963,7 @@ func (g *compute) layer(viewport image.Point, texOps []textureOp) {
} }
} }
for i, op := range l.ops { 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) l.ops[i].layer = len(c.frame.layers)
} }
c.frame.layers = append(c.frame.layers, l) c.frame.layers = append(c.frame.layers, l)
+2 -24
View File
@@ -758,28 +758,6 @@ func (r *renderer) packStencils(pops *[]*pathOp) {
*pops = ops *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) { func (d *drawOps) reset(viewport image.Point) {
d.profile = false d.profile = false
d.viewport = viewport d.viewport = viewport
@@ -983,7 +961,7 @@ loop:
d.addClipPath(&state, clipData, k, bnd, off, false) d.addClipPath(&state, clipData, k, bnd, off, false)
} }
bounds := boundRectF(cl) bounds := cl.Round()
mat := state.materialFor(bnd, off, partialTrans, bounds) mat := state.materialFor(bnd, off, partialTrans, bounds)
rect := state.cpath == nil || state.cpath.rect 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)) m.uvTrans = partTrans.Mul(gradientSpaceTransform(clip, off, d.stop1, d.stop2))
case materialTexture: case materialTexture:
m.material = materialTexture m.material = materialTexture
dr := boundRectF(rect.Add(off)) dr := rect.Add(off).Round()
sz := d.image.src.Bounds().Size() sz := d.image.src.Bounds().Size()
sr := f32.Rectangle{ sr := f32.Rectangle{
Max: f32.Point{ Max: f32.Point{
+1 -23
View File
@@ -157,7 +157,7 @@ func (p *Path) End() PathSpec {
return PathSpec{ return PathSpec{
spec: c, spec: c,
hasSegments: p.hasSegments, hasSegments: p.hasSegments,
bounds: boundRectF(p.bounds), bounds: p.bounds.Round(),
hash: p.hash.Sum64(), 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 // Quad records a quadratic Bézier from the pen to end
// with the control point ctrl. // with the control point ctrl.
func (p *Path) Quad(ctrl, to f32.Point) { func (p *Path) Quad(ctrl, to f32.Point) {