Mercurial > projects > ldc
changeset 41:835320b88ad6 trunk
[svn r45] Added a modified version of scrapple.qd (by downs) to the demos dir. It doesn't compile yet though :(
author | lindquist |
---|---|
date | Fri, 19 Oct 2007 07:45:35 +0200 |
parents | 8b0e809563df |
children | 0b9b286b67b6 |
files | demos/qd.d |
diffstat | 1 files changed, 316 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/demos/qd.d Fri Oct 19 07:45:35 2007 +0200 @@ -0,0 +1,316 @@ +// modified version of scrapple.qd to work with llvmdc +import std.stdio; + +//version(none) +void main() { + screen(640, 480); + pset(10, 10); + line(0, 0, 100, 100, Box, Back(Red~Black)); + for (int i=0; i<=100; i+=10) { + line(i, 0, 100-i, 100); + line(0, i, 100, 100-i); + } + circle(100, 100, 50, 15, White~Black, Fill=White~Black); + paint(200, 200, Red, Back=White); + circle(100, 100, 50, 15, White); + paint(200, 200, Black); + pset(10, 11); pset(10, 11, Black); + pset(10, 10); + SDL_Delay(5000); +} + +extern(C) { + struct SDL_Rect { + short x, y; + ushort w, h; + } + struct SDL_PixelFormat { + //SDL_Palette *palette; + void *palette; + ubyte BitsPerPixel, BytesPerPixel, Rloss, Gloss, Bloss, Aloss, Rshift, Gshift, Bshift, Ashift; + uint Rmask, Gmask, Bmask, Amask, colorkey; ubyte alpha; + } + struct SDL_Surface { + uint flags; + SDL_PixelFormat *format; + int w, h; + ushort pitch; + void *pixels; + int offset; + void *hwdata; + SDL_Rect clip_rect; + uint unused; + uint locked; + void *map; + uint format_version; + int refcount; + } + uint SDL_MapRGBA(SDL_PixelFormat *format, ubyte r, ubyte g, ubyte b, ubyte a); + void SDL_GetRGBA(uint pixel, SDL_PixelFormat *fmt, ubyte *r, ubyte *g, ubyte *b, ubyte *a); + int SDL_LockSurface(SDL_Surface *); + void SDL_UnlockSurface(SDL_Surface *); + SDL_Surface * SDL_SetVideoMode(int width, int height, int bpp, uint flags); + int SDL_Flip(SDL_Surface *); + void SDL_Delay(uint); + const uint SDL_SWSURFACE=0; + const uint SDL_HWSURFACE=1; + const uint SDL_DOUBLEBUF=0x40000000; + const uint SDL_FULLSCREEN=0x80000000; +} + +SDL_Surface *display; + +void putpixel32(SDL_Surface *surf, int x, int y, ubyte[4] col) { + uint *bufp = cast(uint *)surf.pixels + y*surf.pitch/4 + x; + *bufp = SDL_MapRGBA(surf.format, col[0], col[1], col[2], col[3]); +} + +void getpixel32(SDL_Surface *surf, int x, int y, ubyte[4] *col) { + uint *bufp = cast(uint *)surf.pixels + y*surf.pitch/4 + x; + SDL_GetRGBA(*bufp, surf.format, &(*col)[0], &(*col)[1], &(*col)[2], &(*col)[3]); +} + +struct rgb { + ubyte[3] values; + rgb opCat(rgb other) { + rgb res; + foreach (id, ref v; res.values) v=(values[id]+other.values[id])/2; + return res; + } + bool opEquals(rgb r) { + return values == r.values; + } +} + +void putpixel(SDL_Surface *surf, int x, int y, rgb c) { + if ( (x<0) || (y<0) || (x!<surf.w) || (y!<surf.h) ) return; + putpixel32(surf, x, y, [c.values[0], c.values[1], c.values[2], 0]); +} + +const rgb White={[255, 255, 255]}; +const rgb Black={[0, 0, 0]}; +const rgb Red={[255, 0, 0]}; +const rgb Green={[0, 255, 0]}; +const rgb Blue={[0, 0, 255]}; +rgb color=White; +rgb back=Black; + +template failfind(U, T...) { + static if (T.length) + static if (is(T[0] == U)) static assert(false, "Duplicate "~U.stringof~" found!"); + else const bool failfind=failfind!(U, T[1..$]); + else + const bool failfind=true; +} + +template select(U, T...) { + static if(T.length) + static if (is(U == T[0])) { static if (failfind!(U, T[1..$])) { }; const int select = 0; } + else + static if (select!(U, T[1..$]) != -1) + const int select = 1 + select!(U, T[1..$]); + else + const int select = -1; + else + const int select = -1; +} + +typedef rgb back_rgb; +back_rgb Back(rgb r) { return cast(back_rgb) r; } +back_rgb Back() { return cast(back_rgb) back; } +typedef rgb box_rgb; +box_rgb Box(rgb r) { return cast(box_rgb) r; } +box_rgb Box() { return cast(box_rgb) color; } +alias Back Fill; + +void execParams(T...)(T params) { + const int col=select!(rgb, T); + static if (col != -1) color=params[col]; + const int bcol=select!(back_rgb, T); + static if (bcol != -1) back=cast(rgb) params[bcol]; + const int boxcol=select!(box_rgb, T); + static if (boxcol != -1) color=cast(rgb) params[boxcol]; +} + +void pset(T...)(int x, int y, T params) { + SDL_LockSurface(display); + scope(exit) { SDL_UnlockSurface(display); SDL_Flip(display); } + execParams(params); + putpixel(display, x, y, color); +} + +rgb pget(int x, int y) { + SDL_LockSurface(display); + scope(exit) SDL_UnlockSurface(display); + ubyte[4] c; + getpixel32(display, x, y, &c); + rgb res; res.values[]=c[0..3]; return res; +} + +void swap(T)(ref T a, ref T b) { T c=a; a=b; b=c; } + +T abs(T)(T f) { return f < 0 ? -f : f; } + +void bresenham(bool countUp=true, bool steep=false)(int x0, int y0, int x1, int y1) { + auto deltax = x1 - x0, deltay = y1 - y0; + static if (steep) { + auto Δerror = cast(float)deltax / cast(float)deltay; + auto var2 = x0; + const string name="y"; + } else { + auto Δerror = cast(float)deltay / cast(float)deltax; + auto var2 = y0; + const string name="x"; + } + auto error = 0f; + for (auto var1 = mixin(name~'0'); var1 <= mixin(name~'1'); ++var1) { + static if (steep) putpixel(display, var2, var1, color); + else putpixel(display, var1, var2, color); + error += Δerror; + if (abs(error) >= 1f) { static if (countUp) { var2++; error -= 1f; } else { var2--; error += 1f; }} + } +} + +T max(T)(T a, T b) { return a>b?a:b; } +T min(T)(T a, T b) { return a<b?a:b; } + +void line(T...)(int x0, int y0, int x1, int y1, T p) { + execParams(p); + static if (select!(back_rgb, T)!=-1) { + SDL_LockSurface(display); + scope(exit) { SDL_UnlockSurface(display); SDL_Flip(display); } + auto xend=max(x0, x1); + for (int x=min(x0, x1); x<=xend; ++x) { + auto yend=max(y0, y1); + for (int y=min(y0, y1); y<=yend; ++y) { + putpixel(display, x, y, back); + } + } + } + static if (select!(box_rgb, T)!=-1) { + line(x0, y0, x1, y0); + line(x1, y0, x1, y1); + line(x1, y1, x0, y1); + line(x0, y1, x0, y0); + } + static if (select!(box_rgb, T)+select!(back_rgb, T)==-2) { + SDL_LockSurface(display); + scope(exit) { SDL_UnlockSurface(display); SDL_Flip(display); } + bool steep = abs(y1 - y0) > abs(x1 - x0); + void turn() { swap(x0, x1); swap(y0, y1); } + if (steep) { if (y1 < y0) turn; } + else { if (x1 < x0) turn; } + bool stepUp=steep ? (x0 < x1) : (y0 < y1); + if (steep) { + if (stepUp) bresenham!(true, true)(x0, y0, x1, y1); + else bresenham!(false, true)(x0, y0, x1, y1); + } else { + if (stepUp) bresenham!(true, false)(x0, y0, x1, y1); + else bresenham!(false, false)(x0, y0, x1, y1); + } + } +} + +import llvm.intrinsic; +alias llvm_sqrt sqrt; + +template circle_bresenham_pass(bool first) { + const string xy=(first?"x":"y"); + const string yx=(first?"y":"x"); + const string str=" + auto x="~(first?"xradius":"0")~"; + auto y="~(first?"0":"yradius")~"; + auto xchange=yradius*yradius*"~(first?"(1-2*xradius)":"1")~"; + auto ychange=xradius*xradius*"~(first?"1":"(1-2*yradius)")~"; + auto error=0; + auto stopx="~(first?"y2square*xradius":"0")~"; + auto stopy="~(first?"0":"x2square*yradius")~"; + while (stopx"~(first?">=":"<=")~"stopy) { + putpixel(display, cx+x, cy+y, color); + putpixel(display, cx+x, cy-y, color); + putpixel(display, cx-x, cy+y, color); + putpixel(display, cx-x, cy-y, color); + "~yx~"++; + stop"~yx~"+="~xy~"2square; + error+="~yx~"change; + "~yx~"change+="~xy~"2square; + if ((2*error+"~xy~"change)>0) { + --"~xy~"; + stop"~xy~"-="~yx~"2square; + error+="~xy~"change; + "~xy~"change+="~yx~"2square; + } + } + "; +} + +void circle(T...)(int cx, int cy, int xradius, T t) { + SDL_LockSurface(display); + scope(exit) { SDL_UnlockSurface(display); SDL_Flip(display); } + execParams(t); + auto yradius=xradius; + static if (T.length && is(T[0]: int)) yradius=t[0]; + static if (select!(back_rgb, T) != -1) { + auto ratio=xradius*1f/yradius; + for (int i=0; i<=yradius; ++i) { + ushort j=cast(ushort)(sqrt(cast(real)(yradius*yradius-i*i))*ratio); + for (int lx=cx-j; lx<=cx+j; ++lx) putpixel(display, lx, cy+i, back); + for (int lx=cx-j; lx<=cx+j; ++lx) putpixel(display, lx, cy-i, back); + } + } + auto x2square=2*xradius*xradius; + auto y2square=2*yradius*yradius; + { mixin(circle_bresenham_pass!(true).str); } + { mixin(circle_bresenham_pass!(false).str); } +} + +struct floodfill_node { + int x, y; + static floodfill_node opCall(int x, int y) { + floodfill_node res; + res.x=x; res.y=y; + return res; + } +} + +void paint(T...)(int x, int y, T t) { + SDL_LockSurface(display); + scope(exit) { SDL_UnlockSurface(display); SDL_Flip(display); } + execParams(t); + bool border=true; + if (select!(back_rgb, T) == -1) { + back=pget(x, y); + border=false; + } + bool check(rgb r) { + if (border) return (r != back) && (r != color); + else return r == back; + } + if (back == color) throw new Exception("Having identical backgrounds and foregrounds will severely mess up floodfill."); + alias floodfill_node node; + node[] queue; + queue ~= node(x, y); + size_t count=0; + while (count<queue.length) { + scope(exit) count++; + with (queue[count]) { + if (check(pget(x, y))) { + int w=x, e=x; + if (w<display.w) do w++; while ((w<display.w) && check(pget(w, y))); + if (e>=0) do e--; while (e>=0 && check(pget(e, y))); + //SDL_Flip(display); + for (int i=e+1; i<w; ++i) { + putpixel(display, i, y, color); + if (y && check(pget(i, y-1)) && ((i==w-1)||!check(pget(i+1, y-1)))) queue ~= node(i, y-1); + if ((y < display.h-1) && check(pget(i, y+1)) && ((i==w-1)||!check(pget(i+1, y+1)))) queue ~= node(i, y+1); + } + } + } + } +} + +void screen(size_t w, size_t h) { + display = SDL_SetVideoMode(w, h, 32, SDL_SWSURFACE); +} + +void cls() { line(0, 0, display.w-1, display.h-1, Fill=Black); }