Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c4dce027ef | |||
| ee345c10ef | |||
| 6407baed13 |
11
layout.go
11
layout.go
@@ -155,6 +155,17 @@ func DoLine (text []rune, face font.Face, wrap bool, maxWidth fixed.Int26_6) (li
|
||||
return
|
||||
}
|
||||
|
||||
// Length returns the amount of runes within the line, including the trailing
|
||||
// line break if it exists.
|
||||
func (line *LineLayout) Length () int {
|
||||
lineSize := 0
|
||||
for _, word := range line.Words {
|
||||
lineSize += len(word.Runes)
|
||||
}
|
||||
if line.BreakAfter { lineSize ++ }
|
||||
return lineSize
|
||||
}
|
||||
|
||||
// Align aligns the text in the line according to the specified alignment
|
||||
// method.
|
||||
func (line *LineLayout) Align (align Align) {
|
||||
|
||||
67
setter.go
67
setter.go
@@ -30,28 +30,19 @@ func (setter *TypeSetter) needLayout () {
|
||||
setter.layoutClean = true
|
||||
setter.alignClean = false
|
||||
|
||||
// we need to have a font and some text to do anything
|
||||
setter.lines = nil
|
||||
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 {
|
||||
@@ -63,8 +54,25 @@ func (setter *TypeSetter) needLayout () {
|
||||
}
|
||||
setter.lines = append(setter.lines, line)
|
||||
}
|
||||
setter.minWidth = horizontalExtentSpace
|
||||
|
||||
// process every line
|
||||
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 = setter.maxWidth
|
||||
setter.layoutBoundsSpace.Max.X = setter.maxWidth
|
||||
|
||||
@@ -91,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)
|
||||
}
|
||||
@@ -238,27 +249,21 @@ func (setter *TypeSetter) AtPosition (position fixed.Point26_6) (index int) {
|
||||
// find the first line who's bottom bound is greater than position.Y. if
|
||||
// we haven't found it, then dont set the line variable (defaults to the
|
||||
// last line)
|
||||
metrics := setter.face.Metrics()
|
||||
line := setter.lines[len(setter.lines) - 1]
|
||||
lineSize := 0
|
||||
for _, curLine := range setter.lines {
|
||||
for _, curWord := range curLine.Words {
|
||||
lineSize += len(curWord.Runes)
|
||||
}
|
||||
if curLine.BreakAfter { lineSize ++ }
|
||||
index += lineSize
|
||||
|
||||
metrics := setter.face.Metrics()
|
||||
lastLine := setter.lines[len(setter.lines) - 1]
|
||||
for _, curLine := range setter.lines {
|
||||
if curLine.Y + metrics.Descent > position.Y {
|
||||
line = curLine
|
||||
lastLine = curLine
|
||||
break
|
||||
}
|
||||
|
||||
index += curLine.Length()
|
||||
}
|
||||
index -= lineSize
|
||||
|
||||
if line.Words == nil { return }
|
||||
if lastLine.Words == nil { return }
|
||||
|
||||
// find the first rune who's right bound is greater than position.X.
|
||||
for _, curWord := range line.Words {
|
||||
for _, curWord := range lastLine.Words {
|
||||
for _, curChar := range curWord.Runes {
|
||||
x := curWord.X + curChar.X + curChar.Width
|
||||
if x > position.X { goto foundRune }
|
||||
|
||||
Reference in New Issue
Block a user