home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1999 Spring / macformat-077.iso / Shareware Plus / Development / SpriteWorld 2.2 / SpriteWorld files / Utils / SWFastLine.c < prev    next >
Encoding:
Text File  |  1999-01-01  |  57.3 KB  |  2,096 lines  |  [TEXT/CWIE]

  1. ///--------------------------------------------------------------------------------------
  2. //    SWFastLine.c
  3. //
  4. //    Everything except BlitLine68kAsm is by Vern Jensen, 12/21/98. 
  5. //    BlitLine68kAsm is by Oleg Doperchuk, and is believed to be in the public domain.
  6. //    Thanks to Alex Ni for getting it to compile under CodeWarrior.
  7. ///--------------------------------------------------------------------------------------
  8.  
  9. #include "SWFastLine.h"
  10.  
  11. #define SIGN(x) ((x) < 0 ? -1 : ((x) > 0 ? 1 : 0))
  12. #define ABS(x) ((x) < 0 ? -(x) : (x))
  13.  
  14.  
  15. #if !SW_PPC
  16. ///--------------------------------------------------------------------------------------
  17. //    SWDrawLine68kAsm - warning, no clipping is performed by this function!
  18. ///--------------------------------------------------------------------------------------
  19.  
  20. SW_FUNC void SWDrawLine68kAsm(
  21.     FramePtr dstFrameP, 
  22.     Point srcPoint, 
  23.     Point dstPoint, 
  24.     Byte color)
  25. {
  26.     Ptr                baseAddr = dstFrameP->frameBaseAddr + dstFrameP->scanLinePtrArray[0];
  27.     unsigned long    rowBytes = dstFrameP->frameRowBytes;
  28.     
  29.     SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
  30.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
  31.     SW_ASSERT(srcPoint.h >= dstFrameP->frameRect.left && srcPoint.h < dstFrameP->frameRect.right);
  32.     SW_ASSERT(srcPoint.v >= dstFrameP->frameRect.top && srcPoint.v < dstFrameP->frameRect.bottom);
  33.     SW_ASSERT(dstPoint.h >= dstFrameP->frameRect.left && dstPoint.h < dstFrameP->frameRect.right);
  34.     SW_ASSERT(dstPoint.v >= dstFrameP->frameRect.top && dstPoint.v < dstFrameP->frameRect.bottom);
  35.     
  36.     START_32_BIT_MODE
  37.     
  38.     BlitLine68kAsm(baseAddr, rowBytes, srcPoint.h, dstPoint.h, srcPoint.v, dstPoint.v, color);
  39.  
  40.     END_32_BIT_MODE
  41. }
  42. #endif
  43.  
  44.  
  45. ///--------------------------------------------------------------------------------------
  46. //  SWDrawLine
  47. ///--------------------------------------------------------------------------------------
  48.  
  49. SW_FUNC void SWDrawLine(
  50.     FramePtr dstFrameP, 
  51.     Point srcPoint, 
  52.     Point dstPoint, 
  53.     Byte color)
  54. {
  55.     Boolean        thereIsALine = true;
  56.     
  57.     SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
  58.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
  59.     START_32_BIT_MODE
  60.     
  61.         // Check to see if the line is straight horizontally or vertically
  62.     if (srcPoint.v == dstPoint.v || srcPoint.h == dstPoint.h)
  63.     {
  64.         BlitStraightLine(dstFrameP, srcPoint, dstPoint, color);
  65.     }
  66.     else
  67.     {
  68.             // Clip the line with the frameRect
  69.         thereIsALine = SWClipLineWithRect(&srcPoint, &dstPoint, &dstFrameP->frameRect);
  70.         
  71.         if (thereIsALine)
  72.             BlitLine(dstFrameP, srcPoint, dstPoint, color);
  73.     }
  74.     
  75.     END_32_BIT_MODE
  76. }
  77.  
  78.  
  79. ///--------------------------------------------------------------------------------------
  80. //  SWCopyLine
  81. ///--------------------------------------------------------------------------------------
  82.  
  83. SW_FUNC void SWCopyLine(
  84.     FramePtr srcFrameP, 
  85.     FramePtr dstFrameP, 
  86.     Point srcPoint, 
  87.     Point dstPoint)
  88. {
  89.     Boolean        thereIsALine = true;
  90.     
  91.     SW_ASSERT(srcFrameP != NULL && srcFrameP->isFrameLocked);
  92.     SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
  93.     SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
  94.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
  95.     START_32_BIT_MODE
  96.     
  97.         // Check to see if the line is straight horizontally or vertically
  98.     if (srcPoint.v == dstPoint.v || srcPoint.h == dstPoint.h)
  99.     {
  100.         BPCopyStraightLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
  101.     }
  102.     else
  103.     {
  104.             // Clip the line with the dstFrameP->frameRect
  105.         thereIsALine = SWClipLineWithRect(&srcPoint, &dstPoint, &dstFrameP->frameRect);
  106.         
  107.         if (thereIsALine)
  108.             BPCopyLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
  109.     }
  110.     
  111.     END_32_BIT_MODE
  112. }
  113.  
  114.  
  115. ///--------------------------------------------------------------------------------------
  116. //  SWDrawFrameRect
  117. ///--------------------------------------------------------------------------------------
  118.  
  119. SW_FUNC void SWDrawFrameRect(
  120.     FramePtr dstFrameP, 
  121.     Rect *dstRectP, 
  122.     Byte color)
  123. {
  124.     Point    srcPoint, dstPoint;
  125.     Rect    destRect = *dstRectP;
  126.     
  127.     SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
  128.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
  129.     START_32_BIT_MODE
  130.     
  131.         // Swap things around if they're in the wrong order
  132.     if (destRect.right < destRect.left)
  133.     {
  134.         destRect.right = destRect.left;
  135.         destRect.left = dstRectP->right;
  136.     }
  137.     
  138.     if (destRect.bottom < destRect.top)
  139.     {
  140.         destRect.bottom = destRect.top;
  141.         destRect.top = dstRectP->bottom;
  142.     }
  143.     
  144.         // Clip destRect with dstFrameP->frameRect
  145.     if (destRect.top < dstFrameP->frameRect.top)
  146.         destRect.top = dstFrameP->frameRect.top;
  147.     if (destRect.bottom > dstFrameP->frameRect.bottom)
  148.         destRect.bottom = dstFrameP->frameRect.bottom;
  149.     if (destRect.left < dstFrameP->frameRect.left)
  150.         destRect.left = dstFrameP->frameRect.left;
  151.     if (destRect.right > dstFrameP->frameRect.right)
  152.         destRect.right = dstFrameP->frameRect.right;
  153.     
  154.     if (destRect.right <= destRect.left || destRect.bottom <= destRect.top)
  155.         return;
  156.     
  157.     
  158.         // Draw top side
  159.     srcPoint.h = destRect.left;
  160.     srcPoint.v = destRect.top;
  161.     dstPoint.h = destRect.right-1;
  162.     dstPoint.v = destRect.top;
  163.     BlitStraightLine(dstFrameP, srcPoint, dstPoint, color);
  164.     
  165.         // Draw right side
  166.     srcPoint.h = destRect.right-1;
  167.     dstPoint.v = destRect.bottom-1;
  168.     BlitStraightLine(dstFrameP, srcPoint, dstPoint, color);
  169.     
  170.         // Draw bottom side
  171.     srcPoint.h = destRect.left;
  172.     srcPoint.v = destRect.bottom-1;
  173.     BlitStraightLine(dstFrameP, srcPoint, dstPoint, color);
  174.     
  175.         // Draw left side
  176.     srcPoint.v = destRect.top;
  177.     dstPoint.h = destRect.left;
  178.     BlitStraightLine(dstFrameP, srcPoint, dstPoint, color);
  179.     
  180.     END_32_BIT_MODE
  181. }
  182.  
  183.  
  184. ///--------------------------------------------------------------------------------------
  185. //  SWCopyFrameRect
  186. ///--------------------------------------------------------------------------------------
  187.  
  188. SW_FUNC void SWCopyFrameRect(
  189.     FramePtr srcFrameP,
  190.     FramePtr dstFrameP, 
  191.     Rect *dstRectP)
  192. {
  193.     Point    srcPoint, dstPoint;
  194.     Rect    destRect = *dstRectP;
  195.     
  196.     SW_ASSERT(srcFrameP != NULL && srcFrameP->isFrameLocked);
  197.     SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
  198.     SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
  199.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
  200.     START_32_BIT_MODE
  201.     
  202.         // Swap things around if they're in the wrong order
  203.     if (destRect.right < destRect.left)
  204.     {
  205.         destRect.right = destRect.left;
  206.         destRect.left = dstRectP->right;
  207.     }
  208.     
  209.     if (destRect.bottom < destRect.top)
  210.     {
  211.         destRect.bottom = destRect.top;
  212.         destRect.top = dstRectP->bottom;
  213.     }
  214.     
  215.         // Clip destRect with dstFrameP->frameRect
  216.     if (destRect.top < dstFrameP->frameRect.top)
  217.         destRect.top = dstFrameP->frameRect.top;
  218.     if (destRect.bottom > dstFrameP->frameRect.bottom)
  219.         destRect.bottom = dstFrameP->frameRect.bottom;
  220.     if (destRect.left < dstFrameP->frameRect.left)
  221.         destRect.left = dstFrameP->frameRect.left;
  222.     if (destRect.right > dstFrameP->frameRect.right)
  223.         destRect.right = dstFrameP->frameRect.right;
  224.     
  225.     if (destRect.right <= destRect.left || destRect.bottom <= destRect.top)
  226.         return;
  227.     
  228.     
  229.         // Draw top side
  230.     srcPoint.h = destRect.left;
  231.     srcPoint.v = destRect.top;
  232.     dstPoint.h = destRect.right-1;
  233.     dstPoint.v = destRect.top;
  234.     BPCopyStraightLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
  235.     
  236.         // Draw right side
  237.     srcPoint.h = destRect.right-1;
  238.     dstPoint.v = destRect.bottom-1;
  239.     BPCopyStraightLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
  240.     
  241.         // Draw bottom side
  242.     srcPoint.h = destRect.left;
  243.     srcPoint.v = destRect.bottom-1;
  244.     BPCopyStraightLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
  245.     
  246.         // Draw left side
  247.     srcPoint.v = destRect.top;
  248.     dstPoint.h = destRect.left;
  249.     BPCopyStraightLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
  250.     
  251.     END_32_BIT_MODE
  252. }
  253.  
  254.  
  255. ///--------------------------------------------------------------------------------------
  256. //  SWDrawLineInScrollingWorld - clips drawing to the visScrollRect
  257. ///--------------------------------------------------------------------------------------
  258.  
  259. SW_FUNC void SWDrawLineInScrollingWorld(
  260.     SpriteWorldPtr spriteWorldP, 
  261.     FramePtr dstFrameP, 
  262.     Point srcPoint, 
  263.     Point dstPoint, 
  264.     Byte color)
  265. {
  266.     Boolean        thereIsALine;
  267.     Rect        frameRect = dstFrameP->frameRect;
  268.     
  269.     SW_ASSERT(spriteWorldP != NULL);
  270.     SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
  271.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
  272.     START_32_BIT_MODE
  273.     
  274.         // Check to see if the line is straight horizontally or vertically
  275.     if (srcPoint.v == dstPoint.v || srcPoint.h == dstPoint.h)
  276.     {
  277.         Rect    visScrollRect = spriteWorldP->visScrollRect;
  278.         
  279.             // Clip the line with the visScrollRect
  280.         if (srcPoint.v < visScrollRect.top)        srcPoint.v = visScrollRect.top;
  281.         if (dstPoint.v < visScrollRect.top)        dstPoint.v = visScrollRect.top;
  282.         if (srcPoint.v >= visScrollRect.bottom)    srcPoint.v = visScrollRect.bottom-1;
  283.         if (dstPoint.v >= visScrollRect.bottom)    dstPoint.v = visScrollRect.bottom-1;
  284.         if (srcPoint.h < visScrollRect.left)    srcPoint.h = visScrollRect.left;
  285.         if (dstPoint.h < visScrollRect.left)    dstPoint.h = visScrollRect.left;
  286.         if (srcPoint.h >= visScrollRect.right)    srcPoint.h = visScrollRect.right-1;
  287.         if (dstPoint.h >= visScrollRect.right)    dstPoint.h = visScrollRect.right-1;
  288.         
  289.             // Make the line's points local to the offscreen area
  290.         srcPoint.h -= spriteWorldP->horizScrollRectOffset;
  291.         srcPoint.v -= spriteWorldP->vertScrollRectOffset;
  292.         dstPoint.h -= spriteWorldP->horizScrollRectOffset;
  293.         dstPoint.v -= spriteWorldP->vertScrollRectOffset;
  294.         
  295.             // Determine whether to call the wrapping or non-wrapping version
  296.         if (srcPoint.h >= frameRect.left && srcPoint.h < frameRect.right && 
  297.             dstPoint.h >= frameRect.left && dstPoint.h < frameRect.right &&
  298.             srcPoint.v >= frameRect.top && srcPoint.v < frameRect.bottom &&
  299.             dstPoint.v >= frameRect.top && dstPoint.v < frameRect.bottom)
  300.         {
  301.                 // The line is contained entirely inside the dstFrameP
  302.             BlitStraightLine(dstFrameP, srcPoint, dstPoint, color);
  303.         }
  304.         else
  305.         {
  306.                 // The line needs wrapping
  307.             BlitStraightWrappingLine(dstFrameP, srcPoint, dstPoint, color);
  308.         }
  309.     }
  310.     else
  311.     {
  312.             // Clip the line with the visScrollRect
  313.         thereIsALine = SWClipLineWithRect(&srcPoint, &dstPoint, &spriteWorldP->visScrollRect);
  314.         
  315.             // Make the line's points local to the offscreen area
  316.         srcPoint.h -= spriteWorldP->horizScrollRectOffset;
  317.         srcPoint.v -= spriteWorldP->vertScrollRectOffset;
  318.         dstPoint.h -= spriteWorldP->horizScrollRectOffset;
  319.         dstPoint.v -= spriteWorldP->vertScrollRectOffset;
  320.         
  321.         if (thereIsALine)
  322.         {
  323.                 // Determine whether to call the wrapping or non-wrapping version
  324.             if (srcPoint.h >= frameRect.left && srcPoint.h < frameRect.right && 
  325.                 dstPoint.h >= frameRect.left && dstPoint.h < frameRect.right &&
  326.                 srcPoint.v >= frameRect.top && srcPoint.v < frameRect.bottom &&
  327.                 dstPoint.v >= frameRect.top && dstPoint.v < frameRect.bottom)
  328.             {
  329.                     // The line is contained entirely inside the dstFrameP
  330.                 BlitLine(dstFrameP, srcPoint, dstPoint, color);
  331.             }
  332.             else
  333.             {
  334.                     // The line needs wrapping
  335.                 BlitWrappingLine(dstFrameP, srcPoint, dstPoint, color);
  336.             }
  337.         }
  338.     }
  339.     
  340.     END_32_BIT_MODE
  341. }
  342.  
  343.  
  344. ///--------------------------------------------------------------------------------------
  345. //  SWCopyLineInScrollingWorld - clips drawing to the visScrollRect
  346. ///--------------------------------------------------------------------------------------
  347.  
  348. SW_FUNC void SWCopyLineInScrollingWorld(
  349.     SpriteWorldPtr spriteWorldP, 
  350.     FramePtr srcFrameP, 
  351.     FramePtr dstFrameP, 
  352.     Point srcPoint, 
  353.     Point dstPoint,
  354.     Rect *clipRectP)
  355. {
  356.     Boolean        thereIsALine;
  357.     Rect        frameRect = dstFrameP->frameRect;
  358.     short        vertScrollRectOffset, horizScrollRectOffset;
  359.     
  360.     SW_ASSERT(spriteWorldP != NULL);
  361.     SW_ASSERT(srcFrameP != NULL && srcFrameP->isFrameLocked);
  362.     SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
  363.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
  364.     START_32_BIT_MODE
  365.     
  366.         // ClipRectP should be either the visScrollRect or oldVisScrollRect
  367.     vertScrollRectOffset = spriteWorldP->backRect.bottom * 
  368.         (clipRectP->top / spriteWorldP->backRect.bottom);
  369.  
  370.     horizScrollRectOffset = spriteWorldP->backRect.right *
  371.         (clipRectP->left / spriteWorldP->backRect.right);
  372.     
  373.         // Check to see if the line is straight horizontally or vertically
  374.     if (srcPoint.v == dstPoint.v || srcPoint.h == dstPoint.h)
  375.     {
  376.             // Clip the line with the visScrollRect
  377.         if (srcPoint.v < clipRectP->top)        srcPoint.v = clipRectP->top;
  378.         if (dstPoint.v < clipRectP->top)        dstPoint.v = clipRectP->top;
  379.         if (srcPoint.v >= clipRectP->bottom)    srcPoint.v = clipRectP->bottom-1;
  380.         if (dstPoint.v >= clipRectP->bottom)    dstPoint.v = clipRectP->bottom-1;
  381.         if (srcPoint.h < clipRectP->left)        srcPoint.h = clipRectP->left;
  382.         if (dstPoint.h < clipRectP->left)        dstPoint.h = clipRectP->left;
  383.         if (srcPoint.h >= clipRectP->right)        srcPoint.h = clipRectP->right-1;
  384.         if (dstPoint.h >= clipRectP->right)        dstPoint.h = clipRectP->right-1;
  385.         
  386.             // Make the line's points local to the offscreen area
  387.         srcPoint.h -= horizScrollRectOffset;
  388.         srcPoint.v -= vertScrollRectOffset;
  389.         dstPoint.h -= horizScrollRectOffset;
  390.         dstPoint.v -= vertScrollRectOffset;
  391.         
  392.             // Determine whether to call the wrapping or non-wrapping version
  393.         if (srcPoint.h >= frameRect.left && srcPoint.h < frameRect.right && 
  394.             dstPoint.h >= frameRect.left && dstPoint.h < frameRect.right &&
  395.             srcPoint.v >= frameRect.top && srcPoint.v < frameRect.bottom &&
  396.             dstPoint.v >= frameRect.top && dstPoint.v < frameRect.bottom)
  397.         {
  398.                 // The line is contained entirely inside the dstFrameP
  399.             BPCopyStraightLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
  400.         }
  401.         else
  402.         {
  403.                 // The line needs wrapping
  404.             BPCopyStraightWrappingLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
  405.         }
  406.     }
  407.     else
  408.     {
  409.             // Clip the line with clipRectP (visScrollRect or oldVisScrollRect)
  410.         thereIsALine = SWClipLineWithRect(&srcPoint, &dstPoint, clipRectP);
  411.         
  412.             // Make the line's points local to the offscreen area
  413.         srcPoint.h -= horizScrollRectOffset;
  414.         srcPoint.v -= vertScrollRectOffset;
  415.         dstPoint.h -= horizScrollRectOffset;
  416.         dstPoint.v -= vertScrollRectOffset;
  417.         
  418.         if (thereIsALine)
  419.         {
  420.                 // Determine whether to call the wrapping or non-wrapping version
  421.             if (srcPoint.h >= frameRect.left && srcPoint.h < frameRect.right && 
  422.                 dstPoint.h >= frameRect.left && dstPoint.h < frameRect.right &&
  423.                 srcPoint.v >= frameRect.top && srcPoint.v < frameRect.bottom &&
  424.                 dstPoint.v >= frameRect.top && dstPoint.v < frameRect.bottom)
  425.             {
  426.                     // The line is contained entirely inside the frameRect
  427.                 BPCopyLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
  428.             }
  429.             else
  430.             {
  431.                     // The line needs wrapping
  432.                 BPCopyWrappingLine(srcFrameP, dstFrameP, srcPoint, dstPoint);
  433.             }
  434.         }
  435.     }
  436.     
  437.     END_32_BIT_MODE
  438. }
  439.  
  440.  
  441. ///--------------------------------------------------------------------------------------
  442. //  SWDrawFrameRectInScrollingWorld
  443. //    The dstFrameP should be either the work area or the background area.
  444. ///--------------------------------------------------------------------------------------
  445.  
  446. SW_FUNC void SWDrawFrameRectInScrollingWorld(
  447.     SpriteWorldPtr spriteWorldP, 
  448.     FramePtr dstFrameP, 
  449.     Rect *dstRectP, 
  450.     Byte color)
  451. {
  452.     Point            srcPoint, dstPoint;
  453.     Rect            destRect = *dstRectP;
  454.     Rect            frameRect = dstFrameP->frameRect;
  455.     Boolean            leftClipped, topClipped, rightClipped, bottomClipped;
  456.     BlitLineProcPtr    lineProcPtr;
  457.     
  458.     SW_ASSERT(spriteWorldP != NULL);
  459.     SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
  460.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
  461.     START_32_BIT_MODE
  462.     
  463.     leftClipped = topClipped = rightClipped = bottomClipped = false;
  464.     
  465.         // Clip destRect with spriteWorldP->visScrollRect
  466.     if (destRect.top < spriteWorldP->visScrollRect.top)
  467.     {
  468.         destRect.top = spriteWorldP->visScrollRect.top;
  469.         topClipped = true;
  470.     }
  471.     if (destRect.bottom > spriteWorldP->visScrollRect.bottom)
  472.     {
  473.         destRect.bottom = spriteWorldP->visScrollRect.bottom;
  474.         bottomClipped = true;
  475.     }
  476.     if (destRect.left < spriteWorldP->visScrollRect.left)
  477.     {
  478.         destRect.left = spriteWorldP->visScrollRect.left;
  479.         leftClipped = true;
  480.     }
  481.     if (destRect.right > spriteWorldP->visScrollRect.right)
  482.     {
  483.         destRect.right = spriteWorldP->visScrollRect.right;
  484.         rightClipped = true;
  485.     }
  486.         
  487.     if (destRect.right <= destRect.left || destRect.bottom <= destRect.top)
  488.         return;
  489.     
  490.     
  491.         // Make the line's points local to the offscreen area
  492.     destRect.left -= spriteWorldP->horizScrollRectOffset;
  493.     destRect.right -= spriteWorldP->horizScrollRectOffset;
  494.     destRect.top -= spriteWorldP->vertScrollRectOffset;
  495.     destRect.bottom -= spriteWorldP->vertScrollRectOffset;
  496.     
  497.         // Determine whether to call the wrapping or non-wrapping version
  498.     if (destRect.left >= frameRect.left && destRect.left < frameRect.right && 
  499.         destRect.right >= frameRect.left && destRect.right < frameRect.right &&
  500.         destRect.top >= frameRect.top && destRect.top < frameRect.bottom &&
  501.         destRect.bottom >= frameRect.top && destRect.bottom < frameRect.bottom)
  502.     {
  503.         lineProcPtr = BlitLine;     // The line is contained entirely inside the frameRect
  504.     }
  505.     else
  506.     {
  507.         lineProcPtr = BlitWrappingLine;    // The line needs wrapping
  508.     }
  509.     
  510.     
  511.         // Draw top side
  512.     srcPoint.h = destRect.left;
  513.     srcPoint.v = destRect.top;
  514.     dstPoint.h = destRect.right-1;
  515.     dstPoint.v = destRect.top;
  516.     if (!topClipped)
  517.         (*lineProcPtr)(dstFrameP, srcPoint, dstPoint, color);
  518.     
  519.         // Draw right side
  520.     srcPoint.h = destRect.right-1;
  521.     dstPoint.v = destRect.bottom-1;
  522.     if (!rightClipped)
  523.         (*lineProcPtr)(dstFrameP, srcPoint, dstPoint, color);
  524.     
  525.         // Draw bottom side
  526.     srcPoint.h = destRect.left;
  527.     srcPoint.v = destRect.bottom-1;
  528.     if (!bottomClipped)
  529.         (*lineProcPtr)(dstFrameP, srcPoint, dstPoint, color);
  530.     
  531.         // Draw left side
  532.     srcPoint.v = destRect.top;
  533.     dstPoint.h = destRect.left;
  534.     if (!leftClipped)
  535.         (*lineProcPtr)(dstFrameP, srcPoint, dstPoint, color);
  536.  
  537.     END_32_BIT_MODE
  538. }
  539.  
  540.  
  541. ///--------------------------------------------------------------------------------------
  542. //  SWCopyFrameRectInScrollingWorld
  543. //  The dstFrameP should be either the work area or the background area.
  544. ///--------------------------------------------------------------------------------------
  545.  
  546. SW_FUNC void SWCopyFrameRectInScrollingWorld(
  547.     SpriteWorldPtr spriteWorldP, 
  548.     FramePtr srcFrameP, 
  549.     FramePtr dstFrameP, 
  550.     Rect *dstRectP,
  551.     Rect *clipRectP)
  552. {
  553.     Point            srcPoint, dstPoint;
  554.     Rect            destRect = *dstRectP;
  555.     Rect            frameRect = dstFrameP->frameRect;
  556.     Boolean            leftClipped, topClipped, rightClipped, bottomClipped;
  557.     short            horizScrollRectOffset, vertScrollRectOffset;
  558.     CopyLineProcPtr    lineProcPtr;
  559.     
  560.     SW_ASSERT(spriteWorldP != NULL);
  561.     SW_ASSERT(srcFrameP != NULL && srcFrameP->isFrameLocked);
  562.     SW_ASSERT(dstFrameP != NULL && dstFrameP->isFrameLocked);
  563.     SW_ASSERT((*srcFrameP->framePort->portPixMap)->pixelSize == 8);
  564.     SW_ASSERT((*dstFrameP->framePort->portPixMap)->pixelSize == 8);
  565.     START_32_BIT_MODE
  566.     
  567.         // ClipRectP should be either the visScrollRect or oldVisScrollRect
  568.     vertScrollRectOffset = spriteWorldP->backRect.bottom * 
  569.         (clipRectP->top / spriteWorldP->backRect.bottom);
  570.  
  571.     horizScrollRectOffset = spriteWorldP->backRect.right *
  572.         (clipRectP->left / spriteWorldP->backRect.right);
  573.     
  574.     leftClipped = topClipped = rightClipped = bottomClipped = false;
  575.     
  576.         // Clip destRect with spriteWorldP->visScrollRect
  577.     if (destRect.top < clipRectP->top)
  578.     {
  579.         destRect.top = clipRectP->top;
  580.         topClipped = true;
  581.     }
  582.     if (destRect.bottom > clipRectP->bottom)
  583.     {
  584.         destRect.bottom = clipRectP->bottom;
  585.         bottomClipped = true;
  586.     }
  587.     if (destRect.left < clipRectP->left)
  588.     {
  589.         destRect.left = clipRectP->left;
  590.         leftClipped = true;
  591.     }
  592.     if (destRect.right > clipRectP->right)
  593.     {
  594.         destRect.right = clipRectP->right;
  595.         rightClipped = true;
  596.     }
  597.         
  598.     if (destRect.right <= destRect.left || destRect.bottom <= destRect.top)
  599.         return;
  600.     
  601.         // Make the line's points local to the offscreen area
  602.     destRect.left -= horizScrollRectOffset;
  603.     destRect.right -= horizScrollRectOffset;
  604.     destRect.top -= vertScrollRectOffset;
  605.     destRect.bottom -= vertScrollRectOffset;
  606.     
  607.         // Determine whether to call the wrapping or non-wrapping version
  608.     if (destRect.left >= frameRect.left && destRect.left < frameRect.right && 
  609.         destRect.right >= frameRect.left && destRect.right < frameRect.right &&
  610.         destRect.top >= frameRect.top && destRect.top < frameRect.bottom &&
  611.         destRect.bottom >= frameRect.top && destRect.bottom < frameRect.bottom)
  612.     {
  613.         lineProcPtr = BPCopyStraightLine; // The line is contained entirely inside the frameRect
  614.     }
  615.     else
  616.     {
  617.         lineProcPtr = BPCopyStraightWrappingLine;    // The line needs wrapping
  618.     }
  619.     
  620.     
  621.         // Draw top side
  622.     srcPoint.h = destRect.left;
  623.     srcPoint.v = destRect.top;
  624.     dstPoint.h = destRect.right-1;
  625.     dstPoint.v = destRect.top;
  626.     if (!topClipped)        // Draw top if it wasn't clipped
  627.         (*lineProcPtr)(srcFrameP, dstFrameP, srcPoint, dstPoint);
  628.     
  629.         // Draw right side
  630.     srcPoint.h = destRect.right-1;
  631.     dstPoint.v = destRect.bottom-1;
  632.     if (!rightClipped)    // Draw right if it wasn't clipped
  633.         (*lineProcPtr)(srcFrameP, dstFrameP, srcPoint, dstPoint);
  634.     
  635.         // Draw bottom side
  636.     srcPoint.h = destRect.left;
  637.     srcPoint.v = destRect.bottom-1;
  638.     if (!bottomClipped)    // Draw bottom if it wasn't clipped
  639.         (*lineProcPtr)(srcFrameP, dstFrameP, srcPoint, dstPoint);
  640.     
  641.         // Draw left side
  642.     srcPoint.v = destRect.top;
  643.     dstPoint.h = destRect.left;
  644.     if (!leftClipped)        // Draw left if it wasn't clipped
  645.         (*lineProcPtr)(srcFrameP, dstFrameP, srcPoint, dstPoint);
  646.     
  647.     END_32_BIT_MODE
  648. }
  649.  
  650.  
  651. #pragma mark -
  652. #pragma mark *** Diagonal Line Blitters:
  653. ///--------------------------------------------------------------------------------------
  654. //  SWClipLineWithRect    - Note: lines clipped with this routine will always be slightly
  655. //    different than the unclipped version, since the accum and dx or dy from this routine
  656. //    are not passed to the actual line drawing function.
  657. ///--------------------------------------------------------------------------------------
  658.  
  659. SW_FUNC Boolean SWClipLineWithRect(
  660.     Point *srcPoint, 
  661.     Point *dstPoint, 
  662.     Rect *clipRectP)
  663. {
  664.     short        x1 = srcPoint->h, y1 = srcPoint->v, 
  665.                 x2 = dstPoint->h, y2 = dstPoint->v;
  666.     short        dx, dy, sx, sy, accum;
  667.     short        lastX, lastY;
  668.     Boolean        x1IsInRect, y1IsInRect, x2IsInRect, y2IsInRect;
  669.     Boolean        foundStartPt, endPointIsInRect;
  670.     Rect        clipRect = *clipRectP;
  671.     
  672. //    InsetRect(&clipRect, 50, 50);    // Useful for testing
  673.     
  674.     x1IsInRect = (x1 >= clipRect.left && x1 < clipRect.right);
  675.     y1IsInRect = (y1 >= clipRect.top && y1 < clipRect.bottom);
  676.     x2IsInRect = (x2 >= clipRect.left && x2 < clipRect.right);
  677.     y2IsInRect = (y2 >= clipRect.top && y2 < clipRect.bottom);
  678.     
  679.         // If line needs no clipping, return
  680.     if (x1IsInRect && y1IsInRect && x2IsInRect && y2IsInRect)
  681.     {
  682.         return true;
  683.     }
  684.     
  685.     
  686.     dx = x2 - x1;
  687.     dy = y2 - y1;
  688.  
  689.     sx = SIGN(dx);
  690.     sy = SIGN(dy);
  691.     
  692.     dx = ABS(dx);
  693.     dy = ABS(dy);
  694.     
  695.     foundStartPt = false;
  696.     endPointIsInRect = false;
  697.     
  698.         // The possibilities are: A) Both start and end points are outside the rect.
  699.         // B) Only the start point is outside. C) Only the end point is outside.
  700.         // We know that at least one point is outside, since otherwise this function
  701.         // would have returned already.
  702.     
  703.         // Check first pixel in line
  704.     if (x1IsInRect && y1IsInRect)
  705.     {
  706.         foundStartPt = true;
  707.         lastX = x1;            // Store last point in line as well, in case only
  708.         lastY = y1;            // one pixel is inside the clipRect.
  709.     }
  710.     
  711.     if (x2IsInRect && y2IsInRect)
  712.     {
  713.         endPointIsInRect = true;
  714.     }
  715.     
  716.     
  717.     if (dx > dy)    // Longer horizontally than vertically
  718.     {
  719.         accum = dx >> 1;    // accum = dx/2;
  720.         while (x1 != x2)
  721.         {
  722.             accum -= dy;
  723.             if (accum < 0)
  724.             {
  725.                 accum += dx;
  726.                 y1 += sy;
  727.                 y1IsInRect = (y1 >= clipRect.top && y1 < clipRect.bottom);
  728.             }
  729.             x1 += sx;
  730.             x1IsInRect = (x1 >= clipRect.left && x1 < clipRect.right);
  731.             
  732.             if (x1IsInRect && y1IsInRect)    // Determine if current point is in rect
  733.             {
  734.                 if (foundStartPt == false)
  735.                 {
  736.                     srcPoint->h = x1;    // Store first point in line
  737.                     srcPoint->v = y1;
  738.                     foundStartPt = true;
  739.                     
  740.                     if (endPointIsInRect)
  741.                         return true; // Leave early, since we only needed to clip the first half
  742.                 }
  743.  
  744.                 lastX = x1;    // Store last point in line
  745.                 lastY = y1;    // (We keep doing this until we hit the end.)
  746.             }
  747.             else if (foundStartPt == true)
  748.             {
  749.                 break;    // the line is leaving clipRect, so break early to save time
  750.             }
  751.         }
  752.     } 
  753.     else     // Longer vertically than horizontally, or both equal in length
  754.     {
  755.         accum = dy >> 1;    // accum = dy/2;
  756.         while (y1 != y2)
  757.         {
  758.             accum -= dx;
  759.             if (accum < 0)
  760.             {
  761.                 accum += dy;
  762.                 x1 += sx;
  763.                 x1IsInRect = (x1 >= clipRect.left && x1 < clipRect.right);
  764.             }
  765.             y1 += sy;
  766.             y1IsInRect = (y1 >= clipRect.top && y1 < clipRect.bottom);
  767.             
  768.             if (x1IsInRect && y1IsInRect)    // Determine if current point is in rect
  769.             {
  770.                 if (foundStartPt == false)
  771.                 {
  772.                     srcPoint->h = x1;    // Store first point in line
  773.                     srcPoint->v = y1;
  774.                     foundStartPt = true;
  775.                     
  776.                     if (endPointIsInRect)
  777.                         return true; // Leave early, since we only needed to clip the first half
  778.                 }
  779.  
  780.                 lastX = x1;    // Store last point in line
  781.                 lastY = y1;    // (We keep doing this until we hit the end.)
  782.             }
  783.             else if (foundStartPt == true)
  784.             {
  785.                 break;    // the line is leaving clipRect, so break early to save time
  786.             }
  787.         }
  788.     }
  789.     
  790.         // Store last point in line
  791.     dstPoint->h = lastX;    // lastX is the pixel just before we ran into the pixel outside bounds
  792.     dstPoint->v = lastY;    
  793.     
  794.         // Tell caller if we ever found any point of the line inside clipRect
  795.     return foundStartPt;
  796. }
  797.  
  798.  
  799. #if !SW_PPC
  800. ///--------------------------------------------------------------------------------------
  801. //    BlitLine68kAsm - called by SWDrawLine68kAsm. Written by Oleg Doperchuk.
  802. ///--------------------------------------------------------------------------------------
  803.  
  804. SW_ASM_FUNC void BlitLine68kAsm
  805.     (Ptr baseAddr, 
  806.     unsigned long rowBytes, 
  807.     short x1, 
  808.     short x2, 
  809.     short y1, 
  810.     short y2, 
  811.     Byte color)
  812. {
  813.     SW_ASM_BEGIN
  814.  
  815. #if __MWERKS__
  816.         fralloc +
  817. #endif
  818.  
  819.         //dc.w 0xA9FF
  820.         movem.l d0-d7/a0-a6,-(a7)
  821.         moveq #0,d0
  822.         moveq #0,d1
  823.         moveq #0,d2
  824.         moveq #0,d3
  825.         move.w x1,d0
  826.         move.w y1,d1
  827.         move.w x2,d2
  828.         move.w y2,d3
  829.         sub.w d0,d2            // d2 = !x = ( x2 - x1 )
  830.         bpl.s @noswap
  831.         exg d1,d3            // swap endpoints
  832.         neg.w d2            // !x = -!x = ( x1 - x2 )
  833.         sub.w d2,d0            // d0 =  x1 - ( x1 - x2 ) = x2
  834. @noswap:
  835.         sub.w d1,d3            // d3 = !y = ( y2 - y1 )
  836.         move.l baseAddr,a0
  837.         move.l rowBytes,d6    
  838.         mulu.l d6,d1        
  839.         add.l d1,d0            
  840.         add.l d0,a0            // a0 = address of the first point to draw
  841.         move.b color,d7
  842. // now we can freely use d0/d1 
  843.         tst.w d3            // Line upward?
  844.         bmi @LineUp            // yes
  845.         beq @Horiz            // horizontal line
  846.         tst.w d2            // !x = 0 - vertical line downward
  847.         beq @VertDn
  848.         cmp.w d2,d3            // test line slope
  849.         beq @DiagDn            // slope = 1
  850.         bpl @SteepDn        // slope > 1
  851.  
  852.         moveq #0,d0            // lower 32bits    
  853.         divu.l d2,d3:d0        // d0 = 32bit ( !y/!x )        
  854.         moveq #0,d1            // accumulated error
  855. @FDLoop:
  856.         move.b d7,(a0)+        // Plot a point and move 1 pixel rightward
  857.         add.l d0,d1            // Add an accumulated error
  858.         bcs.s @FDCarry
  859.         dbra d2,@FDLoop        
  860.         bra @exit    
  861. @FDCarry:
  862.         add.l d6,a0            // One line down
  863.         dbra d2,@FDLoop
  864.         bra @exit    
  865. @DiagDn:
  866.         addq.l #1,d6        // Offset is rowbytes+1
  867. @DDLoop:
  868.         move.b d7,(a0)        // draw line
  869.         add.l d6,a0
  870.         dbra d2,@DDLoop
  871.         bra @exit
  872. @SteepDn:
  873.         moveq #0,d0
  874.         divu.l d3,d2:d0        // d0 = 32bit ( !x/!y )
  875.         moveq #0,d1            // accumulated error
  876. @SDLoop:
  877.         move.b d7,(a0)        // plot a point
  878.         add.l d6,a0            // move 1 pixel downward
  879.         add.l d0,d1            // Add an accumulated error
  880.         bcs.s @SDCarry
  881.         dbra d3,@SDLoop
  882.         bra @exit
  883. @SDCarry:
  884.         addq.l #1,a0
  885.         dbra d3,@SDLoop
  886.         bra @exit
  887. @Horiz:
  888.         move.b d7,(a0)+
  889.         dbra d2,@Horiz
  890.         bra @exit
  891. @VertDn:
  892.         move.b d7,(a0)        // offset is rowbytes
  893.         add.l d6,a0
  894.         dbra d3,@VertDn
  895.         bra @exit
  896. @LineUp:
  897.         neg.w d3    
  898.         tst.w d2
  899.         beq @VertUp        
  900.         cmp.w d2,d3
  901.         beq @DiagUp            // slope = -1
  902.         bpl @SteepUp        // slope < -1
  903.         
  904.         moveq #0,d0            // lower 32bits
  905.         divu.l d2,d3:d0        // d0 = 32bit ( !y/!x )        
  906.         moveq #0,d1            // accumulated error
  907. @FULoop:
  908.         move.b d7,(a0)+        // Plot a point and move 1 pixel rightward
  909.         add.l d0,d1            // Add an accumulated error
  910.         bcs.s @FUCarry
  911.         dbra d2,@FULoop        
  912.         bra @exit    
  913. @FUCarry:
  914.         sub.l d6,a0            // One line up
  915.         dbra d2,@FULoop
  916.         bra @exit    
  917. @DiagUp:
  918.         subq.l #1,d6        // offset is 1-rowbytes
  919. @DULoop:
  920.         move.b d7,(a0)        // draw line
  921.         sub.l d6,a0
  922.         dbra d2,@DULoop
  923.         bra @exit
  924. @SteepUp:
  925.         moveq #0,d0
  926.         divu.l d3,d2:d0        // d0 = 32bit ( !x/!y )
  927.         moveq #0,d1            // accumulated error
  928. @SULoop:
  929.         move.b d7,(a0)        // plot a point
  930.         sub.l d6,a0            // move 1 pixel upward
  931.         add.l d0,d1            // Add an accumulated error
  932.         bcs.s @SUCarry
  933.         dbra d3,@SULoop
  934.         bra @exit
  935. @SUCarry:
  936.         addq.l #1,a0
  937.         dbra d3,@SULoop
  938.         bra @exit
  939. @VertUp:
  940.         move.b d7,(a0)        // offset is -rowbytes
  941.         sub.l d6,a0
  942.         dbra d3,@VertUp
  943. @exit:    movem.l (a7)+,d0-d7/a0-a6
  944.     
  945. #if __MWERKS__
  946.         frfree
  947. #endif
  948.  
  949.     SW_ASM_END    
  950. }
  951. #endif
  952.  
  953.  
  954. ///--------------------------------------------------------------------------------------
  955. //  BlitLine - line-drawing code in C. Clipping must be done before this is called.
  956. ///--------------------------------------------------------------------------------------
  957.  
  958. SW_FUNC void BlitLine(
  959.     FramePtr dstFrameP, 
  960.     Point srcPoint, 
  961.     Point dstPoint, 
  962.     Byte color)
  963. {
  964.     register Ptr    baseAddr = dstFrameP->frameBaseAddr;
  965.     unsigned long    rowBytes = dstFrameP->frameRowBytes;
  966.     short            x1 = srcPoint.h, y1 = srcPoint.v, 
  967.                     x2 = dstPoint.h, y2 = dstPoint.v;
  968.     short            dx, dy, sx, sy, iy;
  969.     short            accum;
  970.     
  971.     dx = x2 - x1;
  972.     dy = y2 - y1;
  973.  
  974.     sx = SIGN(dx);
  975.     sy = SIGN(dy);
  976.     
  977.     dx = ABS(dx);
  978.     dy = ABS(dy);
  979.     
  980.     iy = (sy < 0) ? -rowBytes : rowBytes;
  981.     
  982.     baseAddr += dstFrameP->scanLinePtrArray[y1] + x1;
  983.     *baseAddr = color;    // Draw the first pixel
  984.     
  985.     if(dx > dy)        // Longer horizontally than vertically
  986.     {
  987.         accum = dx >> 1;
  988.         while(x1 != x2)
  989.         {
  990.             accum -= dy;
  991.             if(accum < 0)
  992.             {
  993.                 accum += dx;
  994.                 baseAddr += iy;
  995.             }
  996.             x1 += sx;
  997.             baseAddr += sx;
  998.             *baseAddr = color;
  999.         }
  1000.     } 
  1001.     else     // Longer vertically than horizontally, or both equal in length
  1002.     {
  1003.         accum = dy >> 1;
  1004.         while(y1 != y2)
  1005.         {
  1006.             accum -= dx;
  1007.             if(accum < 0)
  1008.             {
  1009.                 accum += dy;
  1010.                 baseAddr += sx;
  1011.             }
  1012.             y1 += sy;
  1013.             baseAddr += iy;
  1014.             *baseAddr = color;
  1015.         }
  1016.     }
  1017. }
  1018.  
  1019.  
  1020. ///--------------------------------------------------------------------------------------
  1021. //  BPCopyLine - line-drawing code in C. Clipping must be done before this is called.
  1022. ///--------------------------------------------------------------------------------------
  1023.  
  1024. SW_FUNC void BPCopyLine(
  1025.     FramePtr srcFrameP, 
  1026.     FramePtr dstFrameP, 
  1027.     Point srcPoint, 
  1028.     Point dstPoint)
  1029. {
  1030.     Ptr                srcBaseAddr = srcFrameP->frameBaseAddr;
  1031.     Ptr                dstBaseAddr = dstFrameP->frameBaseAddr;
  1032.     unsigned long    srcRowBytes = srcFrameP->frameRowBytes;
  1033.     unsigned long    dstRowBytes = dstFrameP->frameRowBytes;
  1034.     short            x1 = srcPoint.h, y1 = srcPoint.v, 
  1035.                     x2 = dstPoint.h, y2 = dstPoint.v;
  1036.     short            dx, dy, sx, sy, srciy, dstiy;
  1037.     short            accum;
  1038.     
  1039.     dx = x2 - x1;
  1040.     dy = y2 - y1;
  1041.  
  1042.     sx = SIGN(dx);
  1043.     sy = SIGN(dy);
  1044.     
  1045.     dx = ABS(dx);
  1046.     dy = ABS(dy);
  1047.     
  1048.     srcBaseAddr += srcFrameP->scanLinePtrArray[y1] + x1;
  1049.     dstBaseAddr += dstFrameP->scanLinePtrArray[y1] + x1;
  1050.     
  1051.         // Copy the first pixel in the line
  1052.     *dstBaseAddr = *srcBaseAddr;
  1053.     
  1054.     srciy = (sy < 0) ? -srcRowBytes : srcRowBytes;
  1055.     dstiy = (sy < 0) ? -dstRowBytes : dstRowBytes;
  1056.     
  1057.     
  1058.     if (dx > dy)        // Longer horizontally than vertically
  1059.     {
  1060.         accum = dx >> 1;
  1061.         while(x1 != x2)
  1062.         {
  1063.             accum -= dy;
  1064.             if(accum < 0)
  1065.             {
  1066.                 accum += dx;
  1067.                 srcBaseAddr += srciy;
  1068.                 dstBaseAddr += dstiy;
  1069.             }
  1070.             x1 += sx;
  1071.             srcBaseAddr += sx;
  1072.             dstBaseAddr += sx;
  1073.             *dstBaseAddr = *srcBaseAddr;
  1074.         }
  1075.     } 
  1076.     else     // Longer vertically than horizontally, or both equal in length
  1077.     {
  1078.         accum = dy >> 1;
  1079.         while(y1 != y2)
  1080.         {
  1081.             accum -= dx;
  1082.             if(accum < 0)
  1083.             {
  1084.                 accum += dy;
  1085.                 srcBaseAddr += sx;
  1086.                 dstBaseAddr += sx;
  1087.             }
  1088.             y1 += sy;
  1089.             srcBaseAddr += srciy;
  1090.             dstBaseAddr += dstiy;
  1091.             *dstBaseAddr = *srcBaseAddr;
  1092.         }
  1093.     }
  1094. }
  1095.  
  1096.  
  1097. ///--------------------------------------------------------------------------------------
  1098. //  BlitWrappingLine
  1099. ///--------------------------------------------------------------------------------------
  1100.  
  1101. SW_FUNC void BlitWrappingLine(
  1102.     FramePtr dstFrameP, 
  1103.     Point srcPoint, 
  1104.     Point dstPoint, 
  1105.     Byte color)
  1106. {
  1107.     Ptr                baseAddr;
  1108.     unsigned long    rowBytes = dstFrameP->frameRowBytes;
  1109.     unsigned long    vertOffset;
  1110.     short            x1 = srcPoint.h, y1 = srcPoint.v, 
  1111.                     x2 = dstPoint.h, y2 = dstPoint.v;
  1112.     short            dx, dy, sx, sy, iy;
  1113.     short            accum;
  1114.     Rect            frameRect = dstFrameP->frameRect;
  1115.     short            frameWidth, frameHeight;
  1116.     
  1117.     frameWidth = SW_RECT_WIDTH(frameRect);
  1118.     frameHeight = SW_RECT_HEIGHT(frameRect);
  1119.     
  1120.         // vertOffset = rowBytes * frameHeight;
  1121.     vertOffset = dstFrameP->scanLinePtrArray[dstFrameP->numScanLines-1] + rowBytes -
  1122.                  dstFrameP->scanLinePtrArray[0];
  1123.     
  1124.     dx = x2 - x1;
  1125.     dy = y2 - y1;
  1126.  
  1127.     sx = SIGN(dx);
  1128.     sy = SIGN(dy);
  1129.     
  1130.     dx = ABS(dx);
  1131.     dy = ABS(dy);
  1132.     
  1133.         // Even the very first pixel we draw might need to be wrapped before we draw it.
  1134.     if (y1 >= frameRect.bottom)
  1135.     {
  1136.         y1 -= frameHeight;
  1137.         y2 -= frameHeight;
  1138.     }
  1139.     else if (y1 < frameRect.top)
  1140.     {
  1141.         y1 += frameHeight;
  1142.         y2 += frameHeight;
  1143.     }
  1144.     
  1145.     if (x1 >= frameRect.right)
  1146.     {
  1147.         x1 -= frameWidth;
  1148.         x2 -= frameWidth;
  1149.     }
  1150.     else if (x1 < frameRect.left)
  1151.     {
  1152.         x1 += frameWidth;
  1153.         x2 += frameWidth;
  1154.     }
  1155.     
  1156.     baseAddr = dstFrameP->frameBaseAddr + dstFrameP->scanLinePtrArray[y1] + x1;
  1157.     *baseAddr = color;
  1158.     
  1159.     iy = (sy < 0) ? -rowBytes : rowBytes;
  1160.     
  1161.     if (dx > dy)        // Longer horizontally than vertically
  1162.     {
  1163.         accum = dx >> 1;    // accum = dx/2;
  1164.         while (x1 != x2)
  1165.         {
  1166.             accum -= dy;
  1167.             if (accum < 0)
  1168.             {
  1169.                 accum += dx;
  1170.                 y1 += sy;
  1171.                 baseAddr += iy;        // Move pixel up/down one row
  1172.                 
  1173.                 if (y1 >= frameRect.bottom)
  1174.                 {
  1175.                     y1 -= frameHeight;
  1176.                     y2 -= frameHeight;
  1177.                     baseAddr -= vertOffset;        // Jump to top side
  1178.                 }
  1179.                 else if (y1 < frameRect.top)
  1180.                 {
  1181.                     y1 += frameHeight;
  1182.                     y2 += frameHeight;
  1183.                     baseAddr += vertOffset;        // Jump to bottom side
  1184.                 }
  1185.             }
  1186.             x1 += sx;
  1187.             baseAddr += sx;                // Move left/right one pixel
  1188.             
  1189.             if (x1 >= frameRect.right)
  1190.             {
  1191.                 x1 -= frameWidth;
  1192.                 x2 -= frameWidth;
  1193.                 baseAddr -= frameWidth;    // Jump to left side
  1194.             }
  1195.             else if (x1 < frameRect.left)
  1196.             {
  1197.                 x1 += frameWidth;
  1198.                 x2 += frameWidth;
  1199.                 baseAddr += frameWidth;    // Jump to right side
  1200.             }
  1201.             
  1202.             *baseAddr = color;
  1203.         }
  1204.     } 
  1205.     else     // Longer vertically than horizontally, or both equal in length
  1206.     {
  1207.         accum = dy >> 1;    // accum = dy/2;
  1208.         while (y1 != y2)
  1209.         {
  1210.             accum -= dx;
  1211.             if (accum < 0)
  1212.             {
  1213.                 accum += dy;
  1214.                 x1 += sx;
  1215.                 baseAddr += sx;
  1216.                 
  1217.                 if (x1 >= frameRect.right)
  1218.                 {
  1219.                     x1 -= frameWidth;
  1220.                     x2 -= frameWidth;
  1221.                     baseAddr -= frameWidth;    // Jump to left side
  1222.                 }
  1223.                 else if (x1 < frameRect.left)
  1224.                 {
  1225.                     x1 += frameWidth;
  1226.                     x2 += frameWidth;
  1227.                     baseAddr += frameWidth;    // Jump to right side
  1228.                 }
  1229.             }
  1230.             y1 += sy;
  1231.             baseAddr += iy;
  1232.             
  1233.             if (y1 >= frameRect.bottom)
  1234.             {
  1235.                 y1 -= frameHeight;
  1236.                 y2 -= frameHeight;
  1237.                 baseAddr -= vertOffset;        // Jump to top side
  1238.             }
  1239.             else if (y1 < frameRect.top)
  1240.             {
  1241.                 y1 += frameHeight;
  1242.                 y2 += frameHeight;
  1243.                 baseAddr += vertOffset;        // Jump to bottom side
  1244.             }
  1245.             
  1246.             *baseAddr = color;
  1247.         }
  1248.     }
  1249. }
  1250.  
  1251.  
  1252. ///--------------------------------------------------------------------------------------
  1253. //  BPCopyWrappingLine - assumes srcFrameP and dstFrameP are the same size!
  1254. ///--------------------------------------------------------------------------------------
  1255.  
  1256. SW_FUNC void BPCopyWrappingLine(
  1257.     FramePtr srcFrameP, 
  1258.     FramePtr dstFrameP, 
  1259.     Point srcPoint, 
  1260.     Point dstPoint)
  1261. {
  1262.     Ptr                srcBaseAddr = srcFrameP->frameBaseAddr;
  1263.     Ptr                dstBaseAddr = dstFrameP->frameBaseAddr;
  1264.     unsigned long    srcRowBytes = srcFrameP->frameRowBytes;
  1265.     unsigned long    dstRowBytes = dstFrameP->frameRowBytes;
  1266.     unsigned long    srcVertOffset, dstVertOffset;
  1267.     short            x1 = srcPoint.h, y1 = srcPoint.v, 
  1268.                     x2 = dstPoint.h, y2 = dstPoint.v;
  1269.     short            dx, dy, sx, sy, srciy, dstiy;
  1270.     short            accum;
  1271.     Rect            frameRect = dstFrameP->frameRect;
  1272.     short            frameWidth, frameHeight;
  1273.     
  1274.     frameWidth = SW_RECT_WIDTH(frameRect);
  1275.     frameHeight = SW_RECT_HEIGHT(frameRect);
  1276.     
  1277.         // srcVertOffset = srcRowBytes * frameHeight;
  1278.     srcVertOffset = srcFrameP->scanLinePtrArray[srcFrameP->numScanLines-1] + srcRowBytes -
  1279.                     srcFrameP->scanLinePtrArray[0];
  1280.     dstVertOffset = dstFrameP->scanLinePtrArray[dstFrameP->numScanLines-1] + dstRowBytes -
  1281.                     dstFrameP->scanLinePtrArray[0];
  1282.     
  1283.     dx = x2 - x1;
  1284.     dy = y2 - y1;
  1285.  
  1286.     sx = SIGN(dx);
  1287.     sy = SIGN(dy);
  1288.     
  1289.     dx = ABS(dx);
  1290.     dy = ABS(dy);
  1291.     
  1292.         // Even the very first pixel we draw might need to be wrapped before we draw it.
  1293.     if (y1 >= frameRect.bottom)
  1294.     {
  1295.         y1 -= frameHeight;
  1296.         y2 -= frameHeight;
  1297.     }
  1298.     else if (y1 < frameRect.top)
  1299.     {
  1300.         y1 += frameHeight;
  1301.         y2 += frameHeight;
  1302.     }
  1303.     
  1304.     if (x1 >= frameRect.right)
  1305.     {
  1306.         x1 -= frameWidth;
  1307.         x2 -= frameWidth;
  1308.     }
  1309.     else if (x1 < frameRect.left)
  1310.     {
  1311.         x1 += frameWidth;
  1312.         x2 += frameWidth;
  1313.     }
  1314.     
  1315.     srcBaseAddr += srcFrameP->scanLinePtrArray[y1] + x1;
  1316.     dstBaseAddr += dstFrameP->scanLinePtrArray[y1] + x1;
  1317.     
  1318.         // Copy the first pixel in the line
  1319.     *dstBaseAddr = *srcBaseAddr;
  1320.     
  1321.     srciy = (sy < 0) ? -srcRowBytes : srcRowBytes;
  1322.     dstiy = (sy < 0) ? -dstRowBytes : dstRowBytes;
  1323.     
  1324.     if (dx > dy)        // Longer horizontally than vertically
  1325.     {
  1326.         accum = dx >> 1;    // accum = dx/2;
  1327.         while (x1 != x2)
  1328.         {
  1329.             accum -= dy;
  1330.             if (accum < 0)
  1331.             {
  1332.                 accum += dx;
  1333.                 y1 += sy;
  1334.                 srcBaseAddr += srciy;        // Move pixel up/down one row
  1335.                 dstBaseAddr += dstiy;
  1336.                 
  1337.                 if (y1 >= frameRect.bottom)
  1338.                 {
  1339.                     y1 -= frameHeight;
  1340.                     y2 -= frameHeight;
  1341.                     srcBaseAddr -= srcVertOffset;        // Jump to top side
  1342.                     dstBaseAddr -= dstVertOffset;
  1343.                 }
  1344.                 else if (y1 < frameRect.top)
  1345.                 {
  1346.                     y1 += frameHeight;
  1347.                     y2 += frameHeight;
  1348.                     srcBaseAddr += srcVertOffset;        // Jump to bottom side
  1349.                     dstBaseAddr += dstVertOffset;    
  1350.                 }
  1351.             }
  1352.             x1 += sx;
  1353.             srcBaseAddr += sx;                // Move left/right one pixel
  1354.             dstBaseAddr += sx;
  1355.             
  1356.             if (x1 >= frameRect.right)
  1357.             {
  1358.                 x1 -= frameWidth;
  1359.                 x2 -= frameWidth;
  1360.                 srcBaseAddr -= frameWidth;    // Jump to left side
  1361.                 dstBaseAddr -= frameWidth;
  1362.             }
  1363.             else if (x1 < frameRect.left)
  1364.             {
  1365.                 x1 += frameWidth;
  1366.                 x2 += frameWidth;
  1367.                 srcBaseAddr += frameWidth;    // Jump to right side
  1368.                 dstBaseAddr += frameWidth;
  1369.             }
  1370.             
  1371.             *dstBaseAddr = *srcBaseAddr;    // Copy the pixel
  1372.         }
  1373.     } 
  1374.     else     // Longer vertically than horizontally, or both equal in length
  1375.     {
  1376.         accum = dy >> 1;    // accum = dy/2;
  1377.         while (y1 != y2)
  1378.         {
  1379.             accum -= dx;
  1380.             if (accum < 0)
  1381.             {
  1382.                 accum += dy;
  1383.                 x1 += sx;
  1384.                 srcBaseAddr += sx;
  1385.                 dstBaseAddr += sx;
  1386.                 
  1387.                 if (x1 >= frameRect.right)
  1388.                 {
  1389.                     x1 -= frameWidth;
  1390.                     x2 -= frameWidth;
  1391.                     srcBaseAddr -= frameWidth;    // Jump to left side
  1392.                     dstBaseAddr -= frameWidth;
  1393.                 }
  1394.                 else if (x1 < frameRect.left)
  1395.                 {
  1396.                     x1 += frameWidth;
  1397.                     x2 += frameWidth;
  1398.                     srcBaseAddr += frameWidth;    // Jump to right side
  1399.                     dstBaseAddr += frameWidth;
  1400.                 }
  1401.             }
  1402.             y1 += sy;
  1403.             srcBaseAddr += srciy;
  1404.             dstBaseAddr += dstiy;
  1405.             
  1406.             if (y1 >= frameRect.bottom)
  1407.             {
  1408.                 y1 -= frameHeight;
  1409.                 y2 -= frameHeight;
  1410.                 srcBaseAddr -= srcVertOffset;        // Jump to top side
  1411.                 dstBaseAddr -= dstVertOffset;
  1412.             }
  1413.             else if (y1 < frameRect.top)
  1414.             {
  1415.                 y1 += frameHeight;
  1416.                 y2 += frameHeight;
  1417.                 srcBaseAddr += srcVertOffset;        // Jump to bottom side
  1418.                 dstBaseAddr += dstVertOffset;
  1419.             }
  1420.             
  1421.             *dstBaseAddr = *srcBaseAddr;    // Copy the pixel
  1422.         }
  1423.     }
  1424. }
  1425.  
  1426.  
  1427. #pragma mark -
  1428. #pragma mark ***Straight Line Blitters: 
  1429. ///--------------------------------------------------------------------------------------
  1430. //  BlitStraightLine - Clipping is performed by function, since it's easy for a straight line.
  1431. ///--------------------------------------------------------------------------------------
  1432.  
  1433. SW_FUNC void BlitStraightLine(
  1434.     FramePtr dstFrameP, 
  1435.     Point srcPoint, 
  1436.     Point dstPoint, 
  1437.     register Byte color)
  1438. {
  1439.     unsigned long    rowBytes = dstFrameP->frameRowBytes;
  1440.     short            x1 = srcPoint.h, y1 = srcPoint.v, 
  1441.                     x2 = dstPoint.h, y2 = dstPoint.v;
  1442.     short            dx, dy;
  1443.  
  1444.     
  1445.     if (x1 == x2)        // Straight vertical line
  1446.     {
  1447.         register Ptr    baseAddr;
  1448.         
  1449.         if (y2 < y1)
  1450.         {
  1451.             y1 = dstPoint.v;    // Swap y1 and y2 if they're
  1452.             y2 = srcPoint.v;    // in the wrong order.
  1453.         }
  1454.         
  1455.             // Make sure some part of the line is inside the frameRect
  1456.         if (x1 < dstFrameP->frameRect.left || x1 >= dstFrameP->frameRect.right)
  1457.             return;
  1458.         
  1459.             // Clip the ends of the line
  1460.         if (y1 < dstFrameP->frameRect.top)
  1461.             y1 = dstFrameP->frameRect.top;
  1462.         if (y2 >= dstFrameP->frameRect.bottom)
  1463.             y2 = dstFrameP->frameRect.bottom-1;
  1464.         
  1465.         dy = y2 - y1 + 1;    // dy = number of pixels in line
  1466.         if (dy > 0)    // Make sure there is a line first!
  1467.         {
  1468.             baseAddr = dstFrameP->frameBaseAddr + dstFrameP->scanLinePtrArray[y1] + x1;
  1469.             *baseAddr = color;
  1470.             
  1471.             while (--dy)
  1472.             {
  1473.                 baseAddr += rowBytes;
  1474.                 *baseAddr = color;
  1475.             }
  1476.         }
  1477.     }
  1478.     else if (y1 == y2)    // Straight horizontal line
  1479.     {
  1480.         register unsigned long     *longBaseAddr;
  1481.         register                 numLongBlits;
  1482.         unsigned long            longColor;
  1483.         
  1484.             // Fill longColor with color
  1485.         longColor = (color<<24) | (color<<16) | (color<<8) | (color);
  1486.         
  1487.         if (x2 < x1)
  1488.         {
  1489.             x1 = dstPoint.h;    // Swap x1 and x2 if they're
  1490.             x2 = srcPoint.h;    // in the wrong order.
  1491.         }
  1492.         
  1493.             // Make sure some part of the line is inside the frameRect
  1494.         if (y1 < dstFrameP->frameRect.top || y1 >= dstFrameP->frameRect.bottom)
  1495.             return;
  1496.         
  1497.         if (x1 < dstFrameP->frameRect.left)
  1498.             x1 = dstFrameP->frameRect.left;
  1499.         if (x2 >= dstFrameP->frameRect.right)
  1500.             x2 = dstFrameP->frameRect.right-1;
  1501.         
  1502.         dx = x2 - x1 + 1;    // dx = number of pixels in line
  1503.         if (dx > 0)    // Make sure there is a line first!
  1504.         {
  1505.             numLongBlits = (dx >> 2);
  1506.             longBaseAddr = (unsigned long *)(dstFrameP->frameBaseAddr + 
  1507.                     dstFrameP->scanLinePtrArray[y1] + x1);
  1508.             
  1509.             while (numLongBlits--)
  1510.             {
  1511.                 *(longBaseAddr)++ = longColor;
  1512.             }
  1513.             
  1514. #ifdef __MWERKS__  // Do it nicely
  1515.                 // Handle extra pixels at end of line
  1516.             if (dx & 0x2)
  1517.                 *((unsigned short *) longBaseAddr)++ = (unsigned short)longColor;
  1518.             if (dx & 0x1)
  1519.                 *((unsigned char *) longBaseAddr)++ = color;
  1520. #else     // Make Think C happy
  1521.                 // Handle extra pixels at end of line
  1522.             if (dx & 0x2)
  1523.             {
  1524.                 *((unsigned short *) longBaseAddr) = (unsigned short)longColor;
  1525.                 longBaseAddr = (unsigned long *)(((unsigned short *)longBaseAddr) + 1);
  1526.             }
  1527.             if (dx & 0x1)
  1528.             {
  1529.                 *((unsigned char *) longBaseAddr) = color;
  1530.                 longBaseAddr = (unsigned long *)(((unsigned char *)longBaseAddr) + 1);
  1531.             }
  1532. #endif
  1533.         }
  1534.     }
  1535. }
  1536.  
  1537.  
  1538. ///--------------------------------------------------------------------------------------
  1539. //  BPCopyStraightLine - Clipping is performed by function, since it's easy for a straight 
  1540. //    line. Assumes srcFrameP->frameRect and dstFrameP->frameRect are the same size!
  1541. ///--------------------------------------------------------------------------------------
  1542.  
  1543. SW_FUNC void BPCopyStraightLine(
  1544.     FramePtr srcFrameP, 
  1545.     FramePtr dstFrameP, 
  1546.     Point srcPoint, 
  1547.     Point dstPoint)
  1548. {
  1549.     unsigned long    srcRowBytes = srcFrameP->frameRowBytes;
  1550.     unsigned long    dstRowBytes = dstFrameP->frameRowBytes;
  1551.     short            x1 = srcPoint.h, y1 = srcPoint.v, 
  1552.                     x2 = dstPoint.h, y2 = dstPoint.v;
  1553.     short            dx, dy;
  1554.  
  1555.     
  1556.     if (x1 == x2)        // Straight vertical line
  1557.     {
  1558.         register Ptr    srcBaseAddr;
  1559.         register Ptr    dstBaseAddr;
  1560.         
  1561.         if (y2 < y1)
  1562.         {
  1563.             y1 = dstPoint.v;    // Swap y1 and y2 if they're
  1564.             y2 = srcPoint.v;    // in the wrong order.
  1565.         }
  1566.         
  1567.             // Make sure some part of the line is inside the frameRect
  1568.         if (x1 < dstFrameP->frameRect.left || x1 >= dstFrameP->frameRect.right)
  1569.             return;
  1570.         
  1571.             // Clip the ends of the line
  1572.         if (y1 < dstFrameP->frameRect.top)
  1573.             y1 = dstFrameP->frameRect.top;
  1574.         if (y2 >= dstFrameP->frameRect.bottom)
  1575.             y2 = dstFrameP->frameRect.bottom-1;
  1576.         
  1577.         dy = y2 - y1 + 1;    // dy = number of pixels in line
  1578.         if (dy > 0)    // Make sure there is a line first!
  1579.         {
  1580.             srcBaseAddr = srcFrameP->frameBaseAddr + srcFrameP->scanLinePtrArray[y1] + x1;
  1581.             dstBaseAddr = dstFrameP->frameBaseAddr + dstFrameP->scanLinePtrArray[y1] + x1;
  1582.             
  1583.             *dstBaseAddr = *srcBaseAddr;    // Copy the first pixel
  1584.             
  1585.             while (--dy)
  1586.             {
  1587.                 srcBaseAddr += srcRowBytes;
  1588.                 dstBaseAddr += dstRowBytes;
  1589.                 *dstBaseAddr = *srcBaseAddr;
  1590.             }
  1591.         }
  1592.     }
  1593.     else if (y1 == y2)    // Straight horizontal line
  1594.     {
  1595.         register unsigned long    *srcBaseAddr;
  1596.         register unsigned long    *dstBaseAddr;
  1597.         register                 numLongBlits;
  1598.         
  1599.         if (x2 < x1)
  1600.         {
  1601.             x1 = dstPoint.h;    // Swap x1 and x2 if they're
  1602.             x2 = srcPoint.h;    // in the wrong order.
  1603.         }
  1604.         
  1605.             // Make sure some part of the line is inside the frameRect
  1606.         if (y1 < dstFrameP->frameRect.top || y1 >= dstFrameP->frameRect.bottom)
  1607.             return;
  1608.         
  1609.             // Clip the ends of the line
  1610.         if (x1 < dstFrameP->frameRect.left)
  1611.             x1 = dstFrameP->frameRect.left;
  1612.         if (x2 >= dstFrameP->frameRect.right)
  1613.             x2 = dstFrameP->frameRect.right-1;
  1614.         
  1615.         dx = x2 - x1 + 1;    // dx = number of pixels in line
  1616.         if (dx > 0)        // Make sure there is a line first!
  1617.         {
  1618.             numLongBlits = (dx >> 2);
  1619.             srcBaseAddr = (unsigned long *)(srcFrameP->frameBaseAddr + 
  1620.                     srcFrameP->scanLinePtrArray[y1] + x1);
  1621.             dstBaseAddr = (unsigned long *)(dstFrameP->frameBaseAddr + 
  1622.                     dstFrameP->scanLinePtrArray[y1] + x1);
  1623.             
  1624.             while (numLongBlits--)
  1625.             {
  1626.                 *(dstBaseAddr)++ = *(srcBaseAddr)++;
  1627.             }
  1628.                 
  1629.         
  1630. #ifdef __MWERKS__  // Do it nicely
  1631.                 // Handle extra pixels at end of line
  1632.             if (dx & 0x2)
  1633.                 *((unsigned short *) dstBaseAddr)++ = *((unsigned short *) srcBaseAddr)++;
  1634.             if (dx & 0x1)
  1635.                 *((unsigned char *) dstBaseAddr)++ = *((unsigned char *) srcBaseAddr)++;
  1636. #else     // Make Think C happy
  1637.                 // Handle extra pixels at end of line
  1638.             if (dx & 0x2)
  1639.             {
  1640.                 *((unsigned short *) dstBaseAddr) = *((unsigned short *) srcBaseAddr);
  1641.                 dstBaseAddr = (unsigned long *)(((unsigned short *)dstBaseAddr) + 1);
  1642.                 srcBaseAddr = (unsigned long *)(((unsigned short *)srcBaseAddr) + 1);
  1643.             }
  1644.             if (dx & 0x1)
  1645.             {
  1646.                 *((unsigned char *) dstBaseAddr) = *((unsigned char *) srcBaseAddr);
  1647.                 dstBaseAddr = (unsigned long *)(((unsigned char *)dstBaseAddr) + 1);
  1648.                 srcBaseAddr = (unsigned long *)(((unsigned char *)srcBaseAddr) + 1);
  1649.             }
  1650. #endif
  1651.         }
  1652.     }
  1653. }
  1654.  
  1655.  
  1656. ///--------------------------------------------------------------------------------------
  1657. //  BlitStraightWrappingLine - No clipping performed by function.
  1658. //    Assumes srcFrameP->frameRect and dstFrameP->frameRect are the same size!
  1659. ///--------------------------------------------------------------------------------------
  1660.  
  1661. SW_FUNC void BlitStraightWrappingLine(
  1662.     FramePtr dstFrameP, 
  1663.     Point srcPoint, 
  1664.     Point dstPoint, 
  1665.     register Byte color)
  1666. {
  1667.     unsigned long    rowBytes = dstFrameP->frameRowBytes;
  1668.     short            x1 = srcPoint.h, y1 = srcPoint.v, 
  1669.                     x2 = dstPoint.h, y2 = dstPoint.v;
  1670.     short            dx, dy;
  1671.     
  1672.     if (x1 == x2)        // Straight vertical line
  1673.     {
  1674.         register Ptr    baseAddr;
  1675.         short            y3, y4;        // Second half of wrapped line
  1676.         
  1677.         if (y2 < y1)
  1678.         {
  1679.             y1 = dstPoint.v;    // Swap y1 and y2 if they're
  1680.             y2 = srcPoint.v;    // in the wrong order.
  1681.         }
  1682.         
  1683.             // Wrap line horizontally if necessary before we start (only done once)
  1684.             // Remember x1 and x2 are the same, and x2 isn't used.
  1685.         if (x1 < dstFrameP->frameRect.left)
  1686.             x1 += dstFrameP->frameRect.right;    
  1687.         else if (x1 >= dstFrameP->frameRect.right)
  1688.             x1 -= dstFrameP->frameRect.right;
  1689.         
  1690.             // Now we check to see if the line wraps vertically, in which case we
  1691.             // split it into two lines before drawing it.
  1692.         if (y1 < dstFrameP->frameRect.top)
  1693.         {
  1694.             if (y2 < dstFrameP->frameRect.top)
  1695.                 y4 = y2 + dstFrameP->frameRect.bottom;
  1696.             else
  1697.                 y4 = dstFrameP->frameRect.bottom-1;
  1698.             
  1699.             y3 = y1 + dstFrameP->frameRect.bottom;
  1700.             y1 = dstFrameP->frameRect.top;
  1701.         }
  1702.         else if (y2 >= dstFrameP->frameRect.bottom)
  1703.         {
  1704.             if (y1 >= dstFrameP->frameRect.bottom)
  1705.                 y3 = y1 - dstFrameP->frameRect.bottom;
  1706.             else
  1707.                 y3 = dstFrameP->frameRect.top;
  1708.             
  1709.             y4 = y2 - dstFrameP->frameRect.bottom;
  1710.             y2 = dstFrameP->frameRect.bottom-1;
  1711.         }
  1712.         else
  1713.         {
  1714.             y3 = 0;        // The formula for no second line
  1715.             y4 = -1;
  1716.         }
  1717.         
  1718.             // -----Draw the first line-----
  1719.         dy = y2 - y1 + 1;    // dy = number of pixels in line
  1720.         if (dy > 0)        // Make sure there is a line first!
  1721.         {
  1722.             baseAddr = dstFrameP->frameBaseAddr + dstFrameP->scanLinePtrArray[y1] + x1;
  1723.             *baseAddr = color;
  1724.             
  1725.             while(--dy)
  1726.             {
  1727.                 baseAddr += rowBytes;
  1728.                 *baseAddr = color;
  1729.             } 
  1730.         }
  1731.         
  1732.         
  1733.             // -----Draw the second line-----
  1734.         dy = y4 - y3 + 1;    // dy = number of pixels in line
  1735.         if (dy > 0)            // Make sure there is a line first!
  1736.         {
  1737.             baseAddr = dstFrameP->frameBaseAddr + dstFrameP->scanLinePtrArray[y3] + x1;
  1738.             *baseAddr = color;
  1739.             
  1740.             while(--dy)
  1741.             {
  1742.                 baseAddr += rowBytes;
  1743.                 *baseAddr = color;
  1744.             }
  1745.         }
  1746.     }
  1747.     else if (y1 == y2)    // Straight horizontal line
  1748.     {
  1749.         register unsigned long     *longBaseAddr;
  1750.         register                 numLongBlits;
  1751.         unsigned long            longColor;
  1752.         short                    x3, x4;        // Second half of wrapped line
  1753.         
  1754.             // Fill longColor with color
  1755.         longColor = (color<<24) | (color<<16) | (color<<8) | (color);
  1756.         
  1757.         if (x2 < x1)
  1758.         {
  1759.             x1 = dstPoint.h;    // Swap x1 and x2 if they're
  1760.             x2 = srcPoint.h;    // in the wrong order.
  1761.         }
  1762.         
  1763.             // Wrap line vertically if necessary before we start (only done once)
  1764.             // Remember y1 and y2 are the same, and y2 isn't used.
  1765.         if (y1 < dstFrameP->frameRect.top)
  1766.             y1 += dstFrameP->frameRect.bottom;    
  1767.         else if (y1 >= dstFrameP->frameRect.bottom)
  1768.             y1 -= dstFrameP->frameRect.bottom;
  1769.         
  1770.             // Now we check to see if the line wraps horizontally, in which case we
  1771.             // split it into two lines before drawing it.
  1772.         if (x1 < dstFrameP->frameRect.left)
  1773.         {
  1774.             if (x2 < dstFrameP->frameRect.left)
  1775.                 x4 = x2 + dstFrameP->frameRect.right;
  1776.             else
  1777.                 x4 = dstFrameP->frameRect.right-1;
  1778.             
  1779.             x3 = x1 + dstFrameP->frameRect.right;
  1780.             x1 = dstFrameP->frameRect.left;
  1781.         }
  1782.         else if (x2 >= dstFrameP->frameRect.right)
  1783.         {
  1784.             if (x1 >= dstFrameP->frameRect.right)
  1785.                 x3 = x1 - dstFrameP->frameRect.right;
  1786.             else
  1787.                 x3 = dstFrameP->frameRect.left;
  1788.             
  1789.             x4 = x2 - dstFrameP->frameRect.right;
  1790.             x2 = dstFrameP->frameRect.right-1;
  1791.         }
  1792.         else
  1793.         {
  1794.             x3 = 0;        // The formula for no second line
  1795.             x4 = -1;
  1796.         }
  1797.         
  1798.             // ----Draw the first line----
  1799.         dx = x2 - x1 + 1;    // dx = number of pixels in line
  1800.         if (dx > 0)            // Make sure there is a line first!
  1801.         {
  1802.             numLongBlits = (dx >> 2);
  1803.             longBaseAddr = (unsigned long *)(dstFrameP->frameBaseAddr + 
  1804.                     dstFrameP->scanLinePtrArray[y1] + x1);
  1805.             
  1806.             while (numLongBlits--)
  1807.             {
  1808.                 *(longBaseAddr)++ = longColor;
  1809.             }
  1810.             
  1811. #ifdef __MWERKS__  // Do it nicely
  1812.                 // Handle extra pixels at end of line
  1813.             if (dx & 0x2)
  1814.                 *((unsigned short *) longBaseAddr)++ = (unsigned short)longColor;
  1815.             if (dx & 0x1)
  1816.                 *((unsigned char *) longBaseAddr)++ = color;
  1817. #else     // Make Think C happy
  1818.                 // Handle extra pixels at end of line
  1819.             if (dx & 0x2)
  1820.             {
  1821.                 *((unsigned short *) longBaseAddr) = (unsigned short)longColor;
  1822.                 longBaseAddr = (unsigned long *)(((unsigned short *)longBaseAddr) + 1);
  1823.             }
  1824.             if (dx & 0x1)
  1825.             {
  1826.                 *((unsigned char *) longBaseAddr) = color;
  1827.                 longBaseAddr = (unsigned long *)(((unsigned char *)longBaseAddr) + 1);
  1828.             }
  1829. #endif
  1830.         }
  1831.         
  1832.         
  1833.             // ----Draw the second line----
  1834.         dx = x4 - x3 + 1;    // dx = number of pixels in line
  1835.         if (dx > 0)            // Make sure there is a line first!
  1836.         {
  1837.             numLongBlits = (dx >> 2);
  1838.             longBaseAddr = (unsigned long *)(dstFrameP->frameBaseAddr + 
  1839.                     dstFrameP->scanLinePtrArray[y1] + x3);
  1840.             
  1841.             while (numLongBlits--)
  1842.             {
  1843.                 *(longBaseAddr)++ = longColor;
  1844.             }
  1845.         
  1846. #ifdef __MWERKS__  // Do it nicely
  1847.                 // Handle extra pixels at end of line
  1848.             if (dx & 0x2)
  1849.                 *((unsigned short *) longBaseAddr)++ = (unsigned short)longColor;
  1850.             if (dx & 0x1)
  1851.                 *((unsigned char *) longBaseAddr)++ = color;
  1852. #else     // Make Think C happy
  1853.                 // Handle extra pixels at end of line
  1854.             if (dx & 0x2)
  1855.             {
  1856.                 *((unsigned short *) longBaseAddr) = (unsigned short)longColor;
  1857.                 longBaseAddr = (unsigned long *)(((unsigned short *)longBaseAddr) + 1);
  1858.             }
  1859.             if (dx & 0x1)
  1860.             {
  1861.                 *((unsigned char *) longBaseAddr) = color;
  1862.                 longBaseAddr = (unsigned long *)(((unsigned char *)longBaseAddr) + 1);
  1863.             }
  1864. #endif
  1865.         }
  1866.     }
  1867. }
  1868.  
  1869.  
  1870. ///--------------------------------------------------------------------------------------
  1871. //  BPCopyStraightWrappingLine  - No clipping performed by function. 
  1872. //    Assumes srcFrameP->frameRect and dstFrameP->frameRect are the same size!
  1873. ///--------------------------------------------------------------------------------------
  1874.  
  1875. SW_FUNC void BPCopyStraightWrappingLine(
  1876.     FramePtr srcFrameP, 
  1877.     FramePtr dstFrameP, 
  1878.     Point srcPoint, 
  1879.     Point dstPoint)
  1880. {
  1881.     unsigned long    srcRowBytes = srcFrameP->frameRowBytes;
  1882.     unsigned long    dstRowBytes = dstFrameP->frameRowBytes;
  1883.     short            x1 = srcPoint.h, y1 = srcPoint.v, 
  1884.                     x2 = dstPoint.h, y2 = dstPoint.v;
  1885.     short            dx, dy;
  1886.     
  1887.     if (x1 == x2)        // Straight vertical line
  1888.     {
  1889.         register Ptr    srcBaseAddr, dstBaseAddr;
  1890.         short            y3, y4;        // Second half of wrapped line
  1891.         
  1892.         if (y2 < y1)
  1893.         {
  1894.             y1 = dstPoint.v;    // Swap y1 and y2 if they're
  1895.             y2 = srcPoint.v;    // in the wrong order.
  1896.         }
  1897.         
  1898.             // Wrap line horizontally if necessary before we start (only done once)
  1899.             // Remember x1 and x2 are the same, and x2 isn't used.
  1900.         if (x1 < dstFrameP->frameRect.left)
  1901.             x1 += dstFrameP->frameRect.right;    
  1902.         else if (x1 >= dstFrameP->frameRect.right)
  1903.             x1 -= dstFrameP->frameRect.right;
  1904.         
  1905.             // Now we check to see if the line wraps vertically, in which case we
  1906.             // split it into two lines before drawing it.
  1907.         if (y1 < dstFrameP->frameRect.top)
  1908.         {
  1909.             if (y2 < dstFrameP->frameRect.top)
  1910.                 y4 = y2 + dstFrameP->frameRect.bottom;
  1911.             else
  1912.                 y4 = dstFrameP->frameRect.bottom-1;
  1913.             
  1914.             y3 = y1 + dstFrameP->frameRect.bottom;
  1915.             y1 = dstFrameP->frameRect.top;
  1916.         }
  1917.         else if (y2 >= dstFrameP->frameRect.bottom)
  1918.         {
  1919.             if (y1 >= dstFrameP->frameRect.bottom)
  1920.                 y3 = y1 - dstFrameP->frameRect.bottom;
  1921.             else
  1922.                 y3 = dstFrameP->frameRect.top;
  1923.             
  1924.             y4 = y2 - dstFrameP->frameRect.bottom;
  1925.             y2 = dstFrameP->frameRect.bottom-1;
  1926.         }
  1927.         else
  1928.         {
  1929.             y3 = 0;        // The formula for no second line
  1930.             y4 = -1;
  1931.         }
  1932.         
  1933.             // -----Draw the first line-----
  1934.         dy = y2 - y1 + 1;    // dy = number of pixels in line
  1935.         if (dy > 0)            // Make sure there is a line first!
  1936.         {
  1937.             srcBaseAddr = srcFrameP->frameBaseAddr + srcFrameP->scanLinePtrArray[y1] + x1;
  1938.             dstBaseAddr = dstFrameP->frameBaseAddr + dstFrameP->scanLinePtrArray[y1] + x1;
  1939.             
  1940.             *dstBaseAddr = *srcBaseAddr;    // Copy the first pixel
  1941.             
  1942.             while (--dy)
  1943.             {
  1944.                 srcBaseAddr += srcRowBytes;
  1945.                 dstBaseAddr += dstRowBytes;
  1946.                 *dstBaseAddr = *srcBaseAddr;
  1947.             }
  1948.         }
  1949.         
  1950.         
  1951.             // -----Draw the second line-----
  1952.         dy = y4 - y3 + 1;    // dy = number of pixels in line
  1953.         if (dy > 0)            // Make sure there is a line first!
  1954.         {
  1955.             srcBaseAddr = srcFrameP->frameBaseAddr + srcFrameP->scanLinePtrArray[y3] + x1;
  1956.             dstBaseAddr = dstFrameP->frameBaseAddr + dstFrameP->scanLinePtrArray[y3] + x1;
  1957.             
  1958.             *dstBaseAddr = *srcBaseAddr;    // Copy the first pixel
  1959.             
  1960.             while (--dy)
  1961.             {
  1962.                 srcBaseAddr += srcRowBytes;
  1963.                 dstBaseAddr += dstRowBytes;
  1964.                 *dstBaseAddr = *srcBaseAddr;
  1965.             }
  1966.         }
  1967.     }
  1968.     else if (y1 == y2)    // Straight horizontal line
  1969.     {
  1970.         register unsigned long     *srcBaseAddr, *dstBaseAddr;
  1971.         register                 numLongBlits;
  1972.         short                    x3, x4;        // Second half of wrapped line
  1973.         
  1974.         if (x2 < x1)
  1975.         {
  1976.             x1 = dstPoint.h;    // Swap x1 and x2 if they're
  1977.             x2 = srcPoint.h;    // in the wrong order.
  1978.         }
  1979.         
  1980.             // Wrap line vertically if necessary before we start (only done once)
  1981.             // Remember y1 and y2 are the same, and y2 isn't used.
  1982.         if (y1 < dstFrameP->frameRect.top)
  1983.             y1 += dstFrameP->frameRect.bottom;    
  1984.         else if (y1 >= dstFrameP->frameRect.bottom)
  1985.             y1 -= dstFrameP->frameRect.bottom;
  1986.         
  1987.             // Now we check to see if the line wraps horizontally, in which case we
  1988.             // split it into two lines before drawing it.
  1989.         if (x1 < dstFrameP->frameRect.left)
  1990.         {
  1991.             if (x2 < dstFrameP->frameRect.left)
  1992.                 x4 = x2 + dstFrameP->frameRect.right;
  1993.             else
  1994.                 x4 = dstFrameP->frameRect.right-1;
  1995.             
  1996.             x3 = x1 + dstFrameP->frameRect.right;
  1997.             x1 = dstFrameP->frameRect.left;
  1998.         }
  1999.         else if (x2 >= dstFrameP->frameRect.right)
  2000.         {
  2001.             if (x1 >= dstFrameP->frameRect.right)
  2002.                 x3 = x1 - dstFrameP->frameRect.right;
  2003.             else
  2004.                 x3 = dstFrameP->frameRect.left;
  2005.             
  2006.             x4 = x2 - dstFrameP->frameRect.right;
  2007.             x2 = dstFrameP->frameRect.right-1;
  2008.         }
  2009.         else
  2010.         {
  2011.             x3 = 0;        // The formula for no second line
  2012.             x4 = -1;
  2013.         }
  2014.         
  2015.             // ----Draw the first line----
  2016.         dx = x2 - x1 + 1;    // dx = number of pixels in line
  2017.         if (dx > 0)            // Make sure there is a line first!
  2018.         {
  2019.             numLongBlits = (dx >> 2);
  2020.             srcBaseAddr = (unsigned long *)(srcFrameP->frameBaseAddr + 
  2021.                     srcFrameP->scanLinePtrArray[y1] + x1);
  2022.             dstBaseAddr = (unsigned long *)(dstFrameP->frameBaseAddr + 
  2023.                     dstFrameP->scanLinePtrArray[y1] + x1);
  2024.             
  2025.             while (numLongBlits--)
  2026.             {
  2027.                 *(dstBaseAddr)++ = *(srcBaseAddr)++;
  2028.             }
  2029.             
  2030.         
  2031. #ifdef __MWERKS__  // Do it nicely
  2032.                 // Handle extra pixels at end of line
  2033.             if (dx & 0x2)
  2034.                 *((unsigned short *) dstBaseAddr)++ = *((unsigned short *) srcBaseAddr)++;
  2035.             if (dx & 0x1)
  2036.                 *((unsigned char *) dstBaseAddr)++ = *((unsigned char *) srcBaseAddr)++;
  2037. #else     // Make Think C happy
  2038.                 // Handle extra pixels at end of line
  2039.             if (dx & 0x2)
  2040.             {
  2041.                 *((unsigned short *) dstBaseAddr) = *((unsigned short *) srcBaseAddr);
  2042.                 dstBaseAddr = (unsigned long *)(((unsigned short *)dstBaseAddr) + 1);
  2043.                 srcBaseAddr = (unsigned long *)(((unsigned short *)srcBaseAddr) + 1);
  2044.             }
  2045.             if (dx & 0x1)
  2046.             {
  2047.                 *((unsigned char *) dstBaseAddr) = *((unsigned char *) srcBaseAddr);
  2048.                 dstBaseAddr = (unsigned long *)(((unsigned char *)dstBaseAddr) + 1);
  2049.                 srcBaseAddr = (unsigned long *)(((unsigned char *)srcBaseAddr) + 1);
  2050.             }
  2051. #endif
  2052.         }
  2053.         
  2054.         
  2055.             // ----Draw the second line----
  2056.         dx = x4 - x3 + 1;    // dx = number of pixels in line
  2057.         if (dx > 0)            // Make sure there is a line first!
  2058.         {
  2059.             numLongBlits = (dx >> 2);
  2060.             srcBaseAddr = (unsigned long *)(srcFrameP->frameBaseAddr + 
  2061.                     srcFrameP->scanLinePtrArray[y1] + x3);
  2062.             dstBaseAddr = (unsigned long *)(dstFrameP->frameBaseAddr + 
  2063.                     dstFrameP->scanLinePtrArray[y1] + x3);
  2064.             
  2065.             while (numLongBlits--)
  2066.             {
  2067.                 *(dstBaseAddr)++ = *(srcBaseAddr)++;
  2068.             }
  2069.             
  2070.         
  2071. #ifdef __MWERKS__  // Do it nicely
  2072.                 // Handle extra pixels at end of line
  2073.             if (dx & 0x2)
  2074.                 *((unsigned short *) dstBaseAddr)++ = *((unsigned short *) srcBaseAddr)++;
  2075.             if (dx & 0x1)
  2076.                 *((unsigned char *) dstBaseAddr)++ = *((unsigned char *) srcBaseAddr)++;
  2077. #else     // Make Think C happy
  2078.                 // Handle extra pixels at end of line
  2079.             if (dx & 0x2)
  2080.             {
  2081.                 *((unsigned short *) dstBaseAddr) = *((unsigned short *) srcBaseAddr);
  2082.                 dstBaseAddr = (unsigned long *)(((unsigned short *)dstBaseAddr) + 1);
  2083.                 srcBaseAddr = (unsigned long *)(((unsigned short *)srcBaseAddr) + 1);
  2084.             }
  2085.             if (dx & 0x1)
  2086.             {
  2087.                 *((unsigned char *) dstBaseAddr) = *((unsigned char *) srcBaseAddr);
  2088.                 dstBaseAddr = (unsigned long *)(((unsigned char *)dstBaseAddr) + 1);
  2089.                 srcBaseAddr = (unsigned long *)(((unsigned char *)srcBaseAddr) + 1);
  2090.             }
  2091. #endif
  2092.         }
  2093.     }
  2094. }
  2095.  
  2096.