/* * MandelVroom 2.0 * * (c) Copyright 1987,1989 Kevin L. Clague, San Jose, CA * * All rights reserved. * * Permission is hereby granted to distribute this program's source * executable, and documentation for non-comercial purposes, so long as the * copyright notices are not removed from the sources, executable or * documentation. This program may not be distributed for a profit without * the express written consent of the author Kevin L. Clague. * * This program is not in the public domain. * * Fred Fish is expressly granted permission to distribute this program's * source and executable as part of the "Fred Fish freely redistributable * Amiga software library." * * Permission is expressly granted for this program and it's source to be * distributed as part of the Amicus Amiga software disks, and the * First Amiga User Group's Hot Mix disks. * * contents: this file contains the functions that open, maintain, operate * and close the color palette. */ #include "mandp.h" #include #define PENLEFT 8 #define PENTOP 15 extern struct Gadget *ContGadget[], *SelGadget[]; UBYTE PaletteOpen; /* * Holder for Allocated color potentiometer gadgets. */ struct ColorGads { struct Gadget *RedPot; struct Gadget *GreenPot; struct Gadget *BluePot; }; struct Window *PalWind; struct ColorGads PalGads; LONG CurPen; struct NewWindow NewPal = { 128,0, /* start position */ 70,80, /* width, height */ (UBYTE) 0, (UBYTE) -1, /* detail pen, block pen */ NULL, /* IDCMP flags */ /* MandWind flags */ WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH | NOCAREREFRESH | SMART_REFRESH, (struct Gadget *) NULL, /* first gadget */ (struct Image *) NULL, /* user checkmark */ (UBYTE *) "Colors", /* window title */ (struct Screen *) NULL, /* pointer to screen */ (struct BitMap *) NULL, /* pointer to superbitmap */ 80,80,80,80, /* sizing */ CUSTOMSCREEN /* type of screen */ }; /* * Color Palette Commands */ CopyRGBCmd(Msg) struct IntuiMessage *Msg; { struct Gadget *gadget; register LONG rgb, pen; /* Need contour selection to complete */ gadget = (struct Gadget *) Msg->IAddress; if (Msg->Class == GADGETDOWN) { if (gadget->GadgetID == PALCOPY) { /* Copy command gadget */ SetToPointer(); State = COPYRGBSTATE; } else { if (GADG_TYPE(gadget->GadgetID) == PALPEN) { /* Copy the RGBs from CurPen to NewPen */ pen = GADG_NUM(gadget->GadgetID); rgb = GetRGB4(vp->ColorMap, CurPen); SetRGB4(vp, pen, rgb >> 8, rgb >> 4, rgb); SaveRGBs(CurPict); State = IDLESTATE; } } } } SpreadRGBCmd(Msg) struct IntuiMessage *Msg; { struct Gadget *gadget; register LONG pen; /* Need contour selection to complete */ gadget = (struct Gadget *) Msg->IAddress; if (Msg->Class == GADGETDOWN) { if (gadget->GadgetID == PALRANGE) { /* Spread command gadget */ SetToPointer(); State = SPREADRGBSTATE; } else { if (GADG_TYPE(gadget->GadgetID) == PALPEN) { /* Spread the RGBs from CurPen to NewPen */ pen = GADG_NUM(gadget->GadgetID); ColorRange(CurPen, pen); SaveRGBs(CurPict); State = IDLESTATE; } } } } ExchangeRGBCmd(Msg) struct IntuiMessage *Msg; { register LONG rgb, rgb2, pen; struct Gadget *gadget; /* Need contour selection to complete */ gadget = (struct Gadget *) Msg->IAddress; if (Msg->Class == GADGETDOWN) { if (gadget->GadgetID == PALEXCG) { /* Exchange command gadget */ SetWithPointer(); State = XCHGRGBSTATE; } else { if (GADG_TYPE(gadget->GadgetID) == PALPEN) { /* exchange the RGBs in CurPen and NewPen */ pen = GADG_NUM(gadget->GadgetID); rgb = GetRGB4(vp->ColorMap, CurPen); rgb2 = GetRGB4(vp->ColorMap, pen); SetRGB4(vp, CurPen, rgb2 >> 8, rgb2 >> 4, rgb2 ); SetRGB4(vp, pen, rgb >> 8, rgb >> 4, rgb ); SaveRGBs(CurPict); State = IDLESTATE; } } } } SlideRGBCmd(Msg) struct IntuiMessage *Msg; { struct Gadget *gadget; gadget = (struct Gadget *) Msg->IAddress; switch( Msg->Class ) { case GADGETDOWN: /* Start RGB slide */ StartBarDrag(); State = SLIDERGBSTATE; break; case MOUSEMOVE: ModifyColors(); /* change RGB colors */ break; case GADGETUP: /* Stop the RGB slide */ ModifyColors(); SaveRGBs(CurPict); State = IDLESTATE; break; } } SetCurPen( pen ) int pen; { BoxPen( CurPen, NORMALPEN ); CurPen = pen; SetColorProps(pen); BoxPen( CurPen, MEDIUMPEN ); SaveRGBs( CurPict ); } /* * Blend a range of colors between two pens */ ColorRange(first, last) LONG first, last; { LONG i; register LONG whole, redfraction, greenfraction, bluefraction; register USHORT rgb; LONG firstred, firstgreen, firstblue; LONG lastred, lastgreen, lastblue; LONG workred, workgreen, workblue; if (first > last) { i = first; first = last; last = i; } /* I need to see a spread of at least two, where there's at least one * spot between the endpoints, else there's no work to do so I * might as well just return now. */ if (first >= last - 1) return; rgb = GetRGB4(vp->ColorMap, first); firstred = (rgb >> 8) & 0xF; firstgreen = (rgb >> 4) & 0xF; firstblue = (rgb >> 0) & 0xF; rgb = GetRGB4(vp->ColorMap, last); lastred = (rgb >> 8) & 0xF; lastgreen = (rgb >> 4) & 0xF; lastblue = (rgb >> 0) & 0xF; whole = (lastred - firstred) << 16; redfraction = whole / (last - first); whole = (lastgreen - firstgreen) << 16; greenfraction = whole / (last - first); whole = (lastblue - firstblue) << 16; bluefraction = whole / (last - first); for (i = first + 1; i < last; i++) { lastred = (redfraction * (i - first) + 0x8000) >> 16; workred = firstred + lastred; lastgreen = (greenfraction * (i - first) + 0x8000) >> 16; workgreen = firstgreen + lastgreen; lastblue = (bluefraction * (i - first) + 0x8000) >> 16; workblue = firstblue + lastblue; SetRGB4(vp, i, workred, workgreen, workblue); } } /* ColorRange */ /* * Modify the colors in the current pen */ ModifyColors( ) { register LONG newred, newgreen, newblue; newred = ((struct PropInfo *) PalGads.RedPot->SpecialInfo)->VertPot >> 12; newgreen = ((struct PropInfo *) PalGads.GreenPot->SpecialInfo)->VertPot >> 12; newblue = ((struct PropInfo *) PalGads.BluePot->SpecialInfo)->VertPot >> 12; newred = 0xF ^ newred; newgreen = 0xF ^ newgreen; newblue = 0xF ^ newblue; PrintRGB( newred, newgreen, newblue ); SetRGB4(vp, CurPen, newred, newgreen, newblue); } /* ModifyColors */ PrintRGB( r, g, b ) LONG r,g,b; { PrintGad( PalGads.RedPot, r ); PrintGad( PalGads.GreenPot, g ); PrintGad( PalGads.BluePot, b ); } PrintGad( gadget, Color ) register struct Gadget *gadget; LONG Color; { register struct IntuiText *SaveIntui, *IntuiText = gadget->GadgetText; char d[4]; SaveIntui = IntuiText; Color &= 0xf; sprintf( d, "%x", Color ); d[0] = toupper(d[0]); IntuiText = IntuiText->NextText; IntuiText->IText[0] = d[0]; IntuiText = IntuiText->NextText; IntuiText->IText[0] = d[0]; PrintIText( PalWind->RPort, SaveIntui, gadget->LeftEdge, gadget->TopEdge); } /* * Reflect a pen's new color in the proportional gadget */ SetColorProps(pen) LONG pen; { register LONG rgb, red, green, blue; if (PalWind == NULL) return; pen &= Num_vp_Colors - 1; rgb = GetRGB4(vp->ColorMap, pen); red = 0xF - ((rgb >> 8) & 0xF); green = 0xF - ((rgb >> 4) & 0xF); blue = 0xF - (rgb & 0xF); red |= (red << 4); red |= (red << 8); green |= (green << 4); green |= (green << 8); blue |= (blue << 4); blue |= (blue << 8); NewModifyProp(PalGads.RedPot, PalWind,NULL,FREEVERT|PROPBORDERLESS, 0L,red,0L,0xfffL,1L); NewModifyProp(PalGads.GreenPot,PalWind,NULL,FREEVERT|PROPBORDERLESS, 0L,green,0L,0xfffL,1L); NewModifyProp(PalGads.BluePot, PalWind,NULL,FREEVERT|PROPBORDERLESS, 0L,blue,0L,0xfffL,1L); } /* SetColorProps */ BoxPen(BoxPen, DrawPen) LONG BoxPen, DrawPen; { register LONG Top, Bot, Left, Right; register ULONG row, column; #define PALTOP (PENTOP - 1) #define PALLEFT (PENLEFT - 1) #define PENWIDTH (4 << XScale) #define PENHEIGHT (4 << YScale) #define PENXPITCH (6 << XScale) #define PENYPITCH (6 << YScale) if (PalWind == NULL) return; column = BoxPen/8; row = BoxPen - column*8; SetAPen(PalWind->RPort, DrawPen); Left = PALLEFT + PENXPITCH * column; Top = PALTOP + PENYPITCH * row; Right = Left + PENWIDTH + 2 + XScale; Bot = Top + PENHEIGHT + 2 + YScale; Move(PalWind->RPort, Left, Top); Draw(PalWind->RPort, Right, Top); if (DrawPen == HIGHLIGHTPEN) SetAPen(PalWind->RPort, SHADOWPEN); Draw(PalWind->RPort, Right, Bot); Draw(PalWind->RPort, Left, Bot); SetAPen(PalWind->RPort, DrawPen); Draw(PalWind->RPort, Left, Top + 1); if (DrawPen) { row = GetRGB4(vp->ColorMap, BoxPen & (Num_vp_Colors - 1)); PrintRGB( (long) row >> 8, (long) row >> 4, (long) row ); } } static LONG WindowWidth; static LONG WindowHeight; static LONG BorderLeft; static struct Border *PensBorder; /* * Allocate all the gadgets for the color palette window */ struct Gadget *MakePalette() { struct Gadget *FirstGadget; register struct Gadget *NextGadget; register LONG i,Left,x,y,c = 0; struct IntuiText *Text, *NextText; struct PropInfo *PropInfo; LONG fourx = 4 << XScale; LONG foury = 4 << YScale; char *str; Left = PENLEFT; FirstGadget = NextGadget = MakeBool( Left, PENTOP, fourx, foury, 0, PALPEN, GADGIMAGE ); if ( FirstGadget == NULL ) goto error; i = 1 << (screen->BitMap.Depth); for (x = 0; x < 6*8 && i > 0; x += 6) { for (y = 0; y < 6*8 && i > 0; y += 6) { if (c != 0) { NextGadget->NextGadget = MakeBool( Left, (y<NextGadget) == NULL) goto error; } c++; i--; } Left += 6 << XScale; } WindowHeight = ((6*8) << YScale) + PENTOP + 6; c = ((y + 1) << YScale) + 2; if ( c > WindowHeight ) { WindowHeight = c + 4; } PensBorder = ShadowBorder( BEVELEDUP, 4, 12, Left - 2, c+1); if (PensBorder == NULL) goto error; Left += 9; BorderLeft = Left - 1; i = -2 * ( XScale ^ 1 ); for (x = y = 0; y < 3; x += 10, y++) { NextGadget->NextGadget = MakePot( Left + x, 22, fourx, WindowHeight - 35, PALPOT, y); NextGadget = NextGadget->NextGadget; if ( NextGadget == NULL ) goto error; NextGadget->Activation = GADGIMMEDIATE | FOLLOWMOUSE | RELVERIFY; NextGadget->GadgetText = Text = ShadowIntui("0", i, WindowHeight - 32 ); if ( Text == NULL ) goto error; PropInfo = (struct PropInfo *) NextGadget->SpecialInfo; PropInfo->VertBody = 0xfff; switch (y) { case 0: PalGads.RedPot = NextGadget; str = "R"; break; case 1: PalGads.GreenPot = NextGadget; str = "G"; break; case 2: PalGads.BluePot = NextGadget; str = "B"; break; } NextText = Text; while ( NextText->NextText ) { NextText = NextText->NextText; } NextText->NextText = ShadowIntui( str, i, -11 ); if ( NextText->NextText == NULL ) goto error; } Left += 32; for (c = 0, x = 0; x < 17*3; x += 17) { NextGadget->NextGadget = MakeBool( Left, x + 11, 54, 13, 1, PALCNTL+c, NULL); NextGadget = NextGadget->NextGadget; if ( NextGadget == NULL) goto error; switch (c) { case 0: NextGadget->GadgetText = ShadowIntui("Copy", 12,3); break; case 1: NextGadget->GadgetText = ShadowIntui("Spread",4,3); break; case 2: NextGadget->GadgetText = ShadowIntui("Exchg", 8,3); break; } c++; } WindowWidth = Left + 59; return(FirstGadget); error: FreeBorder( PensBorder ); FreeGadgets( FirstGadget ); return( NULL ); } /* MakePalette */ static struct Gadget *PalGadgets; /* * Open the Palette window */ OpenPalWind() { struct Window *OpenMyWind(); register struct Gadget *gadget; register struct RastPort *Rp; LONG fourx = 4 << XScale; if (CurPict == NULL) return; if ( PalWind == NULL ) { gadget = MakePalette(); if ( gadget == NULL ) { DispErrMsg("Couldn't get palette gadgets", 0 ); return; } PalWind = OpenMyWind( &NewPal, screen, NULL, WindowWidth, WindowHeight); if ( PalWind != NULL ) { ModifyIDCMP( PalWind, (long) PalWind->IDCMPFlags | MOUSEBUTTONS | MOUSEMOVE ); Rp = PalWind->RPort; SetAPen( Rp, NORMALPEN ); RectFill( Rp, LEFTMARG, TOPMARG, WindowWidth,WindowHeight); BorderWindow( PalWind ); PalGadgets = gadget; AddGList( PalWind, gadget, -1, -1); RefreshGadgets( gadget, PalWind, NULL ); DrawBorder( Rp, PensBorder, 0L, 0L ); FreeBorder( PensBorder ); CurPen &= Num_vp_Colors - 1; BoxPen( CurPen, MEDIUMPEN ); SetColorProps( CurPen ); } } else { WindowToFront( PalWind ); } PaletteOpen = 1; } /* OpenPalWind */ /* * Close the Palette window */ ClosePalWind() { if (PalWind != NULL) { NewPal.LeftEdge = PalWind->LeftEdge; NewPal.TopEdge = PalWind->TopEdge; CloseMyWind(PalWind,PalGadgets); PalGadgets = NULL; } PalWind = NULL; } /* ClosePalWind */