bugfix: tseqtuple

This commit is contained in:
Andreas Rumpf
2010-03-10 00:40:34 +01:00
parent 7dff3e64bb
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
## backends some day.
import colors
import colors, math
from sdl import PSurface # Bug
from sdl_ttf import OpenFont
type
TRect* = tuple[x, y, width, height: int]
@@ -23,6 +24,8 @@ type
w, h: int
s: sdl.PSurface
ESDLError = object of EBase
proc surfaceFinalizer(s: PSurface) = sdl.freeSurface(s.s)
proc newSurface*(width, height: int): PSurface =
@@ -35,8 +38,18 @@ proc newSurface*(width, height: int): PSurface =
assert(not sdl.MustLock(result.s))
#proc textBounds*(text: string): tuple[len, height: int]
#proc drawText*(sur: PSurface, p: TPoint, text: string)
proc newScreenSurface(width, height: int): PSurface =
## 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) =
## 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) =
# 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) =
## draws a circle with center `p` and radius `r` with the given color
## 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
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)
assert video != nil
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:
setPix(video, pitch, j, i, col)
proc Plot4EllipsePoints(sur: PSurface, CX, CY, X, Y: Natural, col: TColor) =
var video = cast[PPixels](sur.s.pixels)
var pitch = sur.s.pitch div ColSize
setPix(video, pitch, CX+X, CY+Y, col)
setPix(video, pitch, CX-X, CY+Y, col)
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)
if CX-X < sur.s.w and CY+Y < sur.s.h:
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)
if CX+X < sur.s.w and CY-Y < sur.s.h:
setPix(video, pitch, CX+X, CY-Y, col)
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
X, Y: Natural
XChange, YChange: Natural
@@ -317,27 +421,29 @@ proc drawEllipse*(sur: PSurface, CX, CY, XRadius, YRadius: Natural, col: TColor)
inc(YChange,TwoASquare)
proc plot(sur: PSurface, x, y, c: float, color: TColor) =
var video = cast[PPixels](sur.s.pixels)
var pitch = sur.s.pitch div ColSize
var pixColor = getPix(video, pitch, x.toInt, y.toInt)
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 pitch = sur.s.pitch div ColSize
setPix(video, pitch, x.toInt(), y.toInt(),
pixColor.intensity(1.0 - c) + color.intensity(c))
import math
var pixColor = getPix(video, pitch, x.toInt, y.toInt)
setPix(video, pitch, x.toInt(), y.toInt(),
pixColor.intensity(1.0 - c) + color.intensity(c))
proc ipart(x: float): float =
return x.trunc()
proc fpart(x: float): float =
return x - ipart(x)
proc rfpart(x: float): float =
return 1.0 - fpart(x)
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(),
p1.y.toFloat(), p2.y.toFloat())
var dx = x2 - x1
var dy = y2 - y1
if abs(dx) < abs(dy):
@@ -354,41 +460,87 @@ proc drawLineAA(sur: PSurface, p1: TPoint, p2: TPoint, color: TColor) =
var xgap = rfpart(x1 + 0.5)
var xpxl1 = xend # this will be used in the main loop
var ypxl1 = ipart(yend)
sur.plot(xpxl1, ypxl1, rfpart(yend) * xgap, color)
sur.plot(xpxl1, ypxl1 + 1.0, fpart(yend) * xgap, color)
sur.plotAA(xpxl1, ypxl1, rfpart(yend) * xgap, color)
sur.plotAA(xpxl1, ypxl1 + 1.0, fpart(yend) * xgap, color)
var intery = yend + gradient # first y-intersection for the main loop
# handle second endpoint
xend = x2 # Should be round(x1), but since this is an int anyway..
yend = y2 + gradient * (xend - x2)
xgap = fpart(x2 + 0.5)
var xpxl2 = xend # this will be used in the main loop
var ypxl2 = ipart (yend)
sur.plot(xpxl2, ypxl2, rfpart(yend) * xgap, color)
sur.plot(xpxl2, ypxl2 + 1.0, fpart(yend) * xgap, color)
var ypxl2 = ipart(yend)
sur.plotAA(xpxl2, ypxl2, rfpart(yend) * xgap, color)
sur.plotAA(xpxl2, ypxl2 + 1.0, fpart(yend) * xgap, color)
# main loop
for x in xpxl1.toInt + 1..xpxl2.toInt - 1:
sur.plot(x.toFloat(), ipart(intery), rfpart(intery), color)
sur.plot(x.toFloat(), ipart(intery) + 1.0, fpart(intery), color)
sur.plotAA(x.toFloat(), ipart(intery), rfpart(intery), color)
sur.plotAA(x.toFloat(), ipart(intery) + 1.0, fpart(intery), color)
intery = intery + gradient
if sdl.Init(sdl.INIT_VIDEO) < 0:
echo "init failed"
if sdl.Init(sdl.INIT_VIDEO) < 0:
echo "sdl init failed: " & $SDL.GetError()
if sdl_ttf.Init() < 0:
echo "sdl_ttf init failed: " & $SDL.GetError()
when isMainModule:
var surf = newSurface(800, 600)
#var txtSurf = drawText(
var surf = newScreenSurface(800, 600)
var r: TRect = (0, 0, 900, 900)
# Draw the shapes
surf.fillRect(r, colWhite)
surf.drawLineAA((500, 300), (200, 270), colTan)
surf.drawLineAA((400, 599), (100, 170), colTan)
surf.drawEllipse(400, 300, 415, 200, colSeaGreen)
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.drawVerLine(5, 60, 800, colRed)
surf.setPixel(70, 100, colWhite)
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")
SDL.Quit()

View File

@@ -191,7 +191,7 @@ proc newTupleAccess(tup: PNode, i: int): PNode =
proc unpackTuple(c: PTransf, n, father: PNode) =
# 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],
transform(c, newTupleAccess(n, i))))
@@ -439,8 +439,7 @@ proc gatherVars(c: PTransf, n: PNode, marked: var TIntSet, owner: PSym,
case s.kind
of skVar: found = not (sfGlobal in s.flags)
of skTemp, skForVar, skParam: found = true
else:
nil
else: nil
if found and (owner.id != s.owner.id) and
not IntSetContainsOrIncl(marked, s.id):
incl(s.flags, sfInClosure)

View File

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