Add drawing functions
This commit is contained in:
parent
5dee53b8a9
commit
0cb6e28542
103
draw.go
Normal file
103
draw.go
Normal file
@ -0,0 +1,103 @@
|
||||
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"
|
||||
|
||||
// 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.
|
||||
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 := roundRect(fixed.Rectangle26_6 { Max: minimum }.Add(offset).Add(layoutBounds.Min))
|
||||
drawRectangleOutline(destination, minimumRect, green)
|
||||
|
||||
drawRectangleOutline(destination, roundRect(layoutBoundsSpace.Add(offset)), blue)
|
||||
drawRectangleOutline(destination, 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 := roundRect(bounds).Add(image.Pt (
|
||||
position.X.Round(),
|
||||
position.Y.Round()))
|
||||
drawRectangleOutline(destination, rectBounds, col)
|
||||
}
|
||||
|
||||
func drawRectangleOutline (destination draw.Image, bounds image.Rectangle, col color.Color) {
|
||||
for x := bounds.Min.X; x < bounds.Max.X; x ++ {
|
||||
destination.Set(x, bounds.Min.Y, col)
|
||||
}
|
||||
for y := bounds.Min.Y; y < bounds.Max.Y; y ++ {
|
||||
destination.Set(bounds.Min.X, y, col)
|
||||
destination.Set(bounds.Max.X - 1, y, col)
|
||||
}
|
||||
for x := bounds.Min.X; x < bounds.Max.X; x ++ {
|
||||
destination.Set(x, bounds.Max.Y - 1, col)
|
||||
}
|
||||
}
|
||||
|
||||
func roundRect (rectangle fixed.Rectangle26_6) image.Rectangle {
|
||||
return image.Rect (
|
||||
rectangle.Min.X.Round(),
|
||||
rectangle.Min.Y.Round(),
|
||||
rectangle.Max.X.Round(),
|
||||
rectangle.Max.Y.Round())
|
||||
}
|
Loading…
Reference in New Issue
Block a user