Color Capable
Volume Number: 3
Issue Number: 7
Column Tag: Macintosh II
Lazy Man's Color 
By Steven Sheets, Hoffman Estates, IL
Newsbreak....Cupertino, Calif.....Color is here!
The new Macintosh // computer has color capabilities. Most color video cards
will allow up to 256 specific colors out of a possible color palatte of 16,777,216
selections. A new Color Quickdraw has been designed with Color Tables, Pixel Maps,
Pixel Patterns, Color Icons, Color Grafports and Color Picture Handles to work with
the new machine. Three new Managers have been added to facilitate color; the Color
Manager, the Color Picker Package and the Palette Manager.
Are you ready to program with this new Color Quickdraw?
Before you answer that, did you know there was an alternative way to display
color on the Mac? Use the old Quickdraw color routine! You didn’t know the older
Quickdraw had color? Well...
Old Color
The original Macintosh displays were in black & white. 21,888 bytes of memory
were used to display the normal 512 by 342 pixel screen (1 bit per pixel). However,
the original Quickdraw had the capability to draw in color. In the original Grafport
record, there were 2 fields (fgColor and bkColor) that determined the settings of the
Foreground and Background color.
Quickdraw predefined 8 colors (Black, White, Red, Green, Blue, Cyan, Magenta
and Yellow). Each color had a long integer constant associated with it. By passing these
constants to the procedures ForeColor and BackColor, the respective fields of the
current Grafport were changed. When any Grafport was created, the default settings
for the Foreground and Background were Black and White respectively.
Color fields were treated similar to the more often used Pen Pattern (pnPat) and
Background Pattern (bkPat). Any drawing by the Pen was done in the Foreground
color, any Erasing was done in the Background color. Also Foreground and Background
color affect the Copybits call. When copying a bitmap onto a Grafport, any bit that was
set in the source Bitmap would make the corresponding pixel appear in the Foreground
color on the Grafport. Any unset bit would make the pixel appear in the Background
color.
However on the black and white Macintosh, any color other than white appears as
black. Thus drawing Red on White, Blue on White, or even Yellow on White has the
same effect on the Pre-Mac // computers; Black on White. Interestingly the
Imagewriter // printer driver does use the color commands, thus making the
Imagewriter // with a color ribbon the first color Macintosh output device of any type.
While the new Mac // also has the new Color Quickdraw commands, it also supports the
old commands, including the use of Foreground and Background color.
Fig. 1 Our program uses classic color options
Why Use Old?
There are several reasons for not wanting to use Color Quickdraw for your first
color program. It might prove simpler, until you get a handle on Color Quickdraw (and
the three associated managers), to use the older Quickdraw routines. Color Quickdraw
involves new conceptional models, new data structures, and new routines. While it is
well worth the effort to learn (the graphic effects are stunning), there is a stiff
learning curve.
The Color Quickdraw manual is even larger than the original Quickdraw manual.
That is assuming that you have the new documentation. Inside Macintosh Vol. V is due
out soon, but unless you currently have a beta version, you will have to wait for
APDA’s final release.
Even if you have the new documentation and routines, your development system
may not implement the new ROM calls. Lightspeed C, Lightspeed Pascal, MDS do not
support the new Quickdraw, while MPW has to be updated to version 2.0. Many
programmers will have to wait until the developers of their programming language
come out with a new update until they can use the new routines. Some lucky users can
input all the new calls themselves and do not need the updates. That means typing in
dozens of new calls and data structures (again assuming they have the documentation).
Lucky them! [Apple is still working on the equates file and rumor has it the Pallette
Manager is still changing. -Ed]
Finally there is the actual code size and time in involved programming the new
Quickdraw. Color Quickdraw does take more code to implement and it’s data structures
are larger. The simple ForeColor and BackColor routines take very little code space.
Certainly Color Quickdraw should be used if someone is writing a color Drawing
program for the Mac //. But if you only wish to add color to your existing programs,
using Color Quickdraw requires you to rewrite your code, redo your graphics and in
some cases, even redo your complicated bitmaps. Placing ForeColor and BackColor
calls before your existing code segments is much simpler. If your Program is intended
to run on any Macintosh, the older Quickdraw may be all you need or want to produce
color.
The Code
The source example is an extremely simple, standard Macintosh program. It
loads and displays any MacPaint document in any of the eight Foreground and eight
Background colors. A few notes:
1) The CWindow (which will display the MacPaint document) is centered on large
screens (like a SuperMac monitor) or placed in the offset position.
2) The actual picture is stored in two sets of Bitmaps and Data handles. Data is
stored this way since the size of a MacPaint bitmap is too large to store in 1 set
(32K limit). If there is not enough memory to create the bitmaps, the program
will state this and not allow a MacPaint document to be loaded
3) ForeC and BackC store the selected menu number (1-8), not the predefined Color
constant. GetColor is used to convert the menu number into the color constant.
4) DoColor is the pivotal procedure; it sets the new Foreground/Background colors.
Then it causes an window update so the window is redrawn in the new colors.
{ Lazy Man’s Color by Steve Sheets 4/20/87 }
{ Simple Demonstration of Mac // Color using the
{ ForeColor & BackColor of classical Quickdraw. }
{ This program Loads and displays a MacPaint document }
( in any 2 colors. }
PROGRAM LMC;
{ Various Constants: Menu ID Numbers, Window Size, }
{ Window Placement, BitMap Size and Number of Colors. }
CONST
AppleMenuID = 300;
FileMenuID = 301;
EditMenuID = 302;
ForeMenuID = 303;
BackMenuID = 304;
OffV = 40;
OffH = 40;
AboutH = 300;
AboutV = 140;
SizeH = 576;
SizeV1 = 360;
SizeV2 = 720;
BitW = 72;
NumSec = 2;
XColor = 8;
{ Various Variables: Menus, Bitmaps, Window, Colors, }
{ Done Flag & Title Name }
VAR
Done : boolean;
AppleMenu, FileMenu: EditMenu,
ForeMenu, BackMenu : MenuHandle;
CWindow : windowptr;
CMap : ARRAY[1..NumSec] OF bitmap;
CData : ARRAY[1..NumSec] OF handle;
ForeC, BackC : integer;
Title : str255;
{ Given Color Number ( 1 to XColor, as selected by Menu), }
{ returns actual longint Color Number (for ForeColor or }
{ BackColor). }
FUNCTION GetColor (N : integer) : longint;
BEGIN
CASE N OF
1 :
GetColor := BlackColor;
2 :
GetColor := WhiteColor;
3 :
GetColor := RedColor;
4 :
GetColor := GreenColor;
5 :
GetColor := BlueColor;
6 :
GetColor := CyanColor;
7 :
GetColor := MagentaColor;
8 :
GetColor := YellowColor;
OTHERWISE
GetColor := WhiteColor;
END;
END;
{ Sets new ForeColor & BackColor and forces an Update}
{ so Window is redrawn in the new colors. }
PROCEDURE DoColor (F, B : integer);
VAR
count : integer;
tempPort : Grafptr;
BEGIN
GetPort(tempPort);
SetPort(CWindow);
IF F <> ForeC THEN
BEGIN
FOR count := 1 TO XColor DO
CheckItem(ForeMenu, count, count = F);
ForeC := F;
ForeColor(GetColor(ForeC));
END;
IF B <> BackC THEN
BEGIN
FOR count := 1 TO XColor DO
CheckItem(BackMenu, count, count = B);
BackC := B;
BackColor(GetColor(BackC));
END;
InvalRect(CWindow^.portRect);
SetPort(tempPort);
END;
{ Loads MacPaint Picture in Bitmaps and displays it.}
PROCEDURE DoLoad;
TYPE
diskBlock = PACKED ARRAY[1..512] OF QDbyte;
VAR
MyReply : SFReply;
MyType : SFtypelist;
tempPoint : point;
count : longint;
refNum, scanline, N : integer;
error : OSErr;
srcBuf : ARRAY[1..2] OF diskBlock;
srcPtr, dstPtr : Ptr;
BEGIN
tempPoint.v := 60;
tempPoint.h := 60;
MyType[0] := ‘PNTG’;
SFGetFile(tempPoint, ‘’, NIL, 1, MyType, NIL, MyReply);
IF MyReply.good THEN
BEGIN
Hlock(CData[1]);
Hlock(CData[2]);
IF FSOpen(MyReply.fname, MyReply.vrefnum, refNum) = noErr THEN
BEGIN
count := 512;
error := FSRead(refNum, count, @srcBuf);
count := 1024;
error := FSRead(refNum, count, @srcBuf);
srcPtr := @srcBuf;
FOR N := 1 TO NumSec DO
BEGIN
dstPtr := CData[N]^;
FOR scanline := 1 TO SizeV1 DO
BEGIN
UnpackBits(srcPtr, dstPtr, BitW);
IF ord(srcPtr) > (ord(@srcBuf) + 512) THEN
BEGIN
srcBuf[1] := srcBuf[2];
count := 512;
error := FSRead(refNum, count, @srcBuf[2]);
srcPtr := pointer(ord(srcPtr) - 512);
END;
END;
END;