mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 10:48:53 +01:00
parent
41877bba0b
commit
710f56531f
@ -56,7 +56,6 @@ func drawDebugText(rt *ebiten.Image, str string, ox, oy int, shadow bool) {
|
||||
x := 0
|
||||
y := 0
|
||||
w, _ := debugPrintTextImage.Size()
|
||||
var r image.Rectangle
|
||||
for _, c := range str {
|
||||
const (
|
||||
cw = assets.CharWidth
|
||||
@ -70,15 +69,10 @@ func drawDebugText(rt *ebiten.Image, str string, ox, oy int, shadow bool) {
|
||||
n := w / cw
|
||||
sx := (int(c) % n) * cw
|
||||
sy := (int(c) / n) * ch
|
||||
r.Min.X = sx
|
||||
r.Min.Y = sy
|
||||
r.Max.X = sx + cw
|
||||
r.Max.Y = sy + ch
|
||||
op.SourceRect = &r
|
||||
op.GeoM.Reset()
|
||||
op.GeoM.Translate(float64(x), float64(y))
|
||||
op.GeoM.Translate(float64(ox+1), float64(oy))
|
||||
_ = rt.DrawImage(debugPrintTextImage, op)
|
||||
_ = rt.DrawImage(debugPrintTextImage.SubImage(image.Rect(sx, sy, sx+cw, sy+ch)).(*ebiten.Image), op)
|
||||
x += cw
|
||||
}
|
||||
}
|
||||
|
@ -218,9 +218,7 @@ func drawGroundImage(screen *ebiten.Image, ground *ebiten.Image) {
|
||||
op.GeoM.Scale(1/z, 8) // 8 is an arbitrary number not to make empty lines.
|
||||
op.GeoM.Translate(float64(pw)/2, float64(j)/z)
|
||||
|
||||
src := image.Rect(0, j, gw, j+1)
|
||||
op.SourceRect = &src
|
||||
perspectiveGroundImage.DrawImage(ground, op)
|
||||
perspectiveGroundImage.DrawImage(ground.SubImage(image.Rect(0, j, gw, j+1)).(*ebiten.Image), op)
|
||||
}
|
||||
|
||||
perspectiveGroundImage.DrawImage(fogImage, nil)
|
||||
|
@ -54,9 +54,7 @@ func update(screen *ebiten.Image) error {
|
||||
op.GeoM.Translate(screenWidth/2, screenHeight/2)
|
||||
i := (count / 5) % frameNum
|
||||
sx, sy := frameOX+i*frameWidth, frameOY
|
||||
r := image.Rect(sx, sy, sx+frameWidth, sy+frameHeight)
|
||||
op.SourceRect = &r
|
||||
screen.DrawImage(runnerImage, op)
|
||||
screen.DrawImage(runnerImage.SubImage(image.Rect(sx, sy, sx+frameWidth, sy+frameHeight)).(*ebiten.Image), op)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -175,9 +175,7 @@ func drawBlock(r *ebiten.Image, block BlockType, x, y int, clr ebiten.ColorM) {
|
||||
op.GeoM.Translate(float64(x), float64(y))
|
||||
|
||||
srcX := (int(block) - 1) * blockWidth
|
||||
src := image.Rect(srcX, 0, srcX+blockWidth, blockHeight)
|
||||
op.SourceRect = &src
|
||||
r.DrawImage(imageBlocks, op)
|
||||
r.DrawImage(imageBlocks.SubImage(image.Rect(srcX, 0, srcX+blockWidth, blockHeight)).(*ebiten.Image), op)
|
||||
}
|
||||
|
||||
func (p *Piece) InitialPosition() (int, int) {
|
||||
|
@ -345,9 +345,7 @@ func (g *Game) drawTiles(screen *ebiten.Image) {
|
||||
op.GeoM.Reset()
|
||||
op.GeoM.Translate(float64(i*tileSize-floorMod(g.cameraX, tileSize)),
|
||||
float64((ny-1)*tileSize-floorMod(g.cameraY, tileSize)))
|
||||
r := image.Rect(0, 0, tileSize, tileSize)
|
||||
op.SourceRect = &r
|
||||
screen.DrawImage(tilesImage, op)
|
||||
screen.DrawImage(tilesImage.SubImage(image.Rect(0, 0, tileSize, tileSize)).(*ebiten.Image), op)
|
||||
|
||||
// pipe
|
||||
if tileY, ok := g.pipeAt(floorDiv(g.cameraX, tileSize) + i); ok {
|
||||
@ -357,27 +355,25 @@ func (g *Game) drawTiles(screen *ebiten.Image) {
|
||||
op.GeoM.Translate(float64(i*tileSize-floorMod(g.cameraX, tileSize)),
|
||||
float64(j*tileSize-floorMod(g.cameraY, tileSize)))
|
||||
op.GeoM.Translate(0, tileSize)
|
||||
var r image.Rectangle
|
||||
if j == tileY-1 {
|
||||
r := image.Rect(pipeTileSrcX, pipeTileSrcY, pipeTileSrcX+tileSize*2, pipeTileSrcY+tileSize)
|
||||
op.SourceRect = &r
|
||||
r = image.Rect(pipeTileSrcX, pipeTileSrcY, pipeTileSrcX+tileSize*2, pipeTileSrcY+tileSize)
|
||||
} else {
|
||||
r := image.Rect(pipeTileSrcX, pipeTileSrcY+tileSize, pipeTileSrcX+tileSize*2, pipeTileSrcY+tileSize*2)
|
||||
op.SourceRect = &r
|
||||
r = image.Rect(pipeTileSrcX, pipeTileSrcY+tileSize, pipeTileSrcX+tileSize*2, pipeTileSrcY+tileSize*2)
|
||||
}
|
||||
screen.DrawImage(tilesImage, op)
|
||||
screen.DrawImage(tilesImage.SubImage(r).(*ebiten.Image), op)
|
||||
}
|
||||
for j := tileY + pipeGapY; j < screenHeight/tileSize-1; j++ {
|
||||
op.GeoM.Reset()
|
||||
op.GeoM.Translate(float64(i*tileSize-floorMod(g.cameraX, tileSize)),
|
||||
float64(j*tileSize-floorMod(g.cameraY, tileSize)))
|
||||
var r image.Rectangle
|
||||
if j == tileY+pipeGapY {
|
||||
r := image.Rect(pipeTileSrcX, pipeTileSrcY, pipeTileSrcX+pipeWidth, pipeTileSrcY+tileSize)
|
||||
op.SourceRect = &r
|
||||
r = image.Rect(pipeTileSrcX, pipeTileSrcY, pipeTileSrcX+pipeWidth, pipeTileSrcY+tileSize)
|
||||
} else {
|
||||
r := image.Rect(pipeTileSrcX, pipeTileSrcY+tileSize, pipeTileSrcX+pipeWidth, pipeTileSrcY+tileSize+tileSize)
|
||||
op.SourceRect = &r
|
||||
r = image.Rect(pipeTileSrcX, pipeTileSrcY+tileSize, pipeTileSrcX+pipeWidth, pipeTileSrcY+tileSize+tileSize)
|
||||
}
|
||||
screen.DrawImage(tilesImage, op)
|
||||
screen.DrawImage(tilesImage.SubImage(r).(*ebiten.Image), op)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,8 +78,7 @@ func update(screen *ebiten.Image) error {
|
||||
}
|
||||
op.GeoM.Translate(float64(r.Min.X), float64(r.Min.Y))
|
||||
op.GeoM.Translate(offsetX, offsetY)
|
||||
op.SourceRect = &r
|
||||
screen.DrawImage(keyboardImage, op)
|
||||
screen.DrawImage(keyboardImage.SubImage(r).(*ebiten.Image), op)
|
||||
}
|
||||
|
||||
keyStrs := []string{}
|
||||
|
@ -69,6 +69,7 @@ Press C to clip the images.
|
||||
Scale: %0.2f`, s)
|
||||
ebitenutil.DebugPrint(screen, msg)
|
||||
|
||||
clippedGophersImage := gophersImage.SubImage(image.Rect(10, 10, 100, 100)).(*ebiten.Image)
|
||||
for i, f := range []ebiten.Filter{ebiten.FilterNearest, ebiten.FilterLinear} {
|
||||
w, h := gophersImage.Size()
|
||||
|
||||
@ -82,10 +83,10 @@ Scale: %0.2f`, s)
|
||||
op.GeoM.Translate(32+float64(i*w)*s+float64(i*4), 64)
|
||||
op.Filter = f
|
||||
if clip {
|
||||
r := image.Rect(10, 10, 100, 100)
|
||||
op.SourceRect = &r
|
||||
screen.DrawImage(clippedGophersImage, op)
|
||||
} else {
|
||||
screen.DrawImage(gophersImage, op)
|
||||
}
|
||||
screen.DrawImage(gophersImage, op)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -58,9 +58,7 @@ func update(screen *ebiten.Image) error {
|
||||
// Move the image's center to the screen's center.
|
||||
op.GeoM.Translate(screenWidth/2, screenHeight/2)
|
||||
|
||||
r := image.Rect(0, i, w, i+1)
|
||||
op.SourceRect = &r
|
||||
screen.DrawImage(gophersImage, op)
|
||||
screen.DrawImage(gophersImage.SubImage(image.Rect(0, i, w, i+1)).(*ebiten.Image), op)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -119,9 +119,7 @@ func update(screen *ebiten.Image) error {
|
||||
|
||||
sx := (t % tileXNum) * tileSize
|
||||
sy := (t / tileXNum) * tileSize
|
||||
r := image.Rect(sx, sy, sx+tileSize, sy+tileSize)
|
||||
op.SourceRect = &r
|
||||
screen.DrawImage(tilesImage, op)
|
||||
screen.DrawImage(tilesImage.SubImage(image.Rect(sx, sy, sx+tileSize, sy+tileSize)).(*ebiten.Image), op)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,9 +154,7 @@ func drawNinePatches(dst *ebiten.Image, dstRect image.Rectangle, srcRect image.R
|
||||
op.GeoM.Scale(float64(dw)/float64(sw), float64(dh)/float64(sh))
|
||||
op.GeoM.Translate(float64(dx), float64(dy))
|
||||
op.GeoM.Translate(float64(dstX), float64(dstY))
|
||||
r := image.Rect(sx, sy, sx+sw, sy+sh)
|
||||
op.SourceRect = &r
|
||||
dst.DrawImage(uiImage, op)
|
||||
dst.DrawImage(uiImage.SubImage(image.Rect(sx, sy, sx+sw, sy+sh)).(*ebiten.Image), op)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
128
image.go
128
image.go
@ -141,6 +141,9 @@ type Image struct {
|
||||
// The level 0 image is a regular image and higher-level images are used for mipmap.
|
||||
mipmap *mipmap
|
||||
|
||||
bounds *image.Rectangle
|
||||
original *Image
|
||||
|
||||
filter Filter
|
||||
}
|
||||
|
||||
@ -159,6 +162,10 @@ func (i *Image) isDisposed() bool {
|
||||
return i.mipmap.isDisposed()
|
||||
}
|
||||
|
||||
func (i *Image) isSubimage() bool {
|
||||
return i.bounds != nil
|
||||
}
|
||||
|
||||
// Clear resets the pixels of the image into 0.
|
||||
//
|
||||
// When the image is disposed, Clear does nothing.
|
||||
@ -169,6 +176,12 @@ func (i *Image) Clear() error {
|
||||
if i.isDisposed() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: Implement this.
|
||||
if i.isSubimage() {
|
||||
panic("render to a subimage is not implemented")
|
||||
}
|
||||
|
||||
i.fill(0, 0, 0, 0)
|
||||
return nil
|
||||
}
|
||||
@ -183,6 +196,12 @@ func (i *Image) Fill(clr color.Color) error {
|
||||
if i.isDisposed() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: Implement this.
|
||||
if i.isSubimage() {
|
||||
panic("render to a subimage is not implemented")
|
||||
}
|
||||
|
||||
r, g, b, a := clr.RGBA()
|
||||
i.fill(uint8(r>>8), uint8(g>>8), uint8(b>>8), uint8(a>>8))
|
||||
return nil
|
||||
@ -278,6 +297,11 @@ func (i *Image) drawImage(img *Image, options *DrawImageOptions) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Implement this.
|
||||
if i.isSubimage() {
|
||||
panic("render to a subimage is not implemented")
|
||||
}
|
||||
|
||||
// Calculate vertices before locking because the user can do anything in
|
||||
// options.ImageParts interface without deadlock (e.g. Call Image functions).
|
||||
if options == nil {
|
||||
@ -300,21 +324,32 @@ func (i *Image) drawImage(img *Image, options *DrawImageOptions) {
|
||||
ColorM: options.ColorM,
|
||||
CompositeMode: options.CompositeMode,
|
||||
}
|
||||
r := image.Rect(sx0, sy0, sx1, sy1)
|
||||
op.SourceRect = &r
|
||||
op.GeoM.Scale(
|
||||
float64(dx1-dx0)/float64(sx1-sx0),
|
||||
float64(dy1-dy0)/float64(sy1-sy0))
|
||||
op.GeoM.Translate(float64(dx0), float64(dy0))
|
||||
op.GeoM.Concat(options.GeoM)
|
||||
i.DrawImage(img, op)
|
||||
i.DrawImage(img.SubImage(image.Rect(sx0, sy0, sx1, sy1)).(*Image), op)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
w, h := img.Size()
|
||||
sx0, sy0, sx1, sy1 := 0, 0, w, h
|
||||
if r := options.SourceRect; r != nil {
|
||||
|
||||
// SourceRect is deprecated. This implementation is for backward compatibility.
|
||||
if img.bounds != nil || options.SourceRect != nil {
|
||||
r := img.bounds
|
||||
if r == nil {
|
||||
r = options.SourceRect
|
||||
} else if options.SourceRect != nil {
|
||||
r2 := r.Intersect(*options.SourceRect)
|
||||
r = &r2
|
||||
}
|
||||
if r.Empty() {
|
||||
return
|
||||
}
|
||||
|
||||
sx0 = r.Min.X
|
||||
sy0 = r.Min.Y
|
||||
if sx1 > r.Max.X {
|
||||
@ -324,6 +359,7 @@ func (i *Image) drawImage(img *Image, options *DrawImageOptions) {
|
||||
sy1 = r.Max.Y
|
||||
}
|
||||
}
|
||||
|
||||
geom := &options.GeoM
|
||||
if sx0 < 0 || sy0 < 0 {
|
||||
dx := 0.0
|
||||
@ -460,6 +496,11 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Implement this.
|
||||
if i.isSubimage() {
|
||||
panic("render to a subimage is not implemented")
|
||||
}
|
||||
|
||||
if len(indices)%3 != 0 {
|
||||
panic("ebiten: len(indices) % 3 must be 0")
|
||||
}
|
||||
@ -487,10 +528,51 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
||||
i.disposeMipmaps()
|
||||
}
|
||||
|
||||
// SubImage returns an image representing the portion of the image p visible through r. The returned value shares pixels with the original image.
|
||||
//
|
||||
// The returned value is always *ebiten.Image.
|
||||
//
|
||||
// If the image is disposed, SubImage returns nil.
|
||||
//
|
||||
// In the current Ebiten implementation, SubImage is available only as a rendering source.
|
||||
func (i *Image) SubImage(r image.Rectangle) image.Image {
|
||||
i.copyCheck()
|
||||
if i.isDisposed() {
|
||||
return nil
|
||||
}
|
||||
|
||||
img := &Image{
|
||||
mipmap: i.mipmap,
|
||||
filter: i.filter,
|
||||
}
|
||||
|
||||
// Keep the original image's reference not to dispose that by GC.
|
||||
if i.isSubimage() {
|
||||
img.original = i.original
|
||||
} else {
|
||||
img.original = i
|
||||
}
|
||||
|
||||
img.addr = img
|
||||
runtime.SetFinalizer(img, (*Image).Dispose)
|
||||
|
||||
r = r.Intersect(img.Bounds())
|
||||
// Need to check Empty explicitly. See the standard image package implementations.
|
||||
if r.Empty() {
|
||||
img.bounds = &image.ZR
|
||||
} else {
|
||||
img.bounds = &r
|
||||
}
|
||||
return img
|
||||
}
|
||||
|
||||
// Bounds returns the bounds of the image.
|
||||
func (i *Image) Bounds() image.Rectangle {
|
||||
w, h := i.Size()
|
||||
return image.Rect(0, 0, w, h)
|
||||
if i.bounds == nil {
|
||||
w, h := i.Size()
|
||||
return image.Rect(0, 0, w, h)
|
||||
}
|
||||
return *i.bounds
|
||||
}
|
||||
|
||||
// ColorModel returns the color model of the image.
|
||||
@ -512,6 +594,9 @@ func (i *Image) At(x, y int) color.Color {
|
||||
if i.isDisposed() {
|
||||
return color.RGBA{}
|
||||
}
|
||||
if i.bounds != nil && !image.Pt(x, y).In(*i.bounds) {
|
||||
return color.RGBA{}
|
||||
}
|
||||
return i.mipmap.original().At(x, y)
|
||||
}
|
||||
|
||||
@ -527,7 +612,9 @@ func (i *Image) Dispose() error {
|
||||
if i.isDisposed() {
|
||||
return nil
|
||||
}
|
||||
i.mipmap.dispose()
|
||||
if !i.isSubimage() {
|
||||
i.mipmap.dispose()
|
||||
}
|
||||
runtime.SetFinalizer(i, nil)
|
||||
return nil
|
||||
}
|
||||
@ -548,6 +635,10 @@ func (i *Image) ReplacePixels(p []byte) error {
|
||||
if i.isDisposed() {
|
||||
return nil
|
||||
}
|
||||
// TODO: Implement this.
|
||||
if i.isSubimage() {
|
||||
panic("render to a subimage is not implemented")
|
||||
}
|
||||
i.mipmap.original().ReplacePixels(p)
|
||||
i.disposeMipmaps()
|
||||
return nil
|
||||
@ -555,22 +646,6 @@ func (i *Image) ReplacePixels(p []byte) error {
|
||||
|
||||
// A DrawImageOptions represents options to render an image on an image.
|
||||
type DrawImageOptions struct {
|
||||
// SourceRect is the region of the source image to draw.
|
||||
// If SourceRect is nil, whole image is used.
|
||||
//
|
||||
// It is assured that texels out of the SourceRect are never used.
|
||||
//
|
||||
// Calling DrawImage copies the content of SourceRect pointer. This means that
|
||||
// even if the SourceRect value is modified after passed to DrawImage,
|
||||
// the result of DrawImage doen't change.
|
||||
//
|
||||
// op := &ebiten.DrawImageOptions{}
|
||||
// r := image.Rect(0, 0, 100, 100)
|
||||
// op.SourceRect = &r
|
||||
// dst.DrawImage(src, op)
|
||||
// r.Min.X = 10 // This doesn't affect the previous DrawImage.
|
||||
SourceRect *image.Rectangle
|
||||
|
||||
// GeoM is a geometry matrix to draw.
|
||||
// The default (zero) value is identify, which draws the image at (0, 0).
|
||||
GeoM GeoM
|
||||
@ -595,11 +670,14 @@ type DrawImageOptions struct {
|
||||
// Otherwise, Filter specified at DrawImageOptions is used.
|
||||
Filter Filter
|
||||
|
||||
// Deprecated (as of 1.5.0-alpha): Use SourceRect instead.
|
||||
// Deprecated (as of 1.5.0-alpha): Use SubImage instead.
|
||||
ImageParts ImageParts
|
||||
|
||||
// Deprecated (as of 1.1.0-alpha): Use SourceRect instead.
|
||||
// Deprecated (as of 1.1.0-alpha): Use SubImage instead.
|
||||
Parts []ImagePart
|
||||
|
||||
// Deprecated (as of 1.9.0-alpha): Use SubImage instead.
|
||||
SourceRect *image.Rectangle
|
||||
}
|
||||
|
||||
// NewImage returns an empty image.
|
||||
|
@ -555,21 +555,20 @@ func TestImageEdge(t *testing.T) {
|
||||
angles = append(angles, float64(a)/4096*2*math.Pi)
|
||||
}
|
||||
|
||||
img0Sub := img0.SubImage(image.Rect(img0OffsetWidth, img0InnerHeight, img0Width-img0OffsetWidth, img0Height-img0InnerHeight)).(*Image)
|
||||
|
||||
for _, s := range []float64{1, 0.5, 0.25} {
|
||||
for _, f := range []Filter{FilterNearest, FilterLinear} {
|
||||
for _, a := range angles {
|
||||
img1.Clear()
|
||||
op := &DrawImageOptions{}
|
||||
r := image.Rect(img0OffsetWidth, img0InnerHeight, img0Width-img0OffsetWidth, img0Height-img0InnerHeight)
|
||||
op.SourceRect = &r
|
||||
|
||||
w, h := img0.Size()
|
||||
op.GeoM.Translate(-float64(w)/2, -float64(h)/2)
|
||||
op.GeoM.Scale(s, s)
|
||||
op.GeoM.Rotate(a)
|
||||
op.GeoM.Translate(img1Width/2, img1Height/2)
|
||||
op.Filter = f
|
||||
img1.DrawImage(img0, op)
|
||||
img1.DrawImage(img0Sub, op)
|
||||
for j := 0; j < img1Height; j++ {
|
||||
for i := 0; i < img1Width; i++ {
|
||||
c := img1.At(i, j)
|
||||
@ -641,10 +640,8 @@ func TestImageLinear(t *testing.T) {
|
||||
op := &DrawImageOptions{}
|
||||
op.GeoM.Translate(8, 8)
|
||||
op.GeoM.Scale(2, 2)
|
||||
r := image.Rect(8, 8, 24, 24)
|
||||
op.SourceRect = &r
|
||||
op.Filter = FilterLinear
|
||||
dst.DrawImage(src, op)
|
||||
dst.DrawImage(src.SubImage(image.Rect(8, 8, 24, 24)).(*Image), op)
|
||||
|
||||
for j := 0; j < 64; j++ {
|
||||
for i := 0; i < 64; i++ {
|
||||
@ -683,11 +680,10 @@ func TestImageOutside(t *testing.T) {
|
||||
|
||||
op := &DrawImageOptions{}
|
||||
op.GeoM.Translate(0, 0)
|
||||
op.SourceRect = &image.Rectangle{
|
||||
dst.DrawImage(src.SubImage(image.Rectangle{
|
||||
Min: image.Pt(c.X, c.Y),
|
||||
Max: image.Pt(c.X+c.Width, c.Y+c.Height),
|
||||
}
|
||||
dst.DrawImage(src, op)
|
||||
}).(*Image), op)
|
||||
|
||||
for j := 0; j < 4; j++ {
|
||||
for i := 0; i < 4; i++ {
|
||||
@ -709,12 +705,12 @@ func TestImageOutsideUpperLeft(t *testing.T) {
|
||||
|
||||
op := &DrawImageOptions{}
|
||||
op.GeoM.Rotate(math.Pi / 4)
|
||||
r := image.Rect(-4, -4, 8, 8)
|
||||
op.SourceRect = &r
|
||||
dst1.DrawImage(src, op)
|
||||
dst1.DrawImage(src.SubImage(image.Rect(-4, -4, 8, 8)).(*Image), op)
|
||||
|
||||
op = &DrawImageOptions{}
|
||||
op.GeoM.Translate(4, 4)
|
||||
// The outside part of the source rect is just ignored.
|
||||
// This behavior was changed as of 1.9.0-alpha.
|
||||
// op.GeoM.Translate(4, 4)
|
||||
op.GeoM.Rotate(math.Pi / 4)
|
||||
dst2.DrawImage(src, op)
|
||||
|
||||
@ -829,9 +825,7 @@ func TestImageStretch(t *testing.T) {
|
||||
img1.Clear()
|
||||
op := &DrawImageOptions{}
|
||||
op.GeoM.Scale(1, float64(i)/16)
|
||||
r := image.Rect(0, 0, 16, 16)
|
||||
op.SourceRect = &r
|
||||
img1.DrawImage(img0, op)
|
||||
img1.DrawImage(img0.SubImage(image.Rect(0, 0, 16, 16)).(*Image), op)
|
||||
for j := -1; j <= 1; j++ {
|
||||
got := img1.At(0, i+j).(color.RGBA)
|
||||
want := color.RGBA{}
|
||||
@ -1023,3 +1017,20 @@ func TestImageMiamapAndDrawTriangle(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestImageSubImageAt(t *testing.T) {
|
||||
img, _ := NewImage(16, 16, FilterDefault)
|
||||
img.Fill(color.RGBA{0xff, 0, 0, 0xff})
|
||||
|
||||
got := img.SubImage(image.Rect(1, 1, 16, 16)).At(0, 0).(color.RGBA)
|
||||
want := color.RGBA{}
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
|
||||
got = img.SubImage(image.Rect(1, 1, 16, 16)).At(1, 1).(color.RGBA)
|
||||
want = color.RGBA{0xff, 0, 0, 0xff}
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -18,13 +18,13 @@ import (
|
||||
"image"
|
||||
)
|
||||
|
||||
// An ImagePart is deprecated (as of 1.1.0-alpha): Use SourceRect instead.
|
||||
// An ImagePart is deprecated (as of 1.1.0-alpha): Use SubImage instead.
|
||||
type ImagePart struct {
|
||||
Dst image.Rectangle
|
||||
Src image.Rectangle
|
||||
}
|
||||
|
||||
// An ImageParts is deprecated (as of 1.5.0-alpha): Use SourceRect instead.
|
||||
// An ImageParts is deprecated (as of 1.5.0-alpha): Use SubImage instead.
|
||||
type ImageParts interface {
|
||||
Len() int
|
||||
Dst(i int) (x0, y0, x1, y1 int)
|
||||
|
@ -61,12 +61,8 @@ func drawGlyph(dst *ebiten.Image, face font.Face, r rune, img *glyphImage, x, y
|
||||
b := getGlyphBounds(face, r)
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
op.GeoM.Translate(fixed26_6ToFloat64(x+b.Min.X), fixed26_6ToFloat64(y+b.Min.Y))
|
||||
|
||||
op.ColorM = clr
|
||||
re := image.Rect(img.x, img.y, img.x+img.width, img.y+img.height)
|
||||
op.SourceRect = &re
|
||||
|
||||
_ = dst.DrawImage(img.image, op)
|
||||
_ = dst.DrawImage(img.image.SubImage(image.Rect(img.x, img.y, img.x+img.width, img.y+img.height)).(*ebiten.Image), op)
|
||||
}
|
||||
|
||||
var (
|
||||
|
Loading…
Reference in New Issue
Block a user