diff options
Diffstat (limited to 'lib/impure/graphics.nim')
-rw-r--r-- | lib/impure/graphics.nim | 110 |
1 files changed, 55 insertions, 55 deletions
diff --git a/lib/impure/graphics.nim b/lib/impure/graphics.nim index 1b3d1d5b6..8bd769fd8 100644 --- a/lib/impure/graphics.nim +++ b/lib/impure/graphics.nim @@ -9,7 +9,7 @@ ## This module implements graphical output for Nim; the current ## implementation uses SDL but the interface is meant to support multiple -## backends some day. There is no need to init SDL as this module does that +## backends some day. There is no need to init SDL as this module does that ## implicitly. import colors, math @@ -24,7 +24,7 @@ type Surface* {.pure, final.} = object w*, h*: Natural s*: sdl.PSurface - + EGraphics* = object of IOError Font {.pure, final.} = object @@ -35,7 +35,7 @@ type proc toSdlColor*(c: Color): sdl.Color = ## Convert colors.Color to sdl.Color - var x = c.extractRGB + var x = c.extractRGB result.r = x.r and 0xff result.g = x.g and 0xff result.b = x.b and 0xff @@ -43,7 +43,7 @@ proc toSdlColor*(c: Color): sdl.Color = proc createSdlColor*(sur: PSurface, c: Color, alpha: int = 0): int32 = ## Creates a color using ``sdl.MapRGBA``. var x = c.extractRGB - return sdl.mapRGBA(sur.s.format, x.r and 0xff, x.g and 0xff, + return sdl.mapRGBA(sur.s.format, x.r and 0xff, x.g and 0xff, x.b and 0xff, alpha and 0xff) proc toSdlRect*(r: Rect): sdl.Rect = @@ -53,26 +53,26 @@ proc toSdlRect*(r: Rect): sdl.Rect = result.w = uint16(r.width) result.h = uint16(r.height) -proc raiseEGraphics = +proc raiseEGraphics = raise newException(EGraphics, $sdl.getError()) - + proc surfaceFinalizer(s: PSurface) = sdl.freeSurface(s.s) - + proc newSurface*(width, height: int): PSurface = ## creates a new surface. new(result, surfaceFinalizer) result.w = width result.h = height - result.s = sdl.createRGBSurface(sdl.SWSURFACE, width, height, + result.s = sdl.createRGBSurface(sdl.SWSURFACE, width, height, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0) if result.s == nil: raiseEGraphics() - + assert(not sdl.mustLock(result.s)) proc fontFinalizer(f: PFont) = closeFont(f.f) -proc newFont*(name = "VeraMono.ttf", size = 9, color = colBlack): PFont = +proc newFont*(name = "VeraMono.ttf", size = 9, color = colBlack): PFont = ## Creates a new font object. Raises ``EIO`` if the font cannot be loaded. new(result, fontFinalizer) result.f = openFont(name, size.cint) @@ -84,7 +84,7 @@ var defaultFont*: PFont ## default font that is used; this needs to initialized ## by the client! -proc initDefaultFont*(name = "VeraMono.ttf", size = 9, color = colBlack) = +proc initDefaultFont*(name = "VeraMono.ttf", size = 9, color = colBlack) = ## initializes the `defaultFont` var. defaultFont = newFont(name, size, color) @@ -98,7 +98,7 @@ proc newScreenSurface*(width, height: int): PSurface = raiseEGraphics() 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 ## BMP file. if sdl.saveBMP(sur.s, filename) != 0: raise newException(IOError, "cannot write: " & filename) @@ -111,7 +111,7 @@ type template setPix(video, pitch, x, y, col: expr): stmt = video[y * pitch + x] = int32(col) -template getPix(video, pitch, x, y: expr): expr = +template getPix(video, pitch, x, y: expr): expr = colors.Color(video[y * pitch + x]) const @@ -120,7 +120,7 @@ const proc getPixel(sur: PSurface, x, y: Natural): colors.Color {.inline.} = assert x <% sur.w assert y <% sur.h - result = getPix(cast[PPixels](sur.s.pixels), sur.s.pitch.int div ColSize, + result = getPix(cast[PPixels](sur.s.pixels), sur.s.pitch.int div ColSize, x, y) proc setPixel(sur: PSurface, x, y: Natural, col: colors.Color) {.inline.} = @@ -146,7 +146,7 @@ proc `[]=`*(sur: PSurface, x, y: int, col: Color) = ## set the pixel at position ``(x, y)``. No range checking is done! setPixel(sur, x, y, col) -proc blit*(destSurf: PSurface, destRect: Rect, srcSurf: PSurface, +proc blit*(destSurf: PSurface, destRect: Rect, srcSurf: PSurface, srcRect: Rect) = ## Copies ``srcSurf`` into ``destSurf`` var destTRect, srcTRect: sdl.Rect @@ -175,7 +175,7 @@ proc drawText*(sur: PSurface, p: Point, text: string, font = defaultFont) = ## font. var textSur: PSurface # This surface will have the text drawn on it new(textSur, surfaceFinalizer) - + # Render the text textSur.s = sdl_ttf.renderTextBlended(font.f, text, font.color) # Merge the text surface with sur @@ -183,14 +183,14 @@ proc drawText*(sur: PSurface, p: Point, text: string, font = defaultFont) = proc drawText*(sur: PSurface, p: Point, text: string, bg: Color, font = defaultFont) = - ## Draws text, at location ``p`` with font ``font``. ``bg`` + ## Draws text, at location ``p`` with font ``font``. ``bg`` ## is the background color. var textSur: PSurface # This surface will have the text drawn on it new(textSur, surfaceFinalizer) textSur.s = sdl_ttf.renderTextShaded(font.f, text, font.color, toSdlColor(bg)) # Merge the text surface with sur sur.blit((p.x, p.y, sur.w, sur.h), textSur, (0, 0, sur.w, sur.h)) - + proc drawCircle*(sur: PSurface, p: Point, r: Natural, color: Color) = ## draws a circle with center `p` and radius `r` with the given color ## onto the surface `sur`. @@ -205,7 +205,7 @@ proc drawCircle*(sur: PSurface, p: Point, r: Natural, color: Color) = if x+px <% sur.w: if y+py <% sur.h: setPix(video, pitch, x+px, y+py, color) if y-py <% sur.h: setPix(video, pitch, x+px, y-py, color) - + if x-px <% sur.w: if y+py <% sur.h: setPix(video, pitch, x-px, y+py, color) if y-py <% sur.h: setPix(video, pitch, x-px, y-py, color) @@ -213,7 +213,7 @@ proc drawCircle*(sur: PSurface, p: Point, r: Natural, color: Color) = if x+py <% sur.w: if y+px <% sur.h: setPix(video, pitch, x+py, y+px, color) if y-px <% sur.h: setPix(video, pitch, x+py, y-px, color) - + if x-py <% sur.w: if y+px <% sur.h: setPix(video, pitch, x-py, y+px, color) if y-px <% sur.h: setPix(video, pitch, x-py, y-px, color) @@ -225,10 +225,10 @@ proc drawCircle*(sur: PSurface, p: Point, r: Natural, color: Color) = py = py - 1 px = px + 1 -proc `>-<`(val: int, s: PSurface): int {.inline.} = +proc `>-<`(val: int, s: PSurface): int {.inline.} = return if val < 0: 0 elif val >= s.w: s.w-1 else: val -proc `>|<`(val: int, s: PSurface): int {.inline.} = +proc `>|<`(val: int, s: PSurface): int {.inline.} = return if val < 0: 0 elif val >= s.h: s.h-1 else: val proc drawLine*(sur: PSurface, p1, p2: Point, color: Color) = @@ -242,7 +242,7 @@ proc drawLine*(sur: PSurface, p1, p2: Point, color: Color) = var dy = y1 - y0 var dx = x1 - x0 if dy < 0: - dy = -dy + dy = -dy stepy = -1 else: stepy = 1 @@ -251,7 +251,7 @@ proc drawLine*(sur: PSurface, p1, p2: Point, color: Color) = stepx = -1 else: stepx = 1 - dy = dy * 2 + dy = dy * 2 dx = dx * 2 var video = cast[PPixels](sur.s.pixels) var pitch = sur.s.pitch.int div ColSize @@ -328,17 +328,17 @@ proc drawRect*(sur: PSurface, r: Rect, color: Color) = if (r.x >= 0 and r.x <= sur.s.w) and (r.y >= 0 and r.y <= sur.s.h): var minW = min(sur.s.w - r.x, r.width) var minH = min(sur.s.h - r.y, r.height) - + # Draw Top for i in 0 .. minW - 1: setPix(video, pitch, r.x + i, r.y, color) setPix(video, pitch, r.x + i, r.y + minH - 1, color) # Draw bottom - + # Draw left side for i in 0 .. minH - 1: setPix(video, pitch, r.x, r.y + i, color) setPix(video, pitch, r.x + minW - 1, r.y + i, color) # Draw right side - + proc fillRect*(sur: PSurface, r: Rect, col: Color) = ## Fills a rectangle using sdl's ``FillRect`` function. var rect = toSdlRect(r) @@ -350,23 +350,23 @@ proc plot4EllipsePoints(sur: PSurface, cx, cy, x, y: Natural, col: Color) = var pitch = sur.s.pitch.int div ColSize if cx+x <= sur.s.w-1: if cy+y <= sur.s.h-1: setPix(video, pitch, cx+x, cy+y, col) - if cy-y <= sur.s.h-1: setPix(video, pitch, cx+x, cy-y, col) + if cy-y <= sur.s.h-1: setPix(video, pitch, cx+x, cy-y, col) if cx-x <= sur.s.w-1: if cy+y <= sur.s.h-1: setPix(video, pitch, cx-x, cy+y, col) if cy-y <= sur.s.h-1: setPix(video, pitch, cx-x, cy-y, col) -proc drawEllipse*(sur: PSurface, cx, cy, xRadius, yRadius: Natural, +proc drawEllipse*(sur: PSurface, cx, cy, xRadius, yRadius: Natural, col: Color) = - ## Draws an ellipse, ``CX`` and ``CY`` specify the center X and Y of the + ## Draws an ellipse, ``CX`` and ``CY`` specify the center X and Y of the ## ellipse, ``XRadius`` and ``YRadius`` specify half the width and height ## of the ellipse. - var + var x, y: Natural xChange, yChange: int ellipseError: Natural twoASquare, twoBSquare: Natural stoppingX, stoppingY: Natural - + twoASquare = 2 * xRadius * xRadius twoBSquare = 2 * yRadius * yRadius x = xRadius @@ -376,7 +376,7 @@ proc drawEllipse*(sur: PSurface, cx, cy, xRadius, yRadius: Natural, ellipseError = 0 stoppingX = twoBSquare * xRadius stoppingY = 0 - + while stoppingX >= stoppingY: # 1st set of points, y` > - 1 sur.plot4EllipsePoints(cx, cy, x, y, col) inc(y) @@ -388,7 +388,7 @@ proc drawEllipse*(sur: PSurface, cx, cy, xRadius, yRadius: Natural, dec(stoppingX, twoBSquare) inc(ellipseError, xChange) inc(xChange, twoBSquare) - + # 1st point set is done; start the 2nd set of points x = 0 y = yRadius @@ -408,7 +408,7 @@ proc drawEllipse*(sur: PSurface, cx, cy, xRadius, yRadius: Natural, dec(stoppingY, twoASquare) inc(ellipseError, yChange) inc(yChange,twoASquare) - + proc plotAA(sur: PSurface, x, y: int, c: float, color: Color) = if (x > 0 and x < sur.s.w) and (y > 0 and y < sur.s.h): @@ -419,43 +419,43 @@ proc plotAA(sur: PSurface, x, y: int, c: float, color: Color) = setPix(video, pitch, x, y, pixColor.intensity(1.0 - c) + color.intensity(c)) - -template ipart(x: expr): expr = floor(x) + +template ipart(x: expr): expr = floor(x) template cround(x: expr): expr = ipart(x + 0.5) template fpart(x: expr): expr = x - ipart(x) template rfpart(x: expr): expr = 1.0 - fpart(x) proc drawLineAA*(sur: PSurface, p1, p2: Point, color: Color) = - ## Draws a anti-aliased line from ``p1`` to ``p2``, using Xiaolin Wu's + ## 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()) var dx = x2 - x1 var dy = y2 - y1 - + var ax = dx if ax < 0'f64: ax = 0'f64 - ax var ay = dy if ay < 0'f64: ay = 0'f64 - ay - + if ax < ay: swap(x1, y1) swap(x2, y2) swap(dx, dy) - + template doPlot(x, y: int, c: float, color: Color): stmt = if ax < ay: sur.plotAA(y, x, c, color) else: sur.plotAA(x, y, c, color) - + if x2 < x1: swap(x1, x2) swap(y1, y2) - + var gradient = dy / dx # handle first endpoint var xend = cround(x1) @@ -509,19 +509,19 @@ when not defined(testing) and isMainModule: # Draw the shapes surf.drawLineAA((150, 170), (400, 471), colTan) surf.drawLine((100, 170), (400, 471), colRed) - + surf.drawEllipse(200, 300, 200, 30, colSeaGreen) - surf.drawHorLine(1, 300, 400, colViolet) + 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.drawCircle((600, 500), 60, colRed) - + surf.fillRect((50, 50, 100, 100), colFuchsia) surf.fillRect((150, 50, 100, 100), colGreen) surf.drawRect((50, 150, 100, 100), colGreen) @@ -530,12 +530,12 @@ when not defined(testing) and isMainModule: surf.drawHorLine(250, 150, 100, colRed) surf.drawLineAA((592, 160), (592, 280), colPurple) - + #surf.drawText((300, 300), "TEST", colMidnightBlue) #var textSize = textBounds("TEST") #surf.drawText((300, 300 + textSize.height), $textSize.width & ", " & # $textSize.height, colDarkGreen) - + var mouseStartX = -1 var mouseStartY = -1 withEvents(surf, event): @@ -561,17 +561,17 @@ when not defined(testing) and isMainModule: surf.drawLineAA((mouseStartX, mouseStartY), (int(mbd.x), int(mbd.y)), colPurple) mouseStartX = -1 mouseStartY = -1 - + of sdl.MOUSEMOTION: var mm = sdl.evMouseMotion(eventp) if mouseStartX != -1 and mouseStartY != -1: surf.drawLineAA((mouseStartX, mouseStartY), (int(mm.x), int(mm.y)), colPurple) #echo(mm.x, " ", mm.y, " ", mm.yrel) - + else: discard "echo(event.kind)" - + sdl.updateRect(surf.s, 0, 0, 800, 600) - + surf.writeToBMP("test.bmp") sdl.quit() |