Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!tut.cis.ohio-state.edu!ucbvax!dewey.soe.berkeley.edu!oster From: oster@dewey.soe.berkeley.edu (David Phillip Oster) Newsgroups: comp.sys.mac.programmer Subject: Re: color quickdraw and copybits glitches Message-ID: <33101@ucbvax.BERKELEY.EDU> Date: 8 Dec 89 00:34:41 GMT References: <1609@intercon.com> <3401@ccncsu.ColoState.EDU> Sender: usenet@ucbvax.BERKELEY.EDU Reply-To: oster@dewey.soe.berkeley.edu.UUCP (David Phillip Oster) Organization: School of Education, UC-Berkeley Lines: 325 Once again, here is a short example of using color quickdraw. This program takes a text file called "bush.ps" which is a postscript 16-gray level bitmap of president bush, reads it in and displays it in a window. This example is missing a few resources, and the actual "bush.ps" file. /* ShowBush.c - short program to display a postscript picture of Bush. in color quickdraw. You also get Bush on your clipboard. by David Phillip Oster. Copy and use this in any way you see fit. Basically an example of the pain you have to go through to actually use color quickdraw. In old quickdraw, you had some data and a window, and you CopyBit()s the data to the window. In color quickdraw, you have as your source: a.) the data. b.) a color table. c.) a "pixmap" that connects the data to the color table. as your destination, you have: a.) a color window b.) a palette, that informs the window manager of which colors you'll be using, so the color manager can change the color table in the video board to make those color available. This program works best with at least 16 colors! */ #include #define HEIGHT 200 #define WIDTH 200 #define NIL 0L #define NOT ! SysEnvRec *world; Handle myPixels; WindowPtr myWin; PixMapHandle myPixMap; CTabHandle myCTable; PaletteHandle myPm; enum { READERROR = 1, NEEDSCOLORQD, /* this demo needs color quickdraw */ NOPIXMAP, NOPIXELS, NOCTABLE, NOPALETTE, PIXDATACHANGED }; enum { UNDOI = 1, COPYI = UNDOI + 1 }; main(){ EventRecord myEvent; Init(); for(;;){ if(GetNextEvent(everyEvent, &myEvent)){ HandleEvent(&myEvent); } } } Init(){ PaletteHandle oldPm; FlushEvents(everyEvent, NIL); InitGraf( (Ptr) &thePort); InitFonts(); InitWindows(); InitCursor(); InitDialogs(NIL); InitMenus(); TEInit(); world = (SysEnvRec *) NewPtr(sizeof(SysEnvRec)); SysEnvirons(1, world); if( NOT world->hasColorQD){ Error(NEEDSCOLORQD, ""); } myWin = GetNewCWindow(128, NIL, -1L); /* set up the window */ SetPort(myWin); ClipRect(&thePort->portRect); myPixMap = NewPixMap(); /* allocate the pixmap */ if(NIL == myPixMap){ Error(NOPIXMAP, ""); } myPixels = NewHandle( ((long) HEIGHT/2)*WIDTH); /* allocate the pixel data */ if(NIL == myPixels){ Error(NOPIXELS, ""); } /* allocate the color table */ myCTable = (CTabHandle) NewHandle(sizeof(ColorTable) + 15L*sizeof(ColorSpec)); if(NIL == myCTable){ Error(NOCTABLE, ""); } InitPixels(myPixels); /* set up the pixel data */ InitCTable(myCTable); /* set up the color table */ (**myPixMap).bounds.left = 0; /* set up the pixmap */ (**myPixMap).bounds.top = 0; (**myPixMap).bounds.right = WIDTH; (**myPixMap).bounds.bottom = HEIGHT; (**myPixMap).rowBytes = 0x8000 | (WIDTH/2); if(NIL != (**myPixMap).pmTable) DisposHandle((**myPixMap).pmTable); (**myPixMap).pmTable = myCTable; (**myPixMap).pixelSize = 4; myPm = NewPalette(16, myCTable, pmTolerant, 0); /* set up the palette */ if(NIL == myPm){ Error(NOPALETTE, ""); } if(NIL != (oldPm = GetPalette(thePort))){ DisposePalette(oldPm); } SetPalette(thePort, myPm, TRUE); ActivatePalette(thePort); } /* SwapMove - copy from src to dest, moving scan lines from top to bottom as you go (postscript images are upside down compared to quickdraw images) */ SwapMove(src, dest, cnt)Ptr src, dest;long cnt;{ register short i, j; for(i = 0;i <200;i++){ BlockMove(src + (i*(WIDTH/2)), dest + ((199-i)*(WIDTH/2)), WIDTH/2); } } /* InitPixels- initialize our handle to the bush data SwapMove since Postscript is upside down from Mac. */ InitPixels(h)Handle h;{ register Ptr p, pMax; register short i; Handle h2, GetBush(); h2 = GetBush(); SwapMove(*h2, *h, GetHandleSize(h)); } /* InitCTable - initialize our color table to uniform gray */ InitCTable(ct)CTabHandle ct;{ short i; (**ct).ctSeed = GetCTSeed(); (**ct).ctFlags = 0; (**ct).ctSize = 15; for(i = 0;i < 16;i++){ (**ct).ctTable[i].value = i; (**ct).ctTable[i].rgb.red = (**ct).ctTable[i].rgb.green = (**ct).ctTable[i].rgb.blue = (unsigned) i * 16*257; } } /* Error - print the error message */ Error(i, s1)short i;Str255 s1;{ Str255 s; GetIndString(s, 128, i); ParamText(s, s1, "", ""); Alert(129, NIL); ExitToShell(); } /* HandleEvent - quit on mouse or key event */ HandleEvent(event)EventRecord *event;{ switch(event->what){ case mouseDown: case keyDown: ExitToShell(); case updateEvt: GoUpdate(event); break; } } /* GoUpdate - handle update event, paste it to clipboard */ GoUpdate(event)EventRecord *event;{ SetPort(event->message); BeginUpdate(thePort); CopyMyBits(); EndUpdate(thePort); } /* CopyMyBits - put bits to screen, put bits to clipboard */ CopyMyBits(){ Rect r, r2; PicHandle ph; HLock(myPixels); HLock(myPixMap); (**myPixMap).baseAddr = *myPixels; r.left = 0; r.top = 0; r.right = WIDTH; r.bottom = HEIGHT; r2 = r; r2.top *= 2; r2.left *= 2; r2.right *= 2; r2.bottom *= 2; ph = OpenPicture(&r); CopyBits(*myPixMap, &thePort->portBits, &r, &r, srcCopy, NIL); ClosePicture(); CopyBits(*myPixMap, &thePort->portBits, &r, &r2, srcCopy, NIL); HUnlock(myPixMap); HUnlock(myPixels); ZeroScrap(); HLock(ph); PutScrap(GetHandleSize(ph), 'PICT', *ph); SystemEdit(COPYI-1); /* so multifinder will take the scrap */ KillPicture(ph); } /* GetBush */ Handle GetBush(){ OSErr val; short ref; Handle h; long len; Str255 s; ref = 0; h = NIL; val = FSOpen("\pbush.ps", 0, &ref); if(noErr == val)val = GetEOF(ref, &len); if(noErr == val)h = NewHandle(len - 4); if(noErr == val && NIL != h){ HLock(h); len = GetHandleSize(h); if(noErr == val)val = FSRead(ref, &len, *h); HexToBin(h); HUnlock(h); } if(0 != ref){ FSClose(ref); } if(noErr != val){ NumToString(val, s); Error(READERROR, s); if(NIL != h){ DisposHandle(h); h = NIL; } } return h; } /* SkipHeader - advance p to point to data */ unsigned char *SkipHeader(p)register unsigned char *p;{ while( NOT (p[0] == '\r' && p[1] == '0')) p++; return &p[1]; } /* HexToBin - h is a locked handle containing text. turn it into binary Sorry about this. It is a quick and dirty hex ascii to binary routine. */ HexToBin(h)Handle h;{ register unsigned char *src, *srcMax, *dest; src = dest = (unsigned char *) *h; src = SkipHeader(src); srcMax = src + GetHandleSize(h); while(src < srcMax){ if(*src >= '0' && *src <= '9'){ *dest = (*src++ - '0') << 4; if(*src >= '0' && *src <= '9'){ *dest++ |= *src++ - '0'; }else if(*src >= 'A' && *src <= 'F'){ *dest++ |= *src++ - 'A' + 10; }else if(*src >= 'a' && *src <= 'f'){ *dest++ |= *src++ - 'a' + 10; } }else if(*src >= 'A' && *src <= 'F'){ *dest = (*src++ - 'A' + 10) << 4; if(*src >= '0' && *src <= '9'){ *dest++ |= *src++ - '0'; }else if(*src >= 'A' && *src <= 'F'){ *dest++ |= *src++ - 'A' + 10; }else if(*src >= 'a' && *src <= 'f'){ *dest++ |= *src++ - 'a' + 10; } }else if(*src >= 'a' && *src <= 'f'){ *dest = (*src++ - 'a' + 10) << 4; if(*src >= '0' && *src <= '9'){ *dest++ |= *src++ - '0'; }else if(*src >= 'A' && *src <= 'F'){ *dest++ |= *src++ - 'A' + 10; }else if(*src >= 'a' && *src <= 'f'){ *dest++ |= *src++ - 'a' + 10; } }else{ src++; } } SetHandleSize(h, dest - (unsigned char *) *h); }