source/offscrnGraphics.c

/****************************************************/
/*                                                  */
/*  File:       offscrnGraphics.c                   */
/*                                                  */
/*  Program:    Imageer                             */
/*                                                  */
/*  By:         Jason Hodges-Harris                 */
/*                                                  */
/*  Created:    26/10/95  00:00:00 AM               */
/*                                                  */
/*  Version:    1.0.0d3                             */
/*                                                  */
/*  Copyright:  © 1995-96 Apple Computer, Inc.,     */ 
/*                  all rights reserved.            */      
/*                                                  */
/****************************************************/
 
 
/**** Macintosh Toolbox Headers *****/
 
#ifndef __PALETTES__
#include <Palettes.h>
#endif
 
#ifndef __QDOFFSCREEN__
#include <QDOffscreen.h>
#endif
 
#ifndef __TYPES__
#include <Types.h>
#endif
 
 
/****   Application headers and prototypes   ****/
 
 
#ifndef __IMAGEERAPPHEADER__
#include "Imageer.app.h"
#endif
 
#ifndef __IMAGEERPROTOSHEADER__
#include "Imageer.protos.h"
#endif
 
 
/****   Default RGB Colors  ****/
 
static const RGBColor   kRGBBlack = {0x0000, 0x0000, 0x0000};
static const RGBColor   kRGBWhite = {0xFFFF, 0xFFFF, 0xFFFF};
 
 
/**** Create GWorld attached to the image window document structure ****/
 
#pragma segment ImageWorld
GWorldPtr   CreateOffscreen (CTabHandle theCTabHndl, short theXsize, short theYsize, short theBitDepth,GWorldFlags theFlags)
{
    GWorldPtr   theGWorldPtr = nil;
    QDErr       theError;
    Rect        theRect;
    
    SetRect(&theRect,0,0,theXsize,theYsize);
    theError = NewGWorld (&theGWorldPtr,theBitDepth,&theRect,theCTabHndl,nil,theFlags);
    if (theError)
    {
        DisplayAlert (rGenAlert,rQDMessages,iFailGWorldAlloc);
        return nil;
    }
    return theGWorldPtr;
}
 
 
/**** Draw image palette colors ****/
 
#pragma segment ImageWorld
OSErr       DrawImageColors(WindowPtr   theWindow)
{
    ImageDocHndl    theColorsDocHndl = nil,
                    theFrontDocHndl = nil;
    PaletteHandle   windowPalette;
    WindowPtr       frontWindow,
                    theNextWindow;
    RGBColor        oldForeColor,
                    newForeColor;
    Rect            colorRect;
    short           countX,
                    countY,
                    colorIndex = 0,
                    numberColors;
    OSErr           error = noErr;
    Boolean         isImageWindow = false;
    
    GetForeColor (&oldForeColor);
    frontWindow = FrontWindow();
    while (!isImageWindow && frontWindow)
    {
        theFrontDocHndl = (ImageDocHndl)GetWRefCon(theWindow);
        if (!(**theFrontDocHndl).isColorsWindow)
        {
            isImageWindow = true;
        }
        else
        {
            theNextWindow = &((WindowPeek)frontWindow)->nextWindow->port;
            frontWindow = theNextWindow;
        }
    }
    theColorsDocHndl = (ImageDocHndl)GetWRefCon(theWindow);
    if (theColorsDocHndl)
    {
        switch ((**theColorsDocHndl).theImageDepth)
        {
            case    1:
                DisplayAlert (rGenWarning,rErrMessages,iNotImplemented);
            break;
            case    2:
            windowPalette = (**theColorsDocHndl).theColorsPalette;
            numberColors = (**windowPalette).pmEntries;
            for (countX = 0;countX<128;countX+=32)
            {
                GetEntryColor (windowPalette, colorIndex, &newForeColor);
                SetRect(&colorRect,16+ countX,16,countX+20,52);
                RGBForeColor(&newForeColor);
                PaintRect(&colorRect);
                colorIndex++;
            }
            RGBForeColor(&oldForeColor);
            return error;
            break;
            case    4:
                windowPalette = (**theColorsDocHndl).theColorsPalette;
                numberColors = (**windowPalette).pmEntries;
                for (countY = 0;countY<32;countY+=16)
                {
                    for (countX = 0;countX<128;countX+=32)
                    {
                        GetEntryColor (windowPalette, colorIndex, &newForeColor);
                        SetRect(&colorRect,16+ countX,16+countY,countX+20,32+countY);
                        RGBForeColor(&newForeColor);
                        PaintRect(&colorRect);
                        colorIndex++;
                    }
                }
                RGBForeColor(&oldForeColor);
                return error;
            break;
            case    8:
                windowPalette = (**theColorsDocHndl).theColorsPalette;
                numberColors = (**windowPalette).pmEntries;
                for (countY = 0;countY<32;countY+=4)
                {
                    for (countX = 0;countX<128;countX+=4)
                    {
                        GetEntryColor (windowPalette, colorIndex, &newForeColor);
                        SetRect(&colorRect,16+ countX,16+ countY,countX+20,countY+20);
                        RGBForeColor(&newForeColor);
                        PaintRect(&colorRect);
                        colorIndex++;
                    }
                }
                RGBForeColor(&oldForeColor);
                return error;
            break;
            case    16:
            case    32:
                for (countY = 0;countY<4;countY++)
                {
                    for (countX = 0;countX<128;countX+=2)
                    {
                        SetRect(&colorRect,16+ countX,16+(countY*8),countX+18,24+(countY*8));
                        switch (countY)
                        {
                            case 0:
                                newForeColor.red = countX << 9;
                                newForeColor.green = countX << 9;
                                newForeColor.blue = countX << 9;
                                RGBForeColor(&newForeColor);
                                PaintRect(&colorRect);
                            break;
                            case 1:
                                newForeColor.red = countX << 9;
                                newForeColor.green = 0;
                                newForeColor.blue = 0;
                                RGBForeColor(&newForeColor);
                                PaintRect(&colorRect);
                            break;
                            case 2:
                                newForeColor.red = 0;
                                newForeColor.green = countX << 9;
                                newForeColor.blue = 0;
                                RGBForeColor(&newForeColor);
                                PaintRect(&colorRect);
                            break;
                            case 3:
                                newForeColor.red = 0;
                                newForeColor.green = 0;
                                newForeColor.blue = countX << 9;
                                RGBForeColor(&newForeColor);
                                PaintRect(&colorRect);
                            break;
                        }
                    }
                }
                RGBForeColor(&oldForeColor);
                return error;
            break;
        }
    }
    return kDefaultAppError;
}
 
 
/****   Force the colortable to be reset    ****/
 
#pragma segment ImageWorld
void    ForceRestoreColors(void)
{
    RestoreDeviceClut(nil);
    PaintBehind(nil, GetGrayRgn());
    DrawMenuBar();
}
 
 
/****   Transfer visible portion of GWorld to current window    ****/
 
#pragma segment ImageWorld
OSErr   TransferImageToWindow(ImageDocHndl theWindDocHndl, WindowPtr theWindow)
{
    PixMapHandle    thePixMapHndl = nil;
    CGrafPtr        oldPort;
    GDHandle        oldGDev;
    RGBColor        oldForeColor,
                    oldBackColor;
    Rect            sourceRect,
                    destRect;
    OSErr           error = noErr;
    
    GetGWorld(&oldPort,&oldGDev);
    SetGWorld((**theWindDocHndl).theImageWorld,nil);
    GetForeColor(&oldForeColor);
    GetBackColor(&oldBackColor);
    RGBForeColor(&kRGBBlack);
    RGBBackColor(&kRGBWhite);
    thePixMapHndl = GetGWorldPixMap((**theWindDocHndl).theImageWorld);
    if (PixMap32Bit(thePixMapHndl))                 // if 32bit mode needed == true
        SaveSetMMUMode(true);
    if (!LockPixels(thePixMapHndl))
        error = kFailedLockPixels;
    if (!error)
    {
        sourceRect = (**theWindDocHndl).theImageWorld->portRect;
        destRect = theWindow->portRect;
        destRect.right -= kScrollBarWidth;  // resize port rect to exclude controller area
        destRect.bottom -= kScrollBarWidth;
        if (!EqualRect(&destRect,&sourceRect))
            sourceRect = *CalcVisibleImage(theWindDocHndl,&destRect);
        SetGWorld(oldPort,oldGDev);
        CopyBits((BitMap*)(*thePixMapHndl),
                 (BitMap*)&((*theWindow).portBits),
                 &sourceRect,&destRect,srcCopy,nil);
    }
    UnlockPixels(thePixMapHndl);        // unlock GWorld
    SaveSetMMUMode(false);
    return error;
}
 
 
/****   Calculate the visible area of window contents region ****/
 
#pragma segment ImageWorld
Rect*   CalcVisibleImage(ImageDocHndl theWindDocHndl,const Rect *destRect)
{
    Rect    displayRect;
    short   theXvalue,
            theYvalue;
 
    theXvalue = GetControlValue((**theWindDocHndl).theHScrollBar);
    theYvalue = GetControlValue((**theWindDocHndl).theVScrollBar);
    SetRect(&displayRect,theXvalue,theYvalue,destRect->right+theXvalue,destRect->bottom+theYvalue);
    return &displayRect;
}
 
 
/****   Set and Reset the address mode between 24 and 32 bits   ****/
 
#pragma segment ImageWorld
void    SaveSetMMUMode(Boolean isSaveMode)
{
    static signed char      theAddrMode = true32b;
    static Boolean          swapModeNeeded = false;
    
    if (isSaveMode == true)
    {
        if(GetMMUMode() == false32b)                // get current addr mode
        {
            swapModeNeeded = true;                  // in 24 bit mode swap needed
            SwapMMUMode (&theAddrMode);             // switch to 32 bit mode
        }
    }
    else if (swapModeNeeded == true)
        SwapMMUMode (&theAddrMode);
}
 
 
/****   Calc new index depth colors window palette  ****/
 
#pragma segment ImageWorld
OSErr   UpdateColorsWindPalette(ImageDocHndl theImageWindDocHndl, WindowPtr theImageWindow)
{
    ImageDocHndl    theFrntWindHndl;
    GrafPtr         oldPort;
    WindowPtr       theWindow,
                    theNextWindow;
    OSErr           error = noErr;
    
    GetPort(&oldPort);
    theWindow = FrontWindow();
    while (theWindow)
    {
        theFrntWindHndl = (ImageDocHndl)GetWRefCon(theWindow);
        if ((*theFrntWindHndl)->isColorsWindow)
        {
            if ((*theImageWindDocHndl)->theImageDepth != (*theFrntWindHndl)->theImageDepth)
                (*theFrntWindHndl)->theImageDepth = (*theImageWindDocHndl)->theImageDepth;
            if ((*theFrntWindHndl)->theImageDepth <= 8 && !(*theImageWindDocHndl)->isUsingQDGX)
            {
                if ((*theFrntWindHndl)->theColorsPalette)
                    DisposePalette((*theFrntWindHndl)->theColorsPalette);
                (*theFrntWindHndl)->theColorsPalette = 
                    NewPalette(256,
                               (*(*theImageWindDocHndl)->theImageWorld->portPixMap)->pmTable,
                               pmTolerant+pmExplicit,0);
                if ((*theFrntWindHndl)->theColorsPalette)
                     NSetPalette(theWindow,(*theFrntWindHndl)->theColorsPalette,pmAllUpdates);
                else
                    error = kFailMakePalette;
            }
            SetPort(theWindow);
            InvalRect(&theWindow->portRect);
            SetPort(oldPort);
            theWindow = nil;
        }
        if (theWindow)
        {
            theNextWindow = &((WindowPeek)theWindow)->nextWindow->port;
            theWindow = theNextWindow;
        }
    }
    return error;
}