mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
parent
41877bba0b
commit
710f56531f
@ -56,7 +56,6 @@ func drawDebugText(rt *ebiten.Image, str string, ox, oy int, shadow bool) {
|
|||||||
x := 0
|
x := 0
|
||||||
y := 0
|
y := 0
|
||||||
w, _ := debugPrintTextImage.Size()
|
w, _ := debugPrintTextImage.Size()
|
||||||
var r image.Rectangle
|
|
||||||
for _, c := range str {
|
for _, c := range str {
|
||||||
const (
|
const (
|
||||||
cw = assets.CharWidth
|
cw = assets.CharWidth
|
||||||
@ -70,15 +69,10 @@ func drawDebugText(rt *ebiten.Image, str string, ox, oy int, shadow bool) {
|
|||||||
n := w / cw
|
n := w / cw
|
||||||
sx := (int(c) % n) * cw
|
sx := (int(c) % n) * cw
|
||||||
sy := (int(c) / n) * ch
|
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.Reset()
|
||||||
op.GeoM.Translate(float64(x), float64(y))
|
op.GeoM.Translate(float64(x), float64(y))
|
||||||
op.GeoM.Translate(float64(ox+1), float64(oy))
|
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
|
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.Scale(1/z, 8) // 8 is an arbitrary number not to make empty lines.
|
||||||
op.GeoM.Translate(float64(pw)/2, float64(j)/z)
|
op.GeoM.Translate(float64(pw)/2, float64(j)/z)
|
||||||
|
|
||||||
src := image.Rect(0, j, gw, j+1)
|
perspectiveGroundImage.DrawImage(ground.SubImage(image.Rect(0, j, gw, j+1)).(*ebiten.Image), op)
|
||||||
op.SourceRect = &src
|
|
||||||
perspectiveGroundImage.DrawImage(ground, op)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
perspectiveGroundImage.DrawImage(fogImage, nil)
|
perspectiveGroundImage.DrawImage(fogImage, nil)
|
||||||
|
@ -54,9 +54,7 @@ func update(screen *ebiten.Image) error {
|
|||||||
op.GeoM.Translate(screenWidth/2, screenHeight/2)
|
op.GeoM.Translate(screenWidth/2, screenHeight/2)
|
||||||
i := (count / 5) % frameNum
|
i := (count / 5) % frameNum
|
||||||
sx, sy := frameOX+i*frameWidth, frameOY
|
sx, sy := frameOX+i*frameWidth, frameOY
|
||||||
r := image.Rect(sx, sy, sx+frameWidth, sy+frameHeight)
|
screen.DrawImage(runnerImage.SubImage(image.Rect(sx, sy, sx+frameWidth, sy+frameHeight)).(*ebiten.Image), op)
|
||||||
op.SourceRect = &r
|
|
||||||
screen.DrawImage(runnerImage, op)
|
|
||||||
return nil
|
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))
|
op.GeoM.Translate(float64(x), float64(y))
|
||||||
|
|
||||||
srcX := (int(block) - 1) * blockWidth
|
srcX := (int(block) - 1) * blockWidth
|
||||||
src := image.Rect(srcX, 0, srcX+blockWidth, blockHeight)
|
r.DrawImage(imageBlocks.SubImage(image.Rect(srcX, 0, srcX+blockWidth, blockHeight)).(*ebiten.Image), op)
|
||||||
op.SourceRect = &src
|
|
||||||
r.DrawImage(imageBlocks, op)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Piece) InitialPosition() (int, int) {
|
func (p *Piece) InitialPosition() (int, int) {
|
||||||
|
@ -345,9 +345,7 @@ func (g *Game) drawTiles(screen *ebiten.Image) {
|
|||||||
op.GeoM.Reset()
|
op.GeoM.Reset()
|
||||||
op.GeoM.Translate(float64(i*tileSize-floorMod(g.cameraX, tileSize)),
|
op.GeoM.Translate(float64(i*tileSize-floorMod(g.cameraX, tileSize)),
|
||||||
float64((ny-1)*tileSize-floorMod(g.cameraY, tileSize)))
|
float64((ny-1)*tileSize-floorMod(g.cameraY, tileSize)))
|
||||||
r := image.Rect(0, 0, tileSize, tileSize)
|
screen.DrawImage(tilesImage.SubImage(image.Rect(0, 0, tileSize, tileSize)).(*ebiten.Image), op)
|
||||||
op.SourceRect = &r
|
|
||||||
screen.DrawImage(tilesImage, op)
|
|
||||||
|
|
||||||
// pipe
|
// pipe
|
||||||
if tileY, ok := g.pipeAt(floorDiv(g.cameraX, tileSize) + i); ok {
|
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)),
|
op.GeoM.Translate(float64(i*tileSize-floorMod(g.cameraX, tileSize)),
|
||||||
float64(j*tileSize-floorMod(g.cameraY, tileSize)))
|
float64(j*tileSize-floorMod(g.cameraY, tileSize)))
|
||||||
op.GeoM.Translate(0, tileSize)
|
op.GeoM.Translate(0, tileSize)
|
||||||
|
var r image.Rectangle
|
||||||
if j == tileY-1 {
|
if j == tileY-1 {
|
||||||
r := image.Rect(pipeTileSrcX, pipeTileSrcY, pipeTileSrcX+tileSize*2, pipeTileSrcY+tileSize)
|
r = image.Rect(pipeTileSrcX, pipeTileSrcY, pipeTileSrcX+tileSize*2, pipeTileSrcY+tileSize)
|
||||||
op.SourceRect = &r
|
|
||||||
} else {
|
} else {
|
||||||
r := image.Rect(pipeTileSrcX, pipeTileSrcY+tileSize, pipeTileSrcX+tileSize*2, pipeTileSrcY+tileSize*2)
|
r = image.Rect(pipeTileSrcX, pipeTileSrcY+tileSize, pipeTileSrcX+tileSize*2, pipeTileSrcY+tileSize*2)
|
||||||
op.SourceRect = &r
|
|
||||||
}
|
}
|
||||||
screen.DrawImage(tilesImage, op)
|
screen.DrawImage(tilesImage.SubImage(r).(*ebiten.Image), op)
|
||||||
}
|
}
|
||||||
for j := tileY + pipeGapY; j < screenHeight/tileSize-1; j++ {
|
for j := tileY + pipeGapY; j < screenHeight/tileSize-1; j++ {
|
||||||
op.GeoM.Reset()
|
op.GeoM.Reset()
|
||||||
op.GeoM.Translate(float64(i*tileSize-floorMod(g.cameraX, tileSize)),
|
op.GeoM.Translate(float64(i*tileSize-floorMod(g.cameraX, tileSize)),
|
||||||
float64(j*tileSize-floorMod(g.cameraY, tileSize)))
|
float64(j*tileSize-floorMod(g.cameraY, tileSize)))
|
||||||
|
var r image.Rectangle
|
||||||
if j == tileY+pipeGapY {
|
if j == tileY+pipeGapY {
|
||||||
r := image.Rect(pipeTileSrcX, pipeTileSrcY, pipeTileSrcX+pipeWidth, pipeTileSrcY+tileSize)
|
r = image.Rect(pipeTileSrcX, pipeTileSrcY, pipeTileSrcX+pipeWidth, pipeTileSrcY+tileSize)
|
||||||
op.SourceRect = &r
|
|
||||||
} else {
|
} else {
|
||||||
r := image.Rect(pipeTileSrcX, pipeTileSrcY+tileSize, pipeTileSrcX+pipeWidth, pipeTileSrcY+tileSize+tileSize)
|
r = image.Rect(pipeTileSrcX, pipeTileSrcY+tileSize, pipeTileSrcX+pipeWidth, pipeTileSrcY+tileSize+tileSize)
|
||||||
op.SourceRect = &r
|
|
||||||
}
|
}
|
||||||
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(float64(r.Min.X), float64(r.Min.Y))
|
||||||
op.GeoM.Translate(offsetX, offsetY)
|
op.GeoM.Translate(offsetX, offsetY)
|
||||||
op.SourceRect = &r
|
screen.DrawImage(keyboardImage.SubImage(r).(*ebiten.Image), op)
|
||||||
screen.DrawImage(keyboardImage, op)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
keyStrs := []string{}
|
keyStrs := []string{}
|
||||||
|
@ -69,6 +69,7 @@ Press C to clip the images.
|
|||||||
Scale: %0.2f`, s)
|
Scale: %0.2f`, s)
|
||||||
ebitenutil.DebugPrint(screen, msg)
|
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} {
|
for i, f := range []ebiten.Filter{ebiten.FilterNearest, ebiten.FilterLinear} {
|
||||||
w, h := gophersImage.Size()
|
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.GeoM.Translate(32+float64(i*w)*s+float64(i*4), 64)
|
||||||
op.Filter = f
|
op.Filter = f
|
||||||
if clip {
|
if clip {
|
||||||
r := image.Rect(10, 10, 100, 100)
|
screen.DrawImage(clippedGophersImage, op)
|
||||||
op.SourceRect = &r
|
} else {
|
||||||
|
screen.DrawImage(gophersImage, op)
|
||||||
}
|
}
|
||||||
screen.DrawImage(gophersImage, op)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -58,9 +58,7 @@ func update(screen *ebiten.Image) error {
|
|||||||
// Move the image's center to the screen's center.
|
// Move the image's center to the screen's center.
|
||||||
op.GeoM.Translate(screenWidth/2, screenHeight/2)
|
op.GeoM.Translate(screenWidth/2, screenHeight/2)
|
||||||
|
|
||||||
r := image.Rect(0, i, w, i+1)
|
screen.DrawImage(gophersImage.SubImage(image.Rect(0, i, w, i+1)).(*ebiten.Image), op)
|
||||||
op.SourceRect = &r
|
|
||||||
screen.DrawImage(gophersImage, op)
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -119,9 +119,7 @@ func update(screen *ebiten.Image) error {
|
|||||||
|
|
||||||
sx := (t % tileXNum) * tileSize
|
sx := (t % tileXNum) * tileSize
|
||||||
sy := (t / tileXNum) * tileSize
|
sy := (t / tileXNum) * tileSize
|
||||||
r := image.Rect(sx, sy, sx+tileSize, sy+tileSize)
|
screen.DrawImage(tilesImage.SubImage(image.Rect(sx, sy, sx+tileSize, sy+tileSize)).(*ebiten.Image), op)
|
||||||
op.SourceRect = &r
|
|
||||||
screen.DrawImage(tilesImage, 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.Scale(float64(dw)/float64(sw), float64(dh)/float64(sh))
|
||||||
op.GeoM.Translate(float64(dx), float64(dy))
|
op.GeoM.Translate(float64(dx), float64(dy))
|
||||||
op.GeoM.Translate(float64(dstX), float64(dstY))
|
op.GeoM.Translate(float64(dstX), float64(dstY))
|
||||||
r := image.Rect(sx, sy, sx+sw, sy+sh)
|
dst.DrawImage(uiImage.SubImage(image.Rect(sx, sy, sx+sw, sy+sh)).(*ebiten.Image), op)
|
||||||
op.SourceRect = &r
|
|
||||||
dst.DrawImage(uiImage, 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.
|
// The level 0 image is a regular image and higher-level images are used for mipmap.
|
||||||
mipmap *mipmap
|
mipmap *mipmap
|
||||||
|
|
||||||
|
bounds *image.Rectangle
|
||||||
|
original *Image
|
||||||
|
|
||||||
filter Filter
|
filter Filter
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +162,10 @@ func (i *Image) isDisposed() bool {
|
|||||||
return i.mipmap.isDisposed()
|
return i.mipmap.isDisposed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *Image) isSubimage() bool {
|
||||||
|
return i.bounds != nil
|
||||||
|
}
|
||||||
|
|
||||||
// Clear resets the pixels of the image into 0.
|
// Clear resets the pixels of the image into 0.
|
||||||
//
|
//
|
||||||
// When the image is disposed, Clear does nothing.
|
// When the image is disposed, Clear does nothing.
|
||||||
@ -169,6 +176,12 @@ func (i *Image) Clear() error {
|
|||||||
if i.isDisposed() {
|
if i.isDisposed() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Implement this.
|
||||||
|
if i.isSubimage() {
|
||||||
|
panic("render to a subimage is not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
i.fill(0, 0, 0, 0)
|
i.fill(0, 0, 0, 0)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -183,6 +196,12 @@ func (i *Image) Fill(clr color.Color) error {
|
|||||||
if i.isDisposed() {
|
if i.isDisposed() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Implement this.
|
||||||
|
if i.isSubimage() {
|
||||||
|
panic("render to a subimage is not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
r, g, b, a := clr.RGBA()
|
r, g, b, a := clr.RGBA()
|
||||||
i.fill(uint8(r>>8), uint8(g>>8), uint8(b>>8), uint8(a>>8))
|
i.fill(uint8(r>>8), uint8(g>>8), uint8(b>>8), uint8(a>>8))
|
||||||
return nil
|
return nil
|
||||||
@ -278,6 +297,11 @@ func (i *Image) drawImage(img *Image, options *DrawImageOptions) {
|
|||||||
return
|
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
|
// Calculate vertices before locking because the user can do anything in
|
||||||
// options.ImageParts interface without deadlock (e.g. Call Image functions).
|
// options.ImageParts interface without deadlock (e.g. Call Image functions).
|
||||||
if options == nil {
|
if options == nil {
|
||||||
@ -300,21 +324,32 @@ func (i *Image) drawImage(img *Image, options *DrawImageOptions) {
|
|||||||
ColorM: options.ColorM,
|
ColorM: options.ColorM,
|
||||||
CompositeMode: options.CompositeMode,
|
CompositeMode: options.CompositeMode,
|
||||||
}
|
}
|
||||||
r := image.Rect(sx0, sy0, sx1, sy1)
|
|
||||||
op.SourceRect = &r
|
|
||||||
op.GeoM.Scale(
|
op.GeoM.Scale(
|
||||||
float64(dx1-dx0)/float64(sx1-sx0),
|
float64(dx1-dx0)/float64(sx1-sx0),
|
||||||
float64(dy1-dy0)/float64(sy1-sy0))
|
float64(dy1-dy0)/float64(sy1-sy0))
|
||||||
op.GeoM.Translate(float64(dx0), float64(dy0))
|
op.GeoM.Translate(float64(dx0), float64(dy0))
|
||||||
op.GeoM.Concat(options.GeoM)
|
op.GeoM.Concat(options.GeoM)
|
||||||
i.DrawImage(img, op)
|
i.DrawImage(img.SubImage(image.Rect(sx0, sy0, sx1, sy1)).(*Image), op)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w, h := img.Size()
|
w, h := img.Size()
|
||||||
sx0, sy0, sx1, sy1 := 0, 0, w, h
|
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
|
sx0 = r.Min.X
|
||||||
sy0 = r.Min.Y
|
sy0 = r.Min.Y
|
||||||
if sx1 > r.Max.X {
|
if sx1 > r.Max.X {
|
||||||
@ -324,6 +359,7 @@ func (i *Image) drawImage(img *Image, options *DrawImageOptions) {
|
|||||||
sy1 = r.Max.Y
|
sy1 = r.Max.Y
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
geom := &options.GeoM
|
geom := &options.GeoM
|
||||||
if sx0 < 0 || sy0 < 0 {
|
if sx0 < 0 || sy0 < 0 {
|
||||||
dx := 0.0
|
dx := 0.0
|
||||||
@ -460,6 +496,11 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Implement this.
|
||||||
|
if i.isSubimage() {
|
||||||
|
panic("render to a subimage is not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
if len(indices)%3 != 0 {
|
if len(indices)%3 != 0 {
|
||||||
panic("ebiten: len(indices) % 3 must be 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()
|
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.
|
// Bounds returns the bounds of the image.
|
||||||
func (i *Image) Bounds() image.Rectangle {
|
func (i *Image) Bounds() image.Rectangle {
|
||||||
w, h := i.Size()
|
if i.bounds == nil {
|
||||||
return image.Rect(0, 0, w, h)
|
w, h := i.Size()
|
||||||
|
return image.Rect(0, 0, w, h)
|
||||||
|
}
|
||||||
|
return *i.bounds
|
||||||
}
|
}
|
||||||
|
|
||||||
// ColorModel returns the color model of the image.
|
// ColorModel returns the color model of the image.
|
||||||
@ -512,6 +594,9 @@ func (i *Image) At(x, y int) color.Color {
|
|||||||
if i.isDisposed() {
|
if i.isDisposed() {
|
||||||
return color.RGBA{}
|
return color.RGBA{}
|
||||||
}
|
}
|
||||||
|
if i.bounds != nil && !image.Pt(x, y).In(*i.bounds) {
|
||||||
|
return color.RGBA{}
|
||||||
|
}
|
||||||
return i.mipmap.original().At(x, y)
|
return i.mipmap.original().At(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,7 +612,9 @@ func (i *Image) Dispose() error {
|
|||||||
if i.isDisposed() {
|
if i.isDisposed() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
i.mipmap.dispose()
|
if !i.isSubimage() {
|
||||||
|
i.mipmap.dispose()
|
||||||
|
}
|
||||||
runtime.SetFinalizer(i, nil)
|
runtime.SetFinalizer(i, nil)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -548,6 +635,10 @@ func (i *Image) ReplacePixels(p []byte) error {
|
|||||||
if i.isDisposed() {
|
if i.isDisposed() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
// TODO: Implement this.
|
||||||
|
if i.isSubimage() {
|
||||||
|
panic("render to a subimage is not implemented")
|
||||||
|
}
|
||||||
i.mipmap.original().ReplacePixels(p)
|
i.mipmap.original().ReplacePixels(p)
|
||||||
i.disposeMipmaps()
|
i.disposeMipmaps()
|
||||||
return nil
|
return nil
|
||||||
@ -555,22 +646,6 @@ func (i *Image) ReplacePixels(p []byte) error {
|
|||||||
|
|
||||||
// A DrawImageOptions represents options to render an image on an image.
|
// A DrawImageOptions represents options to render an image on an image.
|
||||||
type DrawImageOptions struct {
|
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.
|
// GeoM is a geometry matrix to draw.
|
||||||
// The default (zero) value is identify, which draws the image at (0, 0).
|
// The default (zero) value is identify, which draws the image at (0, 0).
|
||||||
GeoM GeoM
|
GeoM GeoM
|
||||||
@ -595,11 +670,14 @@ type DrawImageOptions struct {
|
|||||||
// Otherwise, Filter specified at DrawImageOptions is used.
|
// Otherwise, Filter specified at DrawImageOptions is used.
|
||||||
Filter Filter
|
Filter Filter
|
||||||
|
|
||||||
// Deprecated (as of 1.5.0-alpha): Use SourceRect instead.
|
// Deprecated (as of 1.5.0-alpha): Use SubImage instead.
|
||||||
ImageParts ImageParts
|
ImageParts ImageParts
|
||||||
|
|
||||||
// Deprecated (as of 1.1.0-alpha): Use SourceRect instead.
|
// Deprecated (as of 1.1.0-alpha): Use SubImage instead.
|
||||||
Parts []ImagePart
|
Parts []ImagePart
|
||||||
|
|
||||||
|
// Deprecated (as of 1.9.0-alpha): Use SubImage instead.
|
||||||
|
SourceRect *image.Rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewImage returns an empty image.
|
// NewImage returns an empty image.
|
||||||
|
@ -555,21 +555,20 @@ func TestImageEdge(t *testing.T) {
|
|||||||
angles = append(angles, float64(a)/4096*2*math.Pi)
|
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 _, s := range []float64{1, 0.5, 0.25} {
|
||||||
for _, f := range []Filter{FilterNearest, FilterLinear} {
|
for _, f := range []Filter{FilterNearest, FilterLinear} {
|
||||||
for _, a := range angles {
|
for _, a := range angles {
|
||||||
img1.Clear()
|
img1.Clear()
|
||||||
op := &DrawImageOptions{}
|
op := &DrawImageOptions{}
|
||||||
r := image.Rect(img0OffsetWidth, img0InnerHeight, img0Width-img0OffsetWidth, img0Height-img0InnerHeight)
|
|
||||||
op.SourceRect = &r
|
|
||||||
|
|
||||||
w, h := img0.Size()
|
w, h := img0.Size()
|
||||||
op.GeoM.Translate(-float64(w)/2, -float64(h)/2)
|
op.GeoM.Translate(-float64(w)/2, -float64(h)/2)
|
||||||
op.GeoM.Scale(s, s)
|
op.GeoM.Scale(s, s)
|
||||||
op.GeoM.Rotate(a)
|
op.GeoM.Rotate(a)
|
||||||
op.GeoM.Translate(img1Width/2, img1Height/2)
|
op.GeoM.Translate(img1Width/2, img1Height/2)
|
||||||
op.Filter = f
|
op.Filter = f
|
||||||
img1.DrawImage(img0, op)
|
img1.DrawImage(img0Sub, op)
|
||||||
for j := 0; j < img1Height; j++ {
|
for j := 0; j < img1Height; j++ {
|
||||||
for i := 0; i < img1Width; i++ {
|
for i := 0; i < img1Width; i++ {
|
||||||
c := img1.At(i, j)
|
c := img1.At(i, j)
|
||||||
@ -641,10 +640,8 @@ func TestImageLinear(t *testing.T) {
|
|||||||
op := &DrawImageOptions{}
|
op := &DrawImageOptions{}
|
||||||
op.GeoM.Translate(8, 8)
|
op.GeoM.Translate(8, 8)
|
||||||
op.GeoM.Scale(2, 2)
|
op.GeoM.Scale(2, 2)
|
||||||
r := image.Rect(8, 8, 24, 24)
|
|
||||||
op.SourceRect = &r
|
|
||||||
op.Filter = FilterLinear
|
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 j := 0; j < 64; j++ {
|
||||||
for i := 0; i < 64; i++ {
|
for i := 0; i < 64; i++ {
|
||||||
@ -683,11 +680,10 @@ func TestImageOutside(t *testing.T) {
|
|||||||
|
|
||||||
op := &DrawImageOptions{}
|
op := &DrawImageOptions{}
|
||||||
op.GeoM.Translate(0, 0)
|
op.GeoM.Translate(0, 0)
|
||||||
op.SourceRect = &image.Rectangle{
|
dst.DrawImage(src.SubImage(image.Rectangle{
|
||||||
Min: image.Pt(c.X, c.Y),
|
Min: image.Pt(c.X, c.Y),
|
||||||
Max: image.Pt(c.X+c.Width, c.Y+c.Height),
|
Max: image.Pt(c.X+c.Width, c.Y+c.Height),
|
||||||
}
|
}).(*Image), op)
|
||||||
dst.DrawImage(src, op)
|
|
||||||
|
|
||||||
for j := 0; j < 4; j++ {
|
for j := 0; j < 4; j++ {
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
@ -709,12 +705,12 @@ func TestImageOutsideUpperLeft(t *testing.T) {
|
|||||||
|
|
||||||
op := &DrawImageOptions{}
|
op := &DrawImageOptions{}
|
||||||
op.GeoM.Rotate(math.Pi / 4)
|
op.GeoM.Rotate(math.Pi / 4)
|
||||||
r := image.Rect(-4, -4, 8, 8)
|
dst1.DrawImage(src.SubImage(image.Rect(-4, -4, 8, 8)).(*Image), op)
|
||||||
op.SourceRect = &r
|
|
||||||
dst1.DrawImage(src, op)
|
|
||||||
|
|
||||||
op = &DrawImageOptions{}
|
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)
|
op.GeoM.Rotate(math.Pi / 4)
|
||||||
dst2.DrawImage(src, op)
|
dst2.DrawImage(src, op)
|
||||||
|
|
||||||
@ -829,9 +825,7 @@ func TestImageStretch(t *testing.T) {
|
|||||||
img1.Clear()
|
img1.Clear()
|
||||||
op := &DrawImageOptions{}
|
op := &DrawImageOptions{}
|
||||||
op.GeoM.Scale(1, float64(i)/16)
|
op.GeoM.Scale(1, float64(i)/16)
|
||||||
r := image.Rect(0, 0, 16, 16)
|
img1.DrawImage(img0.SubImage(image.Rect(0, 0, 16, 16)).(*Image), op)
|
||||||
op.SourceRect = &r
|
|
||||||
img1.DrawImage(img0, op)
|
|
||||||
for j := -1; j <= 1; j++ {
|
for j := -1; j <= 1; j++ {
|
||||||
got := img1.At(0, i+j).(color.RGBA)
|
got := img1.At(0, i+j).(color.RGBA)
|
||||||
want := 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"
|
"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 {
|
type ImagePart struct {
|
||||||
Dst image.Rectangle
|
Dst image.Rectangle
|
||||||
Src 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 {
|
type ImageParts interface {
|
||||||
Len() int
|
Len() int
|
||||||
Dst(i int) (x0, y0, x1, y1 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)
|
b := getGlyphBounds(face, r)
|
||||||
op := &ebiten.DrawImageOptions{}
|
op := &ebiten.DrawImageOptions{}
|
||||||
op.GeoM.Translate(fixed26_6ToFloat64(x+b.Min.X), fixed26_6ToFloat64(y+b.Min.Y))
|
op.GeoM.Translate(fixed26_6ToFloat64(x+b.Min.X), fixed26_6ToFloat64(y+b.Min.Y))
|
||||||
|
|
||||||
op.ColorM = clr
|
op.ColorM = clr
|
||||||
re := image.Rect(img.x, img.y, img.x+img.width, img.y+img.height)
|
_ = dst.DrawImage(img.image.SubImage(image.Rect(img.x, img.y, img.x+img.width, img.y+img.height)).(*ebiten.Image), op)
|
||||||
op.SourceRect = &re
|
|
||||||
|
|
||||||
_ = dst.DrawImage(img.image, op)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
Loading…
Reference in New Issue
Block a user