bugfix: tseqtuple

This commit is contained in:
Andreas Rumpf 2010-03-10 00:40:34 +01:00
commit 2e280eafa8
4 changed files with 214 additions and 40 deletions

View file

@ -11,8 +11,9 @@
## implementation uses SDL but the interface is meant to support multiple ## implementation uses SDL but the interface is meant to support multiple
## backends some day. ## backends some day.
import colors import colors, math
from sdl import PSurface # Bug from sdl import PSurface # Bug
from sdl_ttf import OpenFont
type type
TRect* = tuple[x, y, width, height: int] TRect* = tuple[x, y, width, height: int]
@ -23,6 +24,8 @@ type
w, h: int w, h: int
s: sdl.PSurface s: sdl.PSurface
ESDLError = object of EBase
proc surfaceFinalizer(s: PSurface) = sdl.freeSurface(s.s) proc surfaceFinalizer(s: PSurface) = sdl.freeSurface(s.s)
proc newSurface*(width, height: int): PSurface = proc newSurface*(width, height: int): PSurface =
@ -35,8 +38,18 @@ proc newSurface*(width, height: int): PSurface =
assert(not sdl.MustLock(result.s)) assert(not sdl.MustLock(result.s))
#proc textBounds*(text: string): tuple[len, height: int] proc newScreenSurface(width, height: int): PSurface =
#proc drawText*(sur: PSurface, p: TPoint, text: string) ## Creates a new screen surface
new(result, surfaceFinalizer)
result.w = width
result.h = height
result.s = SDL.SetVideoMode(width, height, 0, 0)
template withEvents(surf: PSurface, event: expr, actions: stmt): stmt =
while True:
var event: SDL.TEvent
if SDL.PollEvent(addr(event)) == 1:
actions
proc writeToBMP*(sur: PSurface, filename: string) = proc writeToBMP*(sur: PSurface, filename: string) =
## Saves the contents of the surface `sur` to the file `filename` as a ## Saves the contents of the surface `sur` to the file `filename` as a
@ -77,6 +90,91 @@ proc `[]=`*(sur: PSurface, p: TPoint, col: TColor) =
#proc `[,]=`*(sur: PSurface, x, y: int, col: TColor) = #proc `[,]=`*(sur: PSurface, x, y: int, col: TColor) =
# setPixel(sur, x, y, col) # setPixel(sur, x, y, col)
proc blitSurface*(destSurf: PSurface, destRect: TRect, srcSurf: PSurface, srcRect: TRect) =
## Merges ``srcSurf`` into ``destSurf``
var destTRect, srcTRect: SDL.TRect
destTRect.x = int16(destRect.x)
destTRect.y = int16(destRect.y)
destTRect.w = int16(destRect.width)
destTRect.h = int16(destRect.height)
srcTRect.x = int16(srcRect.x)
srcTRect.y = int16(srcRect.y)
srcTRect.w = int16(srcRect.width)
srcTRect.h = int16(srcRect.height)
if SDL.blitSurface(srcSurf.s, addr(srcTRect), destSurf.s, addr(destTRect)) != 0:
raise newException(ESDLError, $SDL.GetError())
proc textBounds*(font: string, fontSize: int,
text: string): tuple[width, height: int] =
var fontFile = OpenFont(font, fontSize) # Open the font file
if fontFile == nil: raise newException(ESDLError, "Could not open font file")
var w, h: cint
if sdl_ttf.SizeUTF8(fontFile, text, w, h) < 0:
raise newException(ESDLError, $SDL.GetError())
return (int(w), int(h))
proc drawText*(sur: PSurface, p: TPoint, font: string, text: string,
fg: TColor = colBlack, fontSize: int = 9) =
## Draws text with a transparent background, at location ``p``.
## ``font`` specifies the path to the ttf file,
## ``fontSize`` specifies the font size in pt, and ``fg``
## specifies the foreground color.
var fontFile = OpenFont(font, fontSize) # Open the font file
if fontFile == nil: raise newException(ESDLError, "Could not open font file")
var textSur: PSurface # This surface will have the text drawn on it
new(textSur, surfaceFinalizer)
var RGBfg = fg.extractRGB
# Convert the colors.TColor to SDL.TColor
var SDLfg: SDL.TColor
SDLfg.r = toU8(RGBfg.r)
SDLfg.g = toU8(RGBfg.g)
SDLfg.b = toU8(RGBfg.b)
# Render the text
textSur.s = sdl_ttf.RenderTextBlended(fontFile, text, SDLfg)
# Merge the text surface with sur
sur.blitSurface((p.x, p.y, sur.w, sur.h), textSur, (0, 0, sur.w, sur.h))
# Free the surface
SDL.FreeSurface(sur.s)
proc drawText*(sur: PSurface, p: TPoint, font: string, text: string,
bg: TColor, fg: TColor = colBlack, fontSize: int = 9) =
## Draws text, at location ``p``, ``font`` specifies the path to
## the ttf file, ``fontSize`` specifies the font size in pt, and ``fg``
## and ``bg`` specify the foreground and background colors.
var fontFile = OpenFont(font, fontSize) # Open the font file
if fontFile == nil: raise newException(ESDLError, "Could not open font file")
var textSur: PSurface # This surface will have the text drawn on it
new(textSur, surfaceFinalizer)
var RGBfg = fg.extractRGB
var RGBbg = bg.extractRGB
# Convert the colors.TColor to SDL.TColor
var SDLfg: SDL.TColor
SDLfg.r = toU8(RGBfg.r)
SDLfg.g = toU8(RGBfg.g)
SDLfg.b = toU8(RGBfg.b)
var SDLbg: SDL.TColor
SDLbg.r = toU8(RGBbg.r)
SDLbg.g = toU8(RGBbg.g)
SDLbg.b = toU8(RGBbg.b)
# Render the text
textSur.s = sdl_ttf.RenderTextShaded(fontFile, text, SDLfg, SDLbg)
# Merge the text surface with sur
sur.blitSurface((p.x, p.y, sur.w, sur.h), textSur, (0, 0, sur.w, sur.h))
# Free the surface
SDL.FreeSurface(sur.s)
proc drawCircle*(sur: PSurface, p: TPoint, r: Natural, color: TColor) = proc drawCircle*(sur: PSurface, p: TPoint, r: Natural, color: TColor) =
## draws a circle with center `p` and radius `r` with the given color ## draws a circle with center `p` and radius `r` with the given color
## onto the surface `sur`. ## onto the surface `sur`.
@ -247,7 +345,7 @@ proc drawRect*(sur: PSurface, r: TRect, color: TColor) =
setPix(video, pitch, r.x + minW - 1, r.y + i, color) # Draw right side setPix(video, pitch, r.x + minW - 1, r.y + i, color) # Draw right side
proc fillRect*(sur: PSurface, r: TRect, col: TColor) = proc fillRect*(sur: PSurface, r: TRect, col: TColor) =
## draws and fills a rectancle. ## draws and fills a rectangle.
var video = cast[PPixels](sur.s.pixels) var video = cast[PPixels](sur.s.pixels)
assert video != nil assert video != nil
var pitch = sur.s.pitch div ColSize var pitch = sur.s.pitch div ColSize
@ -256,17 +354,23 @@ proc fillRect*(sur: PSurface, r: TRect, col: TColor) =
for j in r.x..min(sur.s.w, r.x+r.width-1)-1: for j in r.x..min(sur.s.w, r.x+r.width-1)-1:
setPix(video, pitch, j, i, col) setPix(video, pitch, j, i, col)
proc Plot4EllipsePoints(sur: PSurface, CX, CY, X, Y: Natural, col: TColor) = proc Plot4EllipsePoints(sur: PSurface, CX, CY, X, Y: Natural, col: TColor) =
var video = cast[PPixels](sur.s.pixels) var video = cast[PPixels](sur.s.pixels)
var pitch = sur.s.pitch div ColSize var pitch = sur.s.pitch div ColSize
if CX+X < sur.s.w and CY+Y < sur.s.h:
setPix(video, pitch, CX+X, CY+Y, col) setPix(video, pitch, CX+X, CY+Y, col)
if CX-X < sur.s.w and CY+Y < sur.s.h:
setPix(video, pitch, CX-X, CY+Y, col) setPix(video, pitch, CX-X, CY+Y, col)
if CX-X < sur.s.w and CY-Y < sur.s.h:
setPix(video, pitch, CX-X, CY-Y, col) setPix(video, pitch, CX-X, CY-Y, col)
if CX+X < sur.s.w and CY-Y < sur.s.h:
setPix(video, pitch, CX+X, CY-Y, col) setPix(video, pitch, CX+X, CY-Y, col)
proc drawEllipse*(sur: PSurface, CX, CY, XRadius, YRadius: Natural, col: TColor) = proc drawEllipse*(sur: PSurface, CX, CY, XRadius, YRadius: Natural, col: TColor) =
## Draws an ellipse, ``CX`` and ``CY`` specify the center X and Y of
## the ellipse, ``XRadius`` and ``YRadius`` specify the width and height
## of the ellipse.
var var
X, Y: Natural X, Y: Natural
XChange, YChange: Natural XChange, YChange: Natural
@ -317,14 +421,17 @@ proc drawEllipse*(sur: PSurface, CX, CY, XRadius, YRadius: Natural, col: TColor)
inc(YChange,TwoASquare) inc(YChange,TwoASquare)
proc plot(sur: PSurface, x, y, c: float, color: TColor) = proc plotAA(sur: PSurface, x, y, c: float, color: TColor) =
if (x.toInt() > 0 and x.toInt() < sur.s.w) and (y.toInt() > 0 and
y.toInt() < sur.s.h):
var video = cast[PPixels](sur.s.pixels) var video = cast[PPixels](sur.s.pixels)
var pitch = sur.s.pitch div ColSize var pitch = sur.s.pitch div ColSize
var pixColor = getPix(video, pitch, x.toInt, y.toInt) var pixColor = getPix(video, pitch, x.toInt, y.toInt)
setPix(video, pitch, x.toInt(), y.toInt(), setPix(video, pitch, x.toInt(), y.toInt(),
pixColor.intensity(1.0 - c) + color.intensity(c)) pixColor.intensity(1.0 - c) + color.intensity(c))
import math
proc ipart(x: float): float = proc ipart(x: float): float =
return x.trunc() return x.trunc()
proc fpart(x: float): float = proc fpart(x: float): float =
@ -332,12 +439,11 @@ proc fpart(x: float): float =
proc rfpart(x: float): float = proc rfpart(x: float): float =
return 1.0 - fpart(x) return 1.0 - fpart(x)
proc drawLineAA(sur: PSurface, p1: TPoint, p2: TPoint, color: TColor) = proc drawLineAA(sur: PSurface, p1: TPoint, p2: TPoint, color: TColor) =
## Draws a line from ``p1`` to ``p2``, using the Xiaolin Wu's line algorithm ## Draws a anti-aliased line from ``p1`` to ``p2``, using Xiaolin Wu's line algorithm
var (x1, x2, y1, y2) = (p1.x.toFloat(), p2.x.toFloat(), var (x1, x2, y1, y2) = (p1.x.toFloat(), p2.x.toFloat(),
p1.y.toFloat(), p2.y.toFloat()) p1.y.toFloat(), p2.y.toFloat())
var dx = x2 - x1 var dx = x2 - x1
var dy = y2 - y1 var dy = y2 - y1
if abs(dx) < abs(dy): if abs(dx) < abs(dy):
@ -354,8 +460,8 @@ proc drawLineAA(sur: PSurface, p1: TPoint, p2: TPoint, color: TColor) =
var xgap = rfpart(x1 + 0.5) var xgap = rfpart(x1 + 0.5)
var xpxl1 = xend # this will be used in the main loop var xpxl1 = xend # this will be used in the main loop
var ypxl1 = ipart(yend) var ypxl1 = ipart(yend)
sur.plot(xpxl1, ypxl1, rfpart(yend) * xgap, color) sur.plotAA(xpxl1, ypxl1, rfpart(yend) * xgap, color)
sur.plot(xpxl1, ypxl1 + 1.0, fpart(yend) * xgap, color) sur.plotAA(xpxl1, ypxl1 + 1.0, fpart(yend) * xgap, color)
var intery = yend + gradient # first y-intersection for the main loop var intery = yend + gradient # first y-intersection for the main loop
# handle second endpoint # handle second endpoint
xend = x2 # Should be round(x1), but since this is an int anyway.. xend = x2 # Should be round(x1), but since this is an int anyway..
@ -363,32 +469,78 @@ proc drawLineAA(sur: PSurface, p1: TPoint, p2: TPoint, color: TColor) =
xgap = fpart(x2 + 0.5) xgap = fpart(x2 + 0.5)
var xpxl2 = xend # this will be used in the main loop var xpxl2 = xend # this will be used in the main loop
var ypxl2 = ipart(yend) var ypxl2 = ipart(yend)
sur.plot(xpxl2, ypxl2, rfpart(yend) * xgap, color) sur.plotAA(xpxl2, ypxl2, rfpart(yend) * xgap, color)
sur.plot(xpxl2, ypxl2 + 1.0, fpart(yend) * xgap, color) sur.plotAA(xpxl2, ypxl2 + 1.0, fpart(yend) * xgap, color)
# main loop # main loop
for x in xpxl1.toInt + 1..xpxl2.toInt - 1: for x in xpxl1.toInt + 1..xpxl2.toInt - 1:
sur.plot(x.toFloat(), ipart(intery), rfpart(intery), color) sur.plotAA(x.toFloat(), ipart(intery), rfpart(intery), color)
sur.plot(x.toFloat(), ipart(intery) + 1.0, fpart(intery), color) sur.plotAA(x.toFloat(), ipart(intery) + 1.0, fpart(intery), color)
intery = intery + gradient intery = intery + gradient
if sdl.Init(sdl.INIT_VIDEO) < 0: if sdl.Init(sdl.INIT_VIDEO) < 0:
echo "init failed" echo "sdl init failed: " & $SDL.GetError()
if sdl_ttf.Init() < 0:
echo "sdl_ttf init failed: " & $SDL.GetError()
when isMainModule: when isMainModule:
var surf = newSurface(800, 600) #var txtSurf = drawText(
var r: TRect = (0, 0, 900, 900)
surf.fillRect(r, colWhite)
surf.drawLineAA((500, 300), (200, 270), colTan)
surf.drawEllipse(400, 300, 415, 200, colSeaGreen) var surf = newScreenSurface(800, 600)
var r: TRect = (0, 0, 900, 900)
# Draw the shapes
surf.fillRect(r, colWhite)
surf.drawLineAA((400, 599), (100, 170), colTan)
surf.drawEllipse(200, 300, 200, 30, colSeaGreen)
surf.drawHorLine(1, 300, 400, colViolet) # Check if the ellipse is the size it's suppose to be.
surf.drawVerLine(200, 300 - 30 + 1, 60, colViolet) # ^^ | i suppose it is
surf.drawEllipse(400, 300, 300, 300, colOrange)
surf.drawEllipse(5, 5, 5, 5, colGreen)
surf.drawHorLine(5, 5, 900, colRed) surf.drawHorLine(5, 5, 900, colRed)
surf.drawVerLine(5, 60, 800, colRed) surf.drawVerLine(5, 60, 800, colRed)
surf.setPixel(70, 100, colWhite)
surf.drawCircle((600, 500), 60, colRed) surf.drawCircle((600, 500), 60, colRed)
#surf.setPixel(799, 599, colGreen)
echo(fpart(5.5)) surf.drawText((300, 300), "VeraMono.ttf", "TEST", colTan, colMidnightBlue, 150)
var textSize = textBounds("VeraMono.ttf", 150, "TEST")
surf.drawText((300, 300 + textSize.height), "VeraMono.ttf", $textSize.width & ", " & $textSize.height, colDarkGreen, 50)
var mouseStartX = 0
var mouseStartY = 0
withEvents(surf, event):
case event.theType:
of SDL.QUITEV:
break
of SDL.KEYDOWN:
if event.key.keysym.sym == SDL.K_LEFT:
echo(event.key.keysym.sym)
surf.drawHorLine(395, 300, 5, colPaleGoldenRod)
echo("Drawing")
else:
echo(event.key.keysym.sym)
of SDL.MOUSEBUTTONDOWN:
# button.x/y is F* UP!
echo("MOUSEDOWN", event.button.x)
mouseStartX = event.button.x
mouseStartY = event.button.y
of SDL.MOUSEBUTTONUP:
echo("MOUSEUP ", mouseStartX)
if mouseStartX != 0 and mouseStartY != 0:
echo(mouseStartX, "->", int(event.button.x))
surf.drawLineAA((mouseStartX, MouseStartY),
(int(event.button.x), int(event.button.y)), colPaleGoldenRod)
mouseStartX = 0
mouseStartY = 0
else:
echo(event.theType)
SDL.UpdateRect(surf.s, int32(0), int32(0), int32(800), int32(600))
surf.writeToBMP("test.bmp") surf.writeToBMP("test.bmp")
SDL.Quit()

View file

@ -191,7 +191,7 @@ proc newTupleAccess(tup: PNode, i: int): PNode =
proc unpackTuple(c: PTransf, n, father: PNode) = proc unpackTuple(c: PTransf, n, father: PNode) =
# XXX: BUG: what if `n` is an expression with side-effects? # XXX: BUG: what if `n` is an expression with side-effects?
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(c.transCon.forStmt) - 3):
addSon(father, newAsgnStmt(c, c.transCon.forStmt.sons[i], addSon(father, newAsgnStmt(c, c.transCon.forStmt.sons[i],
transform(c, newTupleAccess(n, i)))) transform(c, newTupleAccess(n, i))))
@ -439,8 +439,7 @@ proc gatherVars(c: PTransf, n: PNode, marked: var TIntSet, owner: PSym,
case s.kind case s.kind
of skVar: found = not (sfGlobal in s.flags) of skVar: found = not (sfGlobal in s.flags)
of skTemp, skForVar, skParam: found = true of skTemp, skForVar, skParam: found = true
else: else: nil
nil
if found and (owner.id != s.owner.id) and if found and (owner.id != s.owner.id) and
not IntSetContainsOrIncl(marked, s.id): not IntSetContainsOrIncl(marked, s.id):
incl(s.flags, sfInClosure) incl(s.flags, sfInClosure)

View file

@ -49,6 +49,7 @@ tregex.nim;key: keyAYes!
treguse.nim;055this should be the casehugh treguse.nim;055this should be the casehugh
tromans.nim;success tromans.nim;success
tseqcon.nim;Hithere, what's your name?Hathere, what's your name? tseqcon.nim;Hithere, what's your name?Hathere, what's your name?
tseqtuple.nim;fA13msg1falsefB14msg2truefC15msg3false
tsets.nim;Ha ein F ist in s! tsets.nim;Ha ein F ist in s!
tsidee2.nim;5 tsidee2.nim;5
tsidee3.nim;5 tsidee3.nim;5

1 tack.nim 125
49 treguse.nim 055this should be the casehugh
50 tromans.nim success
51 tseqcon.nim Hithere, what's your name?Hathere, what's your name?
52 tseqtuple.nim fA13msg1falsefB14msg2truefC15msg3false
53 tsets.nim Ha ein F ist in s!
54 tsidee2.nim 5
55 tsidee3.nim 5

22
tests/accept/run/tseqtuple.nim Executable file
View file

@ -0,0 +1,22 @@
type
TMsg = tuple[
file: string,
line: int,
msg: string,
err: bool]
var s: seq[TMsg] = @[]
s.add(("fA", 13, "msg1", false))
s.add(("fB", 14, "msg2", true))
s.add(("fC", 15, "msg3", false))
for file, line, msg, err in items(s):
stdout.write(file)
stdout.write($line)
stdout.write(msg)
stdout.write($err)
#OUT fA13msg1falsefB14msg2truefC15msg3false