home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / Libraries / GrafSys 2.0 / GrafSys 2.0 source / OffscreenCore.p < prev    next >
Encoding:
Text File  |  1993-08-03  |  21.3 KB  |  626 lines  |  [TEXT/PJMM]

  1. unit OffscreenCore;
  2.  
  3. { this unit defines all procedures required to create, manage and dispose off-screen bitmaps }
  4. { this unit contains the generic off-screen functions while higher units will have specialized }
  5. { procedures for handling off-screen graphics }
  6.  
  7. { © 1993 by Christian Franz }
  8.  
  9. interface
  10.  
  11.  
  12.     type
  13.  
  14.         TOffscreenRec = record (* offscreen data management *)
  15.                 thePort: CGrafPtr;
  16.                 theDevice: GDHandle;
  17.                 theColors: CTabHandle;
  18.                 mainDevice: GDHandle;
  19.             end;
  20.  
  21.     function CreateGDevice (basePixMap: PixMapHandle;        {Handle to the PixMap to base GDevice on}
  22.                                     var retGDevice: GDHandle                    {Returns a handle to the new GDevice}
  23.                                     ): OSErr;
  24.  
  25.     function SetUpPixMap (depth: Integer;        {Desired number of bits/pixel in off-screen}
  26.                                     bound: Rect;                       {Bounding rectangle of off-screen}
  27.                                     colors: CTabHandle;            {Color table to assign to off-screen}
  28.                                     bytesPerRow: Integer;            {Number of bytes in each row of pixels}
  29.                                     aPixMap: PixMapHandle        {Handle to the PixMap being initialized}
  30.                                     ): OSErr;
  31.  
  32.     function CreateOffScreen (bounds: Rect;        {Bounding rectangle of off-screen}
  33.                                     depth: Integer;                        {Desired number of bits per pixel in off-screen}
  34.                                     colors: CTabHandle;                 {Color table to assign to off-screen}
  35.                                     var retPort: CGrafPtr;               {Returns a pointer to the new CGrafPort}
  36.                                     var retGDevice: GDHandle            {Returns a handle to the new GDevice}
  37.                                     ): OSErr;
  38.  
  39.     function UpdateOffScreen (newBounds: Rect;        {New bounding rectangle of off-screen}
  40.                                     newDepth: Integer;                        {New number of bits per pixel in off-screen}
  41.                                     newColors: CTabHandle;                 {New color table to assign to off-screen}
  42.                                     updPort: CGrafPtr;                        {Returns a pointer to the updated CGrafPort}
  43.                                     updGDevice: GDHandle                    {Returns a handle to the updated GDevice}
  44.                                     ): OSErr;
  45.  
  46.     procedure DisposeOffScreen (var doomedPort: CGrafPtr;     {Pointer to the CGrafPort we’re getting rid of}
  47.                                     var doomedGDevice: GDHandle                     {Handle to the GDevice we’re getting rid of}
  48.                                     );
  49.  
  50.  
  51. implementation
  52.  
  53.  
  54.     function CreateGDevice (basePixMap: PixMapHandle;        {Handle to the PixMap to base GDevice on}
  55.                                     var retGDevice: GDHandle                    {Returns a handle to the new GDevice}
  56.                                     ): OSErr;
  57.  
  58.         const
  59.             kITabRes = 4; {Inverse-table resolution}
  60.  
  61.         var
  62.             newDevice: GDHandle;   {Handle to the new GDevice}
  63.             embryoITab: ITabHandle; {Handle to the embryonic inverse table}
  64.             error: OSErr;      {Error code}
  65.  
  66.     begin
  67.    (* Initialize a few things before we begin *)
  68.         error := noErr;
  69.         newDevice := nil;
  70.         embryoITab := nil;
  71.  
  72.    (* Allocate memory for the new GDevice *)
  73.         newDevice := GDHandle(NewHandle(SizeOf(GDevice)));
  74.         if newDevice <> nil then
  75.             begin
  76.          (* Allocate the embryonic inverse table *)
  77.                 embryoITab := ITabHandle(NewHandleClear(2));
  78.                 if embryoITab <> nil then
  79.                     begin
  80.                (* Initialize the new GDevice fields *)
  81.                         with newDevice^^ do
  82.                             begin
  83.                                 gdRefNum := 0;                 {Only used for screens}
  84.                                 gdID := 0;                     {Won’t normally use}
  85.                                 if basePixMap^^.pixelSize <= 8 then
  86.                                     gdType := clutType          {Depth≤8; clut device}
  87.                                 else
  88.                                     gdType := directType;       {Depth>8; direct device}
  89.                                 gdITable := embryoITab;        {2-byte handle for now}
  90.                                 gdResPref := kITabRes;         {Normal inv table res}
  91.                                 gdSearchProc := nil;           {No color-search proc}
  92.                                 gdCompProc := nil;             {No complement proc}
  93.                                 gdFlags := 0;                  {Will set these later}
  94.                                 gdPMap := basePixMap;          {Reference our PixMap}
  95.                                 gdRefCon := 0;                 {Won’t normally use}
  96.                                 gdNextGD := nil;               {Not in GDevice list}
  97.                                 gdRect := basePixMap^^.bounds; {Use PixMap dimensions}
  98.                                 gdMode := -1;                  {For nonscreens}
  99.                                 gdCCBytes := 0;                {Only used for screens}
  100.                                 gdCCDepth := 0;                {Only used for screens}
  101.                                 gdCCXData := nil;              {Only used for screens}
  102.                                 gdCCXMask := nil;              {Only used for screens}
  103.                                 gdReserved := 0;               {Currently unused}
  104.                             end;
  105.  
  106.                (* Set color-device bit if PixMap isn’t black & white *)
  107.                         if basePixMap^^.pixelSize > 1 then
  108.                             SetDeviceAttribute(newDevice, gdDevType, true);
  109.  
  110.                (* Set bit to indicate that the GDevice has no video driver *)
  111.                         SetDeviceAttribute(newDevice, noDriver, true);
  112.  
  113.                (* Initialize the inverse table *)
  114.                         if basePixMap^^.pixelSize <= 8 then
  115.                             begin
  116.                                 MakeITable(basePixMap^^.pmTable, newDevice^^.gdITable, newDevice^^.gdResPref);
  117.                                 error := QDError;
  118.                             end;
  119.                     end
  120.                 else
  121.                     error := MemError;
  122.             end
  123.         else
  124.             error := MemError;
  125.  
  126.    (* Handle any errors along the way *)
  127.         if error <> noErr then
  128.             begin
  129.                 if embryoITab <> nil then
  130.                     DisposHandle(Handle(embryoITab));
  131.                 if newDevice <> nil then
  132.                     DisposHandle(Handle(newDevice));
  133.             end
  134.         else
  135.             retGDevice := newDevice;
  136.  
  137.    (* Return a handle to the new GDevice *)
  138.         CreateGDevice := error;
  139.     end;
  140.  
  141.  
  142.     function SetUpPixMap (depth: Integer;        {Desired number of bits/pixel in off-screen}
  143.                                     bound: Rect;                       {Bounding rectangle of off-screen}
  144.                                     colors: CTabHandle;            {Color table to assign to off-screen}
  145.                                     bytesPerRow: Integer;            {Number of bytes in each row of pixels}
  146.                                     aPixMap: PixMapHandle        {Handle to the PixMap being initialized}
  147.                                     ): OSErr;
  148.  
  149.         const
  150.             kDefaultRes = $00480000; {Default resolution is 72 DPI; Fixed type}
  151.  
  152.         var
  153.             newColors: CTabHandle; {Color table used for the off-screen PixMap}
  154.             offBaseAddr: Ptr;        {Pointer to the off-screen pixel image}
  155.             error: OSErr;      {Returns error code}
  156.  
  157.     begin
  158.         error := noErr;
  159.         newColors := nil;
  160.         offBaseAddr := nil;
  161.  
  162.    (* Clone the clut if indexed color; allocate a dummy clut if direct color *)
  163.         if depth <= 8 then
  164.             begin
  165.                 newColors := colors;
  166.                 error := HandToHand(Handle(newColors));
  167.             end
  168.         else
  169.             begin
  170.                 newColors := CTabHandle(NewHandle(SizeOf(ColorTable) - SizeOf(CSpecArray)));
  171.                 error := MemError;
  172.             end;
  173.         if error = noErr then
  174.             begin
  175.          (* Allocate pixel image; long integer multiplication avoids overflow *)
  176.                 offBaseAddr := NewPtr(LongInt(bytesPerRow) * (bound.bottom - bound.top));
  177.                 if offBaseAddr <> nil then
  178.                     with aPixMap^^ do
  179.                         begin
  180.                   (* Initialize fields common to indexed and direct PixMaps *)
  181.                             baseAddr := offBaseAddr;     {Point to image}
  182.                             rowBytes := BOR(bytesPerRow, $8000); {MSB set for PixMap}
  183.                             bounds := bound;             {Use given bounds}
  184.                             pmVersion := 0;              {No special stuff}
  185.                             packType := 0;               {Default PICT pack}
  186.                             packSize := 0;               {Always zero when in memory}
  187.                             hRes := kDefaultRes;         {72 DPI default resolution}
  188.                             vRes := kDefaultRes;         {72 DPI default resolution}
  189.                             pixelSize := depth;          {Set number of bits/pixel}
  190.                             planeBytes := 0;             {Not used}
  191.                             pmReserved := 0;             {Not used}
  192.  
  193.                   (* Initialize fields specific to indexed and direct PixMaps *)
  194.                             if depth <= 8 then
  195.                                 begin
  196.                         (* PixMap is indexed *)
  197.                                     pixelType := 0;       {Indicates indexed}
  198.                                     cmpCount := 1;        {Have 1 component}
  199.                                     cmpSize := depth;     {Component size=depth}
  200.                                     pmTable := newColors; {Handle to CLUT}
  201.                                 end
  202.                             else
  203.                                 begin
  204.                         (* PixMap is direct *)
  205.                                     pixelType := RGBDirect; {Indicates direct}
  206.                                     cmpCount := 3;          {Have 3 components}
  207.                                     if depth = 16 then
  208.                                         cmpSize := 5         {5 bits/component}
  209.                                     else
  210.                                         cmpSize := 8;        {8 bits/component}
  211.  
  212.                         (* Initialize fields of the dummy color table *)
  213.                                     newColors^^.ctSeed := 3 * aPixMap^^.cmpSize;
  214.                                     newColors^^.ctFlags := 0;
  215.                                     newColors^^.ctSize := 0;
  216.                                     pmTable := newColors;
  217.                                 end;
  218.                         end
  219.                 else
  220.                     error := MemError;
  221.             end
  222.         else
  223.             newColors := nil;
  224.  
  225.    (* If no errors occurred, return a handle to the new off-screen PixMap *)
  226.         if error <> noErr then
  227.             begin
  228.                 if newColors <> nil then
  229.                     DisposCTable(newColors);
  230.             end;
  231.  
  232.     (* Return the error code *)
  233.         SetUpPixMap := error;
  234.     end;
  235.  
  236.  
  237.     function CreateOffScreen (bounds: Rect;        {Bounding rectangle of off-screen}
  238.                                     depth: Integer;                        {Desired number of bits per pixel in off-screen}
  239.                                     colors: CTabHandle;                 {Color table to assign to off-screen}
  240.                                     var retPort: CGrafPtr;               {Returns a pointer to the new CGrafPort}
  241.                                     var retGDevice: GDHandle            {Returns a handle to the new GDevice}
  242.                                     ): OSErr;
  243.  
  244.         const
  245.             kMaxRowBytes = $3FFE; {Maximum number of bytes in a row of pixels}
  246.  
  247.         var
  248.             newPort: CGrafPtr;             {Pointer to the new off-screen CGrafPort}
  249.             newPixMap: PixMapHandle;     {Handle to the new off-screen PixMap}
  250.             newDevice: GDHandle;             {Handle to the new off-screen GDevice}
  251.             qdVersion: LongInt;              {Version of QuickDraw currently in use}
  252.             savedPort: GrafPtr;              {Pointer to GrafPort used for save/restore}
  253.             savedState: SignedByte;       {Saved state of color table handle}
  254.             bytesPerRow: Integer;          {Number of bytes per row in the PixMap}
  255.             error: OSErr;                        {Returns error code}
  256.             BlackRGB, WhiteRGB: RGBColor; {for setting fore- and backgroundcolors }
  257.  
  258.     begin
  259.    (* Initialize a few things before we begin *)
  260.         newPort := nil;
  261.         newPixMap := nil;
  262.         newDevice := nil;
  263.         error := noErr;
  264.  
  265.    (* Save the color table’s current state and make sure it isn’t purgeable *)
  266.         if colors <> nil then
  267.             begin
  268.                 savedState := HGetState(Handle(colors));
  269.                 HNoPurge(Handle(colors));
  270.             end;
  271.  
  272.    (* Calculate the number of bytes per row in the off-screen PixMap *)
  273.         bytesPerRow := ((depth * (bounds.right - bounds.left) + 31) div 32) * 4;
  274.  
  275.    (* Get the current QuickDraw version *)
  276.         error := Gestalt(gestaltQuickdrawVersion, qdVersion);
  277.         error := noErr;
  278.  
  279.    (* Make sure depth is indexed or depth is direct and 32-Bit QD installed *)
  280.         if (depth = 1) or (depth = 2) or (depth = 4) or (depth = 8) or (((depth = 16) or (depth = 32)) and (qdVersion >= gestalt32BitQD)) then
  281.             begin
  282.          (* Maximum number of bytes per row is 16,382; make sure within range *)
  283.                 if bytesPerRow <= kMaxRowBytes then
  284.                     begin
  285.                (* Make sure a color table is provided if the depth is indexed *)
  286.                         if depth <= 8 then
  287.                             if colors = nil then
  288.                      (* Indexed depth and clut is NIL; is parameter error *)
  289.                                 error := paramErr;
  290.                     end
  291.                 else
  292.             (* # of bytes per row is more than 16,382; is parameter error *)
  293.                     error := paramErr;
  294.             end
  295.         else
  296.       (* Pixel depth isn’t valid; is parameter error *)
  297.             error := paramErr;
  298.  
  299.    (* If sanity checks succeed, then allocate a new CGrafPort *)
  300.         if error = noErr then
  301.             begin
  302.                 newPort := CGrafPtr(NewPtr(SizeOf(CGrafPort)));
  303.                 if newPort <> nil then
  304.                     begin
  305.                (* Save the current port *)
  306.                         GetPort(savedPort);
  307.  
  308.                (* Initialize the new CGrafPort and make it the current port *)
  309.                         OpenCPort(newPort);
  310.  
  311.                (* Set portRect, visRgn, and clipRgn to the given bounds rect *)
  312.                         newPort^.portRect := bounds;
  313.                         RectRgn(newPort^.visRgn, bounds);
  314.                         ClipRect(bounds);
  315.  
  316.                (* Initialize the new PixMap for off-screen drawing *)
  317.                         error := SetUpPixMap(depth, bounds, colors, bytesPerRow, newPort^.portPixMap);
  318.                         if error = noErr then
  319.                             begin
  320.                      (* Grab the initialized PixMap handle *)
  321.                                 newPixMap := newPort^.portPixMap;
  322.  
  323.                      (* Allocate and initialize a new GDevice *)
  324.                                 error := CreateGDevice(newPixMap, newDevice);
  325.                             end;
  326.  
  327.                (* set drawing colors and erase whole pixmap *)
  328.                         BlackRGB.red := 0;
  329.                         BlackRGB.green := 0;
  330.                         BlackRGB.blue := 0;
  331.                         WhiteRGB.red := $ffff;
  332.                         WhiteRGB.green := $ffff;
  333.                         WhiteRGB.blue := $ffff;
  334.                         RGBForeColor(BlackRGB);
  335.                         RGBBackColor(WhiteRGB);
  336.                         EraseRect(bounds);
  337.                (* Restore the saved port *)
  338.                         SetPort(savedPort);
  339.                     end
  340.                 else
  341.                     error := MemError;
  342.             end;
  343.  
  344.    (* Restore the given state of the color table *)
  345.         if colors <> nil then
  346.             HSetState(Handle(colors), savedState);
  347.  
  348.    (* One Last Look Around The House Before We Go… *)
  349.         if error <> noErr then
  350.             begin
  351.          (* Some error occurred; dispose of everything we allocated *)
  352.                 if newPixMap <> nil then
  353.                     begin
  354.                         DisposCTable(newPixMap^^.pmTable);
  355.                         DisposPtr(newPixMap^^.baseAddr);
  356.                     end;
  357.                 if newDevice <> nil then
  358.                     begin
  359.                         DisposHandle(Handle(newDevice^^.gdITable));
  360.                         DisposHandle(Handle(newDevice));
  361.                     end;
  362.                 if newPort <> nil then
  363.                     begin
  364.                         CloseCPort(newPort);
  365.                         DisposPtr(Ptr(newPort));
  366.                     end;
  367.             end
  368.         else
  369.             begin
  370.          (* Everything’s OK; return refs to off-screen CGrafPort and GDevice *)
  371.                 retPort := newPort;
  372.                 retGDevice := newDevice;
  373.             end;
  374.         CreateOffScreen := error;
  375.     end;
  376.  
  377.     function UpdateOffScreen (newBounds: Rect;        {New bounding rectangle of off-screen}
  378.                                     newDepth: Integer;                        {New number of bits per pixel in off-screen}
  379.                                     newColors: CTabHandle;                 {New color table to assign to off-screen}
  380.                                     updPort: CGrafPtr;                        {Returns a pointer to the updated CGrafPort}
  381.                                     updGDevice: GDHandle                    {Returns a handle to the updated GDevice}
  382.                                     ): OSErr;
  383.  
  384.         const
  385.             kMaxRowBytes = $3FFE; {Maximum number of bytes per row of pixels}
  386.  
  387.         var
  388.             newPixMap: PixMapHandle; {Handle to the new off-screen PixMap}
  389.             oldPixMap: PixMapHandle; {Handle to the old off-screen PixMap}
  390.             bounds: Rect;         {Boundary rectangle of off-screen}
  391.             depth: Integer;      {Depth of the off-screen PixMap}
  392.             bytesPerRow: Integer;      {Number of bytes per row in the PixMap}
  393.             colors: CTabHandle;   {Colors for the off-screen PixMap}
  394.             savedFore: RGBColor;     {Saved foreground color}
  395.             savedBack: RGBColor;     {Saved background color}
  396.             aColor: RGBColor;     {Used to set foreground and background color}
  397.             qdVersion: LongInt;      {Version of QuickDraw currently in use}
  398.             savedPort: GrafPtr;      {Pointer to GrafPort used for save/restore}
  399.             savedDevice: GDHandle;     {Handle to GDevice used for save/restore}
  400.             savedState: SignedByte;   {Saved state of color table handle}
  401.             error: OSErr;        {Returns error code}
  402.  
  403.     begin
  404.    (* Initialize a few things before we begin *)
  405.         newPixMap := nil;
  406.         error := noErr;
  407.  
  408.    (* Keep the old bounds rectangle, or get the new one *)
  409.         if EmptyRect(newBounds) then
  410.             bounds := updPort^.portRect
  411.         else
  412.             bounds := newBounds;
  413.  
  414.    (* Keep the old depth, or get the old one *)
  415.         if newDepth = 0 then
  416.             depth := updPort^.portPixMap^^.pixelSize
  417.         else
  418.             depth := newDepth;
  419.  
  420.    (* Get the old clut, or save new clut’s state and make it nonpurgeable *)
  421.         if newColors = nil then
  422.             colors := updPort^.portPixMap^^.pmTable
  423.         else
  424.             begin
  425.                 savedState := HGetState(Handle(newColors));
  426.                 HNoPurge(Handle(newColors));
  427.                 colors := newColors;
  428.             end;
  429.  
  430.    (* Calculate the number of bytes per row in the off-screen PixMap *)
  431.         bytesPerRow := ((depth * (bounds.right - bounds.left) + 31) div 32) * 4;
  432.  
  433.    (* Get the current QuickDraw version *)
  434.         error := Gestalt(gestaltQuickdrawVersion, qdVersion);
  435.         error := noErr;
  436.  
  437.    (* Make sure depth is indexed or depth is direct and 32-Bit QD installed *)
  438.         if (depth = 1) or (depth = 2) or (depth = 4) or (depth = 8) or (((depth = 16) or (depth = 32)) and (qdVersion >= gestalt32BitQD)) then
  439.             begin
  440.          (* Maximum number of bytes per row is 16,382; make sure within range *)
  441.                 if bytesPerRow <= kMaxRowBytes then
  442.                     begin
  443.                (* Make sure a color table is provided if the depth is indexed *)
  444.                         if depth <= 8 then
  445.                             if colors = nil then
  446.                      (* Indexed depth and clut is NIL; is parameter error *)
  447.                                 error := paramErr;
  448.                     end
  449.                 else
  450.             (* # of bytes per row is more than 16,382; is parameter error *)
  451.                     error := paramErr;
  452.             end
  453.         else
  454.       (* Pixel depth isn’t valid; is parameter error *)
  455.             error := paramErr;
  456.  
  457.    (* If sanity checks succeed, attempt to update the graphics environment *)
  458.         if error = noErr then
  459.             begin
  460.          (* Allocate a new PixMap *)
  461.                 newPixMap := PixMapHandle(NewHandleClear(SizeOf(PixMap)));
  462.                 if newPixMap <> nil then
  463.                     begin
  464.                (* Initialize the new PixMap for off-screen drawing *)
  465.                         error := SetUpPixMap(depth, bounds, colors, bytesPerRow, newPixMap);
  466.                         if error = noErr then
  467.                             begin
  468.                      (* Save old PixMap and install new, initialized one *)
  469.                                 oldPixMap := updPort^.portPixMap;
  470.                                 updPort^.portPixMap := newPixMap;
  471.  
  472.                      (* Save current port & GDevice; set ones we’re updating *)
  473.                                 GetPort(savedPort);
  474.                                 savedDevice := GetGDevice;
  475.                                 SetPort(GrafPtr(updPort));
  476.                                 SetGDevice(updGDevice);
  477.  
  478.                      (* Set portRect, visRgn, clipRgn to given bounds rect *)
  479.                                 updPort^.portRect := bounds;
  480.                                 RectRgn(updPort^.visRgn, bounds);
  481.                                 ClipRect(bounds);
  482.  
  483.                      (* Update the GDevice *)
  484.                                 if newPixMap^^.pixelSize <= 8 then
  485.                                     updGDevice^^.gdType := clutType
  486.                                 else
  487.                                     updGDevice^^.gdType := directType;
  488.                                 updGDevice^^.gdPMap := newPixMap;
  489.                                 updGDevice^^.gdRect := newPixMap^^.bounds;
  490.  
  491.                      (* Set color-device bit if PixMap isn’t black & white *)
  492.                                 if newPixMap^^.pixelSize > 1 then
  493.                                     SetDeviceAttribute(updGDevice, gdDevType, TRUE)
  494.                                 else
  495.                                     SetDeviceAttribute(updGDevice, gdDevType, FALSE);
  496.  
  497.                      (* Save current fore/back colors and set to B&W *)
  498.                                 GetForeColor(savedFore);
  499.                                 GetBackColor(savedBack);
  500.                                 aColor.red := 0;
  501.                                 aColor.green := 0;
  502.                                 aColor.blue := 0;
  503.                                 RGBForeColor(aColor);
  504.                                 aColor.red := $FFFF;
  505.                                 aColor.green := $FFFF;
  506.                                 aColor.blue := $FFFF;
  507.                                 RGBBackColor(aColor);
  508.  
  509.                      (* Copy old image to the new graphics environment *)
  510.                                 HLock(Handle(oldPixMap));
  511.                                 CopyBits(BitMapPtr(oldPixMap^)^, GrafPtr(updPort)^.portBits, oldPixMap^^.bounds, updPort^.portRect, srcCopy, nil);
  512.                                 HUnlock(Handle(oldPixMap));
  513.  
  514.                      (* Restore the foreground/background color *)
  515.                                 RGBForeColor(savedFore);
  516.                                 RGBBackColor(savedBack);
  517.  
  518.                      (* Restore the saved port *)
  519.                                 SetPort(savedPort);
  520.                                 SetGDevice(savedDevice);
  521.  
  522.                      (* Get rid of the old PixMap and its dependents *)
  523.                                 DisposPtr(oldPixMap^^.baseAddr);
  524.                                 DisposeCTable(oldPixMap^^.pmTable);
  525.                                 DisposHandle(Handle(oldPixMap));
  526.                             end;
  527.                     end
  528.                 else
  529.                     error := MemError;
  530.             end;
  531.  
  532.    (* Restore the given state of the color table *)
  533.         if colors <> nil then
  534.             HSetState(Handle(colors), savedState);
  535.  
  536.    (* One Last Look Around The House Before We Go… *)
  537.         if error <> noErr then
  538.             begin
  539.                 if newPixMap <> nil then
  540.                     begin
  541.                         if newPixMap^^.pmTable <> nil then
  542.                             DisposCTable(newPixMap^^.pmTable);
  543.                         if newPixMap^^.baseAddr <> nil then
  544.                             DisposPtr(newPixMap^^.baseAddr);
  545.                         DisposHandle(Handle(newPixMap));
  546.                     end;
  547.             end;
  548.         UpdateOffScreen := error;
  549.     end;
  550.  
  551.  
  552.     procedure DisposeOffScreen (var doomedPort: CGrafPtr;     {Pointer to the CGrafPort we’re getting rid of}
  553.                                     var doomedGDevice: GDHandle                     {Handle to the GDevice we’re getting rid of}
  554.                                     );
  555.  
  556.         var
  557.             currPort: CGrafPtr; {Pointer to the current port}
  558.             currGDevice: GDHandle; {Handle to the current GDevice}
  559.  
  560.     begin
  561.    (* Check to see whether the doomed CGrafPort is the current port *)
  562.         GetPort(GrafPtr(currPort));
  563.         if currPort = doomedPort then
  564.             begin
  565.          (* It is; set current port to Window Manager CGrafPort *)
  566.                 GetCWMgrPort(currPort);
  567.                 SetPort(GrafPtr(currPort));
  568.             end;
  569.  
  570.    (* Check to see whether the doomed GDevice is the current GDevice *)
  571.         currGDevice := GetGDevice;
  572.         if currGDevice = doomedGDevice then
  573.       (* It is; set current GDevice to the main screen’s GDevice *)
  574.             SetGDevice(GetMainDevice);
  575.  
  576.    (* Throw everything away *)
  577.         doomedGDevice^^.gdPMap := nil;
  578.         DisposGDevice(doomedGDevice);
  579.         DisposPtr(doomedPort^.portPixMap^^.baseAddr);
  580.         if doomedPort^.portPixMap^^.pmTable <> nil then
  581.             DisposCTable(doomedPort^.portPixMap^^.pmTable);
  582.         CloseCPort(doomedPort);
  583.         DisposPtr(Ptr(doomedPort));
  584.         doomedPort := nil;
  585.         doomedGDevice := nil;
  586.     end;
  587.  
  588.     procedure LockOffScreen (offScreenPort: CGrafPtr {Ptr to off-screen CGrafPort}
  589.                                     );
  590.  
  591.         var
  592.             offImageHnd: Handle; {Handle to the off-screen pixel image}
  593.  
  594.     begin
  595.    (* Get the saved handle to the off-screen pixel image *)
  596.         offImageHnd := Handle(offScreenPort^.portPixMap^^.baseAddr);
  597.  
  598.    (* Lock the handle to the pixel image *)
  599.         HLock(offImageHnd);
  600.  
  601.    (* Put pixel image master pointer into baseAddr so that QuickDraw can use it *)
  602.         offScreenPort^.portPixMap^^.baseAddr := offImageHnd^;
  603.     end;
  604.  
  605.  
  606.     procedure UnlockOffScreen (offScreenPort: CGrafPtr {Ptr to off-screen port}
  607.                                     );
  608.  
  609.         var
  610.             offImagePtr: Ptr;    {Pointer to the off-screen pixel image}
  611.             offImageHnd: Handle; {Handle to the off-screen pixel image}
  612.  
  613.     begin
  614.    (* Get the handle to the off-screen pixel image *)
  615.         offImagePtr := offScreenPort^.portPixMap^^.baseAddr;
  616.         offImageHnd := RecoverHandle(offImagePtr);
  617.  
  618.    (* Unlock the handle *)
  619.         HUnlock(offImageHnd);
  620.  
  621.    (* Save the handle back in the baseAddr field *)
  622.         offScreenPort^.portPixMap^^.baseAddr := Ptr(offImageHnd);
  623.     end;
  624.  
  625.  
  626. end.