Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 14deec24f5 | |||
| 388a113a01 | |||
| c4dce027ef | |||
| ee345c10ef |
14
layout.go
14
layout.go
@@ -111,7 +111,7 @@ type LineLayout struct {
|
||||
// wrap is set to true, this function will stop processing words once maxWidth
|
||||
// is crossed. The word which would have crossed over the limit will not be
|
||||
// processed.
|
||||
func DoLine (text []rune, face font.Face, wrap bool, maxWidth fixed.Int26_6) (line LineLayout, remaining []rune) {
|
||||
func DoLine (text []rune, face font.Face, wrap bool, width fixed.Int26_6) (line LineLayout, remaining []rune) {
|
||||
remaining = text
|
||||
x := fixed.Int26_6(0)
|
||||
lastWord := WordLayout { }
|
||||
@@ -122,9 +122,9 @@ func DoLine (text []rune, face font.Face, wrap bool, maxWidth fixed.Int26_6) (li
|
||||
word.X = x
|
||||
x += word.Width
|
||||
|
||||
// if we have gone over the maximum width, stop processing
|
||||
// if we have gone over the preferred width, stop processing
|
||||
// words (if wrap is enabled)
|
||||
if !isFirstWord && wrap && x > maxWidth {
|
||||
if !isFirstWord && wrap && x > width {
|
||||
break
|
||||
}
|
||||
|
||||
@@ -149,9 +149,13 @@ func DoLine (text []rune, face font.Face, wrap bool, maxWidth fixed.Int26_6) (li
|
||||
}
|
||||
|
||||
// set the width of the line's content.
|
||||
line.Width = maxWidth
|
||||
line.ContentWidth = lastWord.X + lastWord.Width
|
||||
line.SpaceAfter = lastWord.SpaceAfter
|
||||
if wrap {
|
||||
line.Width = width
|
||||
} else {
|
||||
line.Width = line.ContentWidth
|
||||
}
|
||||
line.SpaceAfter = lastWord.SpaceAfter
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
76
setter.go
76
setter.go
@@ -34,23 +34,15 @@ func (setter *TypeSetter) needLayout () {
|
||||
setter.layoutBounds = image.Rectangle { }
|
||||
setter.layoutBoundsSpace = image.Rectangle { }
|
||||
setter.minWidth = 0
|
||||
if len(setter.text) == 0 { 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)
|
||||
for len(remaining) > 0 {
|
||||
// process one line
|
||||
line, remainingFromLine := DoLine (
|
||||
remaining, setter.face, setter.wrap,
|
||||
fixed.I(setter.maxWidth))
|
||||
remaining = remainingFromLine
|
||||
|
||||
// add the line
|
||||
metrics := setter.face.Metrics()
|
||||
remaining := setter.text
|
||||
y := fixed.Int26_6(0)
|
||||
|
||||
addLine := func (line LineLayout) {
|
||||
line.Y = y
|
||||
y += metrics.Height
|
||||
if line.ContentWidth > horizontalExtent {
|
||||
@@ -62,10 +54,27 @@ func (setter *TypeSetter) needLayout () {
|
||||
}
|
||||
setter.lines = append(setter.lines, line)
|
||||
}
|
||||
setter.minWidth = horizontalExtentSpace
|
||||
|
||||
setter.layoutBounds.Max.X = setter.maxWidth
|
||||
setter.layoutBoundsSpace.Max.X = setter.maxWidth
|
||||
// process every line until there are no more remaining runes
|
||||
for len(remaining) > 0 {
|
||||
line, remainingFromLine := DoLine (
|
||||
remaining, setter.face, setter.wrap,
|
||||
fixed.I(setter.maxWidth))
|
||||
remaining = remainingFromLine
|
||||
addLine(line)
|
||||
}
|
||||
|
||||
// if there were no lines processed or the last line has a break after
|
||||
// it, add a blank line at the end
|
||||
needBlankLine :=
|
||||
len(setter.lines) == 0 ||
|
||||
setter.lines[len(setter.lines) - 1].BreakAfter
|
||||
if needBlankLine { addLine(LineLayout { }) }
|
||||
|
||||
// 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 {
|
||||
@@ -90,8 +99,11 @@ func (setter *TypeSetter) needAlignedLayout () {
|
||||
|
||||
for index := range setter.lines {
|
||||
align := setter.align
|
||||
if index == len(setter.lines) - 1 && align == AlignJustify {
|
||||
align = AlignLeft
|
||||
if align == AlignJustify {
|
||||
except :=
|
||||
index == len(setter.lines) - 1 ||
|
||||
setter.lines[index].BreakAfter
|
||||
if except { align = AlignLeft }
|
||||
}
|
||||
setter.lines[index].Align(align)
|
||||
}
|
||||
@@ -105,10 +117,10 @@ func (setter *TypeSetter) SetWrap (wrap bool) {
|
||||
}
|
||||
|
||||
// SetAlign sets the alignment method of the typesetter.
|
||||
func (setter *TypeSetter) SetAlign (align Align) {
|
||||
if setter.align == align { return }
|
||||
func (setter *TypeSetter) SetAlign (horizontal, vertical Align) {
|
||||
if setter.align == horizontal { return }
|
||||
setter.alignClean = false
|
||||
setter.align = align
|
||||
setter.align = horizontal
|
||||
}
|
||||
|
||||
// SetText sets the text content of the typesetter.
|
||||
@@ -126,18 +138,19 @@ func (setter *TypeSetter) SetFace (face font.Face) {
|
||||
setter.face = face
|
||||
}
|
||||
|
||||
// SetMaxWidth sets the maximum width of the typesetter.
|
||||
func (setter *TypeSetter) SetMaxWidth (width int) {
|
||||
// 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 }
|
||||
setter.layoutClean = false
|
||||
setter.alignClean = false
|
||||
setter.maxWidth = width
|
||||
}
|
||||
|
||||
// SetMaxHeight sets the maximum height of the typesetter. If the maximum height
|
||||
// is greater than zero, no lines will be laid out past that point. If the
|
||||
// maximum height is zero, the text's maximum height will not be constrained.
|
||||
func (setter *TypeSetter) SetMaxHeight (heignt int) {
|
||||
// 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 }
|
||||
setter.layoutClean = false
|
||||
setter.alignClean = false
|
||||
@@ -158,14 +171,13 @@ func (setter *TypeSetter) LineHeight () fixed.Int26_6 {
|
||||
return setter.face.Metrics().Height
|
||||
}
|
||||
|
||||
// MaxWidth returns the maximum width of the typesetter as set by SetMaxWidth.
|
||||
func (setter *TypeSetter) MaxWidth () int {
|
||||
// Width returns the height of the typesetter as set by SetWidth.
|
||||
func (setter *TypeSetter) Width () int {
|
||||
return setter.maxWidth
|
||||
}
|
||||
|
||||
// MaxHeight returns the maximum height of the typesetter as set by
|
||||
// SetMaxHeight.
|
||||
func (setter *TypeSetter) MaxHeight () int {
|
||||
// Height returns the height of the typesetter as set by SetHeight.
|
||||
func (setter *TypeSetter) Height () int {
|
||||
return setter.maxHeight
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user