From 2c79e7325a85341f9092b55bb95da97e760ac9ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathana=C3=ABl=20Jourdane?= Date: Mon, 10 Aug 2020 15:57:56 +0200 Subject: [PATCH 1/9] Add AnchorPos struct and functions --- geometry.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/geometry.go b/geometry.go index a98b78c..75b414e 100644 --- a/geometry.go +++ b/geometry.go @@ -547,7 +547,55 @@ func (r Rect) Edges() [4]Line { } } +// AnchorPos enumerates available anchor positions, such as `Center`, `Top`, `TopRight`, etc. +type AnchorPos struct{ v Vec } + +var ( + Center = AnchorPos{V(0.5, 0.5)} + Top = AnchorPos{V(0.5, 1)} + TopRight = AnchorPos{V(1, 1)} + Right = AnchorPos{V(1, 0.5)} + BottomRight = AnchorPos{V(1, 0)} + Bottom = AnchorPos{V(0.5, 0)} + BottomLeft = AnchorPos{V(0, 0)} + Left = AnchorPos{V(0, 0.5)} + TopLeft = AnchorPos{V(0, 1)} +) + +// String returns the string representation of an anchor. +func (anchorPos AnchorPos) String() string { + switch anchorPos { + case Center: + return "Center" + case Top: + return "Top" + case TopRight: + return "TopRight" + case Right: + return "Right" + case BottomRight: + return "BottomRight" + case Bottom: + return "Bottom" + case BottomLeft: + return "BottomLeft" + case Left: + return "Left" + case TopLeft: + return "TopLeft" + default: + return "" + } +} + +// AnchorPos returns the position of the given anchor of the Rect. +func (r *Rect) AnchorPos(anchor AnchorPos) Vec { + // func (u Vec) ScaledXY(v Vec) Vec { + return r.Min.Add(r.Size().ScaledXY(anchor.v)) +} + // Center returns the position of the center of the Rect. +// `rect.Center()` is equivalent to `rect.AnchorPos(pixel.AnchorPos.Center)` func (r Rect) Center() Vec { return Lerp(r.Min, r.Max, 0.5) } From 50e1d8c96bf77d07addc6c91d158b0a461959ddd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathana=C3=ABl=20Jourdane?= Date: Mon, 10 Aug 2020 17:25:09 +0200 Subject: [PATCH 2/9] Add Rect.AnchorTo() --- geometry.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/geometry.go b/geometry.go index 75b414e..dd44120 100644 --- a/geometry.go +++ b/geometry.go @@ -548,7 +548,7 @@ func (r Rect) Edges() [4]Line { } // AnchorPos enumerates available anchor positions, such as `Center`, `Top`, `TopRight`, etc. -type AnchorPos struct{ v Vec } +type AnchorPos struct{ Val Vec } var ( Center = AnchorPos{V(0.5, 0.5)} @@ -590,8 +590,14 @@ func (anchorPos AnchorPos) String() string { // AnchorPos returns the position of the given anchor of the Rect. func (r *Rect) AnchorPos(anchor AnchorPos) Vec { - // func (u Vec) ScaledXY(v Vec) Vec { - return r.Min.Add(r.Size().ScaledXY(anchor.v)) + return r.Min.Add(r.Size().ScaledXY(anchor.Val)) +} + +// AnchorTo updates the Rect position to align it on the given anchor. +func (r *Rect) AnchorTo(anchor AnchorPos) { + size := r.Size() + r.Min = r.Min.Sub(size.ScaledXY(anchor.Val)) + r.Max = r.Max.Sub(size.ScaledXY(anchor.Val)) } // Center returns the position of the center of the Rect. From d6663ba0a0d7f6d0f8cbe2b9917ebe2fad4c23d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathana=C3=ABl?= Date: Tue, 11 Aug 2020 08:35:03 +0200 Subject: [PATCH 3/9] Add Matrix.Aligned() --- geometry.go | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/geometry.go b/geometry.go index dd44120..e1ba2e5 100644 --- a/geometry.go +++ b/geometry.go @@ -589,15 +589,22 @@ func (anchorPos AnchorPos) String() string { } // AnchorPos returns the position of the given anchor of the Rect. -func (r *Rect) AnchorPos(anchor AnchorPos) Vec { - return r.Min.Add(r.Size().ScaledXY(anchor.Val)) +func (r *Rect) AnchorPos(anchorPos AnchorPos) Vec { + return r.Min.Add(r.Size().ScaledXY(anchorPos.Val)) } // AnchorTo updates the Rect position to align it on the given anchor. -func (r *Rect) AnchorTo(anchor AnchorPos) { - size := r.Size() - r.Min = r.Min.Sub(size.ScaledXY(anchor.Val)) - r.Max = r.Max.Sub(size.ScaledXY(anchor.Val)) +func (rect *Rect) AnchorTo(anchorPos AnchorPos) { + size := rect.Size() + rect.Min = rect.Min.Sub(size.ScaledXY(anchorPos.Val)) + rect.Max = rect.Max.Sub(size.ScaledXY(anchorPos.Val)) +} + +// Aligned moves everything to align the given rectangle on the given anchor position. +func (m Matrix) Aligned(rect Rect, anchorPos AnchorPos) Matrix { + vect := rect.Size().ScaledXY(anchorPos.Val) + m[4], m[5] = m[4]-vect.X, m[5]-vect.Y + return m } // Center returns the position of the center of the Rect. From e66e94b9433c40efa1c0360f2d6ea56f4c9c4e91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathana=C3=ABl?= Date: Tue, 11 Aug 2020 09:17:51 +0200 Subject: [PATCH 4/9] func AlignedTo is used for Rect instead of Matrix --- geometry.go | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/geometry.go b/geometry.go index e1ba2e5..03b4302 100644 --- a/geometry.go +++ b/geometry.go @@ -589,22 +589,13 @@ func (anchorPos AnchorPos) String() string { } // AnchorPos returns the position of the given anchor of the Rect. -func (r *Rect) AnchorPos(anchorPos AnchorPos) Vec { - return r.Min.Add(r.Size().ScaledXY(anchorPos.Val)) +func (r Rect) AnchorPos(anchorPos AnchorPos) Vec { + return r.Size().ScaledXY(V(0, 0).Sub(anchorPos.Val)) } -// AnchorTo updates the Rect position to align it on the given anchor. -func (rect *Rect) AnchorTo(anchorPos AnchorPos) { - size := rect.Size() - rect.Min = rect.Min.Sub(size.ScaledXY(anchorPos.Val)) - rect.Max = rect.Max.Sub(size.ScaledXY(anchorPos.Val)) -} - -// Aligned moves everything to align the given rectangle on the given anchor position. -func (m Matrix) Aligned(rect Rect, anchorPos AnchorPos) Matrix { - vect := rect.Size().ScaledXY(anchorPos.Val) - m[4], m[5] = m[4]-vect.X, m[5]-vect.Y - return m +// AlignedTo returns the rect moved to be aligned on the given anchor. +func (rect Rect) AlignedTo(anchorPos AnchorPos) Rect { + return rect.Moved(rect.AnchorPos(anchorPos)) } // Center returns the position of the center of the Rect. From 7a106fa572b264afddfee349ee47d98ce8d54c04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathana=C3=ABl=20Jourdane?= Date: Tue, 11 Aug 2020 11:33:05 +0200 Subject: [PATCH 5/9] Makes Anchor a type Vec instead of a struct --- geometry.go | 58 ++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/geometry.go b/geometry.go index 03b4302..1491d9c 100644 --- a/geometry.go +++ b/geometry.go @@ -547,59 +547,59 @@ func (r Rect) Edges() [4]Line { } } -// AnchorPos enumerates available anchor positions, such as `Center`, `Top`, `TopRight`, etc. -type AnchorPos struct{ Val Vec } +// Anchor is a vector used to define anchors, such as `Center`, `Top`, `TopRight`, etc. +type Anchor Vec var ( - Center = AnchorPos{V(0.5, 0.5)} - Top = AnchorPos{V(0.5, 1)} - TopRight = AnchorPos{V(1, 1)} - Right = AnchorPos{V(1, 0.5)} - BottomRight = AnchorPos{V(1, 0)} - Bottom = AnchorPos{V(0.5, 0)} - BottomLeft = AnchorPos{V(0, 0)} - Left = AnchorPos{V(0, 0.5)} - TopLeft = AnchorPos{V(0, 1)} + Center = Anchor{0.5, 0.5} + Top = Anchor{0.5, 1} + TopRight = Anchor{1, 1} + Right = Anchor{1, 0.5} + BottomRight = Anchor{1, 0} + Bottom = Anchor{0.5, 0} + BottomLeft = Anchor{0, 0} + Left = Anchor{0, 0.5} + TopLeft = Anchor{0, 1} ) // String returns the string representation of an anchor. -func (anchorPos AnchorPos) String() string { - switch anchorPos { +func (anchor Anchor) String() string { + switch anchor { case Center: - return "Center" + return "center" case Top: - return "Top" + return "top" case TopRight: - return "TopRight" + return "top-right" case Right: - return "Right" + return "right" case BottomRight: - return "BottomRight" + return "bottom-right" case Bottom: - return "Bottom" + return "bottom" case BottomLeft: - return "BottomLeft" + return "bottom-left" case Left: - return "Left" + return "left" case TopLeft: - return "TopLeft" + return "top-left" default: return "" } } -// AnchorPos returns the position of the given anchor of the Rect. -func (r Rect) AnchorPos(anchorPos AnchorPos) Vec { - return r.Size().ScaledXY(V(0, 0).Sub(anchorPos.Val)) +// AnchorPos returns the relative position of the given anchor. +func (r Rect) AnchorPos(anchor Anchor) Vec { + return r.Size().ScaledXY(V(0, 0).Sub(Vec(anchor))) } -// AlignedTo returns the rect moved to be aligned on the given anchor. -func (rect Rect) AlignedTo(anchorPos AnchorPos) Rect { - return rect.Moved(rect.AnchorPos(anchorPos)) +// AlignedTo returns the rect moved by the given anchor. +func (rect Rect) AlignedTo(anchor Anchor) Rect { + return rect.Moved(rect.AnchorPos(anchor)) } // Center returns the position of the center of the Rect. -// `rect.Center()` is equivalent to `rect.AnchorPos(pixel.AnchorPos.Center)` +// `rect.Center()` is equivalent to `rect.Anchor(pixel.Anchor.Center)` func (r Rect) Center() Vec { return Lerp(r.Min, r.Max, 0.5) } From a8b7779fbe47539aae6634b7c4ef0601652fcca4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathana=C3=ABl?= Date: Tue, 11 Aug 2020 22:16:16 +0200 Subject: [PATCH 6/9] Add Text.AlignedTo() --- text/text.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/text/text.go b/text/text.go index 1247a8d..c6e7317 100644 --- a/text/text.go +++ b/text/text.go @@ -101,6 +101,7 @@ type Text struct { trans pixel.TrianglesData transD pixel.Drawer dirty bool + anchor pixel.Anchor } // New creates a new Text capable of drawing runes contained in the provided Atlas. Orig and Dot @@ -182,6 +183,12 @@ func (txt *Text) BoundsOf(s string) pixel.Rect { return bounds } +// AlignedTo returns the text moved by the given anchor. +func (txt *Text) AlignedTo(anchor pixel.Anchor) *Text { + txt.anchor = anchor + return txt +} + // Clear removes all written text from the Text. The Dot field is reset to Orig. func (txt *Text) Clear() { txt.prevR = -1 @@ -244,6 +251,10 @@ func (txt *Text) DrawColorMask(t pixel.Target, matrix pixel.Matrix, mask color.C txt.mat = matrix txt.dirty = true } + + offset := txt.Bounds().AnchorPos(txt.anchor) + txt.mat = pixel.IM.Moved(offset).Chained(txt.mat) + if mask == nil { mask = pixel.Alpha(1) } From 234298474448571c8bcf021247bb48326eefea25 Mon Sep 17 00:00:00 2001 From: Nathanael Jourdane Date: Wed, 12 Aug 2020 17:24:15 +0200 Subject: [PATCH 7/9] bugfix: inverse all anchors --- geometry.go | 51 +++++++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/geometry.go b/geometry.go index 1491d9c..05c4937 100644 --- a/geometry.go +++ b/geometry.go @@ -552,40 +552,31 @@ type Anchor Vec var ( Center = Anchor{0.5, 0.5} - Top = Anchor{0.5, 1} - TopRight = Anchor{1, 1} - Right = Anchor{1, 0.5} - BottomRight = Anchor{1, 0} - Bottom = Anchor{0.5, 0} - BottomLeft = Anchor{0, 0} - Left = Anchor{0, 0.5} - TopLeft = Anchor{0, 1} + Top = Anchor{0.5, 0} + TopRight = Anchor{0, 0} + Right = Anchor{0, 0.5} + BottomRight = Anchor{0, 1} + Bottom = Anchor{0.5, 1} + BottomLeft = Anchor{1, 1} + Left = Anchor{1, 0.5} + TopLeft = Anchor{1, 0} ) +var anchorStrings map[Anchor]string = map[Anchor]string{ + Center: "center", + Top: "top", + TopRight: "top-right", + Right: "right", + BottomRight: "bottom-right", + Bottom: "bottom", + BottomLeft: "bottom-left", + Left: "left", + TopLeft: "top-left", +} + // String returns the string representation of an anchor. func (anchor Anchor) String() string { - switch anchor { - case Center: - return "center" - case Top: - return "top" - case TopRight: - return "top-right" - case Right: - return "right" - case BottomRight: - return "bottom-right" - case Bottom: - return "bottom" - case BottomLeft: - return "bottom-left" - case Left: - return "left" - case TopLeft: - return "top-left" - default: - return "" - } + return anchorStrings[anchor] } // AnchorPos returns the relative position of the given anchor. From c9681cec8a20e3263f07770bdd9c51fda2d7e8de Mon Sep 17 00:00:00 2001 From: Nathanael Jourdane Date: Wed, 12 Aug 2020 17:25:43 +0200 Subject: [PATCH 8/9] Add Anchor.Opposite() func --- geometry.go | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/geometry.go b/geometry.go index 05c4937..6e8b0c0 100644 --- a/geometry.go +++ b/geometry.go @@ -553,13 +553,13 @@ type Anchor Vec var ( Center = Anchor{0.5, 0.5} Top = Anchor{0.5, 0} - TopRight = Anchor{0, 0} - Right = Anchor{0, 0.5} - BottomRight = Anchor{0, 1} + TopRight = Anchor{0, 0} + Right = Anchor{0, 0.5} + BottomRight = Anchor{0, 1} Bottom = Anchor{0.5, 1} - BottomLeft = Anchor{1, 1} - Left = Anchor{1, 0.5} - TopLeft = Anchor{1, 0} + BottomLeft = Anchor{1, 1} + Left = Anchor{1, 0.5} + TopLeft = Anchor{1, 0} ) var anchorStrings map[Anchor]string = map[Anchor]string{ @@ -579,6 +579,23 @@ func (anchor Anchor) String() string { return anchorStrings[anchor] } +var oppositeAnchors map[Anchor]Anchor = map[Anchor]Anchor{ + Center: Center, + Top: Bottom, + Bottom: Top, + Right: Left, + Left: Right, + TopRight: BottomLeft, + BottomLeft: TopRight, + BottomRight: TopLeft, + TopLeft: BottomRight, +} + +// Opposite returns the opposite position of the anchor (ie. Top -> Bottom; BottomLeft -> TopRight, etc.). +func (anchor Anchor) Opposite() Anchor { + return oppositeAnchors[anchor] +} + // AnchorPos returns the relative position of the given anchor. func (r Rect) AnchorPos(anchor Anchor) Vec { return r.Size().ScaledXY(V(0, 0).Sub(Vec(anchor))) From 3b599e70ec9947a7942791a8f82cad766dd165f2 Mon Sep 17 00:00:00 2001 From: Nathanael Jourdane Date: Sat, 22 Aug 2020 15:31:07 +0200 Subject: [PATCH 9/9] Fix text anchor position when txt.Bounds().W() != txt.Dot.X-txt.Orig.X --- text/text.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/text.go b/text/text.go index c6e7317..84365c2 100644 --- a/text/text.go +++ b/text/text.go @@ -252,7 +252,7 @@ func (txt *Text) DrawColorMask(t pixel.Target, matrix pixel.Matrix, mask color.C txt.dirty = true } - offset := txt.Bounds().AnchorPos(txt.anchor) + offset := txt.Orig.Sub(txt.Bounds().Max.Add(txt.Bounds().AnchorPos(txt.anchor.Opposite()))) txt.mat = pixel.IM.Moved(offset).Chained(txt.mat) if mask == nil {