home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-01-22 | 9.2 KB | 219 lines | [TEXT/MMCC] |
- /*
- CopyWindows.c
-
- CopyWindows(srcWindow,dstWindow,srcRectPtr,dstRectPtr,srcMode,maskRgn);
-
- CopyWindows() provides a high-level interface to CopyBits and CopyBitsQuickly,
- accepting windows (WindowPtr, CWindowPtr, or GWorldPtr) instead of pixmaps or
- bitmaps.
-
- You select CopyBitsQuickly by using a srcMode that has the "copyLiterally" bit
- set, i.e. either srcCopyLiterally, addOverLiterally, addOverParallelLiterally,
- or mulOverLiterally.
-
- For your convenience, CopyWindows normally sets up the foreground and background
- colors to prevent undesired colorizing. If you want to colorize then add
- "copyColorize" to the srcMode argument.
-
- CopyBits() is an extremely useful component of QuickDraw, but it's tricky to
- use, especially if you just want a faithful copy. Its user-interface was frozen
- a long time ago, when off-screen images were referred to by their BitMap
- pointers. Apple generalized its underlying code to accept PixMap pointers as
- well, but the reality is that nowadays the object that we work with is a window,
- either on-screen, or off-screen (i.e. a GWorld). CopyWindows accepts two
- windows, source and destination, figures out where the associated Pix/BitMaps
- are, and calls CopyBits or CopyBitsQuickly, after making all the appropriate
- incantations to get the desired results.
-
- The allowed values for srcMode are documented by Apple along with CopyBits in the
- New Inside Mac: "Imaging with QuickDraw". The additional modes implemented by
- CopyBitsQuickly are documented in CopyBitsQuickly.c. CopyBits and
- CopyBitsQuickly define srcMode as a short. CopyWindows defines srcMode as a
- long, using two bits in the upper word as flags for copyLiterally and
- copyColorize. Here's a summary of the modes that I use most:
-
- srcCopy
-
- This mode is implemented by CopyBits. If the source and destination have the
- same depth (i.e. pixelSize) and exactly the same color table then you'll get
- faithful copying of the actual numbers stored in each pixel. (I'm assuming that
- the destination window has the same color table as its device, which will be
- true if you created the window using GDOpenWindow or NewGWorld.) If the source
- and destination have different color tables, e.g. because the pixel sizes
- differ, then CopyBits will translate via the color tables. CopyBits is perhaps
- Apple's prize piece of code and runs very fast, taking advantage of special
- instructions of particular processors (e.g. to do 64 bit moves on 68040 and
- PowerPC) and can do wonderful things, like stretch and shrink and mask by a
- region. Apple defines many other srcMode values but I never use them with
- CopyBits because they all result in color translations that I don't want.
-
- srcCopyLiterally,addOverLiterally,addOverParallelLiterally,mulOverLiterally
-
- These modes are implemented by CopyBitsQuickly, which never does color
- translation. addOverLiterally adds the pixel values, ignoring overflow.
- addOverParallelLiterally does the same, but does the addition for 32-bits at a
- time, adding several pixels at once, so that if overflow occurs it will overflow
- into an adjoing pixel. mulOverLiterally multiplies the (unsigned) pixels,
- divides the product by 128, and stores the result in the destination.
- CopyBitsQuickly has many restrictions. The source and destination must have the
- same rect size and the same pixel size. addOverLiterally and mulOverLiterally
- insist on 8-bit pixels. All the modes resolve only bytes, not bits, so a few
- bits at the left and right of your image may not be copied if that would require
- writing to a byte not all of whose bits are in the destination.
-
- NOTES:
-
- 0. Read "VideoToolbox:Notes:CopyBits slavishly".
-
- 1. CopyBits has a rarely used feature called "colorizing" whereby if the
- foreground and background colors of the current port are not black and white
- then each source pixel's color is translated by linear interpolation between the
- foreground and background color. Programmers often forget about this, and are
- surprised by the undesired colorizing. To make life easier I've defined an extra
- bit in srcMode. If the "copyColorize" flag is false (nearly always the case)
- then CopyWindows will make sure no colorizing occurs by setting the fore and
- back colors to black and white. (The colors are restored before returning.)
-
- 2. Apple's CopyBits uses the color table and palette of the source pixmap as
- you'd expect, but ignores the color table and palette of the destination pixmap,
- and instead uses the color table of the current device. This is annoying, and
- hard to remember. Apple did it this way because CopyBits uses the inverse color
- table, which takes a long time to compute, and they decided that it would be too
- time and memory intensive to maintain an inverse table for each window, so
- instead they maintain them only for devices. The operating system creates
- inverse color tables for all graphic devices. Thus it is important to remember
- to set the device before calling CopyBits. To save you the trouble, CopyWindows
- sets the device to be whatever device is associated with the destination window.
- The device is found by GetWindowDevice(), which, for an on-screen window,
- returns the screen device with largest intersection with the window's content,
- and for an off-screen window (i.e. GWorld), returns the GWorld's device. When
- you create your GWorld you should supply the color table of your device,
- (*(*device)->gdPMap)->pmTable, if you'll later be copying from the GWorld
- to the device.
-
- 3. CopyWindowsQuickly calls ShieldCursor(), to make up for the fact that
- CopyBitsQuickly doesn't. QuickDraw automatically calls ShieldCursor for all
- screen-drawing operations, but CopyBitsQuickly bypasses QuickDraw. The obvious
- cosmetic benefit of calling ShieldCursor is that it prevents the cursor from
- appearing within screen areas that are being read or written. A further, subtle,
- benefit of calling ShieldCursor is compatibility with the one or two video
- devices, e.g. Radius PowerView, that depend on notification from QuickDraw that
- they've been written to. According to the programmer who wrote the PowerView
- driver, it's enough to call ShieldCursor(), specifying the global rect that was
- modified. That's hard to do within CopyBitsQuickly because the PixMap doesn't
- have any global coordinates; it merely has local coordinates and the address of
- video memory. (One would have to use the video address to figure out the device,
- and get the global coordinates from the device.) But it's easy to call
- ShieldCursor from within CopyWindowsQuickly, since it has access to the windows,
- which include the necessary global coordinates.
-
- HISTORY:
- 10/3/94 dgp wrote it.
- 11/5/94 dgp added the new flags copyLiterally and copyColorize.
- */
- #include "VideoToolbox.h"
- #include <QuickDraw.h>
- static int CopyWindowsQuickly(CWindowPtr srcWindow,CWindowPtr dstWindow
- ,Rect *srcRectPtr,Rect *dstRectPtr,long srcMode,RgnHandle maskRgn);
-
- int CopyWindows(CWindowPtr srcWindow,CWindowPtr dstWindow
- ,Rect *srcRectPtr,Rect *dstRectPtr,long srcMode,RgnHandle maskRgn)
- {
- GWorldPtr oldPort;
- GDHandle oldDevice,device;
- int error;
- static const RGBColor blackRGB={0,0,0},whiteRGB={0xFFFF,0xFFFF,0xFFFF};
- RGBColor foreRGB,backRGB;
- ColorSpec foreColor,backColor;
- BitMap *srcBits,*dstBits;
- static Boolean qd8,qd32,firstTime=1;
- Boolean colorize;
-
- if(srcMode & copyLiterally)
- return CopyWindowsQuickly(srcWindow,dstWindow,srcRectPtr,dstRectPtr,srcMode,maskRgn);
- colorize=(srcMode©Colorize)!=0;
- srcMode&=0xffff; // no more need for upper bits.
- if(firstTime){
- long qd;
- Gestalt(gestaltQuickdrawVersion,&qd);
- qd8 = qd>=gestalt8BitQD;
- qd32 = qd>=gestalt32BitQD;
- firstTime=0;
- }
- device=GetWindowDevice((WindowPtr)dstWindow);
- if(qd32){
- GetGWorld(&oldPort,&oldDevice);
- SetGWorld((GWorldPtr)dstWindow,device);
- }else{
- GetPort((WindowPtr *)&oldPort);
- SetPort((WindowPtr)dstWindow);
- if(qd8){
- oldDevice=GetGDevice();
- SetGDevice(device);
- }
- }
- if(!colorize && qd8){
- GetForeColor(&foreRGB);
- GetBackColor(&backRGB);
- if(qd32){
- SaveFore(&foreColor);
- SaveBack(&backColor);
- }
- RGBForeColor(&blackRGB); /* so CopyBits won't colorize */
- RGBBackColor(&whiteRGB); /* so CopyBits won't colorize */
- }
- srcBits=GetBitMapPtr(srcWindow);
- dstBits=GetBitMapPtr(dstWindow);
- if(srcBits==NULL || dstBits==NULL)return -1;
- CopyBits(srcBits,dstBits,srcRectPtr,dstRectPtr,srcMode,maskRgn);
- error=QDError();
- if(!colorize && qd8){
- RGBForeColor(&foreRGB);
- RGBBackColor(&backRGB);
- if(qd32){
- RestoreFore(&foreColor);
- RestoreBack(&backColor);
- }
- }
- if(qd32){
- SetGWorld(oldPort,oldDevice);
- }else{
- SetPort((WindowPtr)oldPort);
- if(qd8)SetGDevice(oldDevice);
- }
- return error;
- }
-
- static int CopyWindowsQuickly(CWindowPtr srcWindow,CWindowPtr dstWindow
- ,Rect *srcRectPtr,Rect *dstRectPtr,long srcMode,RgnHandle maskRgn)
- {
- int error,i,shields=0;
- BitMap *srcBits,*dstBits;
- Point pt;
- WindowPtr oldPort;
-
- GetPort(&oldPort);
- if(!IsGWorldPtr(srcWindow)){
- SetPort((WindowPtr)srcWindow);
- pt.h=pt.v=0;
- LocalToGlobal(&pt);
- ShieldCursor(srcRectPtr,pt);
- shields++;
- }
- if(!IsGWorldPtr(dstWindow)){
- SetPort((WindowPtr)dstWindow);
- pt.h=pt.v=0;
- LocalToGlobal(&pt);
- ShieldCursor(dstRectPtr,pt);
- shields++;
- }
- SetPort(oldPort);
- srcBits=GetBitMapPtr(srcWindow);
- dstBits=GetBitMapPtr(dstWindow);
- if(srcBits==NULL || dstBits==NULL)return 4;
- error=CopyBitsQuickly(srcBits,dstBits,srcRectPtr,dstRectPtr,srcMode,maskRgn);
- for(i=0;i<shields;i++)ShowCursor();
- return error;
- }
-
-