[comp.sys.mac.programmer] Source code request

rg2c+@andrew.cmu.edu (Robert Nelson Gasch) (04/18/91)

I've been trying to get CopyBits to work properly, but so far I have
managed to generate nothing but junk. This has gone on for quite
a while by now and it's getting annoying. So if anybody out
there has the source code for some program they would be willing
to donate, I'd appreciate hearing from them. Alternativeley,
if some samples exist on some FTP server, I'd be equally happy.
I just want something I can look at and figure out what I'm
doing wrong. Anything will do.

Thanx in advance
--> Rob

vrm@babcock.cerc.wvu.wvnet.edu (Vasile R. Montan) (04/19/91)

From article <4c3JO2600WBLE0ZlJU@andrew.cmu.edu>, by rg2c+@andrew.cmu.edu (Robert Nelson Gasch):
> I've been trying to get CopyBits to work properly, but so far I have
> managed to generate nothing but junk. This has gone on for quite
> a while by now and it's getting annoying. So if anybody out
> there has the source code for some program they would be willing
> to donate, I'd appreciate hearing from them. Alternativeley,
> if some samples exist on some FTP server, I'd be equally happy.
> I just want something I can look at and figure out what I'm
> doing wrong. Anything will do.

Below I've pasted Tech Note #41.  It should do just what you want.
(I know, it's available all over the place, but not all of us have
easy access to it anyway, so here it is.)
--Kurisuto  un020070@vaxa.wvnet.edu

The following is a short example of drawing to, then copying from, an offscreen bitmap. The only major concern when setting this up is that the number of rowBytes in the bitmap is even. Given these constants and variables

    CONST
       myString = 'The EYE';

    VAR
       oldPort   : GrafPtr;     {saved port}
       offScreen : GrafPort;    {our offscreen bitmap}
       ovalRect  : Rect;        {used for example drawing}

the offscreen port and bitmap can be allocated with the following statements:
    
    GetPort(oldPort);
    OpenPort(@offScreen);
    SetPort(oldPort);

    WITH offScreen, portBits, bounds DO BEGIN

 {make bitmap exactly the size of the port}
        portRect := thePort^.portRect;
        bounds := portRect;

        {rowBytes is size of row, rounded up to an even number of bytes}
        rowBytes := (((right - left) + 15) DIV 16) * 2;

        {number of bytes in BitMap is rowBytes * number of rows}
        {this calculation must be done with longs}
        baseAddr:= NewPtr(rowBytes * LongInt(bottom - top));

        {check MemError here to see if we had enough room for the bitmap}

    END;

We are now ready to draw into our offscreen port:

    SetPort(@offScreen);

    {since it's just an area of memory, we'd better clear it before we start}
    EraseRect(thePort^.portRect);

    {Example drawing}
    ovalRect := thePort^.portRect;
    FillOval(ovalRect, black);
    InsetRect(ovalRect, 1, 20);
    FillOval(ovalRect, white);
    InsetRect(ovalRect, 40, 1);
    FillOval(ovalRect, black);
    WITH ovalRect DO
      MoveTo((left+right-StringWidth(myString)) DIV 2, (top+bottom-12) DIV 2);
    TextMode(srcXOr);
    DrawString(myString);

Now we're ready to do the CopyBits, copying the image that we've drawn in the offscreen bitmap to thePort^.portBits, from the rectangle offScreen.bounds to the rectangle thePort^.portRect:

    SetPort(oldPort);
    CopyBits(offScreen.portBits, thePort^.portBits,
                offScreen.portRect, thePort^.portRect, srcCopy, NIL);

Notice here that if thePort^.portRect and offScreen.bounds are not the same size, CopyBits will scale the bit image that is being copied.

From MPW C, given these variables
    char* myString = "\pThe EYE";  /* string to display */

    GrafPtr  oldPort;              /* saved port */
    GrafPort offScreen;            /* our offscreen bitmap */
    Rect     ovalRect;             /* used for example drawing */

the offscreen port and bitmap can be allocated with the following statements:
    
    GetPort(&oldPort);
    
    OpenPort(&offScreen);
    SetPort(oldPort);
    
    /* make bitmap exactly the size of the port */
    offScreen.portRect = qd.thePort->portRect;
    offScreen.portBits.bounds = offScreen.portRect;
    
    /* rowBytes is size of row, rounded up to an even number of bytes */
    offScreen.portBits.rowBytes = (((offScreen.portBits.bounds.right -
        offScreen.portBits.bounds.left) + 15) >> 4) << 1;
        
    /* number of bytes in BitMap is rowBytes * number of rows */
/* this calculation must be done with longs */
    offScreen.portBits.baseAddr = NewPtr(offScreen.portBits.rowBytes *
        (long) (offScreen.portBits.bounds.bottom -
        offScreen.portBits.bounds.top));

    /* check MemError here to see if we had enough room for the bitmap */

We are now ready to draw into our offscreen port:

    SetPort(&offScreen);

    /* since it's just memory, we'd better clear it before we start */
    EraseRect(&qd.thePort->portRect);
 
    /* Example drawing */
    ovalRect = qd.thePort->portRect;
    FillOval(&ovalRect, qd.black);
    InsetRect(&ovalRect, 1, 20);
    FillOval(&ovalRect, qd.white);
    InsetRect(&ovalRect, 40, 1);
    FillOval(&ovalRect, qd.black);
    
MoveTo((ovalRect.left+ovalRect.right-StringWidth(myString)) >> 1,
        (ovalRect.top+ovalRect.bottom-12) >> 1);
    TextMode(srcXor);
    DrawString(myString);

    SetPort(oldPort);
    CopyBits(&offScreen.portBits, &qd.thePort->portBits,
        &offScreen.portRect, &qd.thePort->portRect, srcCopy, NULL);

Please note that this way of doing things is NOT faster than simply defining a picture and then drawing it to your window. There are cases, however, such as text rotation, where it will be advantageous to do the drawing off the screen, manipulate the bit image and then copy the result to the visible window. In addition, this technique will reduce flicker, because all of the drawing done offscreen will appear on the screen at once.

stevec@Apple.COM (Steve Christensen) (04/19/91)

rg2c+@andrew.cmu.edu (Robert Nelson Gasch) writes:
>I've been trying to get CopyBits to work properly, but so far I have
>managed to generate nothing but junk. This has gone on for quite
>a while by now and it's getting annoying. So if anybody out
>there has the source code for some program they would be willing
>to donate, I'd appreciate hearing from them. Alternativeley,
>if some samples exist on some FTP server, I'd be equally happy.
>I just want something I can look at and figure out what I'm
>doing wrong. Anything will do.

Well, here's a sample snippet that uses CopyBits.  Let's assume we have already
created a window and we want to draw an icon in it (yes, I know we could just
call PlotIcon, but this is an example).

WindowPtr	theWindow;
BitMap		theBits;
Rect		destRect;
Handle		theIcon;


theIcon = GetResource('ICON', 128);		// get the icon
HLock(theIcon);					//  and lock it while we use it

theBits.baseAddr = *theIcon;			// point to the icon's data
theBits.rowBytes = 4;				// 32 pixels == 4 bytes
SetRect(&theBits.bounds,0,0,16,16);		// icon's bounding rectangle

SetRect(destRect,20,10,36,26);			// where the icon goes

CopyBits(&theBits,&theWindow->portBits,&theBits.bounds,&destRect,srcCopy,nil);


That's all there is to it.  You could also specify theBits.bounds in the
window's local coordinates and use it as both the srcRect and dstRect in
this case.  You could also specify a portion of the icon by setting up another
rectangle in theBits.bounds' coordinate system and use it for the srcRect...

steve

-- 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Steve Christensen			Never hit a man with glasses.
  stevec@apple.com			Hit him with a baseball bat.

mxmora@unix.SRI.COM (Matt Mora) (04/19/91)

In article <1608@babcock.cerc.wvu.wvnet.edu> un020070@vaxa.wvnet.edu writes:
>    VAR
>       oldPort   : GrafPtr;     {saved port}
>       offScreen : GrafPort;    {our offscreen bitmap}
>       ovalRect  : Rect;        {used for example drawing}
>
>the offscreen port and bitmap can be allocated with the following statements:
>    
>    GetPort(oldPort);
>    OpenPort(@offScreen);
              ^
          IS THAT RIGHT?

I don't think you need the @ sign here. 
Or at the other SetPort(@Offscreen);






-- 
___________________________________________________________
Matthew Mora                |   my Mac  Matt_Mora@sri.com
SRI International           |  my unix  mxmora@unix.sri.com
___________________________________________________________

jcav@quads.uchicago.edu (john cavallino) (04/20/91)

In article <23407@unix.SRI.COM> mxmora@unix.sri.com (Matt Mora) writes:
>In article <1608@babcock.cerc.wvu.wvnet.edu> un020070@vaxa.wvnet.edu writes:
>>    VAR
>>       oldPort   : GrafPtr;     {saved port}
>>       offScreen : GrafPort;    {our offscreen bitmap}
>>       ovalRect  : Rect;        {used for example drawing}
>>
>>the offscreen port and bitmap can be allocated with the following statements:
>>    
>>    GetPort(oldPort);
>>    OpenPort(@offScreen);
>              ^
>          IS THAT RIGHT?
>
>I don't think you need the @ sign here. 
>Or at the other SetPort(@Offscreen);

Actually, it is correct, but the style is somewhat yecchy.

OpenPort takes a GrafPtr, the variable "offscreen" is a GrafPort, the "@"
operator takes the address of something, so @offscreen give you a GrafPtr.

It would be easier to read if there were an explicit variable of type GrafPtr.



-- 
John Cavallino                      |     EMail: jcav@midway.uchicago.edu
University of Chicago Hospitals     |    USMail: 5841 S. Maryland Ave, Box 145
Office of Facilities Management     |            Chicago, IL  60637
B0 f++ w c+ g+ k s(+) e+ h- pv      | Telephone: 312-702-6900