don't draw text that is outside the screen bounds
This commit is contained in:
parent
489a758c3c
commit
0913a92782
2 changed files with 52 additions and 22 deletions
18
freetype.go
18
freetype.go
|
@ -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
24
text.go
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue