/**************************************************************************** * * * Palette Requester * * * * (c) Copyright 1989 Jonathan Potter * * * * This program is freely redistributable, although all rights to it remain * * with the author. It may be used freely in any program as long as this * * notice remains intact, however, if you do this, please mention the * * author in the program. If you wish to use this in a commercial program * * of any kind, you must register with a $15 donation. * * Please send donations, bug reports, comments and suggestions to : * * * * Jonathan Potter * * 3 William Street * * Clarence Park 5034 * * South Australia * * Australia * * * * Ph : (08) 2932788 home * * * ****************************************************************************/ #include #include #include #include #include #include #include "PaletteReq.h" #define RED 32 #define BLUE 33 #define GREEN 34 #define CRESET 35 #define CCANCEL 36 #define COK 37 #define USER 38 #define SPREAD 39 #define COPY 40 #define HUE 41 #define SAT 42 #define LUM 43 #define INITREG(n) (GetRGB4(cvp->ColorMap,n)) #define REDREG(n) ((n>>8)&0xf) #define GREENREG(n) ((n>>4)&0xf) #define BLUEREG(n) (n&0xf) static int redtable[32], greentable[32], bluetable[32]; static char values[4]; static struct IntuiText coktext={1,0,JAM1,41,1,NULL,(UBYTE *)"OKAY",NULL}, canceltext={1,0,JAM1,33,1,NULL,(UBYTE *)"CANCEL",NULL}, usertext={1,0,JAM1,0,1,NULL,(UBYTE *)"",NULL}, resettext={1,0,JAM1,37,1,NULL,(UBYTE *)"RESET",NULL}, spreadtext={1,0,JAM1,33,1,NULL,(UBYTE *)"SPREAD",NULL}, copytext={1,0,JAM1,41,1,NULL,(UBYTE *)"COPY",NULL}, RText={1,0,JAM1,-15,1,NULL,"R",NULL}, GText={1,0,JAM1,-15,1,NULL,"G",NULL}, BText={1,0,JAM1,-15,1,NULL,"B",NULL}, HText={1,0,JAM1,106,1,NULL,"H",NULL}, SText={1,0,JAM1,106,1,NULL,"S",NULL}, LText={1,0,JAM1,106,1,NULL,"L",NULL}, valstext={0,1,JAM2,0,0,NULL,values,NULL}; static short border1_xy[]={ 0,0,115,0,115,10,0,10,0,0}; static struct Border border1={ -1,-1,1,0,JAM1,5,border1_xy,NULL}; static short border2_xy[]={ 0,0,239,0,239,10,0,10,0,0}; static struct Border border2={ -1,-1,1,0,JAM1,5,border2_xy,NULL}; static struct PropInfo RProp={AUTOKNOB|FREEHORIZ,0,0,1<<12}, GProp={AUTOKNOB|FREEHORIZ,0,0,1<<12}, BProp={AUTOKNOB|FREEHORIZ,0,0,1<<12}, HProp={AUTOKNOB|FREEHORIZ,0,0,1<<12}, SProp={AUTOKNOB|FREEHORIZ,0,0,1<<12}, LProp={AUTOKNOB|FREEHORIZ,0,0,1<<12}; static struct Image RImage, GImage, BImage, HImage, SImage, LImage, WCol={0,0,235,8,1,NULL,0,1,NULL}; static struct Gadget cokgadget={ NULL,9,118,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET, (APTR)&border1,NULL,&coktext,NULL,NULL,COK,NULL}, cancelgadget={ &cokgadget,133,118,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET, (APTR)&border1,NULL,&canceltext,NULL,NULL,CCANCEL,NULL}, usergadget={ &cancelgadget,133,105,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET, (APTR)&border1,NULL,&usertext,NULL,NULL,USER,NULL}, resetgadget={ &usergadget,9,105,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET, (APTR)&border1,NULL,&resettext,NULL,NULL,CRESET,NULL}, spreadgadget={ &resetgadget,133,92,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET, (APTR)&border1,NULL,&spreadtext,NULL,NULL,SPREAD,NULL}, copygadget={ &spreadgadget,9,92,114,9,GADGHCOMP,RELVERIFY,BOOLGADGET, (APTR)&border1,NULL,©text,NULL,NULL,COPY,NULL}, Lum={ ©gadget,132,79,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET, (APTR)&LImage,NULL,<ext,NULL,(APTR)&LProp,LUM,NULL}, Sat={ &Lum,132,67,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET, (APTR)&SImage,NULL,&SText,NULL,(APTR)&SProp,SAT,NULL}, Hue={ &Sat,132,55,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET, (APTR)&HImage,NULL,&HText,NULL,(APTR)&HProp,HUE,NULL}, Red={ &Hue,24,55,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET, (APTR)&RImage,NULL,&RText,NULL,(APTR)&RProp,RED,NULL}, Green={ &Red,24,67,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET, (APTR)&GImage,NULL,>ext,NULL,(APTR)&GProp,GREEN,NULL}, Blue={ &Green,24,79,100,10,GADGHNONE|GADGIMAGE,RELVERIFY|GADGIMMEDIATE,PROPGADGET, (APTR)&BImage,NULL,&BText,NULL,(APTR)&BProp,BLUE,NULL}; static struct NewWindow colwin={ 40,23,255,131,0,1,CLOSEWINDOW|GADGETUP|GADGETDOWN|MOUSEBUTTONS|RAWKEY, WINDOWDRAG|WINDOWCLOSE|ACTIVATE|SMART_REFRESH|RMBTRAP, &Blue,NULL,"Palette",NULL,NULL,0,0,0,0,CUSTOMSCREEN}; static struct Window *PWindow; static struct IntuiMessage *PMsg; static struct ViewPort *cvp; extern struct IntuitionBase *IntuitionBase; extern struct GfxBase *GfxBase; static ULONG colb; palette_request(win,winx,winy,hail,user,depth) struct Window *win; int winx, winy; char *hail; char *user; int depth; { int col,reg,i,Class,Code,GadgetID,x,y,last,first,sw,sh; if (!IntuitionBase) return(NO_INTUITION); if (!GfxBase) return(NO_GRAPHICS); if (!win) { colwin.Type=WBENCHSCREEN; sw=640; sh=200; } else { colwin.Screen=win->WScreen; sw=win->WScreen->Width; sh=win->WScreen->Height; } if (hail) colwin.Title=hail; if (user) { if (strlen(user)>14) user[14]='\0'; usertext.IText=user; usertext.LeftEdge=(115-(strlen(user)*8))/2; } else { resetgadget.NextGadget=&cancelgadget; resetgadget.Width=238; resetgadget.GadgetRender=(APTR)&border2; resettext.LeftEdge=99; } if (winx>-1) { colwin.LeftEdge=winx; if (winx+255>sw) colwin.LeftEdge=sw-255; } if (winy>-1) { colwin.TopEdge=winy; if (winy+131>sh) colwin.TopEdge=sh-131; } PWindow=(struct Window *) OpenWindow(&colwin); if (!PWindow) return(OPENWINDOW_FAILED); cvp=&(PWindow->WScreen->ViewPort); if (!depth) depth=2; if (depth<1) depth=1; if (depth>5) depth=5; drawersquares(depth); InitTable(depth); col=1; WCol.PlaneOnOff=col; valstext.FrontPen=col^(power(2,depth)-1); valstext.BackPen=1; DrawImage(PWindow->RPort,&WCol,10,45); PosPots(depth,col); PosHSLPots(depth,col); FOREVER { Wait(1<UserPort->mp_SigBit); while (PMsg=(struct IntuiMessage *) GetMsg(PWindow->UserPort)) { Class=PMsg->Class; Code=PMsg->Code; if (Class==GADGETUP || Class==GADGETDOWN) GadgetID=((struct Gadget *) PMsg->IAddress)->GadgetID; ReplyMsg((struct Message *) PMsg); switch (Class) { case CLOSEWINDOW: for (reg=0;reg<(power(2,depth));reg++) SetRGB4(cvp,reg,redtable[reg],greentable[reg],bluetable[reg]); CloseWindow(PWindow); return(FALSE); break; case MOUSEBUTTONS: if (Code!=SELECTDOWN) break; x=PWindow->MouseX; y=PWindow->MouseY; if (x<12 || x>243 || y<15 || y>40) break; if (col==ReadPixel(PWindow->RPort,x,y)) break; col=ReadPixel(PWindow->RPort,x,y); WCol.PlaneOnOff=col; DrawImage(PWindow->RPort,&WCol,10,45); PosPots(depth,col); PosHSLPots(depth,col); break; case GADGETDOWN: switch (GadgetID) { case RED: case GREEN: case BLUE: SetCols(depth,col); while (!(PMsg=(struct IntuiMessage *) GetMsg(PWindow->UserPort))) SetCols(depth,col); ReplyMsg((struct Message *) PMsg); SetCols(depth,col); break; case HUE: case SAT: case LUM: SetHSLCols(depth,col); while (!(PMsg=(struct IntuiMessage *) GetMsg(PWindow->UserPort))) SetHSLCols(depth,col); ReplyMsg((struct Message *) PMsg); SetHSLCols(depth,col); break; } break; case RAWKEY: if (Code!=0x45) break; GadgetID=CRESET; Class=GADGETUP; case GADGETUP: switch (GadgetID) { case CRESET: for (reg=0;reg<(power(2,depth));reg++) { SetRGB4(cvp,reg,redtable[reg],greentable[reg],bluetable[reg]); if (reg==col) { PosPots(depth,col); PosHSLPots(depth,col); } } break; case USER: if (!user) break; CloseWindow(PWindow); return(5); case COK: CloseWindow(PWindow); return(TRUE); case CCANCEL: for (reg=0;reg<(power(2,depth));reg++) SetRGB4(cvp,reg,redtable[reg],greentable[reg],bluetable[reg]); CloseWindow(PWindow); return(FALSE); case COPY: FOREVER { Wait(1<UserPort->mp_SigBit); if (PMsg=(struct IntuiMessage *) GetMsg(PWindow->UserPort)) { Class=PMsg->Class; Code=PMsg->Code; ReplyMsg((struct Message *) PMsg); if (Class!=MOUSEBUTTONS && Code!=SELECTDOWN) continue; x=PWindow->MouseX; y=PWindow->MouseY; if (x<12 || x>243 || y<15 || y>40) continue; GadgetID=ReadPixel(PWindow->RPort,x,y); if (GadgetID>-1 && GadgetID<32) break; } } colb=INITREG(col); SetRGB4(cvp,GadgetID,REDREG(colb),GREENREG(colb),BLUEREG(colb)); col=GadgetID; WCol.PlaneOnOff=col; DrawImage(PWindow->RPort,&WCol,10,45); PosPots(depth,col); PosHSLPots(depth,col); case SPREAD: FOREVER { Wait(1<UserPort->mp_SigBit); if (PMsg=(struct IntuiMessage *) GetMsg(PWindow->UserPort)) { Class=PMsg->Class; Code=PMsg->Code; ReplyMsg((struct Message *) PMsg); if (Class!=MOUSEBUTTONS && Code!=SELECTDOWN) continue; x=PWindow->MouseX; y=PWindow->MouseY; if (x<12 || x>243 || y<15 || y>40) continue; GadgetID=ReadPixel(PWindow->RPort,x,y); if (GadgetID>-1 && GadgetID<32) break; } } first=col; last=GadgetID; if (first>last) { i=first; first=last; last=i; } if (first>=last-1) break; dospread(first,last); col=GadgetID; WCol.PlaneOnOff=col; DrawImage(PWindow->RPort,&WCol,10,45); PosPots(depth,col); PosHSLPots(depth,col); break; default: break; } } } } } static PosPots(depth,col) int depth,col; { ULONG hpr,hpg,hpb; colb=INITREG(col); hpr=REDREG(colb)*0x1111; hpg=GREENREG(colb)*0x1111; hpb=BLUEREG(colb)*0x1111; if (RProp.HorizPot==hpr && GProp.HorizPot==hpg && BProp.HorizPot==hpb) return(0); NewModifyProp(&Red,PWindow,NULL,FREEHORIZ|AUTOKNOB,hpr,0,1<<12,0,1); NewModifyProp(&Green,PWindow,NULL,FREEHORIZ|AUTOKNOB,hpg,0,1<<12,0,1); NewModifyProp(&Blue,PWindow,NULL,FREEHORIZ|AUTOKNOB,hpb,0,1<<12,0,1); ShowVals(depth,REDREG(colb),GREENREG(colb),BLUEREG(colb),col); return(0); } static PosHSLPots(depth,col) int depth, col; { colb=INITREG(col); RGBToHSL(colb,&HProp.HorizPot,&SProp.HorizPot,&LProp.HorizPot); NewModifyProp(&Hue,PWindow,NULL,FREEHORIZ|AUTOKNOB,HProp.HorizPot,0,1<<12,0,1); NewModifyProp(&Sat,PWindow,NULL,FREEHORIZ|AUTOKNOB,SProp.HorizPot,0,1<<12,0,1); NewModifyProp(&Lum,PWindow,NULL,FREEHORIZ|AUTOKNOB,LProp.HorizPot,0,1<<12,0,1); return(0); } static SetHSLCols(depth,col) int depth,col; { ULONG rgb, red, green, blue; rgb=(ULONG) HSLToRGB(HProp.HorizPot,SProp.HorizPot,LProp.HorizPot); red=rgb>>8; green=rgb>>4; blue=rgb; SetRGB4(cvp,col,red,green,blue); PosPots(depth,col); return(0); } static SetCols(depth,col) int depth; int col; { USHORT re,gr,bl; re=RProp.HorizPot/0x1111; gr=GProp.HorizPot/0x1111; bl=BProp.HorizPot/0x1111; colb=INITREG(col); if (re==REDREG(colb) && gr==GREENREG(colb) && bl==BLUEREG(colb)) return(0); SetRGB4(cvp,col,re,gr,bl); ShowVals(depth,re,gr,bl,col); PosHSLPots(depth,col); return(0); } static InitTable(depth) int depth; { int reg; for (reg=0;reg<(power(2,depth));reg++) { colb=INITREG(reg); redtable[reg]=REDREG(colb); greentable[reg]=GREENREG(colb); bluetable[reg]=BLUEREG(colb); } return(0); } static ShowVals(depth,re,gr,bl,col) int depth,re,gr,bl,col; { values[0]=dostr(re); values[1]=dostr(gr); values[2]=dostr(bl); values[3]='\0'; valstext.FrontPen=col^(power(2,depth)-1); valstext.BackPen=col; PrintIText(PWindow->RPort,&valstext,115,45); return(0); } static power(base,n) int base,n; { int p; for (p=1;n>0;--n) p*=base; return(p); } static drawersquares(depth) int depth; { int w,h,ox,x,y,i; w=235/(power(2,depth)); h=25; ox=12; if (depth==4) { w=29; h=12; ox=13; } if (depth==5) { w=14; h=12; ox=17; } i=0; x=ox; y=15; while (x<255 && y<45) { SetAPen(PWindow->RPort,i); RectFill(PWindow->RPort,x,y,x+w,y+h); ++i; x+=w; if (i>=power(2,depth)) break; if (depth>3 && i==(power(2,(depth-1)))) { x=ox; y+=h; } } return(0); } static dospread(first,last) int first,last; { int redst,greenst,bluest,red1,green1,blue1,red2,green2,blue2, redw,greenw,bluew,i; colb=INITREG(first); red1=REDREG(colb); green1=GREENREG(colb); blue1=BLUEREG(colb); colb=INITREG(last); red2=REDREG(colb); green2=GREENREG(colb); blue2=BLUEREG(colb); redst=((red2-red1)<<8)/(last-first); greenst=((green2-green1)<<8)/(last-first); bluest=((blue2-blue1)<<8)/(last-first); for (i=first+1;i>8); greenw=green1+(((greenst*(i-first))+128)>>8); bluew=blue1+(((bluest*(i-first))+128)>>8); SetRGB4(cvp,i,redw,greenw,bluew); } return(0); } /* HSL <-> RGB routines adapted from the Amiga Programmers' Suite Book 1 by Robert J. Mical ------------------------------------------------------------------------------ * *** hsl.c **************************************************************** * * ColorWindow Routine -- HSL Translation Routines * from Book 1 of the Amiga Programmers' Suite by RJ Mical * * Copyright (C) 1986, 1987, Robert J. Mical * All Rights Reserved. * * Any or all of this code can be used in any program as long as this * entire copyright notice is retained, ok? Thanks. * * The Amiga Programmer's Suite Book 1 is copyrighted but freely distributable. * All copyright notices and all file headers must be retained intact. * The Amiga Programmer's Suite Book 1 may be compiled and assembled, and the * resultant object code may be included in any software product. However, no * portion of the source listings or documentation of the Amiga Programmer's * Suite Book 1 may be distributed or sold for profit or in a for-profit * product without the written authorization of the author, RJ Mical. * * HISTORY NAME DESCRIPTION * ----------- -------------- -------------------------------------------- * 3 Jan 87 RJ >:-{)* Clean-up for release * 27 Feb 86 =RJ Mical= Modified these routines for Zaphod * January 86 =RJ= Modified the originals for Mandelbrot * Late 85 =RJ= Created the color window for Graphicraft * * ************************************************************************* ----------------------------------------------------------------------------- */ static HSLToRGB(hue,sat,lum) USHORT hue, sat, lum; { ULONG red,green,blue,rdiff,gdiff,bdiff,foo,ris,fall,inv; foo=hue/0x2aab; ris=(hue-(foo*0x2aab))*6; fall=0xffff-ris; red=0xffff; green=0xffff; blue=0xffff; switch (foo) { case 0: green=ris; blue=0; break; case 1: red=fall; blue=0; break; case 2: red=0; blue=ris; break; case 3: red=0; green=fall; break; case 4: red=ris; green=0; break; case 5: green=0; blue=fall; break; } red=(red*lum)>>16; green=(green*lum)>>16; blue=(blue*lum)>>16; inv=0xffff-sat; rdiff=lum-red; red=red+((rdiff*inv)>>16); gdiff=lum-green; green=green+((gdiff*inv)>>16); bdiff=lum-blue; blue=blue+((bdiff*inv)>>16); red=(red>>12)&0xf; green=(green>>12)&0xf; blue=(blue>>12)&0xf; return((SHORT)((red<<8)|(green<<4)|(blue))); } static RGBToHSL(rgb,rhue,rsat,rlum) USHORT rgb; USHORT *rhue,*rsat,*rlum; { LONG min,max,hue,sat,lum,diff,rpart,gpart,bpart,rwork,gwork,bwork; rwork=((rgb>>8)&0xf)*0x111; gwork=((rgb>>4)&0xf)*0x111; bwork=(rgb&0xf)*0x111; if (rworkgwork) max=rwork; else max=gwork; if (bwork>max) max=bwork; lum=max; lum<<=4; diff=max-min; if (max) { sat=(diff<<16)/max; if (sat>0xffff) sat=0xffff; } else sat=0; if (sat==0) hue=0; else { rpart=(((max-rwork)<<16)/diff)>>4; gpart=(((max-gwork)<<16)/diff)>>4; bpart=(((max-bwork)<<16)/diff)>>4; if (rwork==max) hue=bpart-gpart; else if (gwork==max) hue=0x2000+rpart-bpart; else if (bwork==max) hue=0x4000+gpart-rpart; if (hue<0) hue+=0x6000; hue=(hue*2667)/1000; } *rhue=hue; *rsat=sat; *rlum=lum; return(0); } /*--------------------------------------------------------------------------*/ dostr(val) int val; { if (val<10) return(val+48); return(val+87); }