make pumkin alllll better!
This commit is contained in:
parent
14deec24f5
commit
92cb318972
27
layout.go
27
layout.go
@ -8,12 +8,11 @@ import "golang.org/x/image/math/fixed"
|
||||
type Align int
|
||||
|
||||
const (
|
||||
// AlignLeft aligns the start of each line to the beginning point
|
||||
// of each dot.
|
||||
AlignLeft Align = iota
|
||||
AlignRight
|
||||
AlignCenter
|
||||
AlignJustify
|
||||
// X | Y
|
||||
AlignStart Align = iota // left | top
|
||||
AlignMiddle // center | center
|
||||
AlignEnd // right | bottom
|
||||
AlignEven // justified | evenly spaced
|
||||
)
|
||||
|
||||
// RuneLayout contains layout information for a single rune relative to its
|
||||
@ -150,11 +149,7 @@ func DoLine (text []rune, face font.Face, wrap bool, width fixed.Int26_6) (line
|
||||
|
||||
// set the width of the line's content.
|
||||
line.ContentWidth = lastWord.X + lastWord.Width
|
||||
if wrap {
|
||||
line.Width = width
|
||||
} else {
|
||||
line.Width = line.ContentWidth
|
||||
}
|
||||
line.Width = width
|
||||
line.SpaceAfter = lastWord.SpaceAfter
|
||||
return
|
||||
}
|
||||
@ -174,17 +169,17 @@ func (line *LineLayout) Length () int {
|
||||
// method.
|
||||
func (line *LineLayout) Align (align Align) {
|
||||
if len(line.Words) == 0 { return }
|
||||
|
||||
if align == AlignJustify {
|
||||
|
||||
if align == AlignEven {
|
||||
line.justify()
|
||||
return
|
||||
}
|
||||
|
||||
leftOffset := -line.Words[0].X
|
||||
|
||||
if align == AlignCenter {
|
||||
if align == AlignMiddle {
|
||||
leftOffset += (line.Width - line.ContentWidth) / 2
|
||||
} else if align == AlignRight {
|
||||
} else if align == AlignEnd {
|
||||
leftOffset += line.Width - line.ContentWidth
|
||||
}
|
||||
|
||||
@ -195,7 +190,7 @@ func (line *LineLayout) Align (align Align) {
|
||||
|
||||
func (line *LineLayout) justify () {
|
||||
if len(line.Words) < 2 {
|
||||
line.Align(AlignLeft)
|
||||
line.Align(AlignStart)
|
||||
return
|
||||
}
|
||||
|
||||
|
54
setter.go
54
setter.go
@ -14,11 +14,10 @@ type TypeSetter struct {
|
||||
layoutClean bool
|
||||
alignClean bool
|
||||
|
||||
align Align
|
||||
face font.Face
|
||||
maxWidth int
|
||||
maxHeight int
|
||||
wrap bool
|
||||
hAlign, vAlign Align
|
||||
face font.Face
|
||||
width, height int
|
||||
wrap bool
|
||||
|
||||
minWidth fixed.Int26_6
|
||||
layoutBounds image.Rectangle
|
||||
@ -34,14 +33,15 @@ func (setter *TypeSetter) needLayout () {
|
||||
setter.layoutBounds = image.Rectangle { }
|
||||
setter.layoutBoundsSpace = image.Rectangle { }
|
||||
setter.minWidth = 0
|
||||
if setter.face == nil { return }
|
||||
if setter.face == nil { return }
|
||||
|
||||
horizontalExtent := fixed.Int26_6(0)
|
||||
horizontalExtentSpace := fixed.Int26_6(0)
|
||||
metrics := setter.face.Metrics()
|
||||
remaining := setter.text
|
||||
y := fixed.Int26_6(0)
|
||||
|
||||
|
||||
// function to add line and update bounds statistics
|
||||
addLine := func (line LineLayout) {
|
||||
line.Y = y
|
||||
y += metrics.Height
|
||||
@ -59,7 +59,7 @@ func (setter *TypeSetter) needLayout () {
|
||||
for len(remaining) > 0 {
|
||||
line, remainingFromLine := DoLine (
|
||||
remaining, setter.face, setter.wrap,
|
||||
fixed.I(setter.maxWidth))
|
||||
fixed.I(setter.width))
|
||||
remaining = remainingFromLine
|
||||
addLine(line)
|
||||
}
|
||||
@ -71,13 +71,19 @@ func (setter *TypeSetter) needLayout () {
|
||||
setter.lines[len(setter.lines) - 1].BreakAfter
|
||||
if needBlankLine { addLine(LineLayout { }) }
|
||||
|
||||
// if we are wrapping text, the width must be the user-set width
|
||||
if setter.wrap {
|
||||
horizontalExtent = fixed.I(setter.width)
|
||||
horizontalExtentSpace = fixed.I(setter.width)
|
||||
}
|
||||
|
||||
// calculate layout boundaries
|
||||
setter.minWidth = horizontalExtentSpace
|
||||
setter.layoutBounds.Max.X = horizontalExtent.Round()
|
||||
setter.layoutBoundsSpace.Max.X = horizontalExtentSpace.Round()
|
||||
|
||||
y -= metrics.Height
|
||||
if setter.maxHeight == 0 {
|
||||
if setter.height == 0 {
|
||||
setter.layoutBounds.Min.Y = -metrics.Ascent.Round()
|
||||
setter.layoutBounds.Max.Y =
|
||||
y.Round() +
|
||||
@ -85,7 +91,7 @@ func (setter *TypeSetter) needLayout () {
|
||||
} else {
|
||||
setter.layoutBounds.Min.Y = -metrics.Ascent.Round()
|
||||
setter.layoutBounds.Max.Y =
|
||||
setter.maxHeight -
|
||||
setter.height -
|
||||
metrics.Ascent.Round()
|
||||
}
|
||||
setter.layoutBoundsSpace.Min.Y = setter.layoutBounds.Min.Y
|
||||
@ -98,13 +104,18 @@ func (setter *TypeSetter) needAlignedLayout () {
|
||||
setter.alignClean = true
|
||||
|
||||
for index := range setter.lines {
|
||||
align := setter.align
|
||||
if align == AlignJustify {
|
||||
align := setter.hAlign
|
||||
|
||||
// if the horizontal align is even, align lines with breaks
|
||||
// after them to the left anyways
|
||||
if align == AlignEven {
|
||||
except :=
|
||||
index == len(setter.lines) - 1 ||
|
||||
setter.lines[index].BreakAfter
|
||||
if except { align = AlignLeft }
|
||||
if except { align = AlignStart }
|
||||
}
|
||||
|
||||
// align line
|
||||
setter.lines[index].Align(align)
|
||||
}
|
||||
}
|
||||
@ -118,9 +129,10 @@ func (setter *TypeSetter) SetWrap (wrap bool) {
|
||||
|
||||
// SetAlign sets the alignment method of the typesetter.
|
||||
func (setter *TypeSetter) SetAlign (horizontal, vertical Align) {
|
||||
if setter.align == horizontal { return }
|
||||
if setter.hAlign == horizontal && setter.vAlign == vertical { return }
|
||||
setter.alignClean = false
|
||||
setter.align = horizontal
|
||||
setter.hAlign = horizontal
|
||||
setter.vAlign = vertical
|
||||
}
|
||||
|
||||
// SetText sets the text content of the typesetter.
|
||||
@ -141,20 +153,20 @@ func (setter *TypeSetter) SetFace (face font.Face) {
|
||||
// SetWidth sets the width of the typesetter. Text will still be able
|
||||
// to overflow outside of this width if wrapping is disabled.
|
||||
func (setter *TypeSetter) SetWidth (width int) {
|
||||
if setter.maxWidth == width { return }
|
||||
if setter.width == width { return }
|
||||
setter.layoutClean = false
|
||||
setter.alignClean = false
|
||||
setter.maxWidth = width
|
||||
setter.width = width
|
||||
}
|
||||
|
||||
// SetHeight sets the height of the typesetter. If the height is greater than
|
||||
// zero, no lines will be laid out past it. If the height is zero, the text's
|
||||
// maximum height will not be constrained.
|
||||
func (setter *TypeSetter) SetHeight (heignt int) {
|
||||
if setter.maxHeight == heignt { return }
|
||||
if setter.height == heignt { return }
|
||||
setter.layoutClean = false
|
||||
setter.alignClean = false
|
||||
setter.maxHeight = heignt
|
||||
setter.height = heignt
|
||||
}
|
||||
|
||||
// Em returns the width of one emspace according to the typesetter's font, which
|
||||
@ -173,12 +185,12 @@ func (setter *TypeSetter) LineHeight () fixed.Int26_6 {
|
||||
|
||||
// Width returns the height of the typesetter as set by SetWidth.
|
||||
func (setter *TypeSetter) Width () int {
|
||||
return setter.maxWidth
|
||||
return setter.width
|
||||
}
|
||||
|
||||
// Height returns the height of the typesetter as set by SetHeight.
|
||||
func (setter *TypeSetter) Height () int {
|
||||
return setter.maxHeight
|
||||
return setter.height
|
||||
}
|
||||
|
||||
// Face returns the TypeSetter's font face as set by SetFace.
|
||||
|
Loading…
Reference in New Issue
Block a user