TweetFollow Us on Twitter

Apr 99 Tips

Volume Number: 15 (1999)
Issue Number: 4
Column Tag: Tips & Tidbits

Apr 99 Tips

by Jeff Clites <online@mactech.com>

PixMap Rotation

CopyBits is one of the most powerful and ubiquitous of the Mac OS toolbox calls. It can scale, convert colors, and mask in a variety of ways. About the only thing it can't do is rotate an image. Similarly, we all know how to use DrawString to put text on the screen - but when we need to draw rotated text (say, for labeling a graph), we find no toolbox call up to the task. The routines below serve both needs.

RotatePixMap takes pointers to two PixMaps, and rotates the first into the second, rotating through a specified number of degrees (counter-clockwise). DrawRotatedString uses RotatePixMap to draw a string rotated to any angle, and then moves the graphics cursor accordingly. It also illustrates how to create a pair of pixel maps, draw into one, rotate into the other, and copy to the screen; a similar technique was used to rotate Clarus the dogcow in the figure below.

The code here only rotates pixel maps with 8-bit color depth or higher; it will return -1 if given a 1-bit image. It uses GWorlds, so requires at least System 7, but will work on both 68k and PowerPC machines. These functions form a valuable addition to the standard toolbox.

#include <Errors.h>
#include <fp.h>
#include "Rotate.h"

static void GetTrigs(float degrees, double_t *sinang, 
   double_t *cosang)
{
   // compute sine and cosine of the angle given in degrees;
   // check for special cases to avoid any rounding error
   if (degrees == 0) {
      *sinang = 0; *cosang = 1;
   } else if (degrees == 90 || degrees == -270) {
      *sinang = -1; *cosang = 0;
   } else if (degrees == 180 || degrees == -180) {
      *sinang = 0; *cosang = -1;
   } else if (degrees == 270 || degrees == -90) {
      *sinang = 1; *cosang = 0;
   } else {
      double_t radians = -degrees * pi / 180.0;
      *cosang = cos(radians);
      *sinang = sin(radians);
   }
}

OSErr RotatePixMap(PixMapPtr srcPm,
                                  PixMapPtr destPm,
   float degrees)
{
   double_t          cosang, sinang;
   short                x,y,x2,y2,i;
   char                *srcbyte, *destbyte;
   short                pixsize = srcPm->pixelSize / 8;
   unsigned char    blankByte = pixsize == 1 ? 0 : 255;

   short srcRowBytes = srcPm->rowBytes & 0x7FFF;
   short destRowBytes = destPm->rowBytes
                                           & 0x7FFF;

   short srcwidth = srcPm->bounds.right
                                           - srcPm->bounds.left,
      destwidth = destPm->bounds.right
                                           - destPm->bounds.left,
      srcheight = srcPm->bounds.bottom
                                           - srcPm->bounds.top,
      destheight = destPm->bounds.bottom
                                           - destPm->bounds.top;

   short srcCx = srcwidth/2,
                                           srcCy = srcheight/2;
   short destCx = destwidth/2,
                                           destCy = destheight/2;

   if (destPm->pixelSize/8
                                  != pixsize || pixsize < 1)
      return -1;   // requires 8 bit pixmap or higher
   
   GetTrigs(degrees, &sinang, &cosang);
   
   // loop over each element in dest, copying from source or          // setting to white
   for (y=0; y<destheight; y++) {
      destbyte = destPm->baseAddr +       y*destRowBytes;
      for (x=0; x<destwidth; x++) {
         x2 = srcCx + cosang*(x-destCx) +    sinang*(y-destCy);
         y2 = srcCy + cosang*(y-destCy) -    sinang*(x-destCx);
         if (x2 >= 0 && x2 < srcwidth
          && y2 >= 0 && y2 < srcheight) {
            srcbyte = srcPm->baseAddr +   y2*srcRowBytes
                  + x2*pixsize;
            for (i=0; i<pixsize; i++) {
               *destbyte++ = *srcbyte++;   // copy color
            }
         } else {
            for (i=0; i<pixsize; i++) {
               *destbyte++ = blankByte;   // fill in blank
            }
         }
      }
   }

   return noErr;
}


OSErr DrawRotatedString(Str255 s, float degrees)
{
   FontInfo   fi;
   short            cheight, cwidth, bufsize;
   Rect               srcR, destR, screenR;
   GWorldPtr      srcGW, destGW;
   PixMapHandle   srcPmH, destPmH;
   PixMapPtr      srcPm, destPm;
   CGrafPtr         origPort;
   GDHandle         origDevice;
   OSErr            err=noErr;
   double_t         cosang, sinang;

   // find the string size
   GetFontInfo( &fi );
   cheight = fi.ascent + fi.descent +   fi.leading;
   cwidth = StringWidth(s);
   
   // set buffer size (allow room for rotation)
   bufsize = (cheight > cwidth ?
                                        cheight*2 : cwidth*2);
   
   // create an offscreen GWorld in which to draw the string,
   // and another in which to draw the rotated version
   SetRect( &srcR, 0, 0, bufsize, cheight*2 );
   err = NewGWorld( &srcGW, 0, &srcR,
                                        NULL, NULL, 0 );
   if (err) return err;

   SetRect( &destR, 0, 0, bufsize, bufsize );
   err = NewGWorld( &destGW, 0, &destR,
                                        NULL, NULL, 0 );
   if (err) { DisposeGWorld( srcGW ); return err; }

   srcPmH = GetGWorldPixMap( srcGW );
   LockPixels( srcPmH );
   srcPm = *srcPmH;

   destPmH = GetGWorldPixMap( destGW );
   LockPixels( destPmH );
   destPm = *destPmH;

   // store original port, and draw string to source GWorld
   GetGWorld( &origPort, &origDevice );

   SetGWorld( srcGW, NULL );
   TextFont( origPort->txFont );
   TextSize( origPort->txSize );
   TextFace( origPort->txFace );
   EraseRect( &srcR );
   MoveTo( bufsize/2, cheight );
   DrawString( s );

   // rotate into the dest buffer
   RotatePixMap( srcPm, destPm, degrees );

   // copy to screen in OR mode, to avoid clobbering background
   SetGWorld( origPort, origDevice );
   SetRect( &screenR, 0, 0, bufsize, bufsize );
   OffsetRect( &screenR, 
                           origPort->pnLoc.h - bufsize/2,
         origPort->pnLoc.v - bufsize/2 );
   CopyBits((BitMap*)destPm,
                        (BitMap*)(*origPort->portPixMap),
         &destR, &screenR, srcOr, NULL );
   
   // release memory
   UnlockPixels( srcPmH );
   DisposeGWorld( srcGW );
   
   UnlockPixels( destPmH );
   DisposeGWorld( destGW );
   
   // finally, move the pen by the proper amount and direction
   GetTrigs(degrees, &sinang, &cosang);
   Move(cosang*cwidth + 0.5, sinang*cwidth+0.5);
   return err;
}


Figure 1. Clarus the dogcow is rotated through 30 degrees using RotatePixMap. DrawRotatedString is used to surround him with moofs.

Joseph J. Strout <joe@strout.net>

You can download a demo of this Tip from ftp://ftp.mactech.com/src.

 
AAPL
$104.94
Apple Inc.
+1.95
MSFT
$45.41
Microsoft Corpora
+1.03
GOOG
$546.88
Google Inc.
+14.17

MacTech Search:
Community Search:

Software Updates via MacUpdate

Art Text 2.4.8 - Create high quality hea...
Art Text is an OS X application for creating high quality textual graphics, headings, logos, icons, Web site elements, and buttons. Thanks to multi-layer support, creating complex graphics is no... Read more
Live Interior 3D Pro 2.9.6 - Powerful an...
Live Interior 3D Pro is a powerful yet very intuitive interior designing application. View Video Tutorials It has every feature of Live Interior 3D Standard, plus some exclusive ones: Create multi... Read more
The Hit List 1.1.7 - Advanced reminder a...
The Hit List manages the daily chaos of your modern life. It's easy to learn - it's as easy as making lists. And it's powerful enough to let you plan, then forget, then act when the time is right.... Read more
jAlbum Pro 12.2.4 - Organize your digita...
jAlbum Pro has all the features you love in jAlbum, but comes with a commercial license. With jAlbum, you can create gorgeous custom photo galleries for the Web without writing a line of code!... Read more
jAlbum 12.2.4 - Create custom photo gall...
With jAlbum, you can create gorgeous custom photo galleries for the Web without writing a line of code! Beginner-friendly, with pro results Simply drag and drop photos into groups, choose a design... Read more
ExpanDrive 4.1.7 - Access remote files o...
ExpanDrive builds cloud storage in every application, acts just like a USB drive plugged into your Mac. With ExpanDrive, you can securely access any remote file server directly from the Finder or... Read more
OmniOutliner Pro 4.1.3 - Pro version of...
OmniOutliner Pro is a flexible program for creating, collecting, and organizing information. Give your creativity a kick start by using an application that's actually designed to help you think. It'... Read more
Evernote 5.6.2 - Create searchable notes...
Evernote allows you to easily capture information in any environment using whatever device or platform you find most convenient, and makes this information accessible and searchable at anytime, from... Read more
OmniOutliner 4.1.3 - Organize your ideas...
OmniOutliner is a flexible program for creating, collecting, and organizing information. Give your creativity a kick start by using an application that's actually designed to help you think. It's... Read more
BBEdit 11.0 - Powerful text and HTML edi...
BBEdit is the leading professional HTML and text editor for the Mac. Specifically crafted in response to the needs of Web authors and software developers, this award-winning product provides a... Read more

Latest Forum Discussions

See All

Puzzle to the Center of the Earth Review
Puzzle to the Center of the Earth Review By Campbell Bird on October 23rd, 2014 Our Rating: :: SPELUNKING PUZZLESUniversal App - Designed for iPhone and iPad Do some puzzles to make some platforms in this smart and fun free-to-play... | Read more »
Sleep Attack TD Review
Sleep Attack TD Review By Jennifer Allen on October 23rd, 2014 Our Rating: :: A TRUE TWISTUniversal App - Designed for iPhone and iPad Sleep Attack TD is a tower defense game with a difference – you can rotate the layout – and it’s... | Read more »
Mecanic (Education)
Mecanic 1.0 Device: iOS Universal Category: Education Price: $1.99, Version: 1.0 (iTunes) Description: Plates, screws, wheels ... Everything you need to achieve whatever you want... MECHANICWith 'MECANIC' kids will have fun... | Read more »
Earn Your Master Camper Badge in Camp Po...
Earn Your Master Camper Badge in Camp Pokemon Posted by Jessica Fisher on October 23rd, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Garruk Gets His Revenge in a New Magic 2...
Garruk Gets His Revenge in a New Magic 2015 Expansion, Coming This November Posted by Jessica Fisher on October 23rd, 2014 [ permalink ] | Read more »
Sentinels of the Multiverse Review
Sentinels of the Multiverse Review By Rob Thomas on October 23rd, 2014 Our Rating: :: SENTINELS ASSEMBLEiPad Only App - Designed for the iPad Greater Than Games’ tabletop classic, Sentinels of the Multiverse swoops in to save the... | Read more »
Build Your Own Fantasy Football Dynasty...
Build Your Own Fantasy Football Dynasty with Draft Day Posted by Jessica Fisher on October 23rd, 2014 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Cars: Fast as Lightning – Tips, Tricks,...
Hey there, Stickers: Want to know all about how impressed we were with Radiator Springs? Check out our Cars: Fast as Lightning review! Cars: Fast as Lightning is a cute and fun app that combines racing and town-building with the charisma and... | Read more »
Jam Messenger Review
Jam Messenger Review By Jennifer Allen on October 23rd, 2014 Our Rating: :: SIMPLE MESSAGINGiPhone App - Designed for the iPhone, compatible with the iPad Want a very quick way to send push-based messages? Jam Messenger is basic... | Read more »
Felllice (Games)
Felllice 1.0 Device: iOS Universal Category: Games Price: $.99, Version: 1.0 (iTunes) Description: EXCLUSIVE PRICE DROP! 50% OFF FOR A LIMITED TIME! EAT EAT EAT AND GROW ! | Read more »

Price Scanner via MacPrices.net

Save up to $125 on Retina MacBook Pros
B&H Photo has the new 2014 13″ and 15″ Retina MacBook Pros on sale for up to $125 off MSRP. Shipping is free, and B&H charges NY sales tax only. They’ll also include free copies of Parallels... Read more
Apple refurbished Time Capsules available sta...
The Apple Store has certified refurbished Time Capsules available for up to $60 off MSRP. Apple’s one-year warranty is included with each Time Capsule, and shipping is free: - 2TB Time Capsule: $255... Read more
Textilus New Word, Notes and PDF Processor fo...
Textilus is new word-crunching, notes, and PDF processor designed exclusively for the iPad. I haven’t had time to thoroughly check it out yet, but it looks great and early reviews are positive.... Read more
WD My Passport Pro Bus-Powered Thunderbolt RA...
WD’s My Passport Pro RAID solution is powered by an integrated Thunderbolt cable for true portability and speeds as high as 233 MB/s. HighlightsOverviewSpecifications Transfer, Back Up And Edit In... Read more
Save with Best Buy’s College Student Deals
Take an additional $50 off all MacBooks and iMacs at Best Buy Online with their College Students Deals Savings, valid through November 1st. Anyone with a valid .EDU email address can take advantage... Read more
iPad Air 2 & iPad mini 3 Best Tablets Yet...
The new iPads turned out to be pretty much everything I’d been hoping for and more than I’d expected.”More” particularly in terms of a drinking-from-a-firehose choice of models and configurations,... Read more
Drafts 4 Reinvents iOS Productivity App
N Richland Hills, Texas based Agile Tortoise has announced the release of Drafts 4 for iPhone and iPad. Drafts is a quick capture note taking app with flexible output actions. Drafts 4 scales from... Read more
AT&T accepting preorders for new iPads fo...
AT&T Wireless is accepting preorders for the new iPad Air 2 and iPad mini 3, cellular models, for $100 off MSRP with a 2-year service agreement: - 16GB iPad Air 2 WiFi + Cellular: $529.99 - 64GB... Read more
Apple offering refurbished Mac Pros for up to...
The Apple Store is offering Apple Certified Refurbished 2013 Mac Pros for up to $600 off the cost of new models. An Apple one-year warranty is included with each Mac Pro, and shipping is free. The... Read more
Select MacBook Airs $100 off MSRP, free shipp...
B&H Photo has 2014 a couple of MacBook Airs on sale for $100 off MSRP. Shipping is free, and B&H charges NY sales tax only. They also include free copies of Parallels Desktop and LoJack for... Read more

Jobs Board

Senior Event Manager, *Apple* Retail Market...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global event strategy. Delivering an overarching brand story; in-store, Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Project Manager / Business Analyst, WW *Appl...
…a senior project manager / business analyst to work within our Worldwide Apple Fulfillment Operations and the Business Process Re-engineering team. This role will work Read more
*Apple* Retail - Multiple Positions (US) - A...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
Position Opening at *Apple* - Apple (United...
…customers purchase our products, you're the one who helps them get more out of their new Apple technology. Your day in the Apple Store is filled with a range of Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.