Skip to content

Commit

Permalink
Add LCDBitmap.set, .get, .width and .height
Browse files Browse the repository at this point in the history
This allows for pixel operations directly on an LCDBitmap
instance, which makes it possible to set clear pixels instead
of having to understand the difference between the bitmap
data and the mask
  • Loading branch information
Nycto authored Sep 30, 2023
1 parent 0384caf commit a30f359
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 2 deletions.
39 changes: 38 additions & 1 deletion src/playdate/graphics.nim
Original file line number Diff line number Diff line change
Expand Up @@ -348,14 +348,40 @@ proc drawRotated*(this: LCDBitmap, x: int, y: int, rotation: float, centerX: flo
playdate.graphics.drawRotatedBitmap(this.resource, x.cint, y.cint, rotation.cfloat, centerX.cfloat, centerY.cfloat,
xScale.cfloat, yScale.cfloat)

proc setBitmapMask*(this: LCDBitmap, mask: LCDBitmap): int =
proc width*(this: LCDBitmap): int = this.getData.width

proc height*(this: LCDBitmap): int = this.getData.height

proc setBitmapMask*(
this: LCDBitmap,
mask: LCDBitmap = playdate.graphics.newBitmap(this.width, this.height, kColorWhite)
): int =
privateAccess(PlaydateGraphics)
return playdate.graphics.setBitmapMask(this.resource, mask.resource).int

proc getBitmapMask*(this: LCDBitmap): LCDBitmap =
privateAccess(PlaydateGraphics)
return LCDBitmap(resource: playdate.graphics.getBitmapMask(this.resource), free: false) # Who should manage this memory? Not clear. Not auto-managed right now.

proc get*(this: LCDBitmap, x, y: int): LCDSolidColor =
## Reads the color of a bitmap, taking into account the color mask
if this.getBitmapMask.resource != nil and this.getBitmapMask.getData.get(x, y) == kColorBlack:
return kColorClear
else:
return this.getData.get(x, y)

proc set*(this: var LCDBitmap, x, y: int, color: LCDSolidColor = kColorBlack) =
## Reads the color of a bitmap, taking into account the color mask
if color == kColorClear:
var mask = this.getBitmapMask.getData
mask.set(x, y, kColorBlack)
else:
if this.getBitmapMask.resource != nil:
var mask = this.getBitmapMask.getData
mask.set(x, y, kColorWhite)
var data = this.getData
data.set(x, y, color)

proc setStencilImage*(this: ptr PlaydateGraphics, bitmap: LCDBitmap, tile: bool) =
privateAccess(PlaydateGraphics)
this.setStencilImage(bitmap.resource, if tile: 1 else: 0)
Expand All @@ -364,3 +390,14 @@ proc makeFont*(this: LCDFontData, wide: bool): LCDFont =
privateAccess(PlaydateGraphics)
privateAccess(LCDFont)
return LCDFont(resource: playdate.graphics.makeFontFromData(this, if wide: 1 else: 0))

proc `$`*(view: BitmapView | LCDBitmap): string =
## Render a string version of a bitmap view
for y in 0..<view.height:
for x in 0..<view.width:
case view.get(x, y)
of kColorBlack: result.add("")
of kColorWhite: result.add("")
of kColorClear: result.add(" ")
of kColorXOR: result.add("X")
result.add("\n")
Binary file added tests/source/boxes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 36 additions & 1 deletion tests/t_graphics.nim
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import unittest, playdate/api
import unittest, playdate/api, strutils


proc execGraphicsTests*(runnable: bool) =
Expand Down Expand Up @@ -51,6 +51,41 @@ proc execGraphicsTests*(runnable: bool) =
let img = playdate.graphics.newBitmap(10, 10, kColorWhite)
discard playdate.graphics.createPattern(img, 0, 0)

test "Bitmaps should be loadable from files":
if runnable:
let img = playdate.graphics.newBitmap("boxes.png")

let expect = join(@[
" ",
" ███░░░ ",
" █░░██░ ",
" █░░██░ ",
" █░░██░ ",
" █░░██░ ",
" █░░██░ ",
" █░░██░ ",
" ███░░░ ",
" \n",
], "\n")

check($(img) == expect)

test "Creating bitmaps programaticlly":
if runnable:
var img = playdate.graphics.newBitmap(2, 2, kColorWhite)
img.set(0, 0, kColorWhite)
img.set(1, 0, kColorBlack)
check($img == "░█\n░░\n")

test "Creating bitmaps programaticlly with clear pixels":
if runnable:
var img = playdate.graphics.newBitmap(2, 2, kColorWhite)
discard img.setBitmapMask()
img.set(0, 0, kColorWhite)
img.set(1, 0, kColorBlack)
img.set(0, 1, kColorClear)
check($img == "░█\n\n")

when isMainModule:
# We can't run these methods from the tests, so we're only interested in
# whether they compile.
Expand Down

0 comments on commit a30f359

Please sign in to comment.