typeset/draw.go

87 lines
2.6 KiB
Go

package typeset
import "image"
import "unicode"
import "image/draw"
import "image/color"
import "golang.org/x/image/font"
import "golang.org/x/image/math/fixed"
import "git.tebibyte.media/tomo/typeset/internal"
// Draw draws the contents of a TypeSetter to an image at the given offset. It
// returns a rectangle containing all pixels in the image that were updated.
func Draw (destination draw.Image, setter *TypeSetter, offset fixed.Point26_6, col color.Color) image.Rectangle {
source := image.NewUniform(col)
face := setter.Face()
var updatedRegion image.Rectangle
bounds := destination.Bounds()
setter.Runes()(func (position fixed.Point26_6, run rune) bool {
// leave empty space for space characters
if unicode.IsSpace(run) {
return true
}
dot := offset.Add(position)
destinationRectangle, mask, maskPoint, _, ok := face.Glyph(dot, run)
if ok {
// don't bother drawing runes that are out of bounds
if destinationRectangle.Min.Y > bounds.Max.Y { return false }
if destinationRectangle.Intersect(bounds).Empty() { return true }
// draw rune
draw.DrawMask (
destination,
destinationRectangle,
source, image.Point { },
mask, maskPoint,
draw.Over)
} else {
// draw tofu
drawTofu(run, destination, dot, face, col)
}
updatedRegion = updatedRegion.Union(destinationRectangle)
return true
})
return updatedRegion
}
// DrawBounds draws the LayoutBounds, MinimumSize, and LayoutBoundsSpace of a
// TypeSetter to the given image using these colors:
// - Red: LayoutBounds
// - Green: MinimumSize
// - Blue: LayoutBoundsSpace
func DrawBounds (destination draw.Image, setter *TypeSetter, offset fixed.Point26_6) {
blue := color.RGBA { B: 255, A: 255 }
red := color.RGBA { R: 255, A: 255 }
green := color.RGBA { G: 255, A: 255 }
layoutBoundsSpace := setter.LayoutBoundsSpace()
layoutBounds := setter.LayoutBounds()
minimum := setter.MinimumSize()
minimumRect := internal.RoundRect(fixed.Rectangle26_6 { Max: minimum }.Add(offset).Add(layoutBounds.Min))
internal.DrawRectangleOutline(destination, minimumRect, green)
internal.DrawRectangleOutline(destination, internal.RoundRect(layoutBoundsSpace.Add(offset)), blue)
internal.DrawRectangleOutline(destination, internal.RoundRect(layoutBounds.Add(offset)), red)
}
func drawTofu (
char rune,
destination draw.Image,
position fixed.Point26_6,
face font.Face,
col color.Color,
) {
bounds, _ := tofuBounds(face)
rectBounds := internal.RoundRect(bounds).Add(image.Pt (
position.X.Round(),
position.Y.Round()))
internal.DrawRectangleOutline(destination, rectBounds, col)
}