home *** CD-ROM | disk | FTP | other *** search
- /** dropshadow.c **/
-
- /* this program copyright 1987, james mackraz. may not be distributed
- * for profit. copies of the source may be made for not-for-profit
- * distribution, but must include this notice.
- *
- * james mackraz, 4021 Second Street, Palo Alto, CA, 94306
- */
-
- #include "ds.h"
- #include <tools/debug.h>
-
- #define printf kprintf
-
- UBYTE *wtitle = (UBYTE *) " DropShadow -- ver 2, rev 0 ";
- struct Window *getNewWind();
-
- struct RastPort *rport2 = NULL; /* for rendering into bmap2 */
- struct Window *window = NULL;
-
- struct Task *mytask;
- UBYTE mysig = 0;
-
- struct IntuitionBase *IntuitionBase;
- struct GfxBase *GfxBase;
- struct LayersBase *LayersBase;
-
- ULONG flg = ACTIVATE | WINDOWCLOSE | NOCAREREFRESH | WINDOWDRAG
- | WINDOWDEPTH | SIMPLE_REFRESH;
-
- ULONG iflg = MOUSEMOVE | CLOSEWINDOW | GADGETDOWN | GADGETUP;
-
- /* for each layer, front to back, not incl. backdrops */
- #define FORLAYERS(l, linfo) for (l = (linfo)->top_layer; \
- l && !(l->Flags & LAYERBACKDROP);l=l->back)
-
- #define BACKTOFRONT(l) for (l = window->WLayer->LayerInfo->top_layer; \
- l && l->back; l = l->back) ; \
- for (; l; l = l->front)
-
- #define PREDLAYERS(pred, l) for (pred = l->front; pred; pred = pred->front)
-
- #define MYPRI 7L /* a little advantage */
- #define INPUTPRI_PLUS 25L /* i guess i could findtask("input.device") */
-
- USHORT hdrop = 7;
- USHORT vdrop = 3;
-
- main()
- {
- struct IntuiMessage *msg;
-
- /* hold data from *msg */
- ULONG class;
- UBYTE code;
- struct Gadget *gaddress;
-
- struct Screen *wbscreen;
- struct BitMap *save_bitmap= NULL; /* original WB RasInfo bitmap */
- struct BitMap *ribitmap = NULL; /* my 3-deep replacement */
- struct BitMap *bmap2 = NULL;
-
- int i;
- int it_is_done = 0; /* success flag */
- WORD exitval = 0;
- ULONG sigmask;
- ULONG sigtaken;
-
- extern struct PropInfo twxtinfo;
- USHORT twxtpot;
-
- if (!(IntuitionBase = (struct IntuitionBase *)
- OpenLibrary("intuition.library", 0L)))
- {
- D( printf("NO INTUITION LIBRARY\n") );
- exitval = 1;
- goto EXITING;
- }
-
- if (!(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0L)))
- {
- D( printf("NO GRAPHICS LIBRARY\n") );
- exitval = 2;
- goto EXITING;
- }
-
- if (!(LayersBase=(struct LayersBase *) OpenLibrary("layers.library", 0L)))
- {
- D( printf("NO LAYERS LIBRARY\n") );
- exitval = 2;
- goto EXITING;
- }
-
- /* get a window on the workbench */
- window = getNewWind(120, 20, 400, 30, flg, iflg);
- if (window == NULL)
- {
- D( printf("test: can't get window.\n") );
- exitval = 1;
- goto EXITING;
- }
-
- /* Add bitplane to the Workbench, as far as ViewPort is concerned */
-
- wbscreen = window->WScreen; /* find it */
-
- /* new 3-deep bitmap will replace the one in WB's RInfo */
- if (!(ribitmap = (struct BitMap *)
- AllocMem((LONG) sizeof(struct BitMap), (LONG) MEMF_PUBLIC|MEMF_CLEAR)))
- {
- D( printf("alloc bitmap failed\n") );
- goto EXITING;
- }
- InitBitMap(ribitmap, 3L, (LONG) wbscreen->Width, (LONG) wbscreen->Height);
-
- /* allocate bitmap for my rastport view of single bitplane */
- if (!(bmap2 = (struct BitMap *)
- AllocMem((LONG) sizeof(struct BitMap), (LONG) MEMF_PUBLIC|MEMF_CLEAR)))
- {
- D( printf("alloc bitmap failed\n") );
- goto EXITING;
- }
-
- /* my rendering bit map: depth 1 */
- InitBitMap(bmap2, 1L, (LONG) wbscreen->Width, (LONG) wbscreen->Height);
-
- if (!(bmap2->Planes[0] =
- (UBYTE *) AllocRaster((LONG) wbscreen->Width, (LONG) wbscreen->Height)))
- {
- D( printf("alloc raster failed\n") );
- goto EXITING;
- }
-
- /* get a rastport, and set it up for rendering into bmap2 */
- if (!(rport2 = (struct RastPort *)
- AllocMem((LONG) sizeof (struct RastPort), (LONG) MEMF_PUBLIC)))
- {
- D( printf("alloc rastport failed\n") );
- goto EXITING;
- }
- InitRastPort(rport2);
- rport2->BitMap = bmap2;
-
- SetRast(rport2, 0L);
-
- /* set up new bitmap for RInfo */
- save_bitmap = wbscreen->ViewPort.RasInfo->BitMap;
- ribitmap->Planes[0] = save_bitmap->Planes[0];
- ribitmap->Planes[1] = save_bitmap->Planes[1];
- ribitmap->Planes[2] = bmap2->Planes[0];
-
- Forbid();
-
- /* add our extra plane to the bit-map as viewed by
- * the WB ViewPort (WB should never know the difference)
- */
- wbscreen->ViewPort.RasInfo->BitMap = ribitmap;
-
- Permit();
-
- it_is_done = 1;
-
- shadowColors(wbscreen);
-
- /* put viewport changed into effect */
- MakeScreen(wbscreen);
- RethinkDisplay();
-
- twxtpot = twxtinfo.HorizPot;
- hdrop = twxtpot >> TWXTSHIFT;
- vdrop = twxtpot >> (TWXTSHIFT + 1);
- drawShadow();
-
- /* hook into the library vectors */
- mytask = FindTask(0L);
- mysig = AllocSignal((LONG) -1);
- sigmask = ((LONG) 1 << mysig);
- sigmask |= ((LONG) 1 << window->UserPort->mp_SigBit);
- setup_hooks();
-
- /* a little help */
- SetTaskPri(mytask, MYPRI);
-
- FOREVER
- {
- if ((msg = (struct IntuiMessage *)GetMsg(window->UserPort)) == NULL)
- {
- sigtaken = Wait(sigmask);
- if (sigtaken & ((LONG) 1 << mysig))
- {
- drawShadow();
- }
- continue;
- }
-
- class = msg->Class;
- code = msg->Code;
- gaddress = (struct Gadget *) msg->IAddress;
- ReplyMsg(msg);
-
- switch (class)
- {
- case MOUSEMOVE: /* taken at higher priority */
- shadowColors(wbscreen);
- break;
-
- case GADGETDOWN:
- SetTaskPri(mytask, INPUTPRI_PLUS);
- break;
-
- case GADGETUP:
- SetTaskPri(mytask, MYPRI);
-
- switch (gaddress->GadgetID)
- {
- case TWIXTID:
- twxtpot = twxtinfo.HorizPot;
- hdrop = twxtpot >> TWXTSHIFT;
- vdrop = twxtpot >> (TWXTSHIFT + 1);
- drawShadow();
- break;
- case DARKID:
- shadowColors(wbscreen);
- break;
- }
- break;
-
- case CLOSEWINDOW:
- SetTaskPri(mytask, 0L);
- if (cleanup_hooks()) goto EXITING;
- default:
- D( printf("unknown event: class %lx\n", class) );
- }
- }
-
- EXITING:
- /* clean up trick */
- if (it_is_done)
- {
- Forbid();
- wbscreen->ViewPort.RasInfo->BitMap = save_bitmap;
- Permit();
- MakeScreen(wbscreen);
- RethinkDisplay();
- }
-
- if (mysig) FreeSignal((LONG) mysig);
-
- if (rport2) FreeMem(rport2, (LONG) sizeof (struct RastPort));
- if (bmap2)
- {
- if (bmap2->Planes[0])
- {
- FreeRaster(bmap2->Planes[0],
- (LONG) wbscreen->Width, (LONG) wbscreen->Height);
- }
- FreeMem(bmap2, (LONG) sizeof (struct BitMap));
- }
- if (ribitmap) FreeMem(ribitmap, (LONG) sizeof (struct BitMap));
-
- if (window) CloseWindow(window);
- if (GfxBase) CloseLibrary(GfxBase);
- if (LayersBase) CloseLibrary(LayersBase);
- if (IntuitionBase) CloseLibrary(IntuitionBase);
-
- exit (exitval);
- }
-
- /* returns true if this layer casts a shadow
- * note that menu layer does not cast a shadow
- */
- shadowCaster(l)
- register struct Layer *l;
- {
- extern struct PropInfo darkinfo;
- register struct Window *w;
- register struct RastPort *brp;
-
- if (l && (w = (struct Window *) l->Window))
- {
- /* must be border layer for GZZ window */
- if (brp = w->BorderRPort)
- {
- /* GZZ */
- return (brp->Layer == l);
- }
- else
- {
- /* non-GZZ */
- return (l == w->WLayer);
- }
- }
- return (0);
- }
-
- /* called by my replacement layers vectors */
- drawShadowSignal(sysret)
- LONG sysret;
- {
- Signal( mytask, ((LONG) 1 << mysig));
- return (sysret);
- }
-
- /* run on my own task's schedule */
- drawShadow(sysret)
- LONG sysret;
- {
- struct Region *shadow;
-
- if ( !(shadow = NewRegion()) ) return (sysret);
-
- bigShadow(shadow);
-
- SetRast(rport2, 0L);
-
- Forbid();
- WaitBOVP(&window->WScreen->ViewPort);
-
- SetAPen(rport2, 1L);
- fillRegion(rport2, shadow);
- Permit();
-
- DisposeRegion(shadow);
- }
-
- /* you want speed? speed this up. */
- bigShadow(rgn)
- struct Region *rgn;
- {
- register struct Layer *pred; /* pred to 'l' */
- register LONG tmprgn; /* accumulates shadow on layer 'l' */
- register struct Layer *l; /* create all shadows on each layer */
-
- int twixt; /* number of "spaces" between l, pred */
- int htwixt;
- int vtwixt;
- struct Rectangle lrect;
- struct Rectangle predrect;
-
- if ( !(tmprgn = (LONG) NewRegion()) ) return;
-
- /* protect the integrity of the layer list */
- LockLayerInfo(window->WLayer->LayerInfo);
-
- BACKTOFRONT(l)
- {
- /* could eliminate any layers you don't want a shadow on here. */
-
- /* layer rectangle */
- lrect = l->bounds;
-
- #if 0
- notRectRegion(rgn, &lrect); /* l obscures shadows behind it */
- #else
- ClearRectRegion(rgn, &lrect); /* dale's version */
- #endif
-
- #if OLDTWIXT
- twixt = 0;
- #else
- htwixt = hdrop << 1;
- vtwixt = vdrop << 1;
- #endif
- ClearRegion(tmprgn); /* will build shadow on single layer */
-
- /* walk through shadow casters */
- PREDLAYERS(pred, l)
- {
- /* menu bar doesn't cast shadow */
- if (!shadowCaster(pred))
- {
- continue;
- }
-
- /* rectangle will cast shadow */
- predrect = pred->bounds; /* layer rect */
-
- /* shadow offset increases with depth */
- #if OLDTWIXT
- translateRect(&predrect,
- HDROP + twixt * (HDROP >> 1), VDROP + twixt * (VDROP >> 1));
-
- ++twixt; /* another level up */
- #else
- translateRect(&predrect, htwixt, vtwixt);
- htwixt += hdrop;
- vtwixt += vdrop;
-
- #endif
- /* add it to accumulated shadow on 'l' */
- OrRectRegion(tmprgn, &predrect);
- }
-
- /* all shadows on 'l' should actually be on 'l' */
- AndRectRegion(tmprgn, &lrect);
-
- /* add shadows on l to shadows on layers behind l */
- OrRegionRegion(tmprgn, rgn);
- }
-
- UnlockLayerInfo(window->WLayer->LayerInfo);
- DisposeRegion(tmprgn);
- }
-
- /* can use dale's ClearRectRegion */
- #if 0
- notRectRegion(rgn, rect)
- struct Region *rgn;
- struct Rectangle *rect;
- {
- OrRectRegion(rgn, rect);
- XorRectRegion(rgn, rect);
- }
- #endif
-
- /* this doesn't get use anymore */
- #define GOODRECT(r) (((r)->MinX < (r)->MaxX) && ((r)->MinY < (r)->MaxY))
-
- fillRegion(rp, rgn)
- struct RastPort *rp;
- struct Region *rgn;
- {
- register struct RegionRectangle *rgnrect;
- register struct Rectangle *bds;
-
- register int minx; /* offsets for all region rectangles */
- register int miny;
-
- minx = rgn->bounds.MinX;
- miny = rgn->bounds.MinY;
- rgnrect = rgn->RegionRectangle;
-
- while (rgnrect)
- {
- bds = &rgnrect->bounds;
- RectFill(rp,
- (LONG)minx + bds->MinX,
- (LONG) miny + bds->MinY,
- (LONG) minx + bds->MaxX,
- (LONG) miny + bds->MaxY);
-
- rgnrect = rgnrect->Next;
- }
- }
-
- translateRect(r, dx, dy)
- register struct Rectangle *r;
- register int dx;
- register int dy;
- {
- r->MinX += dx;
- r->MaxX += dx;
- r->MinY += dy;
- r->MaxY += dy;
- }
-
- screenRect(s, r)
- register struct Screen *s;
- register struct Rectangle *r;
- {
- r->MaxX = (r->MinX = s->LeftEdge) + s->Width - 1;
- r->MaxY = (r->MinY = s->TopEdge) + s->Height - 1;
- }
-
- windowRect(w, r)
- register struct Window *w;
- register struct Rectangle *r;
- {
- r->MaxX = (r->MinX = w->LeftEdge) + w->Width - 1;
- r->MaxY = (r->MinY = w->TopEdge) + w->Height - 1;
- }
-
- struct Window * getNewWind(left, top, width, height, flg, iflg)
- SHORT left, top, width, height;
- ULONG flg, iflg;
- {
- extern struct Gadget darkness;
-
- struct Window *OpenWindow();
- struct NewWindow nw;
-
- nw.LeftEdge = (SHORT) left;
- nw.TopEdge = (SHORT) top;
- nw.Width = (SHORT) width;
- nw.Height = (SHORT) height;
- nw.DetailPen = (UBYTE) -1;
- nw.BlockPen = (UBYTE) -1;
- nw.IDCMPFlags = (ULONG) iflg;
-
- nw.Flags = (ULONG) flg;
-
- nw.FirstGadget = (struct Gadget *) &darkness;
- nw.CheckMark = (struct Image *) NULL;
- nw.Title = (UBYTE *) wtitle;
- nw.Screen = (struct Screen *) NULL;
- nw.BitMap = (struct BitMap *) NULL;
- nw.MinWidth = (SHORT) 50;
- nw.MinHeight= (SHORT) 30;
- /* work around bug */
- nw.MaxWidth = (SHORT) nw.Width;
- nw.MaxHeight = (SHORT) nw.Height;
- nw.Type = (USHORT) WBENCHSCREEN;
-
- return ((struct Window *) OpenWindow(&nw));
- }
-
-
- #define DARKER(c) (((long) (((c) & 0xF) * (darkpot)) ) >> 16)
-
- shadowColors(s)
- struct Screen *s;
- {
- register int i;
- register ULONG rgb;
- ULONG red, green, blue;
- struct ColorMap *cm;
- USHORT darkpot;
-
- darkpot = darkinfo.HorizPot;
-
- cm = s->ViewPort.ColorMap;
-
- for (i = 0; i < 4; ++i)
- {
- /* get three colors */
- rgb = GetRGB4(cm, (LONG) i);
-
- #if 0
- rgb = ~rgb; /* wild colors, not wild enough */
- #endif
-
- blue = DARKER(rgb);
- green = DARKER(rgb >>= 4);
- red = DARKER(rgb >> 4);
- SetRGB4(&s->ViewPort, (LONG) i + 4,(LONG) red,(LONG) green,(LONG) blue);
- }
- }
-