rsbx@cbmvax.commodore.com (Raymond S. Brand) (04/17/91)
Due to the number of requests, I'm posting this instead of emailing. The request was for a way to rotate a bitmap 90 degrees without having to do a readpixel/writepixel for each pixel in the area to rotate. What follows is a shar file with the source (Amiga but you can understand it anyway :-) to 2 rotate functions and 2 test programs. rsbx ------------------------------------------------------------------------ Raymond S. Brand rsbx@cbmvax.commodore.com Commodore-Amiga Engineering ...!uunet!cbmvax!rsbx 1200 Wilson Drive (215)-431-9100 West Chester PA 19380 "Looking" ------------------------------------------------------------------------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # readme # rastport.c # rotate1.c # rotatebitmap.c # rotatebitmap.h # test.c # test.lnk # test1.c # test1.lnk # This archive created: Wed Apr 17 11:57:26 1991 # By: Raymond S. Brand (Commodore-Amiga Inc, West Chester, PA) export PATH; PATH=/bin:$PATH if test -f 'readme' then echo shar: will not over-write existing file "'readme'" else sed 's/^X//' << \HI_MOM > 'readme' XWARNING: I use a Hedley display (big). You may need to change some sizes in X the test/demonstration programs if you don't. X XThe algorithm for the rotate square is from the Smalltalk-80 book referenced Xbelow; the rotate rectangle algorithm is a modification of the square Xalgorithm. X XThe code is not recursive and makes O(log2(M)) calls to the blitter Xfunctions where M is MAX(X_size, Y_size) of the area to rotate. X XIf you do something interesting with this, please let me know what you did. X X rsbx X XReferences: X Goldberg and Robson, Smalltalk-80: The Language and Implementation, X Addison Wesley 1983, pp 408-411. X X------------------------------------------------------------------------ X Raymond S. Brand rsbx@cbmvax.commodore.com X Commodore-Amiga Engineering ...!uunet!cbmvax!rsbx X 1200 Wilson Drive (215)-431-9100 X West Chester PA 19380 "Looking" X------------------------------------------------------------------------ HI_MOM fi # end of overwriting check if test -f 'rastport.c' then echo shar: will not over-write existing file "'rastport.c'" else sed 's/^X//' << \HI_MOM > 'rastport.c' X/* X** $Id$ X** X** Create and free RastPorts. X** X** (C) Copyright 1991 Raymond S. Brand X** All Rights Reserved X*/ X X X#include <exec/types.h> X#include <graphics/rastport.h> X#include <proto/graphics.h> X#include <proto/exec.h> X Xstruct RastPort *NewRastPort(int x, int y, int depth) X { X struct RastPort *rp; X struct BitMap *bm; X int i; X X if (!(rp = AllocMem(sizeof(struct RastPort), 0))) X { X goto Exit1; X } X X if (!(bm = AllocMem(sizeof(struct BitMap), 0))) X { X goto Exit2; X } X X for (i = 0; i < depth; i++) X { X bm->Planes[i] = NULL; X } X X for (i = 0; i < depth; i++) X { X if (!(bm->Planes[i] = AllocRaster(x, y))) X { X goto Exit3; X } X } X X InitBitMap(bm, depth, x, y); X InitRastPort(rp); X rp->BitMap = bm; X X return rp; X X X XExit3: X for (i = 0; i < depth; i++) X { X if (bm->Planes[i]) X { X FreeRaster(bm->Planes[i], x, y); X } X } X FreeMem(bm, sizeof(struct BitMap)); XExit2: X FreeMem(rp, sizeof(struct RastPort)); XExit1: X return 0; X } X X Xvoid FreeRastPort(struct RastPort *rp, int x, int y, int depth) X { X int i; X X if (!rp) X { X return; X } X X if (rp->BitMap) X { X for (i = 0; i < depth; i++) X { X if (rp->BitMap->Planes[i]) X { X FreeRaster(rp->BitMap->Planes[i], x, y); X } X } X FreeMem(rp->BitMap, sizeof(struct BitMap)); X } X X FreeMem(rp, sizeof(struct RastPort)); X } HI_MOM fi # end of overwriting check if test -f 'rotate1.c' then echo shar: will not over-write existing file "'rotate1.c'" else sed 's/^X//' << \HI_MOM > 'rotate1.c' X/* X** $Id$ X** X** Rotate a retacngular area 90 deg. to another retangular area. X** X** (C) Copyright 1991 Raymond S. Brand X** All Rights Reserved X*/ X X X#include <exec/types.h> X#include <graphics/rastport.h> X#include <proto/graphics.h> X#include "rotatebitmap.h" X#include <math.h> X X Xextern struct RastPort *NewRastPort(int x, int y, int depth); Xextern void FreeRastPort(struct RastPort *rp, int x, int y, int depth); X X Xint Rotate(struct RastPort *src, int OsrcX, int Osrcy, struct RastPort *dst, int OdstX, int OdstY, int sizeX, int sizeY, X struct RastPort *mask, struct RastPort *temp) X { X int s; X int q; X int a; X int b; X int z; X int n; X/* X * struct RastPort *mask; X * struct RastPort *temp; X * int depth; X */ X X s = min(sizeX, sizeY); X X q = 1; X X while (q < s) X { X q <<= 1; X } X X s = q >> 1; X q = s >> 1; X/* X * depth = dst->BitMap->Depth; X * X * if (!(temp = NewRastPort(sizeX, sizeY, depth))) X * { X * return ERROR_NEWRASTPORT_FAILED; X * } X * X * if (!(mask = NewRastPort(sizeX, sizeY, depth))) X * { X * FreeRastPort(temp, sizeX, sizeY, depth); X * return ERROR_NEWRASTPORT_FAILED; X * } X */ X ClipBlit(mask, 0, 0, mask, 0, 0, sizeX, sizeY, OP_D_EQ_ZERO ); X X a = b = 0; X X if (sizeX > sizeY) X { X a = sizeX - (sizeX%s); X } X else X { X b = sizeY - (sizeY%s); X } X X while (q) X { X if ((b+s) <= sizeY) X { X for (z=0; z<a; z+=s) X { X X ClipBlit( src, b, sizeX-z-s, dst, z, b, s, s, OP_D_EQ_S ); X X ClipBlit(mask, z, b, mask, z, b, q, q, OP_D_EQ_ONE ); X } X b += s; X } X X if ((a+s) <= sizeX) X { X for (z=0; z<b; z+=s) X { X X ClipBlit( src, z, sizeX-a-s, dst, a, z, s, s, OP_D_EQ_S ); X X ClipBlit(mask, a, z, mask, a, z, q, q, OP_D_EQ_ONE ); X } X a += s; X } X X /* X * exchange right & left halves X */ X ClipBlit(mask, 0, 0, temp, 0, 0, a, b, OP_D_EQ_S ); X ClipBlit(mask, 0, 0, temp, 0, q, a, b-q, OP_D_EQ_S_OR_D ); X ClipBlit( dst, 0, 0, temp, 0, 0, a, b, OP_D_EQ_S_AND_D ); X ClipBlit(temp, 0, 0, dst, 0, 0, a, b, OP_D_EQ_S_XOR_D ); X ClipBlit( dst, q, 0, temp, 0, 0, a-q, b, OP_D_EQ_S_XOR_D ); X ClipBlit( dst, q, 0, dst, 0, 0, a-q, b, OP_D_EQ_S_OR_D ); X ClipBlit(temp, 0, 0, dst, q, 0, a-q, b, OP_D_EQ_S_XOR_D ); X X /* X * exchange diagonals X */ X ClipBlit( dst, 0, 0, temp, 0, 0, a, b, OP_D_EQ_S ); X ClipBlit( dst, q, q, temp, 0, 0, a-q, b-q, OP_D_EQ_S_XOR_D ); X ClipBlit(mask, 0, 0, temp, 0, 0, a, b, OP_D_EQ_S_AND_D ); X ClipBlit(temp, 0, 0, dst, 0, 0, a, b, OP_D_EQ_S_XOR_D ); X ClipBlit(temp, 0, 0, dst, q, q, a-q, b-q, OP_D_EQ_S_XOR_D ); X X X n = q>>1; X ClipBlit(mask, n, n, mask, 0, 0, a-n, b-n, OP_D_EQ_S_AND_D ); X ClipBlit(mask, 0, 0, mask, 0, q, a, b-q, OP_D_EQ_S_OR_D ); X ClipBlit(mask, 0, 0, mask, q, 0, a-q, b, OP_D_EQ_S_OR_D ); X X s = q; X q >>= 1; X } X X/* X * LINEROTATE X */ X if (b < sizeY) X { X for (z=0; z<a; z++) X { X SetAPen(dst, ReadPixel(src, b, sizeX-z-1)); X WritePixel(dst, z, b); X } X b++; X } X X if (a < sizeX) X { X for (z=0; z<b; z++) X { X SetAPen(dst, ReadPixel(src, z, sizeX-a-1)); X WritePixel(dst, a, z); X } X } X X/* X * FreeRastPort(temp, sizeX, sizeY, depth); X * FreeRastPort(mask, sizeX, sizeY, depth); X */ X return 0; X } HI_MOM fi # end of overwriting check if test -f 'rotatebitmap.c' then echo shar: will not over-write existing file "'rotatebitmap.c'" else sed 's/^X//' << \HI_MOM > 'rotatebitmap.c' X/* X** $Id$ X** X** Rotate a square, size 2^n rastport 90 deg. X** X** (C) Copyright 1991 Raymond S. Brand X** All Rights Reserved X*/ X X X#include <exec/types.h> X#include <graphics/rastport.h> X#include <proto/graphics.h> X#include "rotatebitmap.h" X X Xextern struct RastPort *NewRastPort(int x, int y, int depth); Xextern void FreeRastPort(struct RastPort *rp, int x, int y, int depth); X X Xint Rotate(struct RastPort *self, int s) X { X int q; /* control variable */ X int n; /* temp */ X int depth; X struct RastPort *temp; X struct RastPort *mask; X X /* X * need to do RastPort size error checking here X */ X X if (s < 2) X { X return 0; X } X X q = 1; X X while(q < s) X { X q <<= 1; X } X X if (q != s) X { X return ERROR_SIZE_NOT_POWER_OF_TWO; X } X X depth = self->BitMap->Depth; X X if (!(temp = NewRastPort(s, s, depth))) X { X return ERROR_NEWRASTPORT_FAILED; X } X X if (!(mask = NewRastPort(s, s, depth))) X { X FreeRastPort(temp, s, s, depth); X return ERROR_NEWRASTPORT_FAILED; X } X X ClipBlit(mask, 0, 0, mask, 0, 0, s, s, OP_D_EQ_ZERO ); X ClipBlit(mask, 0, 0, mask, 0, 0, s/2, s/2, OP_D_EQ_ONE ); X X while( q >>= 1 ) X { X /* X * exchange right & left halves X */ X ClipBlit(mask, 0, 0, temp, 0, 0, s, s, OP_D_EQ_S ); X ClipBlit(mask, 0, 0, temp, 0, q, s, s-q, OP_D_EQ_S_OR_D ); X ClipBlit(self, 0, 0, temp, 0, 0, s, s, OP_D_EQ_S_AND_D ); X ClipBlit(temp, 0, 0, self, 0, 0, s, s, OP_D_EQ_S_XOR_D ); X ClipBlit(self, q, 0, temp, 0, 0, s-q, s, OP_D_EQ_S_XOR_D ); X ClipBlit(self, q, 0, self, 0, 0, s-q, s, OP_D_EQ_S_OR_D ); X ClipBlit(temp, 0, 0, self, q, 0, s-q, s, OP_D_EQ_S_XOR_D ); X /* X * exchange diagonals X */ X ClipBlit(self, 0, 0, temp, 0, 0, s, s, OP_D_EQ_S ); X ClipBlit(self, q, q, temp, 0, 0, s-q, s-q, OP_D_EQ_S_XOR_D ); X ClipBlit(mask, 0, 0, temp, 0, 0, s, s, OP_D_EQ_S_AND_D ); X ClipBlit(temp, 0, 0, self, 0, 0, s, s, OP_D_EQ_S_XOR_D ); X ClipBlit(temp, 0, 0, self, q, q, s-q, s-q, OP_D_EQ_S_XOR_D ); X /* X * refine mask X */ X n = q>>1; X ClipBlit(mask, n, n, mask, 0, 0, s-n, s-n, OP_D_EQ_S_AND_D ); X ClipBlit(mask, 0, 0, mask, 0, q, s, s-q, OP_D_EQ_S_OR_D ); X ClipBlit(mask, 0, 0, mask, q, 0, s-q, s, OP_D_EQ_S_OR_D ); X } X X FreeRastPort(temp, s, s, depth); X FreeRastPort(mask, s, s, depth); X return 0; X } HI_MOM fi # end of overwriting check if test -f 'rotatebitmap.h' then echo shar: will not over-write existing file "'rotatebitmap.h'" else sed 's/^X//' << \HI_MOM > 'rotatebitmap.h' X/* X** $Id$ X** X** Constants for RoateBitMap.c X** X** (C) Copyright 1991 Raymond S. Brand X** All Rights Reserved X*/ X X X#define OK 0 X#define ERROR_SIZE_NOT_POWER_OF_TWO 1 X#define ERROR_NEWRASTPORT_FAILED 2 X#define OP_D_EQ_ZERO 0x00 X#define OP_D_EQ_ONE 0xf0 X#define OP_D_EQ_S 0xc0 X#define OP_D_EQ_S_OR_D 0xe0 X#define OP_D_EQ_S_AND_D 0x80 X#define OP_D_EQ_S_XOR_D 0x60 HI_MOM fi # end of overwriting check if test -f 'test.c' then echo shar: will not over-write existing file "'test.c'" else sed 's/^X//' << \HI_MOM > 'test.c' X/* X** $Id$ X** X** Test/demonstration program for RotateBiitMap. X** X** (C) Copyright 1991 Raymond S. Brand X** All Rights Reserved X*/ X X X#include <exec/types.h> X#include <graphics/gfxbase.h> X#include <proto/exec.h> X#include <proto/graphics.h> X X#include <intuition/intuition.h> X#include <proto/intuition.h> X X X#define SIZE 512 X X Xint Rotate(struct RastPort *self, int s); X X Xextern struct Library *SysBase; Xstruct IntuitionBase *IntuitionBase = NULL; Xstruct Window *win = NULL; Xstruct GfxBase *GfxBase = NULL; X X Xstruct NewWindow nw = X { X 0, 0, /* LeftEdge, TopEdge */ X SIZE, SIZE, /* Width, Height */ X -1, -1, /* DetailPen, BlockPen */ X SMART_REFRESH|NOCAREREFRESH, /* IDCMPFlags */ X WINDOWDRAG, /* Flags */ X NULL, /* FirstGadget */ X NULL, /* CheckMark */ X "Rotate BitMap Test Window", /* Title */ X NULL, NULL, /* Screen, BitMap */ X SIZE, SIZE, /* MinWidth, MinHeight */ X SIZE, SIZE, /* MaxWidth, MaxHeight */ X WBENCHSCREEN /* Type */ X }; X X X Xvoid main(int argc, char **argv) X { X if (!( IntuitionBase = (struct IntuitionBase *) X OpenLibrary("intuition.library", 0) )) X { X printf("Couldn't open Intuition.\n"); X goto Error; X } X X if (!( GfxBase = (struct GfxBase *) X OpenLibrary("graphics.library", 0) )) X { X printf("Couldn't open Graphics.\n"); X goto Error; X } X X if (!( win = OpenWindow(&nw))) X { X printf("Couldn't open window.\n"); X goto Error; X } X X Delay(200); X X Rotate(win->RPort, SIZE); X X Rotate(win->RPort, SIZE); X X Rotate(win->RPort, SIZE); X X Rotate(win->RPort, SIZE); X X Delay(200); X X XError: X if (win) X CloseWindow(win); X X if (GfxBase) X CloseLibrary(GfxBase); X X if (IntuitionBase) X CloseLibrary(IntuitionBase); X X exit(0); X} HI_MOM fi # end of overwriting check if test -f 'test.lnk' then echo shar: will not over-write existing file "'test.lnk'" else sed 's/^X//' << \HI_MOM > 'test.lnk' XFROM LIB:c.o+"test.o"+"rotatebitmap.o"+"rastport.o" XTO "test" XLIB LIB:lc.lib LIB:amiga.lib X HI_MOM fi # end of overwriting check if test -f 'test1.c' then echo shar: will not over-write existing file "'test1.c'" else sed 's/^X//' << \HI_MOM > 'test1.c' X/* X** $Id$ X** X** Test/demonstration program for Rotate1.c X** X** (C) Copyright 1991 Raymond S. Brand X** All Rights Reserved X*/ X X X#include <exec/types.h> X#include <graphics/gfxbase.h> X#include <proto/exec.h> X#include <proto/graphics.h> X X#include <intuition/intuition.h> X#include <proto/intuition.h> X X X#define XSIZE 255 X#define YSIZE 127 X#define SPACING 300 X X Xint Rotate(struct RastPort *src, int OsrcX, int Osrcy, struct RastPort *dst, int OdstX, int OdstY, int sizeX, int sizeY, X struct RastPort *mask, struct RastPort *temp); X X Xextern struct Library *SysBase; Xstruct IntuitionBase *IntuitionBase = NULL; Xstruct Window *win1 = NULL; Xstruct Window *win2 = NULL; Xstruct Window *win3 = NULL; Xstruct Window *win4 = NULL; Xstruct GfxBase *GfxBase = NULL; X X Xstruct NewWindow nw1 = X { X 0, 0, /* LeftEdge, TopEdge */ X YSIZE, XSIZE, /* Width, Height */ X -1, -1, /* DetailPen, BlockPen */ X SMART_REFRESH|NOCAREREFRESH, /* IDCMPFlags */ X WINDOWDRAG, /* Flags */ X NULL, /* FirstGadget */ X NULL, /* CheckMark */ X "Rotate BitMap src Window", /* Title */ X NULL, NULL, /* Screen, BitMap */ X YSIZE, XSIZE, /* MinWidth, MinHeight */ X YSIZE, XSIZE, /* MaxWidth, MaxHeight */ X WBENCHSCREEN /* Type */ X }; X Xstruct NewWindow nw2 = X { X SPACING, 0, /* LeftEdge, TopEdge */ X XSIZE, YSIZE, /* Width, Height */ X -1, -1, /* DetailPen, BlockPen */ X SMART_REFRESH|NOCAREREFRESH, /* IDCMPFlags */ X WINDOWDRAG, /* Flags */ X NULL, /* FirstGadget */ X NULL, /* CheckMark */ X "Rotate BitMap dst Window", /* Title */ X NULL, NULL, /* Screen, BitMap */ X XSIZE, YSIZE, /* MinWidth, MinHeight */ X XSIZE, YSIZE, /* MaxWidth, MaxHeight */ X WBENCHSCREEN /* Type */ X }; X Xstruct NewWindow nw3 = X { X 0, SPACING, /* LeftEdge, TopEdge */ X XSIZE, YSIZE, /* Width, Height */ X -1, -1, /* DetailPen, BlockPen */ X SMART_REFRESH|NOCAREREFRESH, /* IDCMPFlags */ X WINDOWDRAG, /* Flags */ X NULL, /* FirstGadget */ X NULL, /* CheckMark */ X "Rotate BitMap mask Window", /* Title */ X NULL, NULL, /* Screen, BitMap */ X XSIZE, YSIZE, /* MinWidth, MinHeight */ X XSIZE, YSIZE, /* MaxWidth, MaxHeight */ X WBENCHSCREEN /* Type */ X }; X Xstruct NewWindow nw4 = X { X SPACING, SPACING, /* LeftEdge, TopEdge */ X XSIZE, YSIZE, /* Width, Height */ X -1, -1, /* DetailPen, BlockPen */ X SMART_REFRESH|NOCAREREFRESH, /* IDCMPFlags */ X WINDOWDRAG, /* Flags */ X NULL, /* FirstGadget */ X NULL, /* CheckMark */ X "Rotate BitMap temp Window", /* Title */ X NULL, NULL, /* Screen, BitMap */ X XSIZE, YSIZE, /* MinWidth, MinHeight */ X XSIZE, YSIZE, /* MaxWidth, MaxHeight */ X WBENCHSCREEN /* Type */ X }; X X X Xvoid main(int argc, char **argv) X { X if (!( IntuitionBase = (struct IntuitionBase *) X OpenLibrary("intuition.library", 0) )) X { X printf("Couldn't open Intuition.\n"); X goto Error; X } X X if (!( GfxBase = (struct GfxBase *) X OpenLibrary("graphics.library", 0) )) X { X printf("Couldn't open Graphics.\n"); X goto Error; X } X X if (!( win1 = OpenWindow(&nw1))) X { X printf("Couldn't open window.\n"); X goto Error; X } X X if (!( win2 = OpenWindow(&nw2))) X { X printf("Couldn't open window.\n"); X goto Error; X } X X if (!( win3 = OpenWindow(&nw3))) X { X printf("Couldn't open window.\n"); X goto Error; X } X X if (!( win4 = OpenWindow(&nw4))) X { X printf("Couldn't open window.\n"); X goto Error; X } X X Delay(200); X X Rotate(win1->RPort, 0, 0, win2->RPort, 0, 0, XSIZE, YSIZE, win3->RPort, win4->RPort); X X Delay(200); X X XError: X if (win1) X CloseWindow(win1); X X if (win2) X CloseWindow(win2); X X if (win3) X CloseWindow(win3); X X if (win4) X CloseWindow(win4); X X if (GfxBase) X CloseLibrary(GfxBase); X X if (IntuitionBase) X CloseLibrary(IntuitionBase); X X exit(0); X} HI_MOM fi # end of overwriting check if test -f 'test1.lnk' then echo shar: will not over-write existing file "'test1.lnk'" else sed 's/^X//' << \HI_MOM > 'test1.lnk' XFROM LIB:c.o+"test1.o"+"rotate1.o" XTO "test1" XLIB LIB:lc.lib LIB:amiga.lib XADDSYM X HI_MOM fi # end of overwriting check # End of shell archive exit 0 ------------------------------------------------------------------------ Raymond S. Brand rsbx@cbmvax.commodore.com Commodore-Amiga Engineering ...!uunet!cbmvax!rsbx 1200 Wilson Drive (215)-431-9100 West Chester PA 19380 "Looking" ------------------------------------------------------------------------
jef@well.sf.ca.us (Jef Poskanzer) (04/21/91)
In the referenced message, rsbx@cbmvax.commodore.com (Raymond S. Brand) wrote: }The request was for a way to rotate a bitmap 90 degrees without having to do }a readpixel/writepixel for each pixel in the area to rotate. What follows is }a shar file with the source (Amiga but you can understand it anyway :-) to 2 }rotate functions and 2 test programs. Appended is a version for Suns using raw pixrect calls. It's embedded in a screen-rot program of the same genre as meltdown and termite, but the rotation routine may be useful by itself. --- Jef Jef Poskanzer jef@well.sf.ca.us {apple, ucbvax, hplabs}!well!jef If you eat a live frog in the morning, nothing worse will happen to either of you for the rest of the day. /* ** sunrot - rot a Sun screen by rotating random squares ** ** Compile with: cc -O sunrot.c -lpixrect -s -o sunrot ** ** The rotation algorithm is similar to the one in "Smalltalk-80: The ** Language and Implementation", page 408. In particular, the mask ** refinement step is the same. However, the rest is different, simpler, ** doesn't flash white bars on the screen, and runs slightly faster (same ** number of blits but smaller area), at the cost of three off-screen ** temp areas instead of two. I consider this modified version fairly ** obvious, in case anyone is getting any stupid ideas about patenting ** it. The original version was non-obvious, but memory has gotten a ** lot cheaper since 1983. ** ** Copyright (C) 1991 by Jef Poskanzer. ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. */ #include <stdio.h> #include <sys/types.h> #include <sys/timeb.h> #include <sys/file.h> #include <pixrect/pixrect_hs.h> #define PIX_AND ( PIX_SRC & PIX_DST ) #define PIX_OR ( PIX_SRC | PIX_DST ) Pixrect* my_pr_open(); void pr_rotatepow2square(); void main( argc, argv ) int argc; char* argv[]; { int argn, delay; struct timeb tb; Pixrect* disp_pr; int wid, hgt, maxpow2; int x, y, pow2, cw; char* fb; char* usage = "usage: %s [-fb <framebuffer>] [-delay <msec>]\n"; argn = 1; fb = "/dev/fb"; delay = 0; if ( argn < argc && argv[argn][0] == '-' ) { if ( strcmp( argv[argn], "-fb" ) == 0 || strcmp( argv[argn], "-f" ) == 0 ) { ++argn; fb = argv[argn]; } else if ( strcmp( argv[argn], "-delay" ) == 0 || strcmp( argv[argn], "-dela" ) == 0 || strcmp( argv[argn], "-del" ) == 0 || strcmp( argv[argn], "-de" ) == 0 || strcmp( argv[argn], "-d" ) == 0 ) { ++argn; delay = atoi( argv[argn] ); } else { fprintf( stderr, usage, argv[0] ); exit( 1 ); } ++argn; } if ( argn != argc ) { fprintf( stderr, usage, argv[0] ); exit( 1 ); } if ( ( disp_pr = my_pr_open( fb ) ) == (Pixrect*) 0 ) { fprintf( stderr, "%s: error opening display\n", argv[0] ); exit( 1 ); } wid = disp_pr->pr_size.x; hgt = disp_pr->pr_size.y; for ( maxpow2 = 1; ( 2 << maxpow2 ) <= wid && ( 2 << maxpow2 ) <= hgt; ++maxpow2 ) ; ftime( &tb ); srandom( (int) ( tb.time ^ tb.millitm ^ getpid( ) ) ); for ( ; ; ) { pow2 = random() % ( maxpow2 + 1 ); x = random() % ( wid - ( 1 << pow2 ) ); y = random() % ( hgt - ( 1 << pow2 ) ); cw = random() % 2; pr_rotatepow2square( disp_pr, x, y, pow2, cw ); if ( delay != 0 ) usleep( delay * 1000 ); } } Pixrect* my_pr_open( fb ) char* fb; { int fd; /* Test with open first, to avoid stupid error messages from pr_open(). */ if ( ( fd = open( fb, O_RDWR ) ) == -1 ) return (Pixrect*) 0; close( fd ); return pr_open( fb ); } static Pixrect* temp1 = (Pixrect*) 0; static Pixrect* temp2 = (Pixrect*) 0; static Pixrect* mask = (Pixrect*) 0; void pr_rotatepow2square( pr, x, y, pow2, cw ) Pixrect* pr; int x, y, pow2, cw; { int s, h, q, ts, th, tq; if ( pow2 < 2 ) return; s = 1 << pow2; h = s / 2; q = h / 2; /* Make sure that temps and mask are big enough and the right depth. */ if ( temp1 != (Pixrect*) 0 ) if ( temp1->pr_size.x < s || temp1->pr_size.y < s || temp1->pr_depth != pr->pr_depth ) { pr_destroy( temp1 ); temp1 = (Pixrect*) 0; pr_destroy( temp2 ); temp2 = (Pixrect*) 0; pr_destroy( mask ); mask = (Pixrect*) 0; } if ( temp1 == (Pixrect*) 0 ) { temp1 = mem_create( s, s, pr->pr_depth ); temp2 = mem_create( s, s, pr->pr_depth ); mask = mem_create( s, s, 1 ); } /* Initialize mask to the upper left quadrant. */ pr_rop( mask, 0, 0, s, s, PIX_CLR, (Pixrect*) 0, 0, 0 ); pr_rop( mask, 0, 0, h, h, PIX_SET, (Pixrect*) 0, 0, 0 ); for ( ts = s, th = ts / 2, tq = th / 2; pow2 > 0; --pow2, ts = th, th = tq, tq /= 2 ) { if ( cw ) pr_rop( temp1, 0, 0, s-th, s-th, PIX_SRC, pr, x, y+th ); else pr_rop( temp1, 0, 0, s-th, s-th, PIX_SRC, pr, x+th, y ); pr_rop( temp1, 0, 0, s, s, PIX_AND, mask, 0, 0 ); if ( cw ) pr_rop( temp2, th, 0, s-th, s-th, PIX_SRC, pr, x, y ); else pr_rop( temp2, th, 0, s-th, s-th, PIX_SRC, pr, x+th, y+th ); pr_rop( temp2, th, 0, s-th, s-th, PIX_AND, mask, 0, 0 ); pr_rop( temp1, th, 0, s-th, s-th, PIX_OR, temp2, th, 0 ); if ( cw ) pr_rop( temp2, th, th, s-th, s-th, PIX_SRC, pr, x+th, y ); else pr_rop( temp2, th, th, s-th, s-th, PIX_SRC, pr, x, y+th ); pr_rop( temp2, th, th, s-th, s-th, PIX_AND, mask, 0, 0 ); pr_rop( temp1, th, th, s-th, s-th, PIX_OR, temp2, th, th ); if ( cw ) pr_rop( temp2, 0, th, s-th, s-th, PIX_SRC, pr, x+th, y+th ); else pr_rop( temp2, 0, th, s-th, s-th, PIX_SRC, pr, x, y ); pr_rop( temp2, 0, th, s-th, s-th, PIX_AND, mask, 0, 0 ); pr_rop( temp1, 0, th, s-th, s-th, PIX_OR, temp2, 0, th ); /* And copy back to the screen. */ pr_rop( pr, x, y, s, s, PIX_SRC, temp1, 0, 0 ); /* Refine mask. */ pr_rop( mask, 0, 0, s-tq, s-tq, PIX_AND, mask, tq, tq ); pr_rop( mask, 0, th, s, s-th, PIX_OR, mask, 0, 0 ); pr_rop( mask, th, 0, s-th, s, PIX_OR, mask, 0, 0 ); } }