don't draw text that is outside the screen bounds

This commit is contained in:
Thomas Friedel 2018-04-14 11:56:42 +02:00
parent 489a758c3c
commit 0913a92782
2 changed files with 52 additions and 22 deletions

View file

@ -202,6 +202,24 @@ func (c *frContext) glyphAdvance(glyph truetype.Index) (fixed.Int26_6, error) {
return c.glyphBuf.AdvanceWidth, nil
}
func (c *frContext) glyphBounds(glyph truetype.Index, p fixed.Point26_6) (image.Rectangle, error) {
if err := c.glyphBuf.Load(c.f, c.scale, glyph, c.hinting); err != nil {
return image.Rectangle{}, err
}
fx := p.X & 0x3f
fy := p.Y & 0x3f
xmin := int(fx+c.glyphBuf.Bounds.Min.X) >> 6
ymin := int(fy-c.glyphBuf.Bounds.Max.Y) >> 6
xmax := int(fx+c.glyphBuf.Bounds.Max.X+0x3f) >> 6
ymax := int(fy-c.glyphBuf.Bounds.Min.Y+0x3f) >> 6
bounds := image.Rectangle{
Min: image.Point{X: xmin, Y: ymin},
Max: image.Point{X: xmax, Y: ymax}}
return bounds, nil
}
const maxInt = int(^uint(0) >> 1)
// DrawString draws s at p and returns p advanced by the text extent. The text

24
text.go
View file

@ -2,6 +2,7 @@ package canvas
import (
"errors"
"image"
"io/ioutil"
"unsafe"
@ -90,23 +91,31 @@ func (cv *Canvas) FillText(str string, x, y float64) {
}
x += float64(kern) / 64
}
advance, mask, offset, err := frc.glyph(idx, fixed.Point26_6{})
bounds, err := frc.glyphBounds(idx, fixed.Point26_6{})
var advance fixed.Int26_6
p0 := cv.tf(vec{float64(bounds.Min.X) + x, float64(bounds.Min.Y) + y})
p1 := cv.tf(vec{float64(bounds.Min.X) + x, float64(bounds.Max.Y) + y})
p2 := cv.tf(vec{float64(bounds.Max.X) + x, float64(bounds.Max.Y) + y})
p3 := cv.tf(vec{float64(bounds.Max.X) + x, float64(bounds.Min.Y) + y})
inside := (p0[0] >= 0 || p1[0] >= 0 || p2[0] >= 0 || p3[0] >= 0) &&
(p0[1] >= 0 || p1[1] >= 0 || p2[1] >= 0 || p3[1] >= 0) &&
(p0[0] < cv.fw || p1[0] < cv.fw || p2[0] < cv.fw || p3[0] < cv.fw) &&
(p0[1] < cv.fh || p1[1] < cv.fh || p2[1] < cv.fh || p3[1] < cv.fh)
if inside {
var mask *image.Alpha
advance, mask, _, err = frc.glyph(idx, fixed.Point26_6{})
if err != nil {
prev = 0
hasPrev = false
continue
}
bounds := mask.Bounds().Add(offset)
for y, w, h := 0, bounds.Dx(), bounds.Dy(); y < h; y++ {
off := y * mask.Stride
gli.TexSubImage2D(gl_TEXTURE_2D, 0, 0, int32(alphaTexSize-1-y), int32(w), 1, gl_ALPHA, gl_UNSIGNED_BYTE, gli.Ptr(&mask.Pix[off]))
}
p0 := cv.tf(vec{float64(bounds.Min.X) + x, float64(bounds.Min.Y) + y})
p1 := cv.tf(vec{float64(bounds.Min.X) + x, float64(bounds.Max.Y) + y})
p2 := cv.tf(vec{float64(bounds.Max.X) + x, float64(bounds.Max.Y) + y})
p3 := cv.tf(vec{float64(bounds.Max.X) + x, float64(bounds.Min.Y) + y})
tw := float64(bounds.Dx()) / alphaTexSize
th := float64(bounds.Dy()) / alphaTexSize
data := [16]float32{float32(p0[0]), float32(p0[1]), float32(p1[0]), float32(p1[1]), float32(p2[0]), float32(p2[1]), float32(p3[0]), float32(p3[1]),
@ -120,6 +129,9 @@ func (cv *Canvas) FillText(str string, x, y float64) {
for y, w, h := 0, bounds.Dx(), bounds.Dy(); y < h; y++ {
gli.TexSubImage2D(gl_TEXTURE_2D, 0, 0, int32(alphaTexSize-1-y), int32(w), 1, gl_ALPHA, gl_UNSIGNED_BYTE, gli.Ptr(&zeroes[0]))
}
} else {
advance, _ = frc.glyphAdvance(idx)
}
x += float64(advance) / 64
}