home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / OS / FWGraphx / SLGrUtil.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  11.4 KB  |  456 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                SLGrUtil.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Copyright    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #include "FWOS.hpp"
  11.  
  12. #ifndef SLGRUTIL_H
  13. #include "SLGrUtil.h"
  14. #endif
  15.  
  16. #ifndef FWRECT_H
  17. #include "FWRect.h"
  18. #endif
  19.  
  20. #ifndef FWPOINT_H
  21. #include "FWPoint.h"
  22. #endif
  23.  
  24. #ifndef FWFXMATH_H
  25. #include "FWFxMath.h"
  26. #endif
  27.  
  28. #ifndef FWGRUTIL_H
  29. #include "FWGrUtil.h"
  30. #endif
  31.  
  32. #ifndef FWPRIDEB_H
  33. #include "FWPriDeb.h"
  34. #endif
  35.  
  36. #include <stdio.h>
  37.  
  38. #ifdef FW_BUILD_MAC
  39. #pragma segment FWGraphx_SLGrUtil
  40. #endif
  41.  
  42. //----------------------------------------------------------------------------------------
  43. //    FW_RegionCode
  44. //----------------------------------------------------------------------------------------
  45. //
  46. //     1001 (9)  | 0001 (1) | 0101 (5)
  47. //    --------------------------------
  48. //     1000 (8)  | 0000 (0) | 0100 (4)
  49. //    --------------------------------
  50. //     1010 (10) | 0010 (2) | 0110 (6)
  51. //
  52. short SL_API FW_RegionCode(const FW_SPoint& line, const FW_SRect& rect)
  53. {
  54.     // No try block necessary - Do not throw
  55.     short regionCode = 0;
  56.     if (line.x < rect.left)
  57.         regionCode = 0x0008;
  58.     else if (line.x > rect.right)
  59.         regionCode = 0x0004;
  60.     
  61.     if (line.y < rect.top)
  62.         regionCode |= 0x0001;
  63.     else if (line.y > rect.bottom)
  64.         regionCode |= 0x0002;
  65.         
  66.     return regionCode;
  67. }
  68.  
  69. //----------------------------------------------------------------------------------------
  70. // ::FW_HitTestLine
  71. //----------------------------------------------------------------------------------------
  72. //    Uses a modified Cohen-Suterland with midpoint subdivision. Here we don't try to clip but
  73. //    just to find if a line intersect a rectangle of size 2*tolerance
  74.  
  75. FW_Boolean SL_API FW_HitTestLine(const FW_SPoint& pt1, const FW_SPoint& pt2,
  76.                                 const FW_SPoint& test, FW_Fixed tolerance)
  77. {
  78.     // No try block necessary - Do not throw
  79.  
  80.     FW_CRect rect(test.x - tolerance,
  81.                 test.y - tolerance,
  82.                 test.x + tolerance,
  83.                 test.y + tolerance);
  84.     
  85.     short regionCode1, regionCode2, middleCode;
  86.     
  87.     if ((regionCode1 = FW_RegionCode(pt1, rect)) == 0)
  88.         return TRUE;        // start is inside the rectangle
  89.         
  90.     if ((regionCode2 = FW_RegionCode(pt2, rect)) == 0)
  91.         return TRUE;        // end is inside the rectangle
  92.         
  93.     if ((regionCode1 & regionCode2) != 0)
  94.         return FALSE;        // line totally outside
  95.     
  96.     FW_CPoint h1(pt1), h2(pt2);
  97.     FW_CPoint middle(FW_Half(h1.x + h2.x), FW_Half(h1.y + h2.y));
  98.  
  99.     while (middle != h1 && middle != h2)
  100.     {
  101.         if ((middleCode = FW_RegionCode(middle, rect)) == 0)
  102.             return TRUE;    // middle is in the rectangle
  103.             
  104.         if ((middleCode & regionCode1) != 0)
  105.         {
  106.             // line (middle, h1) outside the rectangle 
  107.             h1 = middle;
  108.             regionCode1 = middleCode;
  109.         }
  110.         else
  111.         {
  112.             // line (h2, middle) outside the rectangle 
  113.             h2 = middle;
  114.             regionCode2 = middleCode;
  115.         }
  116.         
  117.         if ((regionCode1 & regionCode2) != 0)        
  118.             return FALSE;    // line (h1, h2) totally outside
  119.                  
  120.         middle.Set(FW_Half(h1.x + h2.x), FW_Half(h1.y + h2.y));
  121.     }
  122.     
  123.     return FALSE;
  124. }
  125.  
  126. //----------------------------------------------------------------------------------------
  127. //    FW_HitTestPolygon
  128. //
  129. //    Crossings algorithm, Graphics Gems IV, article I.4
  130. //----------------------------------------------------------------------------------------
  131.  
  132. static FW_Fixed XIntersect(const FW_SPoint* vtx0, const FW_SPoint* vtx1, FW_Fixed ty)
  133. {
  134.     return vtx1->x - FW_WideMultiply(vtx1->y - ty, vtx0->x - vtx1->x) / (vtx0->y - vtx1->y);
  135. }
  136.  
  137. FW_Boolean SL_API FW_HitTestPolygon(long pointCount, const FW_SPoint* points, const FW_SPoint& point)
  138. {
  139.     // No try block necessary - Do not throw
  140.  
  141.     FW_Boolean yFlag0, yFlag1, isInside = FALSE, xFlag0;
  142.  
  143.     FW_Fixed tx = point.x;
  144.     FW_Fixed ty = point.y;
  145.  
  146.     const FW_SPoint* vtx0 = points + pointCount - 1;
  147.     const FW_SPoint* vtx1 = points;
  148.  
  149.     yFlag0 = vtx0->y >= ty;
  150.  
  151.     for(long j = 0; j < pointCount; j ++)
  152.     {
  153.         yFlag1 = vtx1->y >= ty;
  154.  
  155.         if(yFlag1 != yFlag0)
  156.         {
  157.             xFlag0 = vtx0->x >= tx;
  158.  
  159.             if(xFlag0 == (vtx1->x >= tx))
  160.             {
  161.                 if(xFlag0)
  162.                     isInside = !isInside;
  163.             }
  164.             else
  165.             {
  166.                 if(::XIntersect(vtx0, vtx1, ty) >= tx)
  167.                     isInside = !isInside;
  168.             }
  169.         }
  170.  
  171.         yFlag0 = yFlag1;
  172.         vtx0 = vtx1;
  173.         vtx1 ++;
  174.     }
  175.  
  176.     return isInside;
  177. }
  178.  
  179. //----------------------------------------------------------------------------------------
  180. //    FW_PtInOval
  181. //----------------------------------------------------------------------------------------
  182.  
  183. FW_Boolean SL_API FW_PtInOval(const FW_SRect& ovalRect, const FW_SPoint& test)
  184. {
  185.     // No try block necessary - Do not throw
  186.  
  187.     // A brief refresher in fifth-grade geometry:
  188.     
  189.     // An ellipse (not an oval!) is defined as a set of points such as:
  190.     //    (x - x0/a)^2 + (y - y0/b)^2 <= 1, where:
  191.     //    <x0, y0> is the center of the ellipse
  192.     //    a is the x-radius and b is the y-radius
  193.  
  194.     // It is possible to get rid of division by evaluating
  195.     //    (bx)^2 + (ay)^2 <= a^2 * b^2, but this can overflow real easy
  196.  
  197.     FW_CRect Oval = ovalRect;
  198.     if(Oval.Contains(test))
  199.     {
  200.         // Adjust center by 0.5 because of rounding
  201.         FW_Fixed xMiddle = FW_Half(ovalRect.left + ovalRect.right  - FW_kFixedPos1);
  202.         FW_Fixed yMiddle = FW_Half(ovalRect.top  + ovalRect.bottom - FW_kFixedPos1);
  203.  
  204.         FW_Fixed a = FW_Half(ovalRect.right - ovalRect.left);
  205.         FW_Fixed b = FW_Half(ovalRect.bottom - ovalRect.top);
  206.         
  207.         FW_Fixed xa = (test.x - xMiddle) / a;
  208.         xa *= xa;
  209.         
  210.         FW_Fixed xb = (test.y - yMiddle) / b;
  211.         xb *= xb;
  212.         
  213.         return xa + xb <= FW_IntToFixed(1);
  214.     }
  215.  
  216.     return FALSE;
  217. }
  218.  
  219. //----------------------------------------------------------------------------------------
  220. //    FW_PtInRoundRect
  221. //----------------------------------------------------------------------------------------
  222.  
  223. FW_Boolean SL_API FW_PtInRoundRect(const FW_SRect& rect, const FW_SPoint& ovalSize, const FW_SPoint& test)
  224. {
  225.     // No try block necessary - Do not throw
  226.  
  227.     FW_CRect r = rect;
  228.     if(r.Contains(test))
  229.     {
  230.         // Find out if the test point may be inside of one of four corner ovals
  231.     
  232.         FW_CRect rectOval;
  233.  
  234.         FW_Fixed halfX = FW_Half(ovalSize.x);
  235.         FW_Fixed halfY = FW_Half(ovalSize.y);
  236.  
  237.         if(test.x < rect.left + halfX)
  238.         {
  239.             // Top-left and bottom-left ovals
  240.             rectOval.left = rect.left;
  241.             rectOval.right = rect.left + ovalSize.x;
  242.         }
  243.         else if(test.x > rect.right - halfX)
  244.         {
  245.             // Top-right and bottom-right ovals
  246.             rectOval.left = rect.right - ovalSize.x;
  247.             rectOval.right = rect.right;
  248.         }
  249.  
  250.         if(test.y < rect.top + halfY)
  251.         {
  252.             // Top-left and top-right
  253.             rectOval.top = rect.top;
  254.             rectOval.bottom = rect.top + ovalSize.y;
  255.         }
  256.         else if(test.y > rect.bottom - halfY)
  257.         {
  258.             // Bottom-left and bottom-right ovals
  259.             rectOval.top = rect.bottom - ovalSize.y;
  260.             rectOval.bottom = rect.bottom;
  261.         }
  262.  
  263.         if(rectOval.IsEmpty())
  264.             return TRUE;
  265.  
  266.         return ::FW_PtInOval(rectOval, test);
  267.     }
  268.  
  269.     return FALSE;
  270. }
  271.  
  272. #ifdef FW_DEBUG
  273. //----------------------------------------------------------------------------------------
  274. // ::Priv_FormatPoint
  275. //----------------------------------------------------------------------------------------
  276.  
  277. static void Priv_FormatPoint(char *s, const char* prompt, const FW_SPoint& point)
  278. {
  279.     sprintf(s, "%s X: %f Y: %f", prompt, FW_FixedToDouble(point.x), FW_FixedToDouble(point.y));
  280. }
  281. #endif
  282.  
  283. #ifdef FW_DEBUG
  284. //----------------------------------------------------------------------------------------
  285. // ::Priv_FormatRect
  286. //----------------------------------------------------------------------------------------
  287.  
  288. static void Priv_FormatRect(char *s, const char* prompt, const FW_SRect& rect)
  289. {
  290.     sprintf(s, "%s left: %f top: %f right: %f bottom: %f",
  291.                 prompt, 
  292.                 FW_FixedToDouble(rect.left), 
  293.                 FW_FixedToDouble(rect.top),
  294.                 FW_FixedToDouble(rect.right), 
  295.                 FW_FixedToDouble(rect.bottom));
  296. }
  297. #endif
  298.  
  299. //----------------------------------------------------------------------------------------
  300. // ::FW_LogPoint
  301. //----------------------------------------------------------------------------------------
  302.  
  303. FW_EXPORT void SL_API FW_LogPoint(Environment* ev, const char* prompt, const FW_SPoint& point)
  304. {
  305.     // No try block necessary - Do not throw
  306. FW_UNUSED(ev);
  307. #ifndef FW_DEBUG
  308.     FW_UNUSED(prompt);
  309.     FW_UNUSED(point);
  310. #else
  311.     char s[255];
  312.     Priv_FormatPoint(s, prompt, point);
  313.     FW_CDebugConsole::LogMessage(s);
  314. #endif
  315. }
  316.  
  317. //----------------------------------------------------------------------------------------
  318. // ::FW_LogRect
  319. //----------------------------------------------------------------------------------------
  320.  
  321. FW_EXPORT void SL_API FW_LogRect(Environment* ev, const char* prompt, const FW_SRect& rect)
  322. {
  323.     // No try block necessary - Do not throw
  324. FW_UNUSED(ev);
  325. #ifndef FW_DEBUG
  326.     FW_UNUSED(prompt);
  327.     FW_UNUSED(rect);
  328. #else
  329.     char s[255];
  330.     Priv_FormatRect(s, prompt, rect);
  331.     FW_CDebugConsole::LogMessage(s);
  332. #endif
  333. }
  334.  
  335. //----------------------------------------------------------------------------------------
  336. // ::FW_LogShape
  337. //----------------------------------------------------------------------------------------
  338.  
  339. FW_EXPORT void SL_API FW_LogShape(Environment* ev, const char* prompt, ODShape* shape)
  340. {
  341.     // No try block necessary - Do not throw
  342. #ifndef FW_DEBUG
  343.     FW_UNUSED(ev);
  344.     FW_UNUSED(prompt);
  345.     FW_UNUSED(shape);
  346. #else
  347.     FW_CRect rect;
  348.     shape->GetBoundingBox(ev, (ODRect*) &rect);
  349.     FW_LogRect(ev, prompt, rect);
  350. #endif
  351. }
  352.  
  353. //----------------------------------------------------------------------------------------
  354. // ::FW_LogTransform
  355. //----------------------------------------------------------------------------------------
  356.  
  357. FW_EXPORT void SL_API FW_LogTransform(Environment* ev, const char* prompt, ODTransform* transform)
  358. {
  359.     // No try block necessary - Do not throw
  360. #ifndef FW_DEBUG
  361.     FW_UNUSED(ev);
  362.     FW_UNUSED(prompt);
  363.     FW_UNUSED(transform);
  364. #else
  365.     FW_CPoint ptScale;
  366.     transform->GetScale(ev, (ODPoint*) &ptScale);
  367.  
  368.     FW_CPoint ptOffset;
  369.     transform->GetOffset(ev, (ODPoint*) &ptOffset);
  370.  
  371.     char s[128];
  372.     ::sprintf(s,
  373.         "xform: %s: pt * [%.2f, %.2f] + [%.2f, %.2f]\n",
  374.         prompt,
  375.         FW_FixedToDouble(ptScale.x),            FW_FixedToDouble(ptScale.y),
  376.         FW_FixedToDouble(ptOffset.x),            FW_FixedToDouble(ptOffset.y)
  377.     );
  378.     FW_CDebugConsole::LogMessage(s);
  379. #endif
  380. }
  381.  
  382. /*
  383. #ifdef FW_BUILD_MAC
  384. //----------------------------------------------------------------------------------------
  385. // ::FW_PrivMacShowColorTable
  386. //----------------------------------------------------------------------------------------
  387.  
  388. void SL_API FW_PrivMacShowColorTable(CTabHandle cth)
  389. {
  390. #ifdef FW_DEBUG
  391.     if (cth == NULL)
  392.         return;
  393.  
  394.     short nColors = (*cth)->ctSize + 1;
  395.  
  396.     short cellSize;
  397.     short xCount, yCount;
  398.     
  399.     if (nColors == 256)
  400.     {
  401.         cellSize = 30;
  402.         xCount = 16;
  403.         yCount = 16;
  404.     }
  405.     else
  406.     {
  407.         cellSize = 50;
  408.         xCount = 4;
  409.         yCount = nColors / xCount;
  410.     }
  411.     
  412.     GDHandle gd = ::GetMainDevice();
  413.     if ((*gd)->gdNextGD != NULL)
  414.         gd = (GDHandle) (*gd)->gdNextGD;
  415.  
  416.     PixMapHandle pmh = (*gd)->gdPMap;
  417.  
  418.     Rect rect;
  419.     rect.left    = (*pmh)->bounds.left + 50;
  420.     rect.top    = (*pmh)->bounds.top + 50;
  421.     rect.right    = rect.left + cellSize * xCount;
  422.     rect.bottom = rect.top + cellSize * yCount;
  423.  
  424.     WindowPtr window = ::NewCWindow(NULL, &rect, "\pColor table", TRUE,
  425.         noGrowDocProc, (WindowPtr) -1L, FALSE, 0);
  426.  
  427.     if (window != NULL)
  428.     {
  429.         FW_CMacTempPort port = window;
  430.         
  431.         short nCurColor = 0;
  432.         for (short xColor = 0; xColor < xCount; ++ xColor)
  433.         {
  434.             for (short yColor = 0; yColor < yCount; ++ yColor)
  435.             {
  436.                 ::RGBBackColor(&(*cth)->ctTable[nCurColor].rgb);
  437.  
  438.                 Rect cell;
  439.                 cell.left    = xColor * cellSize;
  440.                 cell.top    = yColor * cellSize;
  441.                 cell.right    = cell.left + cellSize;
  442.                 cell.bottom    = cell.top + cellSize;
  443.                 ::EraseRect(&cell);
  444.                 
  445.                 ++ nCurColor;
  446.             }
  447.         }
  448.     }
  449.     
  450.     if (window != NULL)
  451.         ::DisposeWindow(window);
  452. #endif
  453. }
  454. #endif
  455. */
  456.