home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Pascal / Snippets / CollectPictColors 1.0 / CLUTBuilder.p next >
Encoding:
Text File  |  1995-10-05  |  9.4 KB  |  323 lines  |  [TEXT/PJMM]

  1. { ------------------------------------------------------------------------------}
  2. {#}
  3. {#    Apple Macintosh Developer Technical Support}
  4. {#}
  5. {#    KnowsPICT  by Jon Zap}
  6. {#}
  7. {#    CLUTBuilder.p    -    Pascal Source}
  8. {#}
  9. {#    Copyright © 1989 Apple Computer, Inc.}
  10. {#    All rights reserved.}
  11. {#}
  12. {# Pascal version 1995 by Guess Who}
  13. {#}
  14. {# this file contains functions used to pull colors from a PICT.  You activate it by}
  15. {# calling CollectColors(PicHandle) with PicHandle set to a PICT that you have already}
  16. {# loaded into memory.  It will almost invariably return a (handle to a) color table}
  17. {# (that contains at least black and white) however the color table is not at all clean}
  18. {# in the current implementation.  It is probably ok if you run it through NewPalette.}
  19. {# If it runs across a direct pixmap it won't bomb but it won't add any colors to the}
  20. {# color table.}
  21. {#}
  22. {# WARNING: This code has been tested but it has not been tested thoroughly;}
  23. {# USE AT YOUR OWN RISK!}
  24. {------------------------------------------------------------------------------ }
  25.  
  26. unit CLUTBuilder;
  27.  
  28. interface
  29.  
  30. {$IFC UNDEFINED THINK_PASCAL}
  31.     uses
  32.         Types, QuickDraw, Memory;
  33. {$ENDC}
  34.  
  35.     function CollectColors (fromPicture: PicHandle; var depthPtr: Integer; var directFlagPtr: Boolean): CTabHandle;
  36.  
  37. implementation
  38.  
  39.     var
  40.         gColorError: OSErr;    (* to report errors from bottlenecks. *)
  41.         gColorTable: CTabHandle;    (* to collect colors from bottlenecks. *)
  42.         gNextCSpec: Integer;        (* next CSpec entry in color table *)
  43.         foundDirect: Boolean;        (* set to true if we uncover a direct pixmap *)
  44.         maxPixDepth: Integer;      (* depth of deepest pixmap found *)
  45.  
  46. (* Add a color to the color table. *)
  47.     procedure AddRGBColor (rgb: RGBColor); {rgb var?}
  48.         var
  49.             numSpecs, sizeInBytes: LongInt;
  50.             i, ctSize: Integer;
  51.             TablePtr: CTabPtr;
  52.             rgbx: RGBColor;
  53.     begin
  54.         if gColorError <> noErr then
  55.             exit(AddRGBColor);
  56.  
  57.         TablePtr := gColorTable^;
  58.         ctSize := TablePtr^.ctSize;
  59.         for i := 0 to ctSize do
  60.             begin
  61.                 rgbx := TablePtr^.ctTable[i].rgb;
  62.                 if (rgbx.red = rgb.red) and (rgbx.green = rgb.green) and (rgbx.blue = rgb.blue) then
  63.                     exit(AddRGBColor);        (* if already there, done *)
  64.             end;
  65.         gColorTable^^.ctSize := gColorTable^^.ctSize + 1;
  66.         numSpecs := LongInt(gColorTable^^.ctSize);    (* add a colorspec to table *)
  67.         sizeInBytes := (numSpecs * sizeof(ColorSpec)) + sizeof(ColorTable);
  68.         SetHandleSize(Handle(gColorTable), sizeInBytes);
  69.         gColorError := MemError;
  70.         if gColorError = noErr then
  71.             begin
  72.                 gColorTable^^.ctTable[numSpecs].rgb := rgb;
  73.                 gColorTable^^.ctTable[numSpecs].value := 0;
  74.             end;
  75.     end; {AddRGBColor}
  76.  
  77. (* Add the contents of another color table to our color table.*)
  78.     procedure AddColorTable (cTab: CTabHandle);
  79.         var
  80.             index, size: Integer;
  81.             color: RGBColor;
  82.     begin
  83.         size := cTab^^.ctSize;        {CW får Bus Error här!}
  84.         for index := 0 to size do
  85.             begin
  86.                 color := cTab^^.ctTable[index].rgb;
  87.                 AddRGBColor(color);
  88.             end;
  89.     end; {AddColorTable}
  90.  
  91. (* Add the foreground color of the current port to the color table. *)
  92.     procedure AddRGBForeColor;
  93.     begin
  94. {$IFC UNDEFINED THINK_PASCAL}
  95.         AddRGBColor(CGrafPtr(qd.thePort)^.rgbFgColor);
  96. {$ELSEC}
  97.         AddRGBColor(CGrafPtr(thePort)^.rgbFgColor);
  98. {$ENDC}
  99.     end; {AddRGBForeColor}
  100.  
  101. (* Add the background color of the current port to the color table. *)
  102.     procedure AddRGBBackColor;
  103.     begin
  104. {$IFC UNDEFINED THINK_PASCAL}
  105.         AddRGBColor(CGrafPtr(qd.thePort)^.rgbBkColor);
  106. {$ELSEC}
  107.         AddRGBColor(CGrafPtr(thePort)^.rgbBkColor);
  108. {$ENDC}
  109.     end; {AddRGBBackColor}
  110.  
  111. (* Add colors from a PixPat to a color table. *)
  112.     procedure AddPixPat (pPat: PixPatHandle);
  113.     begin
  114.         case pPat^^.patType of
  115.             0:        (* one-bit patterns are drawn in the foreground and background color. *)
  116.                 begin
  117.                     AddRGBForeColor;
  118.                     AddRGBBackColor;
  119.                 end;
  120.             1:        (* Type 1 PixPats have a color table. *)
  121.                 AddColorTable(pPat^^.patMap^^.pmTable);
  122.         end; {case}
  123.     end; {AddPixPat}
  124.  
  125. (* Add colors from the pen PixPat to the color table. *)
  126.     procedure AddPenPixPat;
  127.     begin
  128. {$IFC UNDEFINED THINK_PASCAL}
  129.         AddPixPat(CGrafPtr(qd.thePort)^.pnPixPat);
  130. {$ELSEC}
  131.         AddPixPat(CGrafPtr(thePort)^.pnPixPat);
  132. {$ENDC}
  133.     end; {AddPenPixPat}
  134.  
  135. (* Add colors from the fill PixPat to the color table. *)
  136.     procedure AddFillPixPat;
  137.     begin
  138. {$IFC UNDEFINED THINK_PASCAL}
  139.         AddPixPat(CGrafPtr(qd.thePort)^.fillPixPat);
  140. {$ELSEC}
  141.         AddPixPat(CGrafPtr(thePort)^.fillPixPat);
  142. {$ENDC}
  143.     end; {AddFillPixPat}
  144.  
  145. (* Add colors because we are about to draw an object. *)
  146.     procedure AddVerb (verb: GrafVerb);
  147.     begin
  148.         case verb of
  149.             frame, paint: (* Framed and painted objects are drawn in the pen PixPat. *)
  150.                 AddPenPixPat;
  151.             erase: (* Erased objects are drawn in the background color. *)
  152.                 AddRGBBackColor;
  153.             fill:
  154.             (* Filled objects are drawn in the fill PixPat.  The fillPixPat is}
  155. {                a pattern used to record fill commands for pictures.  First, a}
  156. {                command to set the fillPixPat is recorded, then the fill command}
  157. {                is recorded. *)
  158.                 AddFillPixPat;
  159.         end;
  160.     end;
  161.  
  162. (* bottleneck routines follow . . . *)
  163.  
  164.     procedure ColorTextProc (byteCount: Integer; textBuf: Ptr; numer, denom: Point);
  165.     (* Text is drawn with the foreground and background colors.*)
  166.     begin
  167.         AddRGBForeColor;
  168.         AddRGBBackColor;
  169.     end; {ColorTextProc}
  170.  
  171.     procedure ColorLineProc (newPt: Point);
  172.  (* Lines are drawn with the pen PixPat. *)
  173.     begin
  174.         AddPenPixPat;
  175.     end; {ColorLineProc}
  176.  
  177.     procedure ColorRectProc (verb: GrafVerb; r: Rect);
  178.     begin
  179.         AddVerb(verb);
  180.     end;
  181.  
  182.     procedure ColorRRectProc (verb: GrafVerb; r: Rect; ovalWidth: Integer; ovalHeight: Integer);
  183.     begin
  184.         AddVerb(verb);
  185.     end;
  186.  
  187.     procedure ColorOvalProc (verb: GrafVerb; r: Rect);
  188.     begin
  189.         AddVerb(verb);
  190.     end;
  191.  
  192.     procedure ColorArcProc (verb: GrafVerb; r: Rect; startAngle, arcAngle: Integer);
  193.     begin
  194.         AddVerb(verb);
  195.     end;
  196.  
  197.     procedure ColorPolyProc (verb: GrafVerb; poly: PolyHandle);
  198.     begin
  199.         AddVerb(verb);
  200.     end;
  201.  
  202.     procedure ColorRgnProc (verb: GrafVerb; rgn: RgnHandle);
  203.     begin
  204.         AddVerb(verb);
  205.     end;
  206.  
  207.     procedure ColorBitsProc (bitPtr: BitMapPtr; srcRect, dstRect: Rect; mode: Integer; maskRgn: RgnHandle);
  208.         type
  209.             PixMapHandlePtr = ^PixMapHandle;
  210.         var
  211.             aPixMap: PixMapPtr;
  212.             tempRB: Integer;
  213.  
  214.     (* Get the PixMap that we are about to draw.  SrcBits might be a BitMap, or}
  215. {        one of two different kinds of PixMap pointers.  *)
  216.     begin
  217.         tempRB := bitPtr^.rowBytes;            (* local copy of rowBytes *)
  218.         if tempRB < 0 then                    (* high bit set? *)
  219.             begin
  220.                 if BAnd(tempRB, $3000) <> 0 then        (* next to high bit set? *)
  221.                 {if BSL(tempRB, 1) < 0 then            <- unsafe, since it depends on how BSL casts the argument    }
  222.                     aPixMap := PixMapHandlePtr(bitPtr)^^    (* ptr to PixMap handle *)
  223.                 else
  224.                     aPixMap := PixMapPtr(bitPtr);        (* pointer to a PixMap *)
  225.                 if aPixMap^.pixelSize > maxPixDepth then    (* deepest pixmap so far? *)
  226.                     maxPixDepth := aPixMap^.pixelSize;
  227.                 if aPixMap^.pixelType = 16 then
  228.                     begin
  229.                         foundDirect := true;
  230.                         exit(ColorBitsProc);                                (* direct pixmap?  eek! *)
  231.                     end;
  232.                 AddColorTable(aPixMap^.pmTable);        (* it has its own color table. *)
  233.             end
  234.         else
  235.         (* It's just a BitMap; it will use the background and foreground colors. *)
  236.             begin
  237.                 AddRGBBackColor;
  238.                 AddRGBForeColor;
  239.             end;
  240.     end;
  241.  
  242.  
  243.  
  244.     function MakeColor (r, g, b: Integer): RGBColor;
  245.     begin
  246.         MakeColor.red := r;
  247.         MakeColor.green := g;
  248.         MakeColor.blue := b;
  249.     end;
  250.  
  251.  
  252.  
  253.     function CollectColors (fromPicture: PicHandle; var depthPtr: Integer; var directFlagPtr: Boolean): CTabHandle;
  254.         var
  255.             colors: CTabHandle;
  256.             bottlenecks: CQDProcs;
  257. {      Set the bottlenecks.  These bottlenecks will figure out what colors are in    }
  258. {        a picture, but won't draw anything.    }
  259. {    Note: the bottlenecks are installed in thePort, which must be a color port. }
  260.         var
  261.             whiteRGB: RGBColor;
  262.             blackRGB: RGBColor;
  263.     begin
  264.  
  265.         whiteRGB := MakeColor($FFFF, $FFFF, $FFFF);
  266.         blackRGB := MakeColor(0, 0, 0);
  267.  
  268.  
  269.         SetStdCProcs(bottlenecks);
  270.         bottlenecks.textProc := @ColorTextProc;
  271.         bottlenecks.lineProc := @ColorLineProc;
  272.         bottlenecks.rectProc := @ColorRectProc;
  273.         bottlenecks.rRectProc := @ColorRRectProc;
  274.         bottlenecks.ovalProc := @ColorOvalProc;
  275.         bottlenecks.arcProc := @ColorArcProc;
  276.         bottlenecks.polyProc := @ColorPolyProc;
  277.         bottlenecks.rgnProc := @ColorRgnProc;
  278.         bottlenecks.bitsProc := @ColorBitsProc;
  279.  
  280.     (* Create a color table containing black and white. *)
  281.         foundDirect := false;    (* haven't found a direct pixmap yet *)
  282.         maxPixDepth := 1;        (* assume we will find a bitmap *)
  283.         colors := CTabHandle(NewHandle(sizeof(ColorTable) + sizeof(ColorSpec)));
  284.         if colors <> nil then
  285.             begin
  286.                 colors^^.ctSize := 1; (* 2 entries *)
  287.                 colors^^.ctFlags := $8000;
  288.         {colors^^.transIndex := $8000;}
  289.                 colors^^.ctSeed := GetCTSeed;
  290.                 colors^^.ctTable[0].rgb := whiteRGB; (*first entry is white*)
  291.                 colors^^.ctTable[1].rgb := blackRGB; (*second entry is black*)
  292.         (* Now play back the picture to get the colors.  The dstRect doesn't}
  293. {            matter since our bottlenecks will never actually draw. We use global}
  294. {            variables (gColorError and gColorTable) to communicate with the}
  295. {            bottlenecks. *)
  296. {$IFC UNDEFINED THINK_PASCAL}
  297.                 qd.thePort^.grafProcs := @bottlenecks;
  298. {$ELSEC}
  299.                 thePort^.grafProcs := @bottlenecks;
  300. {$ENDC}
  301.                 gColorError := noErr;
  302.                 gColorTable := colors;
  303.                 DrawPicture(fromPicture, fromPicture^^.picFrame);
  304. {$IFC UNDEFINED THINK_PASCAL}
  305.                 qd.thePort^.grafProcs := nil;
  306. {$ELSEC}
  307.                 thePort^.grafProcs := nil;
  308. {$ENDC}
  309.                 depthPtr := maxPixDepth;
  310.                 directFlagPtr := foundDirect;
  311.  
  312.         (* Fail if error occurred while within the color bottlenecks. *)
  313.                 if gColorError <> noErr then
  314.                     begin
  315.                         DisposeHandle(Handle(colors));
  316.                         colors := nil;
  317.                     end;
  318.             end;
  319.         CollectColors := colors;
  320.         Exit(CollectColors);
  321.     end;
  322.  
  323. end.