home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-09-17 | 11.4 KB | 456 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: SLGrUtil.cpp
- // Release Version: $ ODF 2 $
- //
- // Copyright (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "FWOS.hpp"
-
- #ifndef SLGRUTIL_H
- #include "SLGrUtil.h"
- #endif
-
- #ifndef FWRECT_H
- #include "FWRect.h"
- #endif
-
- #ifndef FWPOINT_H
- #include "FWPoint.h"
- #endif
-
- #ifndef FWFXMATH_H
- #include "FWFxMath.h"
- #endif
-
- #ifndef FWGRUTIL_H
- #include "FWGrUtil.h"
- #endif
-
- #ifndef FWPRIDEB_H
- #include "FWPriDeb.h"
- #endif
-
- #include <stdio.h>
-
- #ifdef FW_BUILD_MAC
- #pragma segment FWGraphx_SLGrUtil
- #endif
-
- //----------------------------------------------------------------------------------------
- // FW_RegionCode
- //----------------------------------------------------------------------------------------
- //
- // 1001 (9) | 0001 (1) | 0101 (5)
- // --------------------------------
- // 1000 (8) | 0000 (0) | 0100 (4)
- // --------------------------------
- // 1010 (10) | 0010 (2) | 0110 (6)
- //
- short SL_API FW_RegionCode(const FW_SPoint& line, const FW_SRect& rect)
- {
- // No try block necessary - Do not throw
- short regionCode = 0;
- if (line.x < rect.left)
- regionCode = 0x0008;
- else if (line.x > rect.right)
- regionCode = 0x0004;
-
- if (line.y < rect.top)
- regionCode |= 0x0001;
- else if (line.y > rect.bottom)
- regionCode |= 0x0002;
-
- return regionCode;
- }
-
- //----------------------------------------------------------------------------------------
- // ::FW_HitTestLine
- //----------------------------------------------------------------------------------------
- // Uses a modified Cohen-Suterland with midpoint subdivision. Here we don't try to clip but
- // just to find if a line intersect a rectangle of size 2*tolerance
-
- FW_Boolean SL_API FW_HitTestLine(const FW_SPoint& pt1, const FW_SPoint& pt2,
- const FW_SPoint& test, FW_Fixed tolerance)
- {
- // No try block necessary - Do not throw
-
- FW_CRect rect(test.x - tolerance,
- test.y - tolerance,
- test.x + tolerance,
- test.y + tolerance);
-
- short regionCode1, regionCode2, middleCode;
-
- if ((regionCode1 = FW_RegionCode(pt1, rect)) == 0)
- return TRUE; // start is inside the rectangle
-
- if ((regionCode2 = FW_RegionCode(pt2, rect)) == 0)
- return TRUE; // end is inside the rectangle
-
- if ((regionCode1 & regionCode2) != 0)
- return FALSE; // line totally outside
-
- FW_CPoint h1(pt1), h2(pt2);
- FW_CPoint middle(FW_Half(h1.x + h2.x), FW_Half(h1.y + h2.y));
-
- while (middle != h1 && middle != h2)
- {
- if ((middleCode = FW_RegionCode(middle, rect)) == 0)
- return TRUE; // middle is in the rectangle
-
- if ((middleCode & regionCode1) != 0)
- {
- // line (middle, h1) outside the rectangle
- h1 = middle;
- regionCode1 = middleCode;
- }
- else
- {
- // line (h2, middle) outside the rectangle
- h2 = middle;
- regionCode2 = middleCode;
- }
-
- if ((regionCode1 & regionCode2) != 0)
- return FALSE; // line (h1, h2) totally outside
-
- middle.Set(FW_Half(h1.x + h2.x), FW_Half(h1.y + h2.y));
- }
-
- return FALSE;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_HitTestPolygon
- //
- // Crossings algorithm, Graphics Gems IV, article I.4
- //----------------------------------------------------------------------------------------
-
- static FW_Fixed XIntersect(const FW_SPoint* vtx0, const FW_SPoint* vtx1, FW_Fixed ty)
- {
- return vtx1->x - FW_WideMultiply(vtx1->y - ty, vtx0->x - vtx1->x) / (vtx0->y - vtx1->y);
- }
-
- FW_Boolean SL_API FW_HitTestPolygon(long pointCount, const FW_SPoint* points, const FW_SPoint& point)
- {
- // No try block necessary - Do not throw
-
- FW_Boolean yFlag0, yFlag1, isInside = FALSE, xFlag0;
-
- FW_Fixed tx = point.x;
- FW_Fixed ty = point.y;
-
- const FW_SPoint* vtx0 = points + pointCount - 1;
- const FW_SPoint* vtx1 = points;
-
- yFlag0 = vtx0->y >= ty;
-
- for(long j = 0; j < pointCount; j ++)
- {
- yFlag1 = vtx1->y >= ty;
-
- if(yFlag1 != yFlag0)
- {
- xFlag0 = vtx0->x >= tx;
-
- if(xFlag0 == (vtx1->x >= tx))
- {
- if(xFlag0)
- isInside = !isInside;
- }
- else
- {
- if(::XIntersect(vtx0, vtx1, ty) >= tx)
- isInside = !isInside;
- }
- }
-
- yFlag0 = yFlag1;
- vtx0 = vtx1;
- vtx1 ++;
- }
-
- return isInside;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PtInOval
- //----------------------------------------------------------------------------------------
-
- FW_Boolean SL_API FW_PtInOval(const FW_SRect& ovalRect, const FW_SPoint& test)
- {
- // No try block necessary - Do not throw
-
- // A brief refresher in fifth-grade geometry:
-
- // An ellipse (not an oval!) is defined as a set of points such as:
- // (x - x0/a)^2 + (y - y0/b)^2 <= 1, where:
- // <x0, y0> is the center of the ellipse
- // a is the x-radius and b is the y-radius
-
- // It is possible to get rid of division by evaluating
- // (bx)^2 + (ay)^2 <= a^2 * b^2, but this can overflow real easy
-
- FW_CRect Oval = ovalRect;
- if(Oval.Contains(test))
- {
- // Adjust center by 0.5 because of rounding
- FW_Fixed xMiddle = FW_Half(ovalRect.left + ovalRect.right - FW_kFixedPos1);
- FW_Fixed yMiddle = FW_Half(ovalRect.top + ovalRect.bottom - FW_kFixedPos1);
-
- FW_Fixed a = FW_Half(ovalRect.right - ovalRect.left);
- FW_Fixed b = FW_Half(ovalRect.bottom - ovalRect.top);
-
- FW_Fixed xa = (test.x - xMiddle) / a;
- xa *= xa;
-
- FW_Fixed xb = (test.y - yMiddle) / b;
- xb *= xb;
-
- return xa + xb <= FW_IntToFixed(1);
- }
-
- return FALSE;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PtInRoundRect
- //----------------------------------------------------------------------------------------
-
- FW_Boolean SL_API FW_PtInRoundRect(const FW_SRect& rect, const FW_SPoint& ovalSize, const FW_SPoint& test)
- {
- // No try block necessary - Do not throw
-
- FW_CRect r = rect;
- if(r.Contains(test))
- {
- // Find out if the test point may be inside of one of four corner ovals
-
- FW_CRect rectOval;
-
- FW_Fixed halfX = FW_Half(ovalSize.x);
- FW_Fixed halfY = FW_Half(ovalSize.y);
-
- if(test.x < rect.left + halfX)
- {
- // Top-left and bottom-left ovals
- rectOval.left = rect.left;
- rectOval.right = rect.left + ovalSize.x;
- }
- else if(test.x > rect.right - halfX)
- {
- // Top-right and bottom-right ovals
- rectOval.left = rect.right - ovalSize.x;
- rectOval.right = rect.right;
- }
-
- if(test.y < rect.top + halfY)
- {
- // Top-left and top-right
- rectOval.top = rect.top;
- rectOval.bottom = rect.top + ovalSize.y;
- }
- else if(test.y > rect.bottom - halfY)
- {
- // Bottom-left and bottom-right ovals
- rectOval.top = rect.bottom - ovalSize.y;
- rectOval.bottom = rect.bottom;
- }
-
- if(rectOval.IsEmpty())
- return TRUE;
-
- return ::FW_PtInOval(rectOval, test);
- }
-
- return FALSE;
- }
-
- #ifdef FW_DEBUG
- //----------------------------------------------------------------------------------------
- // ::Priv_FormatPoint
- //----------------------------------------------------------------------------------------
-
- static void Priv_FormatPoint(char *s, const char* prompt, const FW_SPoint& point)
- {
- sprintf(s, "%s X: %f Y: %f", prompt, FW_FixedToDouble(point.x), FW_FixedToDouble(point.y));
- }
- #endif
-
- #ifdef FW_DEBUG
- //----------------------------------------------------------------------------------------
- // ::Priv_FormatRect
- //----------------------------------------------------------------------------------------
-
- static void Priv_FormatRect(char *s, const char* prompt, const FW_SRect& rect)
- {
- sprintf(s, "%s left: %f top: %f right: %f bottom: %f",
- prompt,
- FW_FixedToDouble(rect.left),
- FW_FixedToDouble(rect.top),
- FW_FixedToDouble(rect.right),
- FW_FixedToDouble(rect.bottom));
- }
- #endif
-
- //----------------------------------------------------------------------------------------
- // ::FW_LogPoint
- //----------------------------------------------------------------------------------------
-
- FW_EXPORT void SL_API FW_LogPoint(Environment* ev, const char* prompt, const FW_SPoint& point)
- {
- // No try block necessary - Do not throw
- FW_UNUSED(ev);
- #ifndef FW_DEBUG
- FW_UNUSED(prompt);
- FW_UNUSED(point);
- #else
- char s[255];
- Priv_FormatPoint(s, prompt, point);
- FW_CDebugConsole::LogMessage(s);
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // ::FW_LogRect
- //----------------------------------------------------------------------------------------
-
- FW_EXPORT void SL_API FW_LogRect(Environment* ev, const char* prompt, const FW_SRect& rect)
- {
- // No try block necessary - Do not throw
- FW_UNUSED(ev);
- #ifndef FW_DEBUG
- FW_UNUSED(prompt);
- FW_UNUSED(rect);
- #else
- char s[255];
- Priv_FormatRect(s, prompt, rect);
- FW_CDebugConsole::LogMessage(s);
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // ::FW_LogShape
- //----------------------------------------------------------------------------------------
-
- FW_EXPORT void SL_API FW_LogShape(Environment* ev, const char* prompt, ODShape* shape)
- {
- // No try block necessary - Do not throw
- #ifndef FW_DEBUG
- FW_UNUSED(ev);
- FW_UNUSED(prompt);
- FW_UNUSED(shape);
- #else
- FW_CRect rect;
- shape->GetBoundingBox(ev, (ODRect*) &rect);
- FW_LogRect(ev, prompt, rect);
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // ::FW_LogTransform
- //----------------------------------------------------------------------------------------
-
- FW_EXPORT void SL_API FW_LogTransform(Environment* ev, const char* prompt, ODTransform* transform)
- {
- // No try block necessary - Do not throw
- #ifndef FW_DEBUG
- FW_UNUSED(ev);
- FW_UNUSED(prompt);
- FW_UNUSED(transform);
- #else
- FW_CPoint ptScale;
- transform->GetScale(ev, (ODPoint*) &ptScale);
-
- FW_CPoint ptOffset;
- transform->GetOffset(ev, (ODPoint*) &ptOffset);
-
- char s[128];
- ::sprintf(s,
- "xform: %s: pt * [%.2f, %.2f] + [%.2f, %.2f]\n",
- prompt,
- FW_FixedToDouble(ptScale.x), FW_FixedToDouble(ptScale.y),
- FW_FixedToDouble(ptOffset.x), FW_FixedToDouble(ptOffset.y)
- );
- FW_CDebugConsole::LogMessage(s);
- #endif
- }
-
- /*
- #ifdef FW_BUILD_MAC
- //----------------------------------------------------------------------------------------
- // ::FW_PrivMacShowColorTable
- //----------------------------------------------------------------------------------------
-
- void SL_API FW_PrivMacShowColorTable(CTabHandle cth)
- {
- #ifdef FW_DEBUG
- if (cth == NULL)
- return;
-
- short nColors = (*cth)->ctSize + 1;
-
- short cellSize;
- short xCount, yCount;
-
- if (nColors == 256)
- {
- cellSize = 30;
- xCount = 16;
- yCount = 16;
- }
- else
- {
- cellSize = 50;
- xCount = 4;
- yCount = nColors / xCount;
- }
-
- GDHandle gd = ::GetMainDevice();
- if ((*gd)->gdNextGD != NULL)
- gd = (GDHandle) (*gd)->gdNextGD;
-
- PixMapHandle pmh = (*gd)->gdPMap;
-
- Rect rect;
- rect.left = (*pmh)->bounds.left + 50;
- rect.top = (*pmh)->bounds.top + 50;
- rect.right = rect.left + cellSize * xCount;
- rect.bottom = rect.top + cellSize * yCount;
-
- WindowPtr window = ::NewCWindow(NULL, &rect, "\pColor table", TRUE,
- noGrowDocProc, (WindowPtr) -1L, FALSE, 0);
-
- if (window != NULL)
- {
- FW_CMacTempPort port = window;
-
- short nCurColor = 0;
- for (short xColor = 0; xColor < xCount; ++ xColor)
- {
- for (short yColor = 0; yColor < yCount; ++ yColor)
- {
- ::RGBBackColor(&(*cth)->ctTable[nCurColor].rgb);
-
- Rect cell;
- cell.left = xColor * cellSize;
- cell.top = yColor * cellSize;
- cell.right = cell.left + cellSize;
- cell.bottom = cell.top + cellSize;
- ::EraseRect(&cell);
-
- ++ nCurColor;
- }
- }
- }
-
- if (window != NULL)
- ::DisposeWindow(window);
- #endif
- }
- #endif
- */
-