[comp.sys.mac.programmer] PlotIcons family

gourdol@imag.imag.fr (Gourdol Arnaud) (06/10/91)

Here is a small routine that display icons of 
the icon family (ICN#, icl4, icl8).

Suggested improvements: gray color icons (like the Finder does),
use ics#, ics4 and ics8 when required, C version (no,
that's not an improvement :-)


Arno.


>It uses a library called HIK which provides 
>some utilies I used here, but I think you can 
>figure them by yourself and use some equivalents.
>
>Also, this unit is distributed under the GNU 
>copyleft distribution scheme. It means you can
>use this code to your heart's content, but 
>should you make any improvement or adaptation 
>(suggestions: adapting it to MacApp, TCL, writting
>it in C++) you have the (legal and moral) 
>obligation to send me a copy of the modified code,
>provide appropriate credit and make it publicly 
>available.

>Here it is, enjoy.
>
>Arno.





{DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
{        GetPixelDepth                       }
{DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}


function GetPixelDepth (globalRect: Rect): integer;
{ Returns the pixel depth of the screen which contain globalRect (in global coordinates) }
   var
      gDevice: GDHandle;
begin
   if not gAppl.hasColorQD then
      GetPixelDepth := 3
   else
      begin
         gDevice := GetMaxDevice(globalRect);
         GetPixelDepth := gDevice^^.gdPMap^^.pixelSize;
      end;
end;




{DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}
{        PlotIcons                           }
{DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD}


procedure PlotIcons (wPtr: WindowPtr; bBox: Rect; id: integer; mode: integer);
{ Plot in the winodw wPtr in the rect bBox the icon id }
{ It's either an ICN#, an icl8 or an icl4, according to}
{ what's available on the machine }
   type
{ An ICN# resource contains the following : }
{  * A B&W icon 32x32}
{  * A mask 32x32 }
      ICNRecord = record
            icon: array[0..31] of longint;      { Icon data }
            mask: array[0..31] of longint;      { Icon mask }
         end;
      ICNPtr = ^ICNRecord;
      ICNHdl = ^ICNPtr;
      BitMapPtr = ^BitMap;
   var
      iconBm: BitMap;         { BitMap for the B&W icon }
      maskBm: BitMap;         { BitMap for the mask }
      srcRect: rect;       { Rect enclosing the icon (0,0,32,32) }
      theICN: ICNHdl;
      oldPort: GrafPtr;
      hState: SignedByte;
      pixDepth: integer;
   function PlotIcl8: Boolean;
      var
         iconPm: PixMapHandle;   { PixMap for the color icon }
         pixHandle: Handle;
         i: integer;
   begin
{* Look if the appropriate resource is here }
      pixHandle := GetResource('icl8', id);
      if (pixHandle = nil) | (resError <> noErr) then
         begin
            PlotIcl8 := false;
            Exit(PlotIcl8);
         end
      else
         PlotIcl8 := true;

{* Build the pixmap }
      iconPM := NewPixmap;
      HLock(pixHandle);
      with iconPM^^ do
         begin
            baseAddr := pixHandle^;
            rowBytes := $8000 + 32;       { 32 bytes per row }
            bounds := srcRect;
            packType := 0;                { No packing }
            packSize := 0;                { Absolutely no packing }
            pixelType := 0;               { Chunky }
            pixelSize := 8;               { 8 bits/pixel }
            cmpCount := 1;                { Indexed }
            cmpSize := 8;                 { By 8 bits }
            planeBytes := 0;              { Only one plane }
            pmReserved := 0;              { Must be set to 0 }
         end;
      DisposCTable(iconPM^^.pmTable);
      iconPM^^.pmTable := GetCTable(72);

      if mode = kHilitedIcon then
         begin
{* Plot the icon as hilited }
            CopyBits(maskBm, wPtr^.portBits, srcRect, bBox, srcOr, nil);
            CopyBits(BitMapPtr(iconPM^)^, wPtr^.portBits, srcRect, bBox, srcBic, nil)
         end
      else if mode = kGrayIcon then
         begin
         end
      else
         begin
{* Mode standard }
            CopyBits(maskBm, wPtr^.portBits, srcRect, bBox, srcBic, nil);
            CopyBits(BitMapPtr(iconPM^)^, wPtr^.portBits, srcRect, bBox, srcOr, nil)
         end;

{* Dispose of the pixmap }
      HUnlock(pixHandle);
      ReleaseResource(pixHandle);
      DisposHandle(pixHandle);
      DisposPixMap(iconPM);

   end;

   function PlotIcl4: Boolean;
      var
         iconPm: PixMapHandle;   { PixMap for the color icon }
         pixHandle: Handle;
   begin
{* Look if the appropriate resource is here }
      pixHandle := GetResource('icl4', id);
      if (pixHandle = nil) | (resError <> noErr) then
         begin
            PlotIcl4 := false;
            Exit(PlotIcl4);
         end
      else
         PlotIcl4 := true;


{* Build the pixmap }
      iconPM := NewPixmap;
      HLock(pixHandle);
      with iconPM^^ do
         begin
            baseAddr := pixHandle^;
            rowBytes := $8000 + 16;       { 16 bytes per row }
            bounds := srcRect;
            packType := 0;                { No packing }
            packSize := 0;                { Absolutely no packing }
            pixelType := 0;               { Chunky }
            pixelSize := 4;               { 4 bits/pixel }
            cmpCount := 1;                { Indexed }
            cmpSize := 4;                 { By 4 bits }
            planeBytes := 0;              { Only one plane }
            pmReserved := 0;              { Must be set to 0 }
         end;
      DisposCTable(iconPM^^.pmTable);
      iconPM^^.pmTable := GetCTable(68);

      if mode = kHilitedIcon then
         begin
{* Plot the icon as hilited }
            CopyBits(maskBm, wPtr^.portBits, srcRect, bBox, srcOr, nil);
            CopyBits(BitMapPtr(iconPM^)^, wPtr^.portBits, srcRect, bBox, srcBic, nil)
         end
      else if mode = kGrayIcon then
         begin
         end
      else
         begin
{* Mode standard }
            CopyBits(maskBm, wPtr^.portBits, srcRect, bBox, srcBic, nil);
            CopyBits(BitMapPtr(iconPM^)^, wPtr^.portBits, srcRect, bBox, srcOr, nil)
         end;

{* Dispose of the pixmap }
      HUnlock(pixHandle);
      ReleaseResource(pixHandle);
      DisposHandle(pixHandle);
      DisposPixMap(iconPM);

   end;

   procedure PlotBW;
      var
         grayBM: BitMap;
         grayIcon: ICNRecord;
         i: integer;
   begin
{* Just draw a B&W icon with a mask }
      with iconBM do
         begin
            baseAddr := @theICN^^.icon;
            rowBytes := 4;
            SetRect(bounds, 0, 0, 32, 32);
         end;
      if mode = kHilitedIcon then
         begin
            CopyBits(maskBm, wPtr^.portBits, srcRect, bBox, srcOr, nil);
            CopyBits(iconBM, wPtr^.portBits, srcRect, bBox, srcBic, nil)
         end
      else if mode = kGrayIcon then
         begin
            for i := 0 to 15 do
               begin
                  grayIcon.icon[2 * i] := $AA;
                  grayIcon.icon[2 * i + 1] := $55;
               end;
            with grayBM do
               begin
                  baseAddr := @grayIcon.icon;
                  rowBytes := 4;
                  SetRect(bounds, 0, 0, 32, 32);
               end;
            CopyBits(maskBm, wPtr^.portBits, srcRect, bBox, srcBic, nil);
            CopyBits(iconBM, wPtr^.portBits, srcRect, bBox, srcOr, nil);
            CopyBits(grayBM, wPtr^.portBits, srcRect, bBox, srcBic, nil)
         end
      else
         begin
{* Mode standard }
            CopyBits(maskBm, wPtr^.portBits, srcRect, bBox, srcBic, nil);
            CopyBits(iconBM, wPtr^.portBits, srcRect, bBox, srcOr, nil)
         end;
   end;
begin

{* Get the ICN# resource }
   theICN := ICNHdl(GetResource('ICN#', id));
   if (ResError <> noErr) | (theICN = nil) then
      begin
         Exit(PlotIcons);
      end;

   GetPort(oldPort);
   SetPort(wPtr);

{* Set the source rectangle of the icon }
   SetRect(srcRect, 0, 0, 32, 32);

{* Lock the icon while we're drawing it }
   hState := HGetState(Handle(theICN));
   HLock(Handle(theICN));

{* Build the mask Bitmap }
   with maskBm do
      begin
         baseAddr := @theICN^^.mask;
         rowBytes := 4;
         SetRect(bounds, 0, 0, 32, 32);
      end;

   if mode = kGray then
      PlotBW
   else
      begin
         pixDepth := GetPixelDepth(bBox);
         if pixDepth >= 8 then
            begin
{* Draw an icl8 }
               if not PlotIcl8 & not PlotIcl4 then
                  PlotBW;
            end
         else if pixDepth > 3 then
            begin
{* Draw an icl4 }
               if not PlotIcl4 then
                  PlotBW;
            end
         else
            PlotBW;
      end;

{* Get rid of the ICN# }
   HSetState(Handle(theICN), hState);
   ReleaseResource(Handle(theICN));
   DisposHandle(Handle(theICN));

   SetPort(oldPort);
end;-- 
    /=============================//===================================/
   / Arno Gourdol.               // On the Netland:  Gourdol@imag.fr  /
  / "A keyboard ! How quaint !"   -- Scott, Star Trek                /
 /=============================//===================================/