Skip to content

Commit

Permalink
bitmap font colorization
Browse files Browse the repository at this point in the history
  • Loading branch information
Vladar committed Jun 18, 2012
1 parent 9aae4c4 commit 0202854
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 47 deletions.
23 changes: 18 additions & 5 deletions lib/common.nim
Expand Up @@ -56,9 +56,22 @@ proc screen*(): PSurface {.inline.} =


# create new surface
proc newSurface*(width, height: int): PSurface {.inline.} =
let scr = screen()
return do(
proc newSurface*(width, height: int, alpha: bool = false): PSurface {.inline.} =
let fmt = screen().format
let surface = do(
createRGBSurface(
scr.flags, width, height, scr.format.bitsPerPixel,
scr.format.rMask, scr.format.gMask, scr.format.bMask, scr.format.aMask))
screen().flags, width, height, fmt.bitsPerPixel,
fmt.Rmask, fmt.Gmask, fmt.Bmask, fmt.Amask))
if alpha:
result = displayFormatAlpha(surface)
do(result.fillRect(nil, mapRGBA(result.format, 0'i8, 0'i8, 0'i8, 0'i8)))
freeSurface(surface)
else:
return surface

# blit surface preserving alpha channel
proc blitSurfaceAlpha*(src: PSurface, srcrect: PRect, dst: PSurface, dstrect: PRect): int =
do(src.setAlpha(0, 255'i8))
result = blitSurface(src, srcrect, dst, dstRect)
do(src.setAlpha(SRCALPHA, 255'i8))
do(src.setAlpha(SRCALPHA, 255'i8))
40 changes: 34 additions & 6 deletions lib/font.nim
Expand Up @@ -24,7 +24,8 @@ type
PBitmapFont* = ref TBitmapFont
TBitmapFont* = object of TFontObject
fFont: PSprite
color*: TColor
fColor: TColor
fUseColor: bool


# methods
Expand Down Expand Up @@ -86,9 +87,19 @@ proc newTTFFont*(filename: cstring, # font filename

# Bitmap Font


method color*(obj: PBitmapFont): TColor {.inline.} =
return obj.fColor

method `color=`*(obj: PBitmapFont, value: TColor) {.inline.} =
if obj.fUseColor:
obj.fColor = value
obj.fFont.maskedFill(obj.fColor)


method render*(obj: PBitmapFont, text: string): PSurface {.inline.} =
let width = obj.fFont.w * text.len
result = newSurface(width, obj.fFont.h)
result = newSurface(width, obj.fFont.h, true)
var x: int16 = 0'i16
for chr in text.items():
let idx = ord(chr)
Expand All @@ -99,20 +110,37 @@ method render*(obj: PBitmapFont, text: string): PSurface {.inline.} =
proc init*(obj: PBitmapFont,
filename: cstring,
w, h: UInt16,
color: TColor = color(255, 255, 255),
) =
obj.fUseColor = false
obj.fFont = newSprite(filename, w=w, h=h)
obj.color = color
obj.color = color(0, 0, 0)


proc init*(obj: PBitmapFont,
filename: cstring,
w, h: UInt16,
color: TColor,
) =
obj.fUseColor = true
obj.fFont = newSprite(filename, w=w, h=h)
obj.color = color


proc free*(obj: PBitmapFont) =
obj.fFont.free()
obj.fFont = nil


proc newBitmapFont*(filename: cstring, # font filename
w, h: int,
color: TColor = color(255, 255, 255), # font color
w, h: int, # char dimensions
): PBitmapFont =
new(result, free)
init(result, filename, UInt16(w), UInt16(h))


proc newBitmapFont*(filename: cstring, # font filename
w, h: int, # char dimensions
color: TColor, # font color
): PBitmapFont =
new(result, free)
init(result, filename, UInt16(w), UInt16(h), color)
7 changes: 5 additions & 2 deletions lib/imageex.nim
Expand Up @@ -18,7 +18,7 @@ proc init*(obj: PImageEx,
) =
obj.original = convertSurface(obj.surface,
obj.surface.format,
obj.surface.flags)
obj.surface.flags)
obj.originalPos.x = obj.x
obj.originalPos.y = obj.y
obj.fAngle = 0.0
Expand Down Expand Up @@ -92,7 +92,10 @@ method angle*(obj: PImageEx): float64 {.inline.} =
return obj.fAngle

method `angle=`*(obj: PImageEx, value: float64) {.inline.} =
obj.fAngle = value
var val = value
if value > 360.0: val = float64(int(value) mod 360)
elif value < 360.0: val = float64(int(value) mod 360)
obj.fAngle = val
obj.updateRotZoom()

# Center offset
Expand Down
73 changes: 48 additions & 25 deletions lib/mask.nim
Expand Up @@ -8,6 +8,34 @@ type
w*, h*: UInt16
data*: seq[seq[bool]]


proc setMask*(obj: PMask,
surface: PSurface) =
do(lockSurface(surface))
let format = surface.format
let pixels: PByteArray = cast[PByteArray](surface.pixels)
var offset: int
var pixel, temp: UInt32
var alpha: int16
obj.data = @[]
for y in 0..surface.h-1:
obj.data.add(@[])
#write(stdout, "\n") # DEBUG: Uncomment to output mask
for x in 0..surface.w-1:
offset = y * surface.pitch + x * format.BytesPerPixel + 3
pixel = pixels[offset]
temp = pixel and format.Amask
temp = temp shr format.Ashift
alpha = int16(temp shl format.Aloss)
if alpha < 127:
obj.data[obj.data.high].add(false)
#write(stdout, " ") # DEBUG: Uncomment to output mask
else:
obj.data[obj.data.high].add(true)
#write(stdout, "X") # DEBUG: Uncomment to output mask
unlockSurface(surface)


proc init*(obj: PMask,
filename: cstring,
x: int16 = 0'i16,
Expand All @@ -17,36 +45,22 @@ proc init*(obj: PMask,
obj.y = y
if filename != nil:
let surface: PSurface = do(imgLoad(filename))
let format = surface.format
obj.w = UInt16(surface.w)
obj.h = UInt16(surface.h)
let pixels: PByteArray = cast[PByteArray](surface.pixels)
do(lockSurface(surface))

var offset: int
var pixel, temp: UInt32
var alpha: int16
obj.data = @[]
for y in 0..surface.h-1:
obj.data.add(@[])
#write(stdout, "\n") # DEBUG: Uncomment to output mask
for x in 0..surface.w-1:
offset = y * surface.pitch + x * format.BytesPerPixel + 3
pixel = pixels[offset]
temp = pixel and format.Amask
temp = temp shr format.Ashift
alpha = int16(temp shl format.Aloss)
if alpha < 127:
obj.data[obj.data.high].add(false)
#write(stdout, " ") # DEBUG: Uncomment to output mask
else:
obj.data[obj.data.high].add(true)
#write(stdout, "X") # DEBUG: Uncomment to output mask

unlockSurface(surface)
obj.setMask(surface)
freeSurface(surface)


proc init*(obj: PMask,
surface: PSurface,
x: int16 = 0'i16,
y: int16 = 0'i16,
) =
obj.x = x
obj.y = y
obj.setMask(surface)


proc newMask*(filename: cstring,
x: int = 0,
y: int = 0,
Expand All @@ -55,6 +69,15 @@ proc newMask*(filename: cstring,
init(result, filename, int16(x), int16(y))



proc newMask*(surface: PSurface,
x: int = 0,
y: int = 0,
): PMask =
new(result)
init(result, surface, int16(x), int16(y))


method getRect*(obj: PMask): TRect =
result.x = obj.x
result.y = obj.y
Expand Down
32 changes: 23 additions & 9 deletions lib/sprite.nim
Expand Up @@ -15,27 +15,36 @@ type
fFrame: int


# Fill sprite map with given color but save alpha channel
method maskedFill*(obj: PSprite, color: TColor) =
let colorize = newSurface(obj.fSpritemap.surface.w, obj.fSpritemap.surface.h, true)
do(colorize.fillRect(nil, mapRGBA(colorize.format, color.r, color.g, color.b, 255'i8)))
do(colorize.blitSurface(nil, obj.fSpritemap.surface, nil))
freeSurface(colorize)


# Blit single frame to the given surface without changing current frame
method blitFrame*(obj: PSprite, frame: int, dstSurface: PSurface,
x: int16 = 0'i16, y: int16 = 0'i16) =
var dstRect: TRect
dstRect.x = x
dstRect.y = y
dstRect.w = obj.fSpriteInfo.w
dstRect.h = obj.fSpriteInfo.h
do(blitSurface(obj.fSpritemap.surface,
addr(obj.fSpriteInfo.frames[frame]),
dstSurface,
addr(dstRect)))
do(blitSurfaceAlpha(obj.fSpritemap.surface,
addr(obj.fSpriteInfo.frames[frame]),
dstSurface,
addr(dstRect)))


method changeFrame(obj: PSprite, frame: int) =
obj.fFrame = frame
var dstRect: TRect
do(fillRect(obj.original, nil, 0))
do(blitSurface(obj.fSpritemap.surface,
addr(obj.fSpriteInfo.frames[obj.fFrame]),
obj.original,
addr(dstRect)))
do(blitSurfaceAlpha(obj.fSpritemap.surface,
addr(obj.fSpriteInfo.frames[obj.fFrame]),
obj.original,
addr(dstRect)))
obj.updateRotZoom()


Expand All @@ -60,6 +69,10 @@ proc init*(obj: PSprite,
obj.fSpriteInfo.h = UInt16(obj.fSpritemap.surface.h - offsetY)
obj.fSpriteInfo.cols = 1
obj.fSpriteInfo.rows = 1
# check spritemap size
if obj.fSpriteInfo.w > obj.fSpritemap.surface.w or
obj.fSpriteInfo.w > obj.fSpritemap.surface.h:
echo("Error: spritemap size is too small")
# generate frame rects
for row in 0..obj.fSpriteInfo.rows-1:
for col in 0..obj.fSpriteInfo.cols-1:
Expand All @@ -70,7 +83,8 @@ proc init*(obj: PSprite,
rect.h = UInt16(obj.fSpriteInfo.h)
obj.fSpriteInfo.frames.add(rect)
# create surface
obj.surface = newSurface(obj.fSpriteInfo.w, obj.fSpriteInfo.h)
freeSurface(obj.surface)
obj.surface = newSurface(obj.fSpriteInfo.w, obj.fSpriteInfo.h, true)


proc free*(obj: PSprite) =
Expand Down

0 comments on commit 0202854

Please sign in to comment.