mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-27 11:12:44 +01:00
parent
59aa41a3c2
commit
656d9dccc0
@ -20,6 +20,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"image/color"
|
"image/color"
|
||||||
"log"
|
"log"
|
||||||
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -99,6 +100,14 @@ func (g *Game) Draw(screen *ebiten.Image) {
|
|||||||
ebitenutil.DrawRect(screen, float64(b.Min.X+x), float64(b.Min.Y+y), float64(b.Dx()), float64(b.Dy()), gray)
|
ebitenutil.DrawRect(screen, float64(b.Min.X+x), float64(b.Min.Y+y), float64(b.Dx()), float64(b.Dy()), gray)
|
||||||
text.Draw(screen, sampleText, mplusBigFont, x, y, color.White)
|
text.Draw(screen, sampleText, mplusBigFont, x, y, color.White)
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
const x, y = 20, 240
|
||||||
|
op := &ebiten.DrawImageOptions{}
|
||||||
|
op.GeoM.Rotate(math.Pi / 4)
|
||||||
|
op.GeoM.Translate(x, y)
|
||||||
|
op.Filter = ebiten.FilterLinear
|
||||||
|
text.DrawWithOptions(screen, sampleText, mplusNormalFont, op)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
|
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
|
||||||
|
77
text/text.go
77
text/text.go
@ -49,16 +49,20 @@ func fixed26_6ToFloat64(x fixed.Int26_6) float64 {
|
|||||||
return float64(x>>6) + float64(x&((1<<6)-1))/float64(1<<6)
|
return float64(x>>6) + float64(x&((1<<6)-1))/float64(1<<6)
|
||||||
}
|
}
|
||||||
|
|
||||||
func drawGlyph(dst *ebiten.Image, face font.Face, r rune, img *ebiten.Image, x, y fixed.Int26_6, clr ebiten.ColorM) {
|
func drawGlyph(dst *ebiten.Image, face font.Face, r rune, img *ebiten.Image, dx, dy fixed.Int26_6, op *ebiten.DrawImageOptions) {
|
||||||
if img == nil {
|
if img == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
b := getGlyphBounds(face, r)
|
b := getGlyphBounds(face, r)
|
||||||
op := &ebiten.DrawImageOptions{}
|
op2 := &ebiten.DrawImageOptions{}
|
||||||
op.GeoM.Translate(float64((x+b.Min.X)>>6), float64((y+b.Min.Y)>>6))
|
if op != nil {
|
||||||
op.ColorM = clr
|
*op2 = *op
|
||||||
dst.DrawImage(img, op)
|
}
|
||||||
|
op2.GeoM.Reset()
|
||||||
|
op2.GeoM.Translate(float64((dx+b.Min.X)>>6), float64((dy+b.Min.Y)>>6))
|
||||||
|
op2.GeoM.Concat(op.GeoM)
|
||||||
|
dst.DrawImage(img, op2)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -162,7 +166,7 @@ var textM sync.Mutex
|
|||||||
//
|
//
|
||||||
// It is OK to call Draw with a same text and a same face at every frame in terms of performance.
|
// It is OK to call Draw with a same text and a same face at every frame in terms of performance.
|
||||||
//
|
//
|
||||||
// Draw and CacheGlyphs are implemented like this:
|
// Draw/DrawWithOptions and CacheGlyphs are implemented like this:
|
||||||
//
|
//
|
||||||
// Draw = Create glyphs by `(*ebiten.Image).ReplacePixels` and put them into the cache if necessary
|
// Draw = Create glyphs by `(*ebiten.Image).ReplacePixels` and put them into the cache if necessary
|
||||||
// + Draw them onto the destination by `(*ebiten.Image).DrawImage`
|
// + Draw them onto the destination by `(*ebiten.Image).DrawImage`
|
||||||
@ -173,36 +177,73 @@ var textM sync.Mutex
|
|||||||
//
|
//
|
||||||
// Draw is concurrent-safe.
|
// Draw is concurrent-safe.
|
||||||
func Draw(dst *ebiten.Image, text string, face font.Face, x, y int, clr color.Color) {
|
func Draw(dst *ebiten.Image, text string, face font.Face, x, y int, clr color.Color) {
|
||||||
textM.Lock()
|
|
||||||
defer textM.Unlock()
|
|
||||||
|
|
||||||
cr, cg, cb, ca := clr.RGBA()
|
cr, cg, cb, ca := clr.RGBA()
|
||||||
if ca == 0 {
|
if ca == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var colorm ebiten.ColorM
|
op := &ebiten.DrawImageOptions{}
|
||||||
colorm.Scale(float64(cr)/float64(ca), float64(cg)/float64(ca), float64(cb)/float64(ca), float64(ca)/0xffff)
|
op.GeoM.Translate(float64(x), float64(y))
|
||||||
|
op.ColorM.Scale(float64(cr)/float64(ca), float64(cg)/float64(ca), float64(cb)/float64(ca), float64(ca)/0xffff)
|
||||||
|
DrawWithOptions(dst, text, face, op)
|
||||||
|
}
|
||||||
|
|
||||||
fx, fy := fixed.I(x), fixed.I(y)
|
// DrawWithOptions draws a given text on a given destination image dst.
|
||||||
|
//
|
||||||
|
// face is the font for text rendering.
|
||||||
|
// op is the options to draw glyph images.
|
||||||
|
// The origin point is a 'dot' (period) position.
|
||||||
|
// Be careful that the origin point is not left-upper corner position of dst.
|
||||||
|
// The default glyph color is while. op's ColorM adjusts the color.
|
||||||
|
//
|
||||||
|
// If you want to adjust the position of the text, these functions are useful:
|
||||||
|
//
|
||||||
|
// * text.BoundString: the rendered bounds of the given text.
|
||||||
|
// * golang.org/x/image/font.Face.Metrics: the metrics of the face.
|
||||||
|
//
|
||||||
|
// The '\n' newline character puts the following text on the next line.
|
||||||
|
// Line height is based on Metrics().Height of the font.
|
||||||
|
//
|
||||||
|
// Glyphs used for rendering are cached in least-recently-used way.
|
||||||
|
// Then old glyphs might be evicted from the cache.
|
||||||
|
// As the cache capacity has limit, it is not guaranteed that all the glyphs for runes given at DrawWithOptions are cached.
|
||||||
|
// The cache is shared with CacheGlyphs.
|
||||||
|
//
|
||||||
|
// It is OK to call Draw with a same text and a same face at every frame in terms of performance.
|
||||||
|
//
|
||||||
|
// Draw/DrawWithOptions and CacheGlyphs are implemented like this:
|
||||||
|
//
|
||||||
|
// Draw = Create glyphs by `(*ebiten.Image).ReplacePixels` and put them into the cache if necessary
|
||||||
|
// + Draw them onto the destination by `(*ebiten.Image).DrawImage`
|
||||||
|
// CacheGlyphs = Create glyphs by `(*ebiten.Image).ReplacePixels` and put them into the cache if necessary
|
||||||
|
//
|
||||||
|
// Be careful that the passed font face is held by this package and is never released.
|
||||||
|
// This is a known issue (#498).
|
||||||
|
//
|
||||||
|
// DrawWithOptions is concurrent-safe.
|
||||||
|
func DrawWithOptions(dst *ebiten.Image, text string, face font.Face, options *ebiten.DrawImageOptions) {
|
||||||
|
textM.Lock()
|
||||||
|
defer textM.Unlock()
|
||||||
|
|
||||||
|
var dx, dy fixed.Int26_6
|
||||||
prevR := rune(-1)
|
prevR := rune(-1)
|
||||||
|
|
||||||
faceHeight := face.Metrics().Height
|
faceHeight := face.Metrics().Height
|
||||||
|
|
||||||
for _, r := range text {
|
for _, r := range text {
|
||||||
if prevR >= 0 {
|
if prevR >= 0 {
|
||||||
fx += face.Kern(prevR, r)
|
dx += face.Kern(prevR, r)
|
||||||
}
|
}
|
||||||
if r == '\n' {
|
if r == '\n' {
|
||||||
fx = fixed.I(x)
|
dx = 0
|
||||||
fy += faceHeight
|
dy += faceHeight
|
||||||
prevR = rune(-1)
|
prevR = rune(-1)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
img := getGlyphImage(face, r)
|
img := getGlyphImage(face, r)
|
||||||
drawGlyph(dst, face, r, img, fx, fy, colorm)
|
drawGlyph(dst, face, r, img, dx, dy, options)
|
||||||
fx += glyphAdvance(face, r)
|
dx += glyphAdvance(face, r)
|
||||||
|
|
||||||
prevR = r
|
prevR = r
|
||||||
}
|
}
|
||||||
@ -287,7 +328,7 @@ func BoundString(face font.Face, text string) image.Rectangle {
|
|||||||
// As the cache capacity has limit, it is not guaranteed that all the glyphs for runes given at CacheGlyphs are cached.
|
// As the cache capacity has limit, it is not guaranteed that all the glyphs for runes given at CacheGlyphs are cached.
|
||||||
// The cache is shared with Draw.
|
// The cache is shared with Draw.
|
||||||
//
|
//
|
||||||
// Draw and CacheGlyphs are implemented like this:
|
// Draw/DrawWithOptions and CacheGlyphs are implemented like this:
|
||||||
//
|
//
|
||||||
// Draw = Create glyphs by `(*ebiten.Image).ReplacePixels` and put them into the cache if necessary
|
// Draw = Create glyphs by `(*ebiten.Image).ReplacePixels` and put them into the cache if necessary
|
||||||
// + Draw them onto the destination by `(*ebiten.Image).DrawImage`
|
// + Draw them onto the destination by `(*ebiten.Image).DrawImage`
|
||||||
|
Loading…
Reference in New Issue
Block a user