CodeWarrior (OS 9)/RotateString.c

/*
    File:       RotateString.c
 
    Contains:   This function will return a BitMap that contains the
                text passed rotated 90¡
    
                The font characteristics are copied from
                the current port before creating the BitMap.
    
 
    Written by: RT and BS
 
    Copyright:  Copyright © 1992-1999 by Apple Computer, Inc., All Rights Reserved.
 
                You may incorporate this Apple sample source code into your program(s) without
                restriction. This Apple sample source code has been provided "AS IS" and the
                responsibility for its operation is yours. You are not permitted to redistribute
                this Apple sample source code as "Apple sample source code" after having made
                changes. If you're going to re-distribute the source, we require that you make
                it clear in the source that the code was descended from Apple sample source
                code, but that you've made changes.
 
    Change History (most recent first):
                08/2000     JM              Carbonized, non-Carbon code is commented out
                                            for demonstration purposes.
                7/14/1999   KG              Updated for Metrowerks Codewarror Pro 2.1
                
                8/27/92     BS              added a direction parameter to the end. It will 
                                            rotate in the direction you specify. ALSO fixed 
                                            some LAME bugs, such as the rotate routine did not 
                                            preserve the current port,and it also did not dispose 
                                            of a temporary bitmap it used.  Should be in good
                                            shape now.
 
*/
#include "CarbonPrefix.h"
#include <Memory.h>
#include <QDOffscreen.h>
#include "RotateString.h"
 
/*
    In pascal this is:
 
 function RotateString (str: Str255; var destMap: BitMap, direction : integer): OSErr;
 
*/
 
 
pascal OSErr RotateString( Str255 str, BitMap *destMap, short direction)
{
    //GrafPort  srcPort;
    //GrafPtr       srcPortPtr;
    char        *srcPtr, *destPtr;
    FontInfo    f;
    short       heightBits, heightBytes;
    short       width, widthBytes;
    short       rotateWidth;
    short       rotateHeight;
    short       row, column;
    short       texFont,texFace,texMode,texSize;    
    short       err;
    //Rect      tempRect1;
    RgnHandle   rgnHandle = NewRgn();
    CGrafPtr    currentPort;        /* Saved CGrafPtr for later restore. */
    GDHandle    currentDevice;      /* Saved device for later restore. */
    GWorldPtr   sourceGWorld;
    Rect        rect;
    int         sourceRowBytes;
    
    
    GetGWorld( &currentPort, &currentDevice );
    
    /*texFont = qd.thePort->txFont;
    texFace = qd.thePort->txFace;
    texMode = qd.thePort->txMode;
    texSize = qd.thePort->txSize;*/
    
    texFont = GetPortTextFont(GetQDGlobalsThePort());
    texFace = GetPortTextFace(GetQDGlobalsThePort());
    texMode = GetPortTextMode(GetQDGlobalsThePort());
    texSize = GetPortTextSize(GetQDGlobalsThePort());
    
    //OpenPort( &srcPort);
    //srcPortPtr = CreateNewPort();
    //SetPort(&srcPort);
    //SetPort(srcPortPtr);
    
    TextFont(texFont);  
    TextFace(texFace);  
    TextMode(texMode);  
    TextSize(texSize);
    GetFontInfo( &f);
    
    heightBits = f.ascent + f.descent + f.leading;
    heightBytes = ((heightBits + 7) & 0x7FF8) >> 3;
    width = StringWidth( str );
    widthBytes = ((width + 7) & 0x7FF8) >> 3;
 
    rotateWidth = heightBytes;
    rotateHeight = widthBytes << 3;
    
    //srcPort.portBits.baseAddr = NewPtrClear( widthBytes * heightBits);
    /*(*(GetPortPixMap(srcPortPtr)))->baseAddr = NewPtrClear( widthBytes * heightBits );
    if(err = MemError()) return err;
 
    //srcPort.portBits.rowBytes = widthBytes;
    (*(GetPortPixMap(srcPortPtr)))->rowBytes = widthBytes;
    //SetRect( &srcPort.portBits.bounds, 0, 0, width, heightBits);
    SetRect( GetPortBounds(srcPortPtr, &tempRect1), 0, 0, width, heightBits );*/
    SetRect( &rect, 0, 0, width, heightBits );
    NewGWorld( &sourceGWorld, 1, &rect, nil, nil, 0 );
    SetGWorld( sourceGWorld, nil );
    EraseRect(&rect);
    
    TextFont(texFont);  
    TextFace(texFace);  
    TextMode(texMode);  
    TextSize(texSize);
    
    sourceRowBytes = GetPixRowBytes(GetGWorldPixMap(sourceGWorld));
    
    destMap->baseAddr = NewPtrClear( rotateWidth * rotateHeight);
    if(err = MemError()) {
        //DisposePtr(srcPort.portBits.baseAddr);
        DisposeGWorld(sourceGWorld);
        return err;
    }
    
    destMap->rowBytes = rotateWidth;
    SetRect( &destMap->bounds, 0, 0, rotateWidth * 8, rotateHeight);
    
    //RectRgn(srcPort.visRgn,&srcPort.portBits.bounds);
    RectRgn(GetPortVisibleRegion(sourceGWorld, rgnHandle), &(*(GetGWorldPixMap(sourceGWorld)))->bounds);
    MoveTo( 0, f.ascent);  // change 2.0.1 <CKH> was heightBits
    DrawString( str );
 
    
    /*****************************************/
    /*  Rotate Algorithm                     */
    /*****************************************/
 
    LockPixels(GetGWorldPixMap(sourceGWorld));
    //srcPtr = srcPort.portBits.baseAddr;       // Start at the Top,Left
    srcPtr = (*(GetGWorldPixMap(sourceGWorld)))->baseAddr;
    
    if(direction == counterClockWise)       // Start at the Bottom,Left
        destPtr = destMap->baseAddr + ((rotateHeight-1) * rotateWidth);
    else                                    // Start at the Top,Left
        destPtr = destMap->baseAddr;
                                            
    for( column = 0; column < width; column++)      /* width is in pixels */
    {
        for( row = 0; row < heightBits; row++)      /* height in pixels, too */
        {
        
            if(direction == counterClockWise) {
                /* We are rotating left ( counter clock-wise) thus */
                /*  as we search across the top of the horizontal pixel bit map,    */
                /*  we write down the right edge of the vertical pixel bit map */
 
                if( *(srcPtr                        /* Begin with the upper left corner */ 
                        //+ (row*widthBytes)            /* Move down a row */
                        + (row * sourceRowBytes)
                        + (column >> 3))            /* Go to the first even byte */
                        & (0x80>>(column & 7)) )    /* calculate a shifted bit position based on the column */
                    {
                        *(destPtr                   /* Begin in the lower left corner */
                            - (column*rotateWidth)  /* Subtract, move up for each row */
                            + (row >> 3))           /* Calculate a bit position for the column */
                            |= (0x80>>(row & 7));   /* Set a bit based on the column */
                    }
            } else {    /* clockWise */
                /*  We are rotating right (clock-wise) thus */
                /*  as we search across the top of the horizontal pixel bit map,    */
                /*  we write down the left edge of the vertical pixel bit map */
                
                if( *(srcPtr                        /* Begin with the upper left corner */ 
                        //+ (row*widthBytes)            /* Move down a row */
                        + (row * sourceRowBytes)
                        + (column >> 3))            /* Go to the first even byte */
                        & (0x80>>(column & 7)) )    /* calculate a shifted bit position based on the column */
                    {
                        *(destPtr                   /* Begin in the lower left corner */
                        + (column*rotateWidth) /* Add, move down for each row */
                        - (row >> 3))           /* Calculate a bit position for the column */
                        |= (0x01<<(row & 7));   /* Set a bit based on the column */
                    }
            }
        }
    }
    
    /* clean up the used source BitMap, and restore the ports properly */   
    //DisposePtr(srcPort.portBits.baseAddr);
    UnlockPixels(GetGWorldPixMap(sourceGWorld));
    DisposeGWorld(sourceGWorld);
    //ClosePort(&srcPort);
    SetGWorld( currentPort, currentDevice );
    DisposeRgn(rgnHandle);
    
    return noErr;
}