diff --git a/app/os_macos.go b/app/os_macos.go index 5e6d7db6..d606617f 100644 --- a/app/os_macos.go +++ b/app/os_macos.go @@ -13,7 +13,7 @@ import ( "unicode" "unicode/utf8" - "gioui.org/f32" + "gioui.org/internal/f32" "gioui.org/io/clipboard" "gioui.org/io/key" "gioui.org/io/pointer" diff --git a/f32/f32.go b/f32/f32.go index 044cc51b..1938ffb5 100644 --- a/f32/f32.go +++ b/f32/f32.go @@ -2,7 +2,7 @@ /* Package f32 is a float32 implementation of package image's -Point and Rectangle. +Point and affine transformations. The coordinate space has the origin in the top left corner with the axes extending right and down. @@ -26,30 +26,6 @@ func (p Point) String() string { "," + strconv.FormatFloat(float64(p.Y), 'f', -1, 32) + ")" } -// A Rectangle contains the points (X, Y) where Min.X <= X < Max.X, -// Min.Y <= Y < Max.Y. -type Rectangle struct { - Min, Max Point -} - -// String return a string representation of r. -func (r Rectangle) String() string { - return r.Min.String() + "-" + r.Max.String() -} - -// Rect is a shorthand for Rectangle{Point{x0, y0}, Point{x1, y1}}. -// The returned Rectangle has x0 and y0 swapped if necessary so that -// it's correctly formed. -func Rect(x0, y0, x1, y1 float32) Rectangle { - if x0 > x1 { - x0, x1 = x1, x0 - } - if y0 > y1 { - y0, y1 = y1, y0 - } - return Rectangle{Point{x0, y0}, Point{x1, y1}} -} - // Pt is shorthand for Point{X: x, Y: y}. func Pt(x, y float32) Point { return Point{X: x, Y: y} @@ -75,12 +51,6 @@ func (p Point) Div(s float32) Point { return Point{X: p.X / s, Y: p.Y / s} } -// In reports whether p is in r. -func (p Point) In(r Rectangle) bool { - return r.Min.X <= p.X && p.X < r.Max.X && - r.Min.Y <= p.Y && p.Y < r.Max.Y -} - // Round returns the integer point closest to p. func (p Point) Round() image.Point { return image.Point{ @@ -88,117 +58,3 @@ func (p Point) Round() image.Point { Y: int(math.Round(float64(p.Y))), } } - -// Size returns r's width and height. -func (r Rectangle) Size() Point { - return Point{X: r.Dx(), Y: r.Dy()} -} - -// Dx returns r's width. -func (r Rectangle) Dx() float32 { - return r.Max.X - r.Min.X -} - -// Dy returns r's Height. -func (r Rectangle) Dy() float32 { - return r.Max.Y - r.Min.Y -} - -// Intersect returns the intersection of r and s. -func (r Rectangle) Intersect(s Rectangle) Rectangle { - if r.Min.X < s.Min.X { - r.Min.X = s.Min.X - } - if r.Min.Y < s.Min.Y { - r.Min.Y = s.Min.Y - } - if r.Max.X > s.Max.X { - r.Max.X = s.Max.X - } - if r.Max.Y > s.Max.Y { - r.Max.Y = s.Max.Y - } - if r.Empty() { - return Rectangle{} - } - return r -} - -// Union returns the union of r and s. -func (r Rectangle) Union(s Rectangle) Rectangle { - if r.Empty() { - return s - } - if s.Empty() { - return r - } - if r.Min.X > s.Min.X { - r.Min.X = s.Min.X - } - if r.Min.Y > s.Min.Y { - r.Min.Y = s.Min.Y - } - if r.Max.X < s.Max.X { - r.Max.X = s.Max.X - } - if r.Max.Y < s.Max.Y { - r.Max.Y = s.Max.Y - } - return r -} - -// Canon returns the canonical version of r, where Min is to -// the upper left of Max. -func (r Rectangle) Canon() Rectangle { - if r.Max.X < r.Min.X { - r.Min.X, r.Max.X = r.Max.X, r.Min.X - } - if r.Max.Y < r.Min.Y { - r.Min.Y, r.Max.Y = r.Max.Y, r.Min.Y - } - return r -} - -// Empty reports whether r represents the empty area. -func (r Rectangle) Empty() bool { - return r.Min.X >= r.Max.X || r.Min.Y >= r.Max.Y -} - -// Add offsets r with the vector p. -func (r Rectangle) Add(p Point) Rectangle { - return Rectangle{ - Point{r.Min.X + p.X, r.Min.Y + p.Y}, - Point{r.Max.X + p.X, r.Max.Y + p.Y}, - } -} - -// Sub offsets r with the vector -p. -func (r Rectangle) Sub(p Point) Rectangle { - return Rectangle{ - Point{r.Min.X - p.X, r.Min.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))) -} diff --git a/gpu/caches.go b/gpu/caches.go index c6a71bcd..762f3e77 100644 --- a/gpu/caches.go +++ b/gpu/caches.go @@ -5,7 +5,7 @@ package gpu import ( "fmt" - "gioui.org/f32" + "gioui.org/internal/f32" ) type resourceCache struct { diff --git a/gpu/clip.go b/gpu/clip.go index 8ae25b53..e9dfa3f8 100644 --- a/gpu/clip.go +++ b/gpu/clip.go @@ -1,7 +1,7 @@ package gpu import ( - "gioui.org/f32" + "gioui.org/internal/f32" "gioui.org/internal/stroke" ) diff --git a/gpu/compute.go b/gpu/compute.go index 7afb179c..83196a74 100644 --- a/gpu/compute.go +++ b/gpu/compute.go @@ -21,9 +21,9 @@ import ( "unsafe" "gioui.org/cpu" - "gioui.org/f32" "gioui.org/gpu/internal/driver" "gioui.org/internal/byteslice" + "gioui.org/internal/f32" "gioui.org/internal/f32color" "gioui.org/internal/ops" "gioui.org/internal/scene" @@ -855,7 +855,7 @@ func (g *compute) blitLayers(d driver.LoadDesc, fbo driver.Texture, viewport ima for _, l := range layers { placef := layout.FPt(l.alloc.rect.Min) sizef := layout.FPt(l.rect.Size()) - r := frect(l.rect) + r := f32.FRect(l.rect) quad := [4]layerVertex{ {posX: float32(r.Min.X), posY: float32(r.Min.Y), u: placef.X, v: placef.Y}, {posX: float32(r.Max.X), posY: float32(r.Min.Y), u: placef.X + sizef.X, v: placef.Y}, @@ -1782,7 +1782,7 @@ func (c *collector) collect(root *op.Ops, viewport image.Point, texOps *[]textur case ops.TypeClip: var op ops.ClipOp op.Decode(encOp.Data) - bounds := frect(op.Bounds) + bounds := f32.FRect(op.Bounds) c.addClip(&state, fview, bounds, pathData.data, pathData.key, pathData.hash, strWidth, true) pathData.data = nil strWidth = 0 diff --git a/gpu/gpu.go b/gpu/gpu.go index 8bb6fa69..43300492 100644 --- a/gpu/gpu.go +++ b/gpu/gpu.go @@ -18,9 +18,9 @@ import ( "time" "unsafe" - "gioui.org/f32" "gioui.org/gpu/internal/driver" "gioui.org/internal/byteslice" + "gioui.org/internal/f32" "gioui.org/internal/f32color" "gioui.org/internal/ops" "gioui.org/internal/scene" @@ -695,8 +695,8 @@ func (r *renderer) intersectPath(p *pathOp, clip image.Rectangle) { } fbo := r.pather.stenciler.cover(p.place.Idx) r.ctx.BindTexture(0, fbo.tex) - coverScale, coverOff := texSpaceTransform(frect(uv), fbo.size) - subScale, subOff := texSpaceTransform(frect(sub), p.clip.Size()) + coverScale, coverOff := texSpaceTransform(f32.FRect(uv), fbo.size) + subScale, subOff := texSpaceTransform(f32.FRect(sub), p.clip.Size()) r.pather.stenciler.ipipeline.uniforms.vert.uvTransform = [4]float32{coverScale.X, coverScale.Y, coverOff.X, coverOff.Y} r.pather.stenciler.ipipeline.uniforms.vert.subUVTransform = [4]float32{subScale.X, subScale.Y, subOff.X, subOff.Y} r.pather.stenciler.ipipeline.pipeline.UploadUniforms(r.ctx) @@ -888,7 +888,7 @@ loop: var op ops.ClipOp op.Decode(encOp.Data) quads.key.outline = op.Outline - bounds := frect(op.Bounds) + bounds := f32.FRect(op.Bounds) trans, off := splitTransform(state.t) if len(quads.aux) > 0 { // There is a clipping path, build the gpu data and update the @@ -1108,7 +1108,7 @@ func (r *renderer) drawOps(cache *resourceCache, ops []imageOp) { Min: img.place.Pos, Max: img.place.Pos.Add(drc.Size()), } - coverScale, coverOff := texSpaceTransform(frect(uv), fbo.size) + coverScale, coverOff := texSpaceTransform(f32.FRect(uv), fbo.size) p := r.pather.coverer.pipelines[m.material] r.ctx.BindPipeline(p.pipeline) r.ctx.BindVertexBuffer(r.blitter.quadVerts, 0) @@ -1406,17 +1406,3 @@ func isPureOffset(t f32.Affine2D) bool { a, b, _, d, e, _ := t.Elems() return a == 1 && b == 0 && d == 0 && e == 1 } - -// frect converts a rectangle to a f32.Rectangle. -func frect(r image.Rectangle) f32.Rectangle { - return f32.Rectangle{ - Min: fpt(r.Min), Max: fpt(r.Max), - } -} - -// fpt converts an point to a f32.Point. -func fpt(p image.Point) f32.Point { - return f32.Point{ - X: float32(p.X), Y: float32(p.Y), - } -} diff --git a/gpu/internal/rendertest/render_test.go b/gpu/internal/rendertest/render_test.go index 57b29274..48b7c01b 100644 --- a/gpu/internal/rendertest/render_test.go +++ b/gpu/internal/rendertest/render_test.go @@ -10,7 +10,7 @@ import ( "golang.org/x/image/colornames" - "gioui.org/f32" + "gioui.org/internal/f32" "gioui.org/internal/f32color" "gioui.org/op" "gioui.org/op/clip" diff --git a/gpu/path.go b/gpu/path.go index c14d5928..e0662843 100644 --- a/gpu/path.go +++ b/gpu/path.go @@ -11,9 +11,9 @@ import ( "math" "unsafe" - "gioui.org/f32" "gioui.org/gpu/internal/driver" "gioui.org/internal/byteslice" + "gioui.org/internal/f32" "gioui.org/internal/f32color" "gioui.org/shader" "gioui.org/shader/gio" diff --git a/internal/f32/f32.go b/internal/f32/f32.go index 044cc51b..771b0988 100644 --- a/internal/f32/f32.go +++ b/internal/f32/f32.go @@ -1,30 +1,23 @@ // SPDX-License-Identifier: Unlicense OR MIT /* -Package f32 is a float32 implementation of package image's -Point and Rectangle. - -The coordinate space has the origin in the top left -corner with the axes extending right and down. +Package f32 is an internal version of the public package f32 with +extra types for internal use. */ package f32 import ( "image" "math" - "strconv" + + "gioui.org/f32" ) -// A Point is a two dimensional point. -type Point struct { - X, Y float32 -} +type Point = f32.Point -// String return a string representation of p. -func (p Point) String() string { - return "(" + strconv.FormatFloat(float64(p.X), 'f', -1, 32) + - "," + strconv.FormatFloat(float64(p.Y), 'f', -1, 32) + ")" -} +type Affine2D = f32.Affine2D + +var NewAffine2D = f32.NewAffine2D // A Rectangle contains the points (X, Y) where Min.X <= X < Max.X, // Min.Y <= Y < Max.Y. @@ -51,43 +44,7 @@ func Rect(x0, y0, x1, y1 float32) Rectangle { } // Pt is shorthand for Point{X: x, Y: y}. -func Pt(x, y float32) Point { - return Point{X: x, Y: y} -} - -// Add return the point p+p2. -func (p Point) Add(p2 Point) Point { - return Point{X: p.X + p2.X, Y: p.Y + p2.Y} -} - -// Sub returns the vector p-p2. -func (p Point) Sub(p2 Point) Point { - return Point{X: p.X - p2.X, Y: p.Y - p2.Y} -} - -// Mul returns p scaled by s. -func (p Point) Mul(s float32) Point { - return Point{X: p.X * s, Y: p.Y * s} -} - -// Div returns the vector p/s. -func (p Point) Div(s float32) Point { - return Point{X: p.X / s, Y: p.Y / s} -} - -// In reports whether p is in r. -func (p Point) In(r Rectangle) bool { - return r.Min.X <= p.X && p.X < r.Max.X && - r.Min.Y <= p.Y && p.Y < r.Max.Y -} - -// Round returns the integer point closest to p. -func (p Point) Round() image.Point { - return image.Point{ - X: int(math.Round(float64(p.X))), - Y: int(math.Round(float64(p.Y))), - } -} +var Pt = f32.Pt // Size returns r's width and height. func (r Rectangle) Size() Point { @@ -195,6 +152,20 @@ func (r Rectangle) Round() image.Rectangle { } } +// fRect converts a rectangle to a f32internal.Rectangle. +func FRect(r image.Rectangle) Rectangle { + return Rectangle{ + Min: FPt(r.Min), Max: FPt(r.Max), + } +} + +// Fpt converts an point to a f32.Point. +func FPt(p image.Point) Point { + return Point{ + X: float32(p.X), Y: float32(p.Y), + } +} + func ceil(v float32) int { return int(math.Ceil(float64(v))) } diff --git a/internal/scene/scene.go b/internal/scene/scene.go index 03588587..1868d2e9 100644 --- a/internal/scene/scene.go +++ b/internal/scene/scene.go @@ -11,7 +11,7 @@ import ( "math" "unsafe" - "gioui.org/f32" + "gioui.org/internal/f32" ) type Op uint32 diff --git a/internal/stroke/stroke.go b/internal/stroke/stroke.go index a115dc79..34f656f0 100644 --- a/internal/stroke/stroke.go +++ b/internal/stroke/stroke.go @@ -29,7 +29,7 @@ import ( "encoding/binary" "math" - "gioui.org/f32" + "gioui.org/internal/f32" "gioui.org/internal/ops" "gioui.org/internal/scene" ) diff --git a/io/router/pointer.go b/io/router/pointer.go index 60a3be84..8c518134 100644 --- a/io/router/pointer.go +++ b/io/router/pointer.go @@ -7,6 +7,7 @@ import ( "io" "gioui.org/f32" + f32internal "gioui.org/internal/f32" "gioui.org/internal/ops" "gioui.org/io/event" "gioui.org/io/key" @@ -189,13 +190,6 @@ func (c *pointerCollector) pushArea(kind areaKind, bounds image.Rectangle) { }) } -// fpt converts a point to a f32.Point. -func fpt(p image.Point) f32.Point { - return f32.Point{ - X: float32(p.X), Y: float32(p.Y), - } -} - func (c *pointerCollector) popArea() { n := len(c.nodeStack) c.state.nodePlusOne = c.nodeStack[n-1] + 1 @@ -911,8 +905,8 @@ func firstMimeMatch(src, tgt *pointerHandler) (first string, matched bool) { } func (op *areaOp) Hit(pos f32.Point) bool { - pos = pos.Sub(fpt(op.rect.Min)) - size := fpt(op.rect.Size()) + pos = pos.Sub(f32internal.FPt(op.rect.Min)) + size := f32internal.FPt(op.rect.Size()) switch op.kind { case areaRect: return 0 <= pos.X && pos.X < size.X && @@ -931,9 +925,9 @@ func (op *areaOp) Hit(pos f32.Point) bool { } func (a *areaNode) bounds() image.Rectangle { - return f32.Rectangle{ - Min: a.trans.Transform(fpt(a.area.rect.Min)), - Max: a.trans.Transform(fpt(a.area.rect.Max)), + return f32internal.Rectangle{ + Min: a.trans.Transform(f32internal.FPt(a.area.rect.Min)), + Max: a.trans.Transform(f32internal.FPt(a.area.rect.Max)), }.Round() } diff --git a/io/router/router.go b/io/router/router.go index f3a901fc..018b6a3e 100644 --- a/io/router/router.go +++ b/io/router/router.go @@ -19,6 +19,7 @@ import ( "time" "gioui.org/f32" + f32internal "gioui.org/internal/f32" "gioui.org/internal/ops" "gioui.org/io/clipboard" "gioui.org/io/event" @@ -242,7 +243,7 @@ func (q *Router) ScrollFocus(dist image.Point) { q.pointer.queue.Deliver(area, pointer.Event{ Type: pointer.Scroll, Source: pointer.Touch, - Scroll: fpt(dist), + Scroll: f32internal.FPt(dist), }, &q.handlers) } diff --git a/op/clip/clip.go b/op/clip/clip.go index 89bb07cc..2d9a9ba0 100644 --- a/op/clip/clip.go +++ b/op/clip/clip.go @@ -9,6 +9,7 @@ import ( "math" "gioui.org/f32" + f32internal "gioui.org/internal/f32" "gioui.org/internal/ops" "gioui.org/internal/scene" "gioui.org/internal/stroke" @@ -51,7 +52,7 @@ func (p Op) add(o *op.Ops) { if !path.hasSegments && p.width > 0 { switch p.path.shape { case ops.Rect: - b := frect(path.bounds) + b := f32internal.FRect(path.bounds) var rect Path rect.Begin(o) rect.MoveTo(b.Min) @@ -129,7 +130,7 @@ type Path struct { macro op.MacroOp start f32.Point hasSegments bool - bounds f32.Rectangle + bounds f32internal.Rectangle hash maphash.Hash } @@ -219,7 +220,7 @@ func (p *Path) cmd(data []byte, c scene.Command) { func (p *Path) expand(pt f32.Point) { if !p.hasSegments { p.hasSegments = true - p.bounds = f32.Rectangle{Min: pt, Max: pt} + p.bounds = f32internal.Rectangle{Min: pt, Max: pt} } else { b := p.bounds if pt.X < b.Min.X { @@ -339,17 +340,3 @@ func (o Outline) Op() Op { outline: true, } } - -// frect converts a rectangle to a f32.Rectangle. -func frect(r image.Rectangle) f32.Rectangle { - return f32.Rectangle{ - Min: fpt(r.Min), Max: fpt(r.Max), - } -} - -// fpt converts an point to a f32.Point. -func fpt(p image.Point) f32.Point { - return f32.Point{ - X: float32(p.X), Y: float32(p.Y), - } -} diff --git a/op/clip/shapes.go b/op/clip/shapes.go index 2fc32331..4892d8da 100644 --- a/op/clip/shapes.go +++ b/op/clip/shapes.go @@ -7,6 +7,7 @@ import ( "math" "gioui.org/f32" + f32internal "gioui.org/internal/f32" "gioui.org/internal/ops" "gioui.org/op" ) @@ -81,7 +82,7 @@ func (rr RRect) Path(ops *op.Ops) PathSpec { const iq = 1 - q se, sw, nw, ne := float32(rr.SE), float32(rr.SW), float32(rr.NW), float32(rr.NE) - rrf := frect(rr.Rect) + rrf := f32internal.FRect(rr.Rect) w, n, e, s := rrf.Min.X, rrf.Min.Y, rrf.Max.X, rrf.Max.Y p.MoveTo(f32.Point{X: w + nw, Y: n}) @@ -133,7 +134,7 @@ func (e Ellipse) Path(o *op.Ops) PathSpec { var p Path p.Begin(o) - bf := frect(bounds) + bf := f32internal.FRect(bounds) center := bf.Max.Add(bf.Min).Mul(.5) diam := bf.Dx() r := diam * .5