package tins2020 import ( "strings" ) type Label struct { ControlBase Text string Alignment TextAlignment } func (l *Label) Render(ctx *Context) { font := ctx.Fonts.Font(l.ActualFontName()) color := l.ActualForeground() bottom := l.Bounds.Y + l.Bounds.H switch l.Alignment { case TextAlignmentCenter: font.RenderCopyAlign(ctx.Renderer, l.Text, Pt(l.Bounds.X+l.Bounds.W/2, bottom), color, TextAlignmentCenter) case TextAlignmentLeft: font.RenderCopyAlign(ctx.Renderer, l.Text, Pt(l.Bounds.X, bottom), color, TextAlignmentLeft) case TextAlignmentRight: font.RenderCopyAlign(ctx.Renderer, l.Text, Pt(l.Bounds.X+l.Bounds.W, bottom), color, TextAlignmentRight) } } type Paragraph struct { Label } func (p *Paragraph) Render(ctx *Context) { font := ctx.Fonts.Font(p.ActualFontName()) color := p.ActualForeground() fontHeight := int32(font.Height()) lines := strings.Split(p.Text, "\n") measure := func(s string) int32 { w, _, _ := font.SizeUTF8(s) return int32(w) } spaces := func(s string) []int { var spaces []int offset := 0 for { space := strings.Index(s[offset:], " ") if space == -1 { return spaces } offset += space spaces = append(spaces, offset) offset++ } } fit := func(s string) string { if measure(s) < p.Bounds.W { return s } spaces := spaces(s) for split := len(spaces) - 1; split >= 0; split-- { clipped := s[:spaces[split]] if measure(clipped) < p.Bounds.W { return clipped } } return s } offset := p.Bounds.Y for _, line := range lines { if len(line) == 0 { offset += fontHeight continue } for len(line) > 0 { offset += fontHeight clipped := fit(line) line = strings.TrimLeft(line[len(clipped):], " ") font.RenderCopy(ctx.Renderer, clipped, Pt(p.Bounds.X, offset), color) } } }