home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1999 Spring / macformat-077.iso / Shareware Plus / Development / SpriteWorld 2.2 / SpriteWorld files / Utils / Brian's Extensions / BlitPixieScaled.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-08  |  44.6 KB  |  1,578 lines  |  [TEXT/CWIE]

  1. /*  -----------------------------------------------------------------------------------
  2.     -----------------------------------------------------------------------------------
  3.     BlitPixieScaled8Bit.c
  4.     
  5.     by Brian Roddy, 5/31/97
  6.     
  7.     Bug fixes by Vern Jensen, 12/7/98. Optimizations by Vern Jensen 2/7/99.
  8.     
  9.     These routines are 8-bit and 16-bit blitters that dynamically shrink or 
  10.     stretch the sprite. 
  11.     
  12.     Use SWSetSpriteScaledSize to set the scaling size.  When the sprite is drawn, it
  13.     will be stretched or shrunk to the new width and height you specify.  
  14.     SWSetSpriteScaledSize takes a sprite pointer and a width and a height.  e.g.:
  15.     
  16.      SWSetSpriteScaledSize(mySpritePtr, 20, 50);  // Scale it
  17.     
  18.     Use a width or height <= 0 to turn off scaling.  Note that just resetting 
  19.     the sprite's draw procedure will not turn off scaling properly.  Make sure to 
  20.     call SWSetSpriteScaledSize with a negative width or height.  e.g.:
  21.  
  22.      SWSetSpriteScaledSize(mySpritePtr, -1, -1);  // Reset it back to normal
  23.      
  24.      The maximum scaled width is 800. Values larger than this are permissible as long as the Sprite
  25.      is clipped so that the visible portion of the Sprite after being clipped is no larger than 800.
  26.      For instance, if your SpriteWorld's window is 800 pixels wide and your Sprites are clipped
  27.      to that window, then your may scale your Sprites larger than 800 pixels. Otherwise, you will
  28.      get an assertion error if you try to scale them larger. You can get around this limitation
  29.      if necessary; simply change the definition of kMaxScaledWidth at the beginning of 
  30.      BlitPixieScaled.c to any value, and your Sprites can then be scaled to that maximum size.
  31.      There is no maximum scaled height; your height can be any size.
  32.      
  33.     Also note that scaling is done while drawing to the screen.  As a result, the
  34.     pixels in the frames don't match what shows up on the screen.  This means that 
  35.     functions which rely on the sprite's mask, such as SWPixelCollision, won't work as 
  36.     expected.  Thus using the pixel or mask collision routines with scaled sprites 
  37.     won't work accurately.
  38.     
  39.     SWSetSpriteScaledSize sets the scaling DrawProc for you automatically, so you don't 
  40.     need to call SWSetSpriteDrawProc, unless you want to use a RectDrawProc instead of the 
  41.     automatically assigned ScaledMaskDrawProc. It will also change the DrawProc back to one
  42.     of the standard BlitPixieMaskDrawProcs when you set the scaled size to -1 to turn off
  43.     scaling. Here is a list of the available DrawProcs:
  44.     
  45.         // User DrawProcs:
  46.     BlitPixie8BitScaledRectDrawProc
  47.     BlitPixie16BitScaledRectDrawProc
  48.     
  49.         // Sprite DrawProcs:
  50.     BP8BitScaledSpriteRectDrawProc
  51.     BP8BitScaledSpriteMaskDrawProc
  52.     BP16BitScaledSpriteRectDrawProc
  53.     BP16BitScaledSpriteMaskDrawProc
  54.     
  55.     The User DrawProcs are available for you to use directly if you want to do some direct
  56.     scaling, such as scaling the contents of the work area as you copy it to the screen.
  57.     The Sprite DrawProcs are what you should use when assigning a Sprite a scaling
  58.     DrawProc. Do not get these two types of DrawProcs mixed up.
  59.     
  60.     
  61.     -----------------------------------------------------------------------------------
  62.     Implementation Notes:
  63.  
  64.     These blitters use the "Bresenham line drawing algorithm" to do the scaling.  This is
  65.     the standard technique used for many scaling and texture mapping algorithms.  Additionally,
  66.     the scaling data is pre-computed and stored in an array to speed up each line. In particular,
  67.     this allows much faster blitting of shrunk Sprites, clipped Sprites, and direct-to-screen
  68.     scaling.
  69.     
  70.     This source code is available for free use.
  71.  
  72.     ----------------------------------------------------------------------------------- 
  73.     ----------------------------------------------------------------------------------- */
  74.  
  75.  
  76. #include "BlitPixieScaled.h"
  77.  
  78. #define kMaxScaledWidth            800            // Change this to a larger value if necessary
  79.  
  80.     // The following variables are used by PrecomputeLookupTable
  81. static short            gSrcLeftClip,
  82.                         gNumPixelsToCopy;
  83. static unsigned short    gLookupArray[kMaxScaledWidth];        // Note: change this to a short
  84.                                                             // instead of a char to avoid the
  85.                                                             // 255 src pixels to 1 dst pixel
  86.                                                             // ratio limit mentioned in the
  87.                                                             // docs. Other code that creates
  88.                                                             // a pointer to this array must
  89.                                                             // be changed as well.
  90.  
  91.  
  92. #pragma mark ----------- Public API -------------
  93.  
  94. ///--------------------------------------------------------------------------------------
  95. //    SWSetSpriteScaledSize
  96. ///--------------------------------------------------------------------------------------
  97.  
  98. SW_FUNC OSErr SWSetSpriteScaledSize(
  99.     SpritePtr srcSpriteP,
  100.     short width,
  101.     short height) 
  102. {
  103.     short         currentPixelDepth;
  104.     OSErr        err = noErr;
  105.     
  106.     
  107.     currentPixelDepth = (*srcSpriteP->frameArray[0]->framePort->portPixMap)->pixelSize;
  108.     
  109.     if (currentPixelDepth == 8)
  110.     {
  111.         if ((width <= 0) || (height <= 0))
  112.         {
  113.             srcSpriteP->scaledWidth = -1;
  114.             srcSpriteP->scaledHeight = -1;
  115.             srcSpriteP->frameDrawProc = BlitPixie8BitMaskDrawProc;
  116.         } 
  117.         else
  118.         {
  119.             srcSpriteP->scaledWidth = width;
  120.             srcSpriteP->scaledHeight = height;
  121.             srcSpriteP->frameDrawProc = BP8BitScaledSpriteMaskDrawProc;
  122.         }
  123.     }
  124.     else if (currentPixelDepth == 16)
  125.     {
  126.         if ((width <= 0) || (height <= 0))
  127.         {
  128.             srcSpriteP->scaledWidth = -1;
  129.             srcSpriteP->scaledHeight = -1;
  130.             srcSpriteP->frameDrawProc = BlitPixieAllBitMaskDrawProc;
  131.         } 
  132.         else
  133.         {
  134.             srcSpriteP->scaledWidth = width;
  135.             srcSpriteP->scaledHeight = height;
  136.             srcSpriteP->frameDrawProc = BP16BitScaledSpriteMaskDrawProc;
  137.         }
  138.     }
  139.     else
  140.     {    
  141.         err = kWrongDepthErr;
  142.     }
  143.     
  144.     if (err == noErr)
  145.     {
  146.             // Force a refresh of the sprite in the case of sprites with one frame
  147.         SWSetCurrentFrameIndex(srcSpriteP, srcSpriteP->curFrameIndex);
  148.     }
  149.     
  150.     SWSetStickyIfError( err );
  151.     return err;
  152. }
  153.  
  154. ///--------------------------------------------------------------------------------------
  155. //    SWGetSpriteScaledWidth
  156. ///--------------------------------------------------------------------------------------
  157.  
  158. SW_FUNC short SWGetSpriteScaledWidth(
  159.     SpritePtr srcSpriteP)
  160. {
  161.     return srcSpriteP->scaledWidth;
  162. }
  163.  
  164. ///--------------------------------------------------------------------------------------
  165. //    SWGetSpriteScaledHeight
  166. ///--------------------------------------------------------------------------------------
  167.  
  168. SW_FUNC short SWGetSpriteScaledHeight(
  169.     SpritePtr srcSpriteP)
  170. {
  171.     return srcSpriteP->scaledHeight;
  172. }
  173.  
  174.  
  175.  
  176. ///--------------------------------------------------------------------------------------
  177. /// BLITTERS
  178. ///--------------------------------------------------------------------------------------
  179.  
  180. extern SInt8                 gSWmmuMode;
  181. extern SpritePtr            gCurrentSpriteBeingDrawn;
  182.  
  183.  
  184. #pragma mark ----------- 8 Bit Blitters -------------
  185. ///--------------------------------------------------------------------------------------
  186. //    BlitPixie8BitScaledRectDrawProc - doesn't "unclip" the source rect, so it
  187. //    can be used directly by the user.
  188. ///--------------------------------------------------------------------------------------
  189.  
  190. SW_FUNC void BlitPixie8BitScaledRectDrawProc(
  191.     FramePtr srcFrameP,
  192.     FramePtr dstFrameP,
  193.     Rect* srcRect,
  194.     Rect* dstRect)
  195. {
  196.     Rect         srcBlitRect = *srcRect;
  197.     Rect         dstBlitRect = *dstRect;
  198.     short        topClip, rightClip, bottomClip, leftClip;
  199.     
  200.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  201.     SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
  202.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
  203.  
  204.         // Make sure some part of the Sprite is inside the dstFrame
  205.     if (dstBlitRect.left >= dstFrameP->frameRect.right ||
  206.         dstBlitRect.right <= dstFrameP->frameRect.left ||
  207.         dstBlitRect.top >= dstFrameP->frameRect.bottom ||
  208.         dstBlitRect.bottom <= dstFrameP->frameRect.top )
  209.     {
  210.         return;
  211.     }
  212.  
  213.     topClip = rightClip = bottomClip = leftClip = 0;
  214.     
  215.         // Clip dstRect with dstFrameP->frameRect
  216.     if (dstBlitRect.top < dstFrameP->frameRect.top)
  217.     {
  218.         topClip = dstFrameP->frameRect.top - dstBlitRect.top;
  219.         dstBlitRect.top = dstFrameP->frameRect.top;
  220.     }
  221.     
  222.     if (dstBlitRect.bottom > dstFrameP->frameRect.bottom)
  223.         bottomClip = dstBlitRect.bottom - dstFrameP->frameRect.bottom; 
  224.     
  225.     if (dstBlitRect.left < dstFrameP->frameRect.left)
  226.         leftClip = dstFrameP->frameRect.left - dstBlitRect.left;
  227.     
  228.     if (dstBlitRect.right > dstFrameP->frameRect.right)
  229.         rightClip = dstBlitRect.right - dstFrameP->frameRect.right;
  230.     
  231.     START_32_BIT_MODE
  232.     
  233.     PrecomputeLookupTable(
  234.         (srcBlitRect.right - srcBlitRect.left),
  235.         (dstBlitRect.right - dstBlitRect.left),
  236.         leftClip, 
  237.         rightClip);
  238.  
  239.  
  240.     BlitPixie8BitScaled(
  241.             // calculate the address of the first byte of the source
  242.         (unsigned char *)(srcFrameP->frameBaseAddr + 
  243.             (srcFrameP->scanLinePtrArray[srcBlitRect.top - srcFrameP->frameRect.top]) + 
  244.             srcBlitRect.left),
  245.  
  246.             // calculate the address of the first byte of the destination
  247.         (unsigned char *)(dstFrameP->frameBaseAddr + 
  248.             (dstFrameP->scanLinePtrArray[dstBlitRect.top]) + 
  249.             dstBlitRect.left),
  250.  
  251.             // calculate the number of rows to blit
  252.         (srcBlitRect.bottom - srcBlitRect.top),
  253.         (dstBlitRect.bottom - dstBlitRect.top) + topClip,
  254.  
  255.         srcFrameP->frameRowBytes,
  256.         dstFrameP->frameRowBytes,
  257.         
  258.             // clipping information
  259.         leftClip,
  260.         topClip,
  261.         bottomClip,
  262.         
  263.             // are we blitting direct-to-screen?
  264.         dstFrameP->isWindowFrame
  265.     );
  266.     
  267.  
  268.     END_32_BIT_MODE
  269. }
  270.  
  271.  
  272. ///--------------------------------------------------------------------------------------
  273. //    BP8BitScaledSpriteRectDrawProc
  274. ///--------------------------------------------------------------------------------------
  275.  
  276. SW_FUNC void BP8BitScaledSpriteRectDrawProc(
  277.     FramePtr srcFrameP,
  278.     FramePtr dstFrameP,
  279.     Rect* srcRect,
  280.     Rect* dstRect)
  281. {
  282.     Rect         srcBlitRect = *srcRect;
  283.     Rect         dstBlitRect = *dstRect;
  284.     short        topClip, rightClip, bottomClip, leftClip;
  285.     short        topClip2, rightClip2, bottomClip2, leftClip2;
  286.     
  287.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  288.     SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
  289.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
  290.  
  291.         // Make sure some part of the Sprite is inside the dstFrame
  292.     if (dstBlitRect.left >= dstFrameP->frameRect.right ||
  293.         dstBlitRect.right <= dstFrameP->frameRect.left ||
  294.         dstBlitRect.top >= dstFrameP->frameRect.bottom ||
  295.         dstBlitRect.bottom <= dstFrameP->frameRect.top )
  296.     {
  297.         return;
  298.     }
  299.  
  300.     topClip = rightClip = bottomClip = leftClip = 0;
  301.     topClip2 = rightClip2 = bottomClip2 = leftClip2 = 0;
  302.     
  303.         // Clip dstRect with dstFrameP->frameRect
  304.     if (dstBlitRect.top < dstFrameP->frameRect.top)
  305.     {
  306.         topClip = dstFrameP->frameRect.top - dstBlitRect.top;
  307.         dstBlitRect.top = dstFrameP->frameRect.top;
  308.     }
  309.     
  310.     if (dstBlitRect.bottom > dstFrameP->frameRect.bottom)
  311.         bottomClip = dstBlitRect.bottom - dstFrameP->frameRect.bottom; 
  312.     
  313.     if (dstBlitRect.left < dstFrameP->frameRect.left)
  314.         leftClip = dstFrameP->frameRect.left - dstBlitRect.left;
  315.     
  316.     if (dstBlitRect.right > dstFrameP->frameRect.right)
  317.         rightClip = dstBlitRect.right - dstFrameP->frameRect.right;
  318.     
  319.     
  320.         // "Unclip" sprite if it was already clipped before this function was called
  321.     if (srcBlitRect.top > srcFrameP->frameRect.top)
  322.     {
  323.         topClip2 = srcBlitRect.top - srcFrameP->frameRect.top;
  324.         srcBlitRect.top = srcFrameP->frameRect.top;
  325.     }
  326.     
  327.     if (srcBlitRect.bottom < srcFrameP->frameRect.bottom)
  328.     {
  329.         bottomClip2 = srcFrameP->frameRect.bottom - srcBlitRect.bottom; 
  330.         srcBlitRect.bottom = srcFrameP->frameRect.bottom;
  331.         dstBlitRect.bottom += bottomClip2;
  332.     }
  333.  
  334.     if (srcBlitRect.left > srcFrameP->frameRect.left)
  335.     {
  336.         leftClip2 = srcBlitRect.left - srcFrameP->frameRect.left;
  337.         srcBlitRect.left = srcFrameP->frameRect.left;
  338.         dstBlitRect.left -= leftClip2;
  339.     }
  340.     
  341.     if (srcBlitRect.right < srcFrameP->frameRect.right)
  342.     {
  343.         rightClip2 = srcFrameP->frameRect.right - srcBlitRect.right; 
  344.         srcBlitRect.right = srcFrameP->frameRect.right;
  345.         dstBlitRect.right += rightClip2;
  346.     }    
  347.     
  348.     topClip += topClip2;
  349.     leftClip += leftClip2;
  350.     rightClip += rightClip2;
  351.     bottomClip += bottomClip2;
  352.         
  353.  
  354.     START_32_BIT_MODE
  355.     
  356.     PrecomputeLookupTable(
  357.         (srcBlitRect.right - srcBlitRect.left),
  358.         (dstBlitRect.right - dstBlitRect.left),
  359.         leftClip, 
  360.         rightClip);
  361.  
  362.  
  363.     BlitPixie8BitScaled(
  364.             // calculate the address of the first byte of the source
  365.         (unsigned char *)(srcFrameP->frameBaseAddr + 
  366.             (srcFrameP->scanLinePtrArray[srcBlitRect.top - srcFrameP->frameRect.top]) + 
  367.             srcBlitRect.left),
  368.  
  369.             // calculate the address of the first byte of the destination
  370.         (unsigned char *)(dstFrameP->frameBaseAddr + 
  371.             (dstFrameP->scanLinePtrArray[dstBlitRect.top]) + 
  372.             dstBlitRect.left),
  373.  
  374.             // calculate the number of rows to blit
  375.         (srcBlitRect.bottom - srcBlitRect.top),
  376.         (dstBlitRect.bottom - dstBlitRect.top) + topClip,
  377.  
  378.         srcFrameP->frameRowBytes,
  379.         dstFrameP->frameRowBytes,
  380.         
  381.             // clipping information
  382.         leftClip,
  383.         topClip,
  384.         bottomClip,
  385.         
  386.             // are we blitting direct-to-screen?
  387.         dstFrameP->isWindowFrame
  388.     );
  389.  
  390.  
  391.     END_32_BIT_MODE
  392. }
  393.  
  394. ///--------------------------------------------------------------------------------------
  395. //    BP8BitScaledSpriteMaskDrawProc
  396. ///--------------------------------------------------------------------------------------
  397.  
  398. SW_FUNC void BP8BitScaledSpriteMaskDrawProc(
  399.     FramePtr srcFrameP,
  400.     FramePtr dstFrameP,
  401.     Rect *srcRect,
  402.     Rect *dstRect)
  403. {
  404.     Rect                dstBlitRect = *dstRect;
  405.     Rect                srcBlitRect = *srcRect;
  406.     unsigned long         srcBaseOffset;
  407.     short                topClip, rightClip, bottomClip, leftClip;
  408.     short                topClip2, rightClip2, bottomClip2, leftClip2;
  409.     
  410.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  411.     SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
  412.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
  413.     SW_ASSERT(srcFrameP->maskPort != NULL);
  414.  
  415.         // Make sure some part of the Sprite is inside the dstFrame
  416.     if (dstBlitRect.left >= dstFrameP->frameRect.right ||
  417.         dstBlitRect.right <= dstFrameP->frameRect.left ||
  418.         dstBlitRect.top >= dstFrameP->frameRect.bottom ||
  419.         dstBlitRect.bottom <= dstFrameP->frameRect.top )
  420.     {
  421.         return;
  422.     }
  423.  
  424.     topClip = rightClip = bottomClip = leftClip = 0;
  425.     topClip2 = rightClip2 = bottomClip2 = leftClip2 = 0;
  426.     
  427.         // Clip dstRect with dstFrameP->frameRect
  428.     if (dstBlitRect.top < dstFrameP->frameRect.top)
  429.     {
  430.         topClip = dstFrameP->frameRect.top - dstBlitRect.top;
  431.         dstBlitRect.top = dstFrameP->frameRect.top;
  432.     }
  433.     
  434.     if (dstBlitRect.bottom > dstFrameP->frameRect.bottom)
  435.         bottomClip = dstBlitRect.bottom - dstFrameP->frameRect.bottom; 
  436.     
  437.     if (dstBlitRect.left < dstFrameP->frameRect.left)
  438.         leftClip = dstFrameP->frameRect.left - dstBlitRect.left;
  439.     
  440.     if (dstBlitRect.right > dstFrameP->frameRect.right)
  441.         rightClip = dstBlitRect.right - dstFrameP->frameRect.right;
  442.     
  443.     
  444.         // "Unclip" sprite if it was already clipped before this function was called
  445.     if (srcBlitRect.top > srcFrameP->frameRect.top)
  446.     {
  447.         topClip2 = srcBlitRect.top - srcFrameP->frameRect.top;
  448.         srcBlitRect.top = srcFrameP->frameRect.top;
  449.     }
  450.     
  451.     if (srcBlitRect.bottom < srcFrameP->frameRect.bottom)
  452.     {
  453.         bottomClip2 = srcFrameP->frameRect.bottom - srcBlitRect.bottom; 
  454.         srcBlitRect.bottom = srcFrameP->frameRect.bottom;
  455.         dstBlitRect.bottom += bottomClip2;
  456.     }
  457.  
  458.     if (srcBlitRect.left > srcFrameP->frameRect.left)
  459.     {
  460.         leftClip2 = srcBlitRect.left - srcFrameP->frameRect.left;
  461.         srcBlitRect.left = srcFrameP->frameRect.left;
  462.         dstBlitRect.left -= leftClip2;
  463.     }
  464.     
  465.     if (srcBlitRect.right < srcFrameP->frameRect.right)
  466.     {
  467.         rightClip2 = srcFrameP->frameRect.right - srcBlitRect.right; 
  468.         srcBlitRect.right = srcFrameP->frameRect.right;
  469.         dstBlitRect.right += rightClip2;
  470.     }    
  471.     
  472.     topClip += topClip2;
  473.     leftClip += leftClip2;
  474.     rightClip += rightClip2;
  475.     bottomClip += bottomClip2;
  476.     
  477.         
  478.         // Cache this value since it's used twice
  479.     srcBaseOffset = (srcFrameP->scanLinePtrArray[srcBlitRect.top - 
  480.             srcFrameP->frameRect.top]) + srcBlitRect.left;
  481.  
  482.     START_32_BIT_MODE
  483.     
  484.     PrecomputeLookupTable(
  485.             (srcBlitRect.right - srcBlitRect.left),
  486.             (dstBlitRect.right - dstBlitRect.left),
  487.             leftClip, 
  488.             rightClip);
  489.  
  490.  
  491.     BlitPixieMask8BitScaled(
  492.             // calculate the address of the first byte of the source
  493.         (unsigned char *)(srcFrameP->frameBaseAddr + srcBaseOffset),
  494.  
  495.             // calculate the address of the first byte of the destination
  496.         (unsigned char *)(dstFrameP->frameBaseAddr + 
  497.             (dstFrameP->scanLinePtrArray[dstBlitRect.top]) + 
  498.             dstBlitRect.left),
  499.  
  500.                 // calculate the address of the first byte of the mask
  501.         (unsigned char *)(srcFrameP->maskBaseAddr + srcBaseOffset),
  502.  
  503.             // calculate the number of rows to blit
  504.         (srcBlitRect.bottom - srcBlitRect.top),
  505.         (dstBlitRect.bottom - dstBlitRect.top) + topClip,
  506.         
  507.         srcFrameP->frameRowBytes,
  508.         dstFrameP->frameRowBytes,
  509.         
  510.             // clipping information
  511.         leftClip,
  512.         topClip,
  513.         bottomClip,
  514.                 
  515.             // are we blitting direct-to-screen?
  516.         dstFrameP->isWindowFrame
  517.     );
  518.  
  519.  
  520.     END_32_BIT_MODE
  521. }
  522.  
  523.  
  524. ///--------------------------------------------------------------------------------------
  525. //    BlitPixie8BitScaled
  526. ///--------------------------------------------------------------------------------------
  527.  
  528. void BlitPixie8BitScaled(
  529.     register unsigned char *srcPixelP,
  530.     register unsigned char *dstPixelP,
  531.     long srcRowsToCopy,
  532.     long dstRowsToCopy,
  533.     unsigned long srcOffset,
  534.     unsigned long dstOffset,
  535.     short leftClip,
  536.     short topClip,
  537.     short bottomClip,
  538.     Boolean isBlittingToScreen)
  539. {
  540.     register unsigned char *startSrcPixelP;
  541.     register unsigned char *startDstPixelP;
  542.     long    verticalEps;
  543.     short    curRow, numRowsToCopy;
  544.     
  545.     startSrcPixelP = srcPixelP;
  546.     startDstPixelP = dstPixelP;
  547.  
  548.     if (srcRowsToCopy >= dstRowsToCopy)
  549.         verticalEps = srcRowsToCopy / 2;
  550.     else
  551.         verticalEps = -dstRowsToCopy / 2;
  552.     
  553.         // Clip off the top if necessary
  554.     for (curRow = 0; curRow < topClip; curRow++)
  555.     {
  556.         if (srcRowsToCopy >= dstRowsToCopy) 
  557.         {
  558.             while ((verticalEps * 2) <= srcRowsToCopy) 
  559.             {
  560.                     // shrink
  561.                 startSrcPixelP += srcOffset;
  562.                 verticalEps += dstRowsToCopy;
  563.             }
  564.             verticalEps -= srcRowsToCopy;
  565.         } 
  566.         else 
  567.         {
  568.                 // grow
  569.             verticalEps += srcRowsToCopy;
  570.             if ((verticalEps * 2) > dstRowsToCopy)  
  571.             {
  572.                 startSrcPixelP += srcOffset;
  573.                 verticalEps -= dstRowsToCopy;
  574.             }
  575.         }
  576.     }
  577.  
  578.         // Handle the bottom clip
  579.     numRowsToCopy = dstRowsToCopy - bottomClip;
  580.     
  581.         // Draw the thing
  582.     for (; curRow < numRowsToCopy; curRow++)
  583.     {
  584.         BlitScaledLine8Bit(startSrcPixelP + gSrcLeftClip, startDstPixelP + leftClip, 
  585.                 isBlittingToScreen);    
  586.         
  587.             // bump to next row    
  588.         startDstPixelP += dstOffset;
  589.  
  590.         if (srcRowsToCopy >= dstRowsToCopy) 
  591.         {
  592.             while ((verticalEps * 2) <= srcRowsToCopy)
  593.             {
  594.                     // shrink
  595.                 startSrcPixelP += srcOffset;
  596.                 verticalEps += dstRowsToCopy;
  597.             }
  598.             verticalEps -= srcRowsToCopy;
  599.         } 
  600.         else
  601.         {
  602.                 // grow
  603.             verticalEps += srcRowsToCopy;
  604.             if ((verticalEps * 2) > dstRowsToCopy) 
  605.             {
  606.                 startSrcPixelP += srcOffset;
  607.                 verticalEps -= dstRowsToCopy;
  608.             }
  609.         }
  610.     }
  611. }
  612.  
  613.  
  614. ///--------------------------------------------------------------------------------------
  615. //    BlitPixieMask8BitScaled
  616. ///--------------------------------------------------------------------------------------
  617.  
  618. void BlitPixieMask8BitScaled(
  619.     register unsigned char *srcPixelP,
  620.     register unsigned char *dstPixelP,
  621.     register unsigned char *maskPixelP,
  622.     long srcRowsToCopy,
  623.     long dstRowsToCopy,
  624.     unsigned long srcOffset,
  625.     unsigned long dstOffset,
  626.     short leftClip,
  627.     short topClip,
  628.     short bottomClip,
  629.     short isBlittingToScreen)
  630. {
  631.     register unsigned char *startSrcPixelP;
  632.     register unsigned char *startDstPixelP;
  633.     register unsigned char *startMaskPixelP;
  634.     long    verticalEps;
  635.     short    curRow, numRowsToCopy;
  636.     
  637.     startSrcPixelP = srcPixelP;
  638.     startDstPixelP = dstPixelP;
  639.     startMaskPixelP = maskPixelP;
  640.  
  641.     if (srcRowsToCopy >= dstRowsToCopy)
  642.         verticalEps = srcRowsToCopy / 2;
  643.     else
  644.         verticalEps = -dstRowsToCopy / 2;
  645.     
  646.         // Clip off the top if necessary
  647.     for (curRow = 0; curRow < topClip; curRow++)
  648.     {
  649.         if (srcRowsToCopy >= dstRowsToCopy) {
  650.             while ((verticalEps * 2) <= srcRowsToCopy) {
  651.                 // shrink
  652.                 startSrcPixelP += srcOffset;
  653.                 startMaskPixelP += srcOffset;
  654.                 verticalEps += dstRowsToCopy;
  655.             }
  656.             verticalEps -= srcRowsToCopy;
  657.         } else {
  658.             // grow
  659.             verticalEps += srcRowsToCopy;
  660.             if ((verticalEps * 2) > dstRowsToCopy)  {
  661.                 startSrcPixelP += srcOffset;
  662.                 startMaskPixelP += srcOffset;
  663.                 verticalEps -= dstRowsToCopy;
  664.             }
  665.         }
  666.     }
  667.  
  668.         // Handle the bottom clip
  669.     numRowsToCopy = dstRowsToCopy - bottomClip;
  670.     
  671.         // Draw the thing
  672.     for (; curRow < numRowsToCopy; curRow++)
  673.     {
  674.         BlitScaledMaskedLine8Bit(startSrcPixelP + gSrcLeftClip, startMaskPixelP + gSrcLeftClip,
  675.             startDstPixelP + leftClip, isBlittingToScreen);
  676.         
  677.             // bump to next row    
  678.         startDstPixelP += dstOffset;
  679.  
  680.         if (srcRowsToCopy >= dstRowsToCopy) {
  681.             while ((verticalEps * 2) <= srcRowsToCopy) {
  682.                 // shrink
  683.                 startSrcPixelP += srcOffset;
  684.                 startMaskPixelP += srcOffset;
  685.                 verticalEps += dstRowsToCopy;
  686.             }
  687.             verticalEps -= srcRowsToCopy;
  688.         } else {
  689.             // grow
  690.             verticalEps += srcRowsToCopy;
  691.             if ((verticalEps * 2) > dstRowsToCopy)  {
  692.                 startSrcPixelP += srcOffset;
  693.                 startMaskPixelP += srcOffset;
  694.                 verticalEps -= dstRowsToCopy;
  695.             }
  696.         }
  697.     }
  698. }
  699.  
  700.  
  701. ///--------------------------------------------------------------------------------------
  702. //    BlitScaledLine8Bit - it makes it slightly faster on 68k Macs to put this code in its
  703. //  own function, instead of placing it directly in BlitPixie8BitScaled. It goes the same
  704. //  speed on PPC. This must be because we're "breaking the cache" on 68k Macs otherwise.
  705. ///--------------------------------------------------------------------------------------
  706.  
  707. void BlitScaledLine8Bit(
  708.     register unsigned char *srcPixelP,
  709.     register unsigned char *dstPixelP,
  710.     Boolean weAreBlittingToScreen)
  711. {
  712.     register unsigned short *lookupArrayP;
  713.     short    numPixelsToCopy;
  714.  
  715.     lookupArrayP = gLookupArray;
  716.     
  717.     numPixelsToCopy = gNumPixelsToCopy;
  718.     
  719.         // The following code speeds up both 68k and PPC Macs when blitting directly to the
  720.         // screen, as well as 68k Macs slightly when blitting offscreen. (But not PPC
  721.         // when blitting offscreen)
  722.     if (weAreBlittingToScreen || !SW_PPC)
  723.     {
  724.         unsigned long    srcBuffer;
  725.         register unsigned char  *srcBufferPixelP;
  726.         
  727.         while (numPixelsToCopy >= 4) 
  728.         {
  729.                 // Get char pointer to our 4-byte buffer
  730.             srcBufferPixelP = (unsigned char *)&srcBuffer;
  731.             
  732.                 // Load 1st pixel into buffer
  733.             srcPixelP += *lookupArrayP;
  734.             *srcBufferPixelP++ = *srcPixelP;
  735.             lookupArrayP++;
  736.             
  737.                 // Load 2nd pixel into buffer
  738.             srcPixelP += *lookupArrayP;
  739.             *srcBufferPixelP++ = *srcPixelP;
  740.             lookupArrayP++;
  741.             
  742.                 // Load 3rd pixel into buffer
  743.             srcPixelP += *lookupArrayP;
  744.             *srcBufferPixelP++ = *srcPixelP;
  745.             lookupArrayP++;
  746.             
  747.                 // Load 4th pixel into buffer
  748.             srcPixelP += *lookupArrayP;
  749.             *srcBufferPixelP++ = *srcPixelP;
  750.             lookupArrayP++;
  751.             
  752.                 // Copy from our 4-byte buffer to the destination
  753.             *((unsigned long *) dstPixelP)++ = srcBuffer;
  754.             
  755.             numPixelsToCopy -= 4;
  756.         }
  757.     }
  758.  
  759.  
  760.         // This code draws the rest of the line that was not handled above on 68k Macs,
  761.         // or it draws the entire line on PowerMacs.
  762.     while (numPixelsToCopy--) 
  763.     {
  764.         srcPixelP += *lookupArrayP;
  765.         lookupArrayP++;
  766.         
  767.         *dstPixelP = *srcPixelP;
  768.         dstPixelP++;
  769.     }
  770. }
  771.  
  772.  
  773. ///--------------------------------------------------------------------------------------
  774. //    BlitScaledMaskedLine8Bit - it makes it slightly faster on 68k Macs to put this code in its
  775. //  own function, instead of placing it directly in BlitPixieMask8BitScaled. It goes the
  776. //    same speed on PPC. This must be because we're "breaking the cache" on 68k Macs otherwise.
  777. ///--------------------------------------------------------------------------------------
  778.  
  779. void BlitScaledMaskedLine8Bit(
  780.     register unsigned char *srcPixelP,
  781.     register unsigned char *maskPixelP,
  782.     register unsigned char *dstPixelP,
  783.     Boolean weAreBlittingToScreen)
  784. {
  785.     register unsigned short *lookupArrayP;
  786.     short    numPixelsToCopy;
  787.  
  788.     lookupArrayP = gLookupArray;
  789.     
  790.     numPixelsToCopy = gNumPixelsToCopy;
  791.     
  792.         // The following code speeds up both 68k and PPC Macs when blitting directly to the
  793.         // screen, as well as 68k Macs slightly when blitting offscreen. (But not PPC
  794.         // when blitting offscreen)
  795.     if (weAreBlittingToScreen || !SW_PPC)
  796.     {
  797.         unsigned long    srcBuffer, maskBuffer;
  798.         register unsigned char  *srcBufferPixelP, *maskBufferPixelP;
  799.         register unsigned long temp1;
  800.         
  801.         while (numPixelsToCopy >= 4) 
  802.         {
  803.                 // Get char pointers to our 4-byte buffers
  804.             srcBufferPixelP = (unsigned char *)&srcBuffer;
  805.             maskBufferPixelP = (unsigned char *)&maskBuffer;
  806.             
  807.                 // Load 1st pixel into buffer
  808.             srcPixelP += *lookupArrayP;
  809.             maskPixelP += *lookupArrayP;
  810.             *srcBufferPixelP++ = *srcPixelP;
  811.             *maskBufferPixelP++ = *maskPixelP;
  812.             lookupArrayP++;
  813.             
  814.                 // Load 2nd pixel into buffer
  815.             srcPixelP += *lookupArrayP;
  816.             maskPixelP += *lookupArrayP;
  817.             *srcBufferPixelP++ = *srcPixelP;
  818.             *maskBufferPixelP++ = *maskPixelP;
  819.             lookupArrayP++;
  820.             
  821.                 // Load 3rd pixel into buffer
  822.             srcPixelP += *lookupArrayP;
  823.             maskPixelP += *lookupArrayP;
  824.             *srcBufferPixelP++ = *srcPixelP;
  825.             *maskBufferPixelP++ = *maskPixelP;
  826.             lookupArrayP++;
  827.             
  828.                 // Load 4th pixel into buffer
  829.             srcPixelP += *lookupArrayP;
  830.             maskPixelP += *lookupArrayP;
  831.             *srcBufferPixelP = *srcPixelP;
  832.             *maskBufferPixelP = *maskPixelP;
  833.             lookupArrayP++;
  834.  
  835.                 // Copy from our 4-byte buffer to the destination
  836.             temp1 = *((unsigned long *) dstPixelP) & maskBuffer | srcBuffer;
  837.             *((unsigned long *) dstPixelP)++ = temp1;
  838.             
  839.             numPixelsToCopy -= 4;
  840.         }
  841.     }
  842.  
  843.         // This code draws the rest of the line that was not handled above on 68k Macs,
  844.         // or it draws the entire line on PowerMacs.
  845.     while (numPixelsToCopy--) 
  846.     {
  847.         srcPixelP += *lookupArrayP;
  848.         maskPixelP += *lookupArrayP;
  849.         
  850.         if (*maskPixelP == 0)
  851.             *dstPixelP = *srcPixelP;
  852.         
  853.         dstPixelP++;
  854.         lookupArrayP++;
  855.     }
  856. }
  857.  
  858.  
  859. #pragma mark ----------- 16 Bit Blitters -------------
  860.  
  861. ///--------------------------------------------------------------------------------------
  862. //    BlitPixie16BitScaledRectDrawProc - doesn't "unclip" the source rect, so it
  863. //    can be used directly by the user.
  864. ///--------------------------------------------------------------------------------------
  865.  
  866. SW_FUNC void BlitPixie16BitScaledRectDrawProc(
  867.     FramePtr srcFrameP,
  868.     FramePtr dstFrameP,
  869.     Rect* srcRect,
  870.     Rect* dstRect)
  871. {
  872.     Rect         srcBlitRect = *srcRect;
  873.     Rect         dstBlitRect = *dstRect;
  874.     short        topClip, rightClip, bottomClip, leftClip;
  875.     
  876.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  877.     SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 16);
  878.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 16);
  879.  
  880.         // Make sure some part of the Sprite is inside the dstFrame
  881.     if (dstBlitRect.left >= dstFrameP->frameRect.right ||
  882.         dstBlitRect.right <= dstFrameP->frameRect.left ||
  883.         dstBlitRect.top >= dstFrameP->frameRect.bottom ||
  884.         dstBlitRect.bottom <= dstFrameP->frameRect.top )
  885.     {
  886.         return;
  887.     }
  888.  
  889.     topClip = rightClip = bottomClip = leftClip = 0;
  890.     
  891.         // Clip dstRect with dstFrameP->frameRect
  892.     if (dstBlitRect.top < dstFrameP->frameRect.top)
  893.     {
  894.         topClip = dstFrameP->frameRect.top - dstBlitRect.top;
  895.         dstBlitRect.top = dstFrameP->frameRect.top;
  896.     }
  897.     
  898.     if (dstBlitRect.bottom > dstFrameP->frameRect.bottom)
  899.         bottomClip = dstBlitRect.bottom - dstFrameP->frameRect.bottom; 
  900.     
  901.     if (dstBlitRect.left < dstFrameP->frameRect.left)
  902.         leftClip = dstFrameP->frameRect.left - dstBlitRect.left;
  903.     
  904.     if (dstBlitRect.right > dstFrameP->frameRect.right)
  905.         rightClip = dstBlitRect.right - dstFrameP->frameRect.right;
  906.     
  907.         
  908.     START_32_BIT_MODE
  909.     
  910.     PrecomputeLookupTable(
  911.         (srcBlitRect.right - srcBlitRect.left),
  912.         (dstBlitRect.right - dstBlitRect.left),
  913.         leftClip, 
  914.         rightClip);
  915.  
  916.  
  917.     BlitPixie16BitScaled(
  918.             // calculate the address of the first byte of the source
  919.         (unsigned short *)(srcFrameP->frameBaseAddr + 
  920.             (srcFrameP->scanLinePtrArray[srcBlitRect.top - srcFrameP->frameRect.top]) + 
  921.             (srcBlitRect.left << 1)),
  922.  
  923.             // calculate the address of the first byte of the destination
  924.         (unsigned short *)(dstFrameP->frameBaseAddr + 
  925.             (dstFrameP->scanLinePtrArray[dstBlitRect.top]) + 
  926.             (dstBlitRect.left << 1)),
  927.  
  928.             // calculate the number of rows to blit
  929.         srcBlitRect.bottom - srcBlitRect.top,
  930.         dstBlitRect.bottom - dstBlitRect.top + topClip,
  931.  
  932.             // for PPC, just frameRowBytes
  933.         srcFrameP->frameRowBytes,
  934.         dstFrameP->frameRowBytes,
  935.         
  936.             // clipping information
  937.         leftClip,
  938.         topClip,
  939.         bottomClip,
  940.                         
  941.             // are we blitting direct-to-screen?
  942.         dstFrameP->isWindowFrame
  943.     );
  944.  
  945.  
  946.     END_32_BIT_MODE
  947. }
  948.  
  949.  
  950. ///--------------------------------------------------------------------------------------
  951. //        BP16BitScaledSpriteRectDrawProc
  952. ///--------------------------------------------------------------------------------------
  953.  
  954. SW_FUNC void BP16BitScaledSpriteRectDrawProc(
  955.     FramePtr srcFrameP,
  956.     FramePtr dstFrameP,
  957.     Rect* srcRect,
  958.     Rect* dstRect)
  959. {
  960.     Rect         srcBlitRect = *srcRect;
  961.     Rect         dstBlitRect = *dstRect;
  962.     short        topClip, rightClip, bottomClip, leftClip;
  963.     short        topClip2, rightClip2, bottomClip2, leftClip2;
  964.     
  965.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  966.     SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 16);
  967.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 16);
  968.  
  969.         // Make sure some part of the Sprite is inside the dstFrame
  970.     if (dstBlitRect.left >= dstFrameP->frameRect.right ||
  971.         dstBlitRect.right <= dstFrameP->frameRect.left ||
  972.         dstBlitRect.top >= dstFrameP->frameRect.bottom ||
  973.         dstBlitRect.bottom <= dstFrameP->frameRect.top )
  974.     {
  975.         return;
  976.     }
  977.  
  978.     topClip = rightClip = bottomClip = leftClip = 0;
  979.     topClip2 = rightClip2 = bottomClip2 = leftClip2 = 0;
  980.     
  981.         // Clip dstRect with dstFrameP->frameRect
  982.     if (dstBlitRect.top < dstFrameP->frameRect.top)
  983.     {
  984.         topClip = dstFrameP->frameRect.top - dstBlitRect.top;
  985.         dstBlitRect.top = dstFrameP->frameRect.top;
  986.     }
  987.     
  988.     if (dstBlitRect.bottom > dstFrameP->frameRect.bottom)
  989.         bottomClip = dstBlitRect.bottom - dstFrameP->frameRect.bottom; 
  990.     
  991.     if (dstBlitRect.left < dstFrameP->frameRect.left)
  992.         leftClip = dstFrameP->frameRect.left - dstBlitRect.left;
  993.     
  994.     if (dstBlitRect.right > dstFrameP->frameRect.right)
  995.         rightClip = dstBlitRect.right - dstFrameP->frameRect.right;
  996.     
  997.     
  998.         // "Unclip" sprite if it was already clipped before this function was called
  999.     if (srcBlitRect.top > srcFrameP->frameRect.top)
  1000.     {
  1001.         topClip2 = srcBlitRect.top - srcFrameP->frameRect.top;
  1002.         srcBlitRect.top = srcFrameP->frameRect.top;
  1003.     }
  1004.     
  1005.     if (srcBlitRect.bottom < srcFrameP->frameRect.bottom)
  1006.     {
  1007.         bottomClip2 = srcFrameP->frameRect.bottom - srcBlitRect.bottom; 
  1008.         srcBlitRect.bottom = srcFrameP->frameRect.bottom;
  1009.         dstBlitRect.bottom += bottomClip2;
  1010.     }
  1011.  
  1012.     if (srcBlitRect.left > srcFrameP->frameRect.left)
  1013.     {
  1014.         leftClip2 = srcBlitRect.left - srcFrameP->frameRect.left;
  1015.         srcBlitRect.left = srcFrameP->frameRect.left;
  1016.         dstBlitRect.left -= leftClip2;
  1017.     }
  1018.     
  1019.     if (srcBlitRect.right < srcFrameP->frameRect.right)
  1020.     {
  1021.         rightClip2 = srcFrameP->frameRect.right - srcBlitRect.right; 
  1022.         srcBlitRect.right = srcFrameP->frameRect.right;
  1023.         dstBlitRect.right += rightClip2;
  1024.     }    
  1025.     
  1026.     topClip += topClip2;
  1027.     leftClip += leftClip2;
  1028.     rightClip += rightClip2;
  1029.     bottomClip += bottomClip2;
  1030.  
  1031.     START_32_BIT_MODE
  1032.     
  1033.     PrecomputeLookupTable(
  1034.         (srcBlitRect.right - srcBlitRect.left),
  1035.         (dstBlitRect.right - dstBlitRect.left),
  1036.         leftClip, 
  1037.         rightClip);
  1038.  
  1039.  
  1040.     BlitPixie16BitScaled(
  1041.             // calculate the address of the first byte of the source
  1042.         (unsigned short *)(srcFrameP->frameBaseAddr + 
  1043.             (srcFrameP->scanLinePtrArray[srcBlitRect.top - srcFrameP->frameRect.top]) + 
  1044.             (srcBlitRect.left << 1)),
  1045.  
  1046.             // calculate the address of the first byte of the destination
  1047.         (unsigned short *)(dstFrameP->frameBaseAddr + 
  1048.             (dstFrameP->scanLinePtrArray[dstBlitRect.top]) + 
  1049.             (dstBlitRect.left << 1)),
  1050.  
  1051.             // calculate the number of rows to blit
  1052.         srcBlitRect.bottom - srcBlitRect.top,
  1053.         dstBlitRect.bottom - dstBlitRect.top + topClip,
  1054.  
  1055.             // for PPC, just frameRowBytes
  1056.         srcFrameP->frameRowBytes,
  1057.         dstFrameP->frameRowBytes,
  1058.         
  1059.             // clipping information
  1060.         leftClip,
  1061.         topClip,
  1062.         bottomClip,
  1063.                         
  1064.             // are we blitting direct-to-screen?
  1065.         dstFrameP->isWindowFrame
  1066.     );
  1067.  
  1068.  
  1069.     END_32_BIT_MODE
  1070. }
  1071.  
  1072. ///--------------------------------------------------------------------------------------
  1073. //    BP16BitScaledSpriteMaskDrawProc
  1074. ///--------------------------------------------------------------------------------------
  1075.  
  1076. SW_FUNC void BP16BitScaledSpriteMaskDrawProc(
  1077.     FramePtr srcFrameP,
  1078.     FramePtr dstFrameP,
  1079.     Rect *srcRect,
  1080.     Rect *dstRect)
  1081. {
  1082.     Rect dstBlitRect = *dstRect;
  1083.     Rect srcBlitRect = *srcRect;
  1084.     unsigned long         srcBaseOffset;
  1085.     short        topClip, rightClip, bottomClip, leftClip;
  1086.     short        topClip2, rightClip2, bottomClip2, leftClip2;
  1087.     
  1088.     SW_ASSERT(srcFrameP->isFrameLocked && dstFrameP->isFrameLocked);
  1089.     SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 16);
  1090.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 16);
  1091.     SW_ASSERT(srcFrameP->maskPort != NULL);
  1092.  
  1093.         // Make sure some part of the Sprite is inside the dstFrame
  1094.     if (dstBlitRect.left >= dstFrameP->frameRect.right ||
  1095.         dstBlitRect.right <= dstFrameP->frameRect.left ||
  1096.         dstBlitRect.top >= dstFrameP->frameRect.bottom ||
  1097.         dstBlitRect.bottom <= dstFrameP->frameRect.top )
  1098.     {
  1099.         return;
  1100.     }
  1101.  
  1102.     topClip = rightClip = bottomClip = leftClip = 0;
  1103.     topClip2 = rightClip2 = bottomClip2 = leftClip2 = 0;
  1104.     
  1105.         // Clip dstRect with dstFrameP->frameRect
  1106.     if (dstBlitRect.top < dstFrameP->frameRect.top)
  1107.     {
  1108.         topClip = dstFrameP->frameRect.top - dstBlitRect.top;
  1109.         dstBlitRect.top = dstFrameP->frameRect.top;
  1110.     }
  1111.     
  1112.     if (dstBlitRect.bottom > dstFrameP->frameRect.bottom)
  1113.         bottomClip = dstBlitRect.bottom - dstFrameP->frameRect.bottom; 
  1114.     
  1115.     if (dstBlitRect.left < dstFrameP->frameRect.left)
  1116.         leftClip = dstFrameP->frameRect.left - dstBlitRect.left;
  1117.     
  1118.     if (dstBlitRect.right > dstFrameP->frameRect.right)
  1119.         rightClip = dstBlitRect.right - dstFrameP->frameRect.right;
  1120.     
  1121.     
  1122.         // "Unclip" sprite if it was already clipped before this function was called
  1123.     if (srcBlitRect.top > srcFrameP->frameRect.top)
  1124.     {
  1125.         topClip2 = srcBlitRect.top - srcFrameP->frameRect.top;
  1126.         srcBlitRect.top = srcFrameP->frameRect.top;
  1127.     }
  1128.     
  1129.     if (srcBlitRect.bottom < srcFrameP->frameRect.bottom)
  1130.     {
  1131.         bottomClip2 = srcFrameP->frameRect.bottom - srcBlitRect.bottom; 
  1132.         srcBlitRect.bottom = srcFrameP->frameRect.bottom;
  1133.         dstBlitRect.bottom += bottomClip2;
  1134.     }
  1135.  
  1136.     if (srcBlitRect.left > srcFrameP->frameRect.left)
  1137.     {
  1138.         leftClip2 = srcBlitRect.left - srcFrameP->frameRect.left;
  1139.         srcBlitRect.left = srcFrameP->frameRect.left;
  1140.         dstBlitRect.left -= leftClip2;
  1141.     }
  1142.     
  1143.     if (srcBlitRect.right < srcFrameP->frameRect.right)
  1144.     {
  1145.         rightClip2 = srcFrameP->frameRect.right - srcBlitRect.right; 
  1146.         srcBlitRect.right = srcFrameP->frameRect.right;
  1147.         dstBlitRect.right += rightClip2;
  1148.     }    
  1149.     
  1150.     topClip += topClip2;
  1151.     leftClip += leftClip2;
  1152.     rightClip += rightClip2;
  1153.     bottomClip += bottomClip2;
  1154.         
  1155.     // calculate the offset to the first byte of the source
  1156.     srcBaseOffset = srcFrameP->scanLinePtrArray[srcBlitRect.top - 
  1157.         srcFrameP->frameRect.top] + (srcBlitRect.left << 1);
  1158.  
  1159.     START_32_BIT_MODE
  1160.     
  1161.     PrecomputeLookupTable(
  1162.         (srcBlitRect.right - srcBlitRect.left),
  1163.         (dstBlitRect.right - dstBlitRect.left),
  1164.         leftClip, 
  1165.         rightClip);
  1166.  
  1167.  
  1168.     BlitPixieMask16BitScaled(
  1169.             // calculate the address of the first byte of the source
  1170.         (unsigned short *)(srcFrameP->frameBaseAddr + srcBaseOffset),
  1171.  
  1172.             // calculate the address of the first byte of the destination
  1173.         (unsigned short *)(dstFrameP->frameBaseAddr + 
  1174.             (dstFrameP->scanLinePtrArray[dstBlitRect.top]) + 
  1175.             (dstBlitRect.left << 1)),
  1176.  
  1177.             // calculate the address of the first byte of the mask
  1178.         (unsigned short *)(srcFrameP->maskBaseAddr + srcBaseOffset),
  1179.  
  1180.             // calculate the number of rows to blit
  1181.         srcBlitRect.bottom - srcBlitRect.top,
  1182.         dstBlitRect.bottom - dstBlitRect.top + topClip,  
  1183.  
  1184.         srcFrameP->frameRowBytes,
  1185.         dstFrameP->frameRowBytes,
  1186.         
  1187.             // clipping information
  1188.         leftClip,
  1189.         topClip,
  1190.         bottomClip
  1191.     );
  1192.     
  1193.  
  1194.     END_32_BIT_MODE
  1195. }
  1196.  
  1197.  
  1198. ///--------------------------------------------------------------------------------------
  1199. //    BlitPixie16BitScaled
  1200. ///--------------------------------------------------------------------------------------
  1201.  
  1202. void BlitPixie16BitScaled(
  1203.     unsigned short *srcPixelP,
  1204.     unsigned short *dstPixelP,
  1205.     register long srcRowsToCopy,
  1206.     register long dstRowsToCopy,
  1207.     register unsigned long srcOffset,
  1208.     register unsigned long dstOffset,
  1209.     short leftClip,
  1210.     short topClip,
  1211.     short bottomClip,
  1212.     short isBlittingToScreen)
  1213. {
  1214.     register unsigned short *startSrcPixelP;    // Stores the start of the
  1215.     register unsigned short *startDstPixelP;    // line currently being drawn
  1216.     long    verticalEps = 0;
  1217.     short    curRow, numRowsToCopy;
  1218.     
  1219.     startSrcPixelP = srcPixelP;
  1220.     startDstPixelP = dstPixelP;
  1221.     
  1222.     if (srcRowsToCopy >= dstRowsToCopy)
  1223.         verticalEps = srcRowsToCopy / 2;
  1224.     else
  1225.         verticalEps = -dstRowsToCopy / 2;
  1226.     
  1227.     // divide by 2 to get number of shorts from bytes
  1228.     srcOffset >>= 1;
  1229.     dstOffset >>= 1;
  1230.     
  1231.         // Clip off the top if necessary
  1232.     for (curRow = 0; curRow < topClip; curRow++)
  1233.     {
  1234.         if (srcRowsToCopy >= dstRowsToCopy) {
  1235.             while ((verticalEps * 2) <= srcRowsToCopy) {
  1236.                 // shrink
  1237.                 startSrcPixelP += srcOffset;    // Bump source to next row
  1238.                 verticalEps += dstRowsToCopy;
  1239.             }
  1240.             verticalEps -= srcRowsToCopy;
  1241.         } else {
  1242.             // grow
  1243.             verticalEps += srcRowsToCopy;
  1244.             if ((verticalEps * 2) > dstRowsToCopy)  {
  1245.                 startSrcPixelP += srcOffset;    // Bump source to next row
  1246.                 verticalEps -= dstRowsToCopy;
  1247.             }
  1248.         }
  1249.     }
  1250.  
  1251.         // Handle the bottom clip
  1252.     numRowsToCopy = dstRowsToCopy - bottomClip;
  1253.     
  1254.         // Draw the thing
  1255.     for (; curRow < numRowsToCopy; curRow++)
  1256.     {
  1257.         BlitScaledLine16Bit(startSrcPixelP + gSrcLeftClip, startDstPixelP + leftClip,
  1258.             isBlittingToScreen);
  1259.         
  1260.             // bump to next row    
  1261.         startDstPixelP += dstOffset;
  1262.  
  1263.         if (srcRowsToCopy >= dstRowsToCopy) {
  1264.             while ((verticalEps * 2) <= srcRowsToCopy) {
  1265.                 // shrink
  1266.                 startSrcPixelP += srcOffset;
  1267.                 verticalEps += dstRowsToCopy;
  1268.             }
  1269.             verticalEps -= srcRowsToCopy;
  1270.         } else {
  1271.             // grow
  1272.             verticalEps += srcRowsToCopy;
  1273.             if ((verticalEps * 2) > dstRowsToCopy)  {
  1274.                 startSrcPixelP += srcOffset;
  1275.                 verticalEps -= dstRowsToCopy;
  1276.             }
  1277.         }
  1278.     }
  1279. }
  1280.  
  1281.  
  1282. ///--------------------------------------------------------------------------------------
  1283. //    BlitPixieMask16BitScaled
  1284. ///--------------------------------------------------------------------------------------
  1285.  
  1286. void BlitPixieMask16BitScaled(
  1287.     unsigned short *srcPixelP,
  1288.     unsigned short *dstPixelP,
  1289.     unsigned short *maskPixelP,
  1290.     register long srcRowsToCopy,
  1291.     register long dstRowsToCopy,
  1292.     register unsigned long srcOffset,
  1293.     register unsigned long dstOffset,
  1294.     short leftClip,
  1295.     short topClip,
  1296.     short bottomClip)
  1297. {
  1298.     register unsigned short *startSrcPixelP;
  1299.     register unsigned short *startDstPixelP;
  1300.     register unsigned short *startMaskPixelP;
  1301.     long    verticalEps = 0;
  1302.     short    curRow, numRowsToCopy;
  1303.     
  1304.     startSrcPixelP = srcPixelP;
  1305.     startDstPixelP = dstPixelP;
  1306.     startMaskPixelP = maskPixelP;
  1307.     
  1308.     if (srcRowsToCopy >= dstRowsToCopy)
  1309.         verticalEps = srcRowsToCopy / 2;
  1310.     else
  1311.         verticalEps = -dstRowsToCopy / 2;
  1312.  
  1313.     // divide by 2 to get number of shorts from bytes
  1314.     srcOffset >>= 1;
  1315.     dstOffset >>= 1;
  1316.     
  1317.         // Clip off the top if necessary
  1318.     for (curRow = 0; curRow < topClip; curRow++)
  1319.     {
  1320.         if (srcRowsToCopy >= dstRowsToCopy) {
  1321.             while ((verticalEps * 2) <= srcRowsToCopy) {
  1322.                 // shrink
  1323.                 startSrcPixelP += srcOffset;
  1324.                 startMaskPixelP += srcOffset;
  1325.                 verticalEps += dstRowsToCopy;
  1326.             }
  1327.             verticalEps -= srcRowsToCopy;
  1328.         } else {
  1329.             // grow
  1330.             verticalEps += srcRowsToCopy;
  1331.             if ((verticalEps * 2) > dstRowsToCopy)  {
  1332.                 startSrcPixelP += srcOffset;
  1333.                 startMaskPixelP += srcOffset;
  1334.                 verticalEps -= dstRowsToCopy;
  1335.             }
  1336.         }
  1337.     }
  1338.  
  1339.         // Handle the bottom clip
  1340.     numRowsToCopy = dstRowsToCopy - bottomClip;
  1341.     
  1342.         // Draw the thing
  1343.     for (; curRow < numRowsToCopy; curRow++)
  1344.     {
  1345.         BlitScaledMaskedLine16Bit(startSrcPixelP + gSrcLeftClip, startMaskPixelP + gSrcLeftClip,
  1346.             startDstPixelP + leftClip);
  1347.         
  1348.             // bump to next row    
  1349.         startDstPixelP += dstOffset;
  1350.  
  1351.         if (srcRowsToCopy >= dstRowsToCopy) {
  1352.             while ((verticalEps * 2) <= srcRowsToCopy) {
  1353.                 // shrink
  1354.                 startSrcPixelP += srcOffset;
  1355.                 startMaskPixelP += srcOffset;
  1356.                 verticalEps += dstRowsToCopy;
  1357.             }
  1358.             verticalEps -= srcRowsToCopy;
  1359.         } else {
  1360.             // grow
  1361.             verticalEps += srcRowsToCopy;
  1362.             if ((verticalEps * 2) > dstRowsToCopy)  {
  1363.                 startSrcPixelP += srcOffset;
  1364.                 startMaskPixelP += srcOffset;
  1365.                 verticalEps -= dstRowsToCopy;
  1366.             }
  1367.         }
  1368.     }
  1369. }
  1370.  
  1371.  
  1372. ///--------------------------------------------------------------------------------------
  1373. //    BlitScaledLine16Bit - it makes it slightly faster on 68k Macs to put this code in its
  1374. //  own function, instead of placing it directly in BlitPixie16BitScaled. It goes the
  1375. //    same speed on PPC. This must be because we're "breaking the cache" on 68k Macs otherwise.
  1376. ///--------------------------------------------------------------------------------------
  1377.  
  1378. void BlitScaledLine16Bit(
  1379.     register unsigned short *srcPixelP,
  1380.     register unsigned short *dstPixelP,
  1381.     Boolean weAreBlittingToScreen)
  1382. {
  1383.     register unsigned short *lookupArrayP;
  1384.     short    numPixelsToCopy;
  1385.  
  1386.     lookupArrayP = gLookupArray;
  1387.     
  1388.     numPixelsToCopy = gNumPixelsToCopy;
  1389.  
  1390.         // The following code speeds up direct-to-screen blits, since we can make maximum
  1391.         // use of the bus.
  1392.     if (weAreBlittingToScreen)
  1393.     {
  1394.         unsigned long    srcBuffer;
  1395.         register unsigned short  *srcBufferPixelP;
  1396.         
  1397.         
  1398.         while (numPixelsToCopy >= 2) 
  1399.         {
  1400.                 // Get char pointers to our 4-byte buffers
  1401.             srcBufferPixelP = (unsigned short *)&srcBuffer;
  1402.             
  1403.                 // Load 1st pixel into buffer
  1404.             srcPixelP += *lookupArrayP;
  1405.             *srcBufferPixelP++ = *srcPixelP;
  1406.             lookupArrayP++;
  1407.             
  1408.                 // Load 2nd pixel into buffer
  1409.             srcPixelP += *lookupArrayP;
  1410.             *srcBufferPixelP = *srcPixelP;
  1411.             lookupArrayP++;
  1412.  
  1413.                 // Copy from our 4-byte buffer to the destination
  1414.             *((unsigned long *) dstPixelP)++ = srcBuffer;
  1415.             
  1416.             numPixelsToCopy -= 2;
  1417.         }
  1418.     }
  1419.     
  1420.  
  1421.         // Finish any part of the line not drawn above, or draw the entire line if necessary
  1422.     while (numPixelsToCopy--) 
  1423.     {
  1424.         srcPixelP += *lookupArrayP;
  1425.         lookupArrayP++;
  1426.         
  1427.         *dstPixelP = *srcPixelP;
  1428.         dstPixelP++;
  1429.     }
  1430. }
  1431.  
  1432.  
  1433. ///--------------------------------------------------------------------------------------
  1434. //    BlitScaledMaskedLine16Bit - it makes it slightly faster on 68k Macs to put this code in its
  1435. //  own function, instead of placing it directly in BlitPixieMask16BitScaled. It goes the
  1436. //    same speed on PPC. This must be because we're "breaking the cache" on 68k Macs otherwise.
  1437. ///--------------------------------------------------------------------------------------
  1438.  
  1439. void BlitScaledMaskedLine16Bit(
  1440.     register unsigned short *srcPixelP,
  1441.     register unsigned short *maskPixelP,
  1442.     register unsigned short *dstPixelP)
  1443. {
  1444.     register unsigned short *lookupArrayP;
  1445.     register short            numPixelsToCopy;
  1446.  
  1447.     lookupArrayP = gLookupArray;
  1448.     
  1449.     numPixelsToCopy = gNumPixelsToCopy;
  1450.  
  1451.         // Draw the line
  1452.     while (numPixelsToCopy--) 
  1453.     {
  1454.         srcPixelP += *lookupArrayP;
  1455.         maskPixelP += *lookupArrayP;
  1456.         
  1457.         if (*maskPixelP == 0)
  1458.             *dstPixelP = *srcPixelP;
  1459.         
  1460.         dstPixelP++;
  1461.         lookupArrayP++;
  1462.     }
  1463. }
  1464.  
  1465.  
  1466.  
  1467. #pragma mark ----------- Misc -------------
  1468. ///--------------------------------------------------------------------------------------
  1469. //    PrecomputeLookupTable - calculates the data used to speed up the scaling blitter
  1470. ///--------------------------------------------------------------------------------------
  1471.  
  1472. void PrecomputeLookupTable(
  1473.     register long srcNumPixelsPerRow,
  1474.     register long dstNumPixelsPerRow,
  1475.     short leftClip,
  1476.     short rightClip)
  1477. {
  1478.     register short    numDstPixelsToDraw, eps;
  1479.     register short    destIndex, srcIndex, srcAccum;
  1480.  
  1481.     if (srcNumPixelsPerRow >= dstNumPixelsPerRow)
  1482.     {
  1483.             // Shrink it. For now we don't do any pixel blending for this case.
  1484.         destIndex = 0;
  1485.         eps = srcNumPixelsPerRow / 2;
  1486.  
  1487.             // Clip off the left if necessary
  1488.         for (srcIndex = 0; destIndex < leftClip && srcIndex < srcNumPixelsPerRow; srcIndex++)
  1489.         {
  1490.             eps += dstNumPixelsPerRow;
  1491.             if ( (eps << 1) > srcNumPixelsPerRow ) 
  1492.             {
  1493.                 destIndex++;
  1494.                 eps -= srcNumPixelsPerRow;
  1495.             }
  1496.         }
  1497.         
  1498.             // Store the left clip of the source
  1499.         gSrcLeftClip = srcIndex;
  1500.         
  1501.             // Clip off the right
  1502.         numDstPixelsToDraw = dstNumPixelsPerRow - rightClip;
  1503.         
  1504.             // This lets us reset dstIndex to 0
  1505.         numDstPixelsToDraw -= destIndex;
  1506.         SW_ASSERT(numDstPixelsToDraw > 0);
  1507.         SW_ASSERT(numDstPixelsToDraw <= kMaxScaledWidth);
  1508.         
  1509.         gNumPixelsToCopy = numDstPixelsToDraw;
  1510.         destIndex = 0;
  1511.         srcAccum = 0;
  1512.         
  1513.             // Bresenham line draw
  1514.         while (srcIndex < srcNumPixelsPerRow && destIndex < numDstPixelsToDraw) 
  1515.         {
  1516.             eps += dstNumPixelsPerRow;
  1517.             if ( (eps << 1) > srcNumPixelsPerRow ) 
  1518.             {
  1519.                 gLookupArray[destIndex] = srcAccum;
  1520.                 destIndex++;
  1521.                 srcAccum = 0;
  1522.                 eps -= srcNumPixelsPerRow;
  1523.             }
  1524.             srcAccum++;
  1525.             srcIndex++;
  1526.         }
  1527.     }
  1528.     else
  1529.     {
  1530.             // Stretch It. For now we don't do any anti aliasing for this case.
  1531.         srcIndex = 0;
  1532.         eps = -dstNumPixelsPerRow / 2;
  1533.         
  1534.             // Clip off the left if necessary
  1535.         for (destIndex = 0; destIndex < leftClip; destIndex++)
  1536.         {
  1537.             eps += srcNumPixelsPerRow;
  1538.             if ( (eps << 1) > dstNumPixelsPerRow )
  1539.             {
  1540.                 srcIndex++;
  1541.                 eps -= dstNumPixelsPerRow;
  1542.             }
  1543.         }
  1544.         
  1545.             // Store the left clip of the source
  1546.         gSrcLeftClip = srcIndex;
  1547.         
  1548.             // Clip off the right
  1549.         numDstPixelsToDraw = dstNumPixelsPerRow - rightClip;
  1550.     
  1551.             // This lets us reset dstIndex to 0
  1552.         numDstPixelsToDraw -= destIndex;
  1553.         SW_ASSERT(numDstPixelsToDraw > 0);
  1554.         SW_ASSERT(numDstPixelsToDraw <= kMaxScaledWidth);
  1555.         
  1556.         gNumPixelsToCopy = numDstPixelsToDraw;
  1557.         destIndex = 0;
  1558.         srcAccum = 0;
  1559.         
  1560.             // Use Bresenham's line drawing algorithm to store the values in gLookupArray
  1561.         while (destIndex < numDstPixelsToDraw)
  1562.         {
  1563.             gLookupArray[destIndex] = srcAccum;
  1564.             eps += srcNumPixelsPerRow;
  1565.             if ( (eps << 1) > dstNumPixelsPerRow )
  1566.             {
  1567.                 srcIndex++;
  1568.                 srcAccum = 1;
  1569.                 eps -= dstNumPixelsPerRow;
  1570.             }
  1571.             else
  1572.                 srcAccum = 0;
  1573.             destIndex++;
  1574.         }
  1575.     }
  1576. }
  1577.  
  1578.