home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / opendc12.zip / od124os2.exe / od12osp1.exe / src / utils / AltPoly.cpp < prev    next >
C/C++ Source or Header  |  1997-04-02  |  42KB  |  1,633 lines

  1. /* @(#)Z 1.34 com/src/pubutils/src/AltPoly.cpp, odpubutils, od96os2, odos29712d 97/03/21 17:21:16 (96/10/29 09:28:46) */
  2. //====START_GENERATED_PROLOG======================================
  3. //
  4. //
  5. //   COMPONENT_NAME: odpubutils
  6. //
  7. //   CLASSES: none
  8. //
  9. //   ORIGINS: 82,27,94
  10. //
  11. //
  12. //   (C) COPYRIGHT International Business Machines Corp. 1995,1996
  13. //   All Rights Reserved
  14. //   Licensed Materials - Property of IBM
  15. //   US Government Users Restricted Rights - Use, duplication or
  16. //   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  17. //       
  18. //   IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  19. //   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  20. //   PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  21. //   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  22. //   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  23. //   OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  24. //   OR PERFORMANCE OF THIS SOFTWARE.
  25. //
  26. //====END_GENERATED_PROLOG========================================
  27. //
  28.  
  29. /*
  30.     File:        AltPoly.cpp
  31.  
  32.     Contains:    OpenDoc polygon: optional C++ savvy classes
  33.  
  34.     Owned by:    Jens Alfke
  35.  
  36.     Copyright:    ⌐ 1993 - 1995 by Apple Computer, Inc., all rights reserved.
  37.  
  38.     To Do:
  39.                   
  40.         Improve the equality tests for contours and polygons. See comments
  41.         in the two "operator==" methods for details.
  42.     
  43.     In Progress:
  44.         
  45. */
  46.  
  47. #define _OD_DONT_IMPORT_CPP_
  48.  
  49. #ifndef _ALTPOINT_
  50. #include "AltPoint.h"            // Use C++ savvy ODPoint and ODRect
  51. #endif
  52.  
  53. #ifndef _ALTPOLY_
  54. #include "AltPoly.h"
  55. #endif
  56.  
  57. #ifndef SOM_ODTransform_xh
  58. #include "Trnsform.xh"
  59. #endif
  60.  
  61. #ifndef _LINEOPS_
  62. #include "LineOps.h"
  63. #endif
  64.  
  65. #ifndef _ODMEMORY_
  66. #include "ODMemory.h"
  67. #endif
  68.  
  69. #ifndef _ODEXCEPT_
  70. #include "ODExcept.h"
  71. #endif
  72.  
  73. #ifndef SOM_ODStorageUnit_xh
  74. #include "StorageU.xh"
  75. #endif
  76.  
  77. #ifndef _STDTYPES_
  78. #include "StdTypes.xh"
  79. #endif
  80.  
  81. #ifndef _ODDEBUG_
  82. #include "ODDebug.h"
  83. #endif
  84.  
  85. #ifndef _STORUTIL_
  86. #include <StorUtil.h>
  87. #endif
  88.  
  89. #ifndef _STDTYPIO_
  90. #include <StdTypIO.h>
  91. #endif
  92.  
  93. #ifndef _UTILERRS_
  94. #include "UtilErrs.h"
  95. #endif
  96.  
  97. #ifdef _PLATFORM_MACINTOSH_
  98.     #ifndef __GXERRORS__
  99.     #include "GXErrors.h"
  100.     #endif
  101.     #ifndef __GXGRAPHICS__
  102.     #include "GXGraphics.h"
  103.     #endif
  104. #endif
  105.  
  106. #include <stddef.h>                    // Defines offsetof() macro
  107.  
  108. #ifndef _ODDEBUG_
  109. #include "ODDebug.h"
  110. #endif
  111.  
  112. #ifdef _PLATFORM_AIX_
  113. #ifndef _ODMATH_
  114. #include "ODMath.h"
  115. #endif
  116. Region DrawToXRegion(ODContour* temp_contour);
  117. ODBoolean IsPositive(ODContour* target_contour);
  118. #endif  // _PLATFORM_AIX_
  119.  
  120. #if ((defined (_PLATFORM_WIN32_) || defined (_PLATFORM_OS2_)) \
  121.       || defined (_PLATFORM_AIX_) ) && defined(DEBUG)
  122. #include <stdio.h>
  123.  
  124. #define CHECKRES(x) \
  125.   if( ( x ) ) \
  126.       printf("PASS\n"); \
  127.   else \
  128.       printf("FAIL\n");
  129.  
  130.   struct MyContour   // Used in ODPolygon::SelfTest
  131.   {             // Microsoft Visual C++ won't allow this in ODPolygon::SelfTest
  132.     ODSLong nVertices;
  133.     ODPoint vertex [4];
  134.   };
  135.  
  136.   struct MyPolygonData  // Used in ODPolygon::SelfTest 
  137.   {             // Microsoft Visual C++ won't allow this in ODPolygon::SelfTest
  138.     ODSLong nContours;
  139.     MyContour firstContour;
  140.   };
  141. #endif // defined (_PLATFORM_WIN32_ || OS2 || AIX ) && defined(DEBUG)
  142.  
  143. const ODSLong kMaxLong    = 0x7FFFFFFF;
  144.  
  145. #ifdef _PLATFORM_MACINTOSH_
  146. #pragma segment ODShape
  147. #endif  // _PLATFORM_MACINTOSH_
  148.  
  149. //==============================================================================
  150. // Destructos
  151. //==============================================================================
  152.  
  153.  
  154. WIN32_DLLEXPORT ODTempPolygon::ODTempPolygon( )
  155. {
  156.     // This constructor doesn't do anything special, but if not declared it will
  157.     // be inlined at the call site, resulting in lots of extra code due to the
  158.     // multiple inheritance.
  159. }
  160.  
  161.  
  162. WIN32_DLLEXPORT ODTempPolygon::~ODTempPolygon( )
  163. {
  164.     this->Clear();
  165. }
  166.  
  167.  
  168. WIN32_DLLEXPORT ODTempPolygonPtr::ODTempPolygonPtr( )
  169.     :fPoly(kODNULL)
  170. {
  171. }
  172.  
  173.  
  174. WIN32_DLLEXPORT ODTempPolygonPtr::ODTempPolygonPtr( ODPolygon *p )
  175.     :fPoly(p)
  176. {
  177. }
  178.  
  179.  
  180. WIN32_DLLEXPORT ODTempPolygonPtr::~ODTempPolygonPtr( )
  181. {
  182.     delete fPoly;
  183.     fPoly = kODNULL;
  184. }
  185.  
  186.  
  187. #ifdef _PLATFORM_MACINTOSH_
  188. TempGXShape::TempGXShape( )
  189.     :fShape(kODNULL)
  190. {
  191. }
  192.  
  193.  
  194. TempGXShape::TempGXShape( gxShape s )
  195.     :fShape(s)
  196. {
  197. }
  198.  
  199.  
  200. TempGXShape::~TempGXShape( )
  201. {
  202.     if( fShape ) {
  203.         GXDisposeShape(fShape);
  204.         fShape = kODNULL;
  205.     }
  206. }
  207.  
  208. #endif // _PLATFORM_MACINTOSH_
  209.  
  210. //==============================================================================
  211. // QuickDraw GX Utilities
  212. //==============================================================================
  213.  
  214.  
  215. #ifdef _PLATFORM_MACINTOSH_
  216. #pragma segment QDGXShape
  217.  
  218.  
  219. static void
  220. ClearGXError( )
  221. {
  222.     GXGetGraphicsError(kODNULL);
  223.     // GX error status is cleared after asking for errors.
  224. }
  225.  
  226.  
  227. static void
  228. ThrowIfGXError( )
  229. {
  230.     gxGraphicsError err = GXGetGraphicsError(kODNULL);    // Get latest graphics error
  231.     if( err )
  232.         THROW(err,"QuickDraw GX error");
  233. }
  234.  
  235.  
  236. static void
  237. ThrowIfFirstGXError( )
  238. {
  239.     gxGraphicsError err;
  240.     (void) GXGetGraphicsError(&err);            // Get first error, not last
  241.     if( err )
  242.         THROW(err,"QuickDraw GX error");
  243. }
  244.  
  245. #endif // _PLATFORM_MACINTOSH_
  246.  
  247. /******************************************************************************/
  248. //**    ALLOCATION
  249. /******************************************************************************/
  250.  
  251.  
  252. WIN32_DLLEXPORT ODPolygon::ODPolygon( )
  253.     :_maximum(0),
  254.      _length(0),
  255.      _buf(kODNULL)
  256. {
  257. }
  258.  
  259.  
  260. #if ODDebug
  261. ODPolygon::~ODPolygon( )
  262. {
  263.     // To help catch double-deletes of ODPolygon structures!
  264.     _buf = (ODPolygonData*)0xDDDDDDDD;
  265.     _length = _maximum = 0xDDDDDDDD;
  266. }
  267. #endif
  268.  
  269.  
  270. WIN32_DLLEXPORT void
  271. ODPolygon::Delete( )
  272. {
  273.     ODDisposePtr(_buf);
  274.     delete this;
  275. }
  276.  
  277.  
  278. WIN32_DLLEXPORT void
  279. ODPolygon::Clear( )
  280. {
  281.     ODDisposePtr(_buf);
  282.     _buf = kODNULL;
  283.     _length = _maximum = 0;
  284. }
  285.  
  286.  
  287. static ODULong
  288. CalcDataSize( ODSLong nVertices )
  289. {
  290.     if( nVertices==0 )
  291.         return 0;
  292.     else
  293. #if ( (defined (_PLATFORM_WIN32_) || defined(_PLATFORM_OS2_))  \
  294.        || defined(_PLATFORM_AIX_) )
  295.         return sizeof(ODPolygonData)+(nVertices-1)*sizeof(ODPoint);
  296. #else
  297.         return offsetof(ODPolygonData,firstContour.vertex[nVertices]);
  298. #endif // _PLATFORM_WIN32_ || _PLATFORM_OS2_ || _PLATFORM_AIX_
  299. }
  300.  
  301.  
  302. void
  303. ODPolygon::Realloc( ODULong dataSize )
  304. {
  305.     if( _buf!=kODNULL && dataSize>=_length && dataSize<=_maximum )
  306.         _length = dataSize;
  307.     else {
  308.         ODPtr newData;
  309.         if( dataSize!=0 )
  310.             newData = ODNewPtr(dataSize);
  311.         ODDisposePtr(_buf);
  312.         if( dataSize!=0 )
  313.             _buf = (ODPolygonData*)newData;
  314.         else
  315.             _buf = kODNULL;
  316.         _length = _maximum = dataSize;
  317.     }
  318. }
  319.  
  320.  
  321. WIN32_DLLEXPORT void
  322. ODPolygon::SetData( const ODPolygonData *data )
  323. {
  324.     _length = sizeof(ODULong) * (1+data->nContours);
  325.     const ODContour *c = &data->firstContour;
  326.     for( ODULong i=data->nContours; i!=0; i-- ) {
  327.         _length += c->nVertices * sizeof(ODPoint);
  328.         c = c->NextContour();
  329.     }
  330.     
  331.     ODDisposePtr(_buf);
  332.     _buf = (ODPolygonData*)data;
  333.     _maximum = _length;
  334. }
  335.  
  336.  
  337. WIN32_DLLEXPORT ODPolygon*
  338. ODPolygon::SetNVertices( ODSLong nVertices )
  339. {
  340.     ASSERT(nVertices>=0,kODErrValueOutOfRange);
  341.     
  342.     this->Realloc(CalcDataSize(nVertices));
  343.     if( nVertices>0 ) {
  344.         _buf->nContours = 1;
  345.         _buf->firstContour.nVertices = nVertices;
  346.     }
  347.     return this;
  348. }
  349.  
  350.  
  351. WIN32_DLLEXPORT ODPolygon*
  352. ODPolygon::SetVertices( ODSLong nVertices, const ODPoint *vertices )
  353. {
  354.     ASSERT(nVertices>=0,kODErrValueOutOfRange);
  355.     ASSERT(vertices!=kODNULL,kODErrIllegalNullInput);
  356.     
  357.     this->SetNVertices(nVertices);
  358.     if( nVertices>0 )
  359.         ODBlockMove( (void *) vertices, _buf->firstContour.vertex, nVertices*sizeof(ODPoint) );
  360.     return this;
  361. }
  362.  
  363.  
  364. WIN32_DLLEXPORT ODPolygon*
  365. ODPolygon::SetContours( ODSLong nContours, const ODSLong *contourVertices )
  366. {
  367.     ASSERT(nContours>=0,kODErrValueOutOfRange);
  368.     if( nContours==0 )
  369.         return this->SetNVertices(0);
  370.     else {
  371.         ASSERT(contourVertices!=kODNULL,kODErrIllegalNullInput);
  372.         ODULong totalVertices = 0;
  373.         ODSLong i;
  374.         for( i=nContours-1; i>=0; i-- )
  375.             totalVertices += contourVertices[i];
  376.         this->Realloc( offsetof(ODPolygonData,firstContour)
  377.                      + offsetof(ODContour,vertex[0]) * nContours
  378.                      + sizeof(ODPoint)*totalVertices );
  379.         _buf->nContours = nContours;
  380.         ODContour *cont = this->FirstContour();
  381.         for( i=0; i<nContours; i++ ) {
  382.             cont->nVertices = contourVertices[i];
  383.             cont = cont->NextContour();
  384.         }
  385.         return this;
  386.     }
  387. }
  388.  
  389.  
  390. WIN32_DLLEXPORT ODPolygon*
  391. ODPolygon::SetRect( const ODRect &r )
  392. {
  393.     if( r.IsEmpty() )
  394.         return this->SetNVertices(0);
  395.     else {
  396.         this->SetNVertices(4);
  397. #ifdef _PLATFORM_OS2_ 
  398.         _buf->firstContour.vertex[0].Set(r.left,r.bottom); 
  399.         _buf->firstContour.vertex[1] = r.TopLeft(); 
  400.         _buf->firstContour.vertex[2].Set(r.right,r.top); 
  401.         _buf->firstContour.vertex[3] = r.BotRight(); 
  402. #else 
  403.         _buf->firstContour.vertex[0] = r.TopLeft();
  404.         _buf->firstContour.vertex[1].Set(r.right,r.top);
  405.         _buf->firstContour.vertex[2] = r.BotRight();
  406.         _buf->firstContour.vertex[3].Set(r.left,r.bottom);
  407. #endif
  408.     }
  409.     return this;
  410. }
  411.  
  412.  
  413. WIN32_DLLEXPORT ODPolygon*
  414. ODPolygon::CopyFrom( const ODPolygon &poly )
  415. {
  416.     if( poly._buf != _buf ) {
  417.         ODULong size = poly.GetDataSize();
  418.         this->Realloc(size);
  419.         ODBlockMove(poly.GetData(),_buf,size);
  420.     }
  421.     return this;
  422. }
  423.  
  424.  
  425. WIN32_DLLEXPORT ODPolygon*
  426. ODPolygon::MoveFrom( ODPolygon &poly )
  427. {
  428.     if( poly._buf != _buf ) {
  429.         ODDisposePtr(_buf);
  430.         _buf = poly._buf;
  431.         _length = poly._length;
  432.         _maximum = poly._maximum;
  433.     }
  434.     if( &poly._buf != &_buf ) {            // Don't clear poly if it's myself!
  435.         poly._buf = kODNULL;
  436.         poly._length = poly._maximum = 0;
  437.     }
  438.     return this;
  439. }
  440.  
  441.  
  442.  
  443. #ifdef _PLATFORM_MACINTOSH_
  444. #pragma segment ODGXShape
  445.  
  446. ODPolygon*
  447. ODPolygon::CopyFrom( gxShape shape )
  448. {
  449.     ClearGXError();
  450.     TempGXShape copiedShape = GXCopyToShape(kODNULL,shape);
  451.     GXPrimitiveShape(copiedShape);
  452.     GXSimplifyShape(copiedShape);
  453.     GXSetShapeType(copiedShape,gxPolygonType);
  454.     ThrowIfFirstGXError();
  455.     
  456.     ODULong size = GXGetPolygonParts(copiedShape, 1,gxSelectToEnd, kODNULL);
  457.     ThrowIfGXError();
  458.     this->Realloc(size);
  459.     GXGetPolygonParts(copiedShape, 1,gxSelectToEnd, (gxPolygons*)_buf);
  460.     ThrowIfGXError();
  461.     
  462.     return this;
  463. }
  464. #pragma segment ODShape
  465. #endif
  466.  
  467.  
  468. WIN32_DLLEXPORT ODPolygon*
  469. ODPolygon::ReadFrom( Environment *ev, ODStorageUnit *su )
  470. {
  471.  
  472.     if( !su->Exists(ev,kODNULL,kODPolygon,kODPosUndefined) ) {
  473.         this->Clear();
  474.     } else {
  475.         ODPropertyName propName = su->GetProperty(ev);
  476.         ODGetPolygonProp(ev, su, propName, kODPolygon, this);
  477.         ODDisposePtr((ODPtr) propName);
  478.     }
  479.  
  480.     return this;
  481. }
  482.  
  483.  
  484. WIN32_DLLEXPORT ODPolygon*
  485. ODPolygon::WriteTo( Environment *ev, ODStorageUnit *su )  const
  486. {
  487.     ODPropertyName propName = su->GetProperty(ev);
  488.     ODSetPolygonProp(ev, su, propName, kODPolygon, this);
  489.     ODDisposePtr((ODPtr) propName);
  490.     
  491.     return (ODPolygon*)this;
  492. }
  493.  
  494.  
  495. /******************************************************************************/
  496. //**    POLYGON STUFF
  497. /******************************************************************************/
  498.  
  499.  
  500. WIN32_DLLEXPORT ODSLong
  501. ODPolygon::GetNContours( )  const
  502. {
  503.     return _length>0 ?_buf->nContours :0;
  504. }
  505.  
  506.  
  507. WIN32_DLLEXPORT const ODContour*
  508. ODPolygon::FirstContour( )  const
  509. {
  510.     return _length>0 ?&_buf->firstContour :kODNULL;
  511. }
  512.  
  513.  
  514. WIN32_DLLEXPORT ODContour*
  515. ODPolygon::FirstContour( )
  516. {
  517.     return _length>0 ?&_buf->firstContour :kODNULL;
  518. }
  519.  
  520.  
  521. WIN32_DLLEXPORT ODPolygon*
  522. ODPolygon::Copy( ) const
  523. {
  524.     ODTempPolygonPtr poly = new ODPolygon;
  525.     poly->CopyFrom(*this);
  526.     return poly.DontDelete();
  527. }
  528.  
  529.  
  530. WIN32_DLLEXPORT void
  531. ODPolygon::ComputeBoundingBox( ODRect *bbox ) const
  532. {
  533.     ASSERT(bbox!=kODNULL,kODErrIllegalNullInput);
  534.     
  535.     if( _buf==kODNULL || _buf->nContours <= 0 ) {
  536.         bbox->Clear();
  537.         return;
  538.     }
  539.     
  540.     // Start bbox out as maximally empty:
  541. #ifdef _PLATFORM_OS2_ 
  542.         bbox->left = bbox->bottom = kMaxLong; 
  543.         bbox->right = bbox->top   = -kMaxLong; 
  544. #else 
  545.     bbox->left    = bbox->top        =  kMaxLong;
  546.     bbox->right = bbox->bottom    = -kMaxLong;
  547. #endif
  548.     
  549.     const ODContour *c = this->FirstContour();
  550.     for( ODSLong i=this->GetNContours(); i>0; i-- ) {
  551.         ODPoint *pt = (ODPoint*)c->vertex;
  552.         for( ODSLong v=c->nVertices; v>0; v--,pt++ ) {
  553.             if( pt->x < bbox->left )    bbox->left    = pt->x;
  554.             if( pt->x > bbox->right )    bbox->right    = pt->x;
  555. #ifdef _PLATFORM_OS2_ 
  556.                         if( pt->y > bbox->top )  bbox->top = pt->y; 
  557.                         if( pt->y < bbox->bottom ) bbox->bottom = pt->y; 
  558. #else 
  559.             if( pt->y < bbox->top )        bbox->top    = pt->y;
  560.             if( pt->y > bbox->bottom )    bbox->bottom= pt->y;
  561. #endif
  562.         }
  563.         if( i>1 )
  564.             c = c->NextContour();
  565.     }
  566. }
  567.  
  568.  
  569. WIN32_DLLEXPORT ODBoolean
  570. ODContour::operator== ( const ODContour &cont ) const
  571. {
  572.     /*    This test is complicated by the fact that the two contours might have the
  573.         same points, but out of phase. Therefore we have to compare the points
  574.         in sequence, once per possible phase difference.  */
  575.     
  576.     ODSLong nv = this->nVertices;
  577.     if( nv != cont.nVertices )
  578.         return kODFalse;
  579.     
  580.     for( ODSLong phase=0; phase<nv; phase++ ) {
  581.         const ODPoint *p0 = &this->vertex[0];
  582.         const ODPoint *p1 = &cont.vertex[phase];
  583.         ODSLong i;
  584.         for( i=nVertices; i>0; i-- ) {
  585.             if( i==phase )
  586.                 p1 = &cont.vertex[0];
  587.             if( ! (p0++)->ApproxEquals(*p1++) )        // Coords may differ very slightly
  588.                 break;
  589.         }
  590.         if( i==0 )
  591.             return kODTrue;
  592.     }
  593.     return kODFalse;
  594. }
  595.  
  596.  
  597. #if ( (defined (_PLATFORM_WIN32_) || defined(_PLATFORM_OS2_))  \
  598.        || defined(_PLATFORM_AIX_) )
  599. WIN32_DLLEXPORT ODBoolean
  600. #else
  601. Boolean
  602. #endif //  _PLATFORM_WIN32_ || _PLATFORM_OS2_ || _PLATFORM_AIX_
  603. ODPolygon::operator== ( ODPolygon &poly ) const
  604. {
  605.     /*    This test is complicated by the fact that the two polygons may not have their
  606.         contours in the same order. Our approach is to step through my contours in
  607.         order, trying to match each to a unique contour in the target. To ensure
  608.         uniqueness, the sign of the nVertices field in a target contour is flipped
  609.         after it's matched.  */
  610.     
  611.     if( this->GetNContours() != poly.GetNContours() )
  612.         return kODFalse;
  613.     if( &poly == this )
  614.         return kODTrue;
  615.     
  616.     ODBoolean result = kODTrue;
  617.     const ODContour * c = this->FirstContour();
  618.     ODContour *pc;
  619.     
  620.     ODSLong i;
  621.     for( i=this->GetNContours(); i>0; i-- ) {
  622.         pc = poly.FirstContour();
  623.         ODSLong j;
  624.         for( j=poly.GetNContours(); j>0; j-- ) {
  625.             if( pc->nVertices>0 && *c==*pc ) {        // Compare contours!
  626.                 pc->nVertices = -pc->nVertices;        // Use sign bit as a flag (yech)
  627.                 break;
  628.             }
  629.             if( j>1 )
  630. #ifdef OD_BUG // 21439
  631.                 pc = pc->NextContourEx( (abs(pc->nVertices) ) );
  632. #else
  633.                 pc = pc->NextContour();
  634. #endif // OD_BUG
  635.         }
  636.         if( j<=0 ) {
  637.             result = kODFalse;                    // No match for contour
  638.             break;
  639.         }
  640.  
  641.         if( i>1 )
  642.             c = c->NextContour();
  643.     }
  644.  
  645.     // Now that we know, clear all the sign bits:
  646.     pc = poly.FirstContour();
  647.     for( i=poly.GetNContours(); i>0; i-- ) {
  648.         if( pc->nVertices<0 )
  649.             pc->nVertices = -pc->nVertices;
  650.         pc = pc->NextContour();
  651.     }
  652.     return result;
  653. }
  654.  
  655.  
  656. #if ( (defined (_PLATFORM_WIN32_) || defined(_PLATFORM_OS2_))  \
  657.        || defined(_PLATFORM_AIX_) )
  658. WIN32_DLLEXPORT ODBoolean
  659. #else
  660. Boolean
  661. #endif // _PLATFORM_WIN32_ || _PLATFORM_OS2_ || _PLATFORM_AIX_
  662.  
  663. ODPolygon::IsEmpty( ) const
  664. {
  665.     // FIX: This is not very smart. It will probably be necessary to compute the area
  666.     // of each contour...
  667.     
  668.     return _buf==kODNULL || _buf->nContours==0;
  669. }
  670.  
  671. #ifdef OD_BUG  // 21439
  672. WIN32_DLLEXPORT ODContour*
  673. ODContour::NextContourEx(const ODSLong& specifiedVertices )
  674. {
  675. // NextContourEx(plicit)
  676. // This is a workaround to a OD_BUG.  Basically, the 
  677. // ODPolygon::operator== sets the sign bit on the contours that
  678. // it has determined to be equal.  The problem is, when 
  679. // NextContour is called, it takes the vertex and moves up by
  680. // that amount.  Since the sign bit has been set to negative,
  681. // this moves us backwards (i.e., the wrong way) in our contour
  682. // table.  This version of NextContour takes a paramater that 
  683. // allows you to specify the increment.  For us, we basically 
  684. // pass in the same vertex, but we also take the absolute value
  685. // of it as well.
  686.              return   (ODContour*)&vertex[specifiedVertices];
  687. }
  688. #endif // OD_BUG
  689.  
  690. #if ( (defined (_PLATFORM_WIN32_) || defined(_PLATFORM_OS2_))  \
  691.        || defined(_PLATFORM_AIX_) )
  692. WIN32_DLLEXPORT ODBoolean
  693. #else
  694. Boolean
  695. #endif // _PLATFORM_WIN32_ || _PLATFORM_OS2_ || _PLATFORM_AIX_
  696. ODPolygon::IsRectangular( ) const
  697. {
  698.     return _buf==kODNULL || _buf->nContours==0 ||
  699.             (_buf->nContours==1  && _buf->firstContour.IsRectangular());
  700. }
  701.  
  702.  
  703. #if ( (defined (_PLATFORM_WIN32_) || defined(_PLATFORM_OS2_))  \
  704.        || defined(_PLATFORM_AIX_) )
  705. WIN32_DLLEXPORT ODBoolean
  706. #else
  707. Boolean
  708. #endif // _PLATFORM_WIN32_ || _PLATFORM_OS2_ || _PLATFORM_AIX_
  709. ODPolygon::AsRectangle( ODRect *r ) const
  710. {
  711.     if( _buf==kODNULL || _buf->nContours==0 ) {
  712.         r->Clear();
  713.         return kODTrue;
  714.     } else if( _buf->nContours==1 )
  715.         return _buf->firstContour.AsRectangle(r);
  716.     else
  717.         return kODFalse;
  718. }
  719.  
  720.  
  721. #if ( (defined (_PLATFORM_WIN32_) || defined(_PLATFORM_OS2_))  \
  722.        || defined(_PLATFORM_AIX_) )
  723. WIN32_DLLEXPORT ODBoolean
  724. #else
  725. Boolean
  726. #endif // _PLATFORM_WIN32_ || _PLATFORM_OS2_ || _PLATFORM_AIX_
  727. ODContour::IsRectangular( ) const
  728. {
  729.     if( nVertices != 4 )
  730.         return kODFalse;
  731.     else if( vertex[0].x == vertex[1].x )            // 1st edge is vertical
  732.         return vertex[1].y==vertex[2].y
  733.             && vertex[2].x==vertex[3].x
  734.             && vertex[3].y==vertex[0].y;
  735.     else if( vertex[0].y == vertex[1].y )            // 1st edge is horizontal
  736.         return vertex[1].x==vertex[2].x
  737.             && vertex[2].y==vertex[3].y
  738.             && vertex[3].x==vertex[0].x;
  739.     else
  740.         return kODFalse;
  741. }
  742.  
  743.  
  744. #if ( (defined (_PLATFORM_WIN32_) || defined(_PLATFORM_OS2_))  \
  745.        || defined(_PLATFORM_AIX_) )
  746. WIN32_DLLEXPORT ODBoolean
  747. #else
  748. Boolean
  749. #endif // _PLATFORM_WIN32_ || _PLATFORM_OS2_ || _PLATFORM_AIX_
  750. ODContour::AsRectangle( ODRect *r ) const
  751. {
  752.     ASSERT(r!=kODNULL,kODErrIllegalNullInput);
  753.     
  754.     if( this->IsRectangular() ) {
  755.         ODRect r2(vertex[0],vertex[2]);            // C'tor properly orders the coords
  756.         *r = r2;
  757.         return kODTrue;
  758.     } else
  759.         return kODFalse;
  760. }
  761.  
  762.  
  763. /******************************************************************************/
  764. //**    REGION CONVERSION
  765. /******************************************************************************/
  766.  
  767.  
  768. WIN32_DLLEXPORT ODBoolean
  769. ODContour::HasExactRegion( ) const
  770. {
  771.     const ODPoint *b = &vertex[0];
  772. #ifndef _PLATFORM_MACINTOSH_    // OD_BUG
  773.     for( ODSLong i=nVertices; i>0; i-- ) {
  774.         const ODPoint *a = &vertex[i-1];
  775. #else  // The original code uses vertex[i] which is beyond vertex array.
  776.     for( ODSLong i=nVertices; i>=0; i-- ) {
  777.         const ODPoint *a = &vertex[i];
  778. #endif  // OD_BUG
  779.         if( (a->x & 0xFFFF) || (a->y & 0xFFFF) )
  780.             return kODFalse;                        // Non-integer coordinates
  781.         if( a->x!=b->x && a->y!=b->y )
  782.             return kODFalse;                        // Diagonal line
  783.         b = a;
  784.     }
  785.     return kODTrue;
  786. }
  787.  
  788.  
  789. WIN32_DLLEXPORT ODBoolean
  790. ODPolygon::HasExactRegion( ) const
  791. {
  792.     const ODContour *c = this->FirstContour();
  793.     for( long i=this->GetNContours(); i>0; i-- ) {
  794.         if( !c->HasExactRegion() )
  795.             return kODFalse;
  796.         if( i>1 )
  797.             c = c->NextContour();
  798.     }
  799.     return kODTrue;
  800. }
  801.  
  802.  
  803. #ifdef _PLATFORM_MACINTOSH_
  804. PolyHandle
  805. ODContour::AsQDPolygon( ) const
  806. {
  807.     ODSLong size = (sizeof(short)+sizeof(Rect)+sizeof(Point)) + nVertices*sizeof(Point);
  808.     if( size > 32767 )
  809.         THROW(kODErrShapeTooComplex);
  810.     PolyHandle p = (PolyHandle) ODNewHandle(size);
  811.     (**p).polySize = (short)size;
  812.     Rect &bbox = (**p).polyBBox;
  813.     SetRect(&bbox,32767,32767,-32767,-32767);
  814.     
  815.     const ODPoint *src = &vertex[0];
  816.     Point *dst = &(**p).polyPoints[0];
  817.     for( ODSLong i=nVertices; i>0; i-- ) {
  818.         *dst = src->AsQDPoint();
  819.         if( dst->h < bbox.left  )    bbox.left  = dst->h;
  820.         if( dst->v < bbox.top   )    bbox.top   = dst->v;
  821.         if( dst->h > bbox.right )    bbox.right = dst->h;
  822.         if( dst->v > bbox.bottom)    bbox.bottom= dst->v;
  823.         src++;
  824.         dst++;
  825.     }
  826.     *dst = vertex[0].AsQDPoint();    // QD makes us repeat the 1st pt at the end
  827.     
  828.     return p;
  829. }
  830. #endif
  831.  
  832. #ifdef _PLATFORM_WIN32_
  833. WIN32_DLLEXPORT Point *
  834. ODContour::AsWinPolygon( ) const
  835. {
  836.     ODSLong size = 10 + nVertices*sizeof(Point);
  837.     if( size > 32767 )
  838.         THROW(kODErrShapeTooComplex);
  839.     Point *p = (Point *) ODNewPtr(size);
  840.     ODSLong* pl = (ODSLong*)p;
  841.     *pl = nVertices;
  842.     RECT bbox;
  843.     SetRect(&bbox,32767,32767,-32767,-32767);
  844.     
  845.     const ODPoint *src = &vertex[0];
  846.     Point *dst = &p[1];
  847.     for( ODSLong i=nVertices; i>0; i-- ) {
  848.         *dst = src->AsWinPoint();
  849.         if( dst->x < bbox.left  )    bbox.left  = dst->x;
  850.         if( dst->y < bbox.top   )    bbox.top   = dst->y;
  851.         if( dst->x > bbox.right )    bbox.right = dst->x;
  852.         if( dst->y > bbox.bottom)    bbox.bottom= dst->y;
  853.         src++;
  854.         dst++;
  855.     }
  856.     return p;
  857. }
  858.  
  859. #endif // _PLATFORM_WIN32_
  860.  
  861. #ifdef _PLATFORM_AIX_
  862. Point *
  863. ODContour::AsXPolygon( ) const
  864. {
  865.     ODSLong size = 10 + nVertices*sizeof(Point);
  866.     Point *p = (Point *) ODNewPtr(size);
  867.     ODSLong* pl = (ODSLong*)p;
  868.     *pl = nVertices;
  869.     
  870.     const ODPoint *src = &vertex[0];
  871.     Point *dst = &p[1];
  872.     for( ODSLong i=nVertices; i>0; i-- ) {
  873.         *dst = src->AsXPoint();
  874.         src++;
  875.         dst++;
  876.     }
  877.     return p;
  878. }
  879. #endif // _PLATFORM_AIX_
  880.  
  881. #ifdef _PLATFORM_OS2_
  882. void ODContour::AsPOLYGON( POLYGON& p) const
  883. {
  884.  
  885.   p.aPointl = (PPOINTL)SOMMalloc(nVertices * sizeof(POINTL));
  886.  
  887.   const ODPoint *src = &vertex[0];
  888.   POINTL *dst = p.aPointl;
  889.   for( ODSLong i=nVertices; i>0; i-- ) {
  890.     *dst = (src++)->AsPOINTL();
  891.     (dst++)->y -= 1;              // OS/2 polygons are bottom-right exclusive
  892.                                   // while OpenDoc polygons are top-right
  893.                                   // exclusive.
  894.   }
  895.   p.ulPoints = nVertices;
  896. }
  897.  
  898.  
  899. // The canvas (HPS) is assumed to be associated with the target device
  900. // for the which the region will be used, and already set up with the
  901. // desired transforms.
  902.  
  903. HRGN
  904. ODPolygon::AsRegion(HPS hps) const
  905. {
  906.   ODRgnHandle rgn;
  907.   POLYGON poly;
  908.  
  909.   if( !this->HasData() )
  910.     return GpiCreateRegion(hps, 0, 0);
  911.  
  912.   GpiSavePS(hps);
  913.   GpiBeginPath(hps, 1);
  914.   try {
  915.     const ODContour *cont = this->FirstContour();
  916.     for( ODSLong i=_buf->nContours; i>0; i-- ) {
  917.       POLYGON poly;
  918.       cont->AsPOLYGON( poly );
  919.       GpiSetCurrentPosition(hps, &poly.aPointl[poly.ulPoints-1]);
  920.       GpiPolyLine(hps, poly.ulPoints, poly.aPointl);
  921.       //delete poly.aPointl;
  922.       poly.aPointl = NULL;
  923.       cont = cont->NextContour();
  924.     }
  925.   } catch (ODException _exception) {
  926.     delete[] poly.aPointl;
  927.     GpiEndPath(hps);
  928.     GpiRestorePS(hps, -1);
  929.     throw;
  930.   }
  931.  
  932.   GpiEndPath(hps);
  933.   rgn = GpiPathToRegion(hps, 1, FPATH_WINDING | FPATH_EXCL);
  934.   GpiRestorePS(hps, -1);
  935.   THROW_IF_NULL((void*)rgn);
  936.   return rgn;
  937. }
  938. #endif // _PLATFORM_OS2_
  939.  
  940. #ifdef _PLATFORM_MACINTOSH_
  941. RgnHandle
  942. ODPolygon::AsQDRegion( ) const
  943. {
  944.     // NOTE: This method will not work properly for self-intersecting polygons!
  945.     // QuickDraw uses even-odd filling, while OpenDoc uses winding-number.
  946.     
  947.     if( !this->HasData() )
  948.         return ODNewRgn();
  949.  
  950.     GrafPtr port, myPort;
  951.  
  952.     // Make sure we have a real port to work with:
  953.     GetPort(&port);
  954.     if( FrontWindow() ) {
  955.         SetPort(FrontWindow());
  956.         myPort = kODNULL;
  957.     } else {
  958.         myPort = new GrafPort;
  959.         OpenPort(myPort);
  960.     }
  961.     
  962.     RgnHandle rgn = ODNewRgn();
  963.     
  964.     OpenRgn();
  965.     try {
  966.         PolyHandle poly;
  967.         const ODContour *cont = this->FirstContour();
  968.         for( ODSLong i=_buf->nContours; i>0; i-- ) {
  969.             poly = cont->AsQDPolygon();
  970.             FramePoly(poly);
  971.             KillPoly(poly);
  972.             cont = cont->NextContour();
  973.         }
  974.     } catch(ODException _exception) {
  975.         CloseRgn(rgn);
  976.         DisposeRgn(rgn);
  977.         SetPort(port);
  978.         if( myPort ) {
  979.             ClosePort(myPort);
  980.             delete myPort;
  981.         }
  982.         throw;
  983.     }
  984.     
  985.     CloseRgn(rgn);
  986.     
  987.     SetPort(port);
  988.     if( myPort ) {
  989.         ClosePort(myPort);
  990.         delete myPort;
  991.     }
  992.     return rgn;
  993. }
  994. #endif
  995.  
  996.  
  997. #ifdef _PLATFORM_MACINTOSH_
  998. gxShape
  999. ODPolygon::AsGXShape( ) const
  1000. {
  1001.     gxShape shape;
  1002.     if( this->HasData() ) {
  1003.         shape = GXNewPolygons( (gxPolygons*)this->GetData() );
  1004.         GXSetShapeFill(shape,gxWindingFill);
  1005.     } else
  1006.         shape = GXNewShape(gxEmptyType);
  1007.     
  1008.     ThrowIfFirstGXError();
  1009.     return shape;
  1010. }
  1011. #endif
  1012.  
  1013. #ifdef _PLATFORM_WIN32_
  1014. WIN32_DLLEXPORT ODRgnHandle
  1015. ODPolygon::AsWinRegion( ) const
  1016. {
  1017.     
  1018.     ODRgnHandle rgn;
  1019.     HDC hdc = CreateCompatibleDC (NULL);
  1020.     
  1021.     try {
  1022.         Point *poly;
  1023.         const ODContour *cont = this->FirstContour();
  1024.         BeginPath(hdc);
  1025.         for( ODSLong i=_buf->nContours; i>0; i-- ) {
  1026.             poly = cont->AsWinPolygon();
  1027.             Polyline (hdc, &poly[1], *((ODSLong*)poly));
  1028.             CloseFigure(hdc);
  1029.             ODDisposePtr (poly);
  1030.             cont = cont->NextContour();
  1031.         }
  1032.         EndPath(hdc);
  1033.         rgn = PathToRegion(hdc);
  1034. //ShowRgn (rgn);
  1035.     } catch (ODException _exception) {
  1036.         DeleteObject(rgn);
  1037.         DeleteDC (hdc);
  1038.         throw;
  1039.     }
  1040.  
  1041.     DeleteDC (hdc);
  1042.     
  1043.     return rgn;
  1044. }
  1045. #endif // _PLATFORM_WIN32_
  1046.  
  1047. #ifdef _PLATFORM_AIX_
  1048. Region DrawToXRegion(ODContour* target_contour) 
  1049. {
  1050.     unsigned long v_count = target_contour->nVertices;
  1051.     XPoint* xpoints = new XPoint[v_count];
  1052.     ODPoint* temp_vertex = kODNULL;
  1053.  
  1054.     for (unsigned long v = 0; v < v_count; v++)
  1055.     {
  1056.             temp_vertex = &target_contour->vertex[v];
  1057.         if (!temp_vertex) break;
  1058.  
  1059.         xpoints[v].x = ODFixedRound(temp_vertex->x);
  1060.         xpoints[v].y = ODFixedRound(temp_vertex->y);
  1061.     }
  1062.  
  1063.     Region new_region = XPolygonRegion(xpoints, v_count, WindingRule);
  1064.  
  1065.     delete xpoints;
  1066.  
  1067.     return new_region;
  1068.  
  1069. }
  1070.  
  1071. WIN32_DLLEXPORT ODBoolean IsPositive(ODContour* target_contour) 
  1072. {
  1073. // Note:
  1074. // If the IsPositive function and the DrawToXRegion function are made into
  1075. // ODContour methods for AIX and
  1076. // if the data members fIsPositive and fSignKnown are added to the
  1077. // ODContour structure for AIX, we'd have to add a default c'tor that inits
  1078. // these fields (if a default c'tor can be added to a struct).  We'd also have
  1079. // to make sure that ODContours exist when the ODContour methods are 
  1080. // called.  If a user creates a struct myContour containing only nVertices and
  1081. // vertex[x] and NOT fIsPositive and NOT fSignKnown and then the user simply 
  1082. // creates a pointer to a ODContour and inits it to the myContour struct to 
  1083. // use the ODContour methods, the fIsPositive and fSignKnown fields would not
  1084. // be initialized causing us problems.  Assuming we can avoid these problems,
  1085. // saving _fIsPositive and _fSignKnown would be a performance enhancement.
  1086.  
  1087. // If this is changed to a ODContour method and the data fields are added:
  1088. // if (_SignKnown)
  1089. //    {
  1090. //    return (_fIsPositive);
  1091. //    }
  1092.  
  1093.     ODBoolean fIsPositive = kODTrue;  // Should this default to true????
  1094.  
  1095.     if (! target_contour->nVertices)
  1096.     {
  1097.         WARNMSG_DEBUG(WARN_INDEX(-1),"ODContour::IsPositive - contour is empty\n");
  1098.         return 0;
  1099.     }
  1100.     
  1101.     long area_x_minus2 = 0;
  1102.     long v_count = target_contour->nVertices;
  1103.  
  1104.     ODPoint* v_i        = kODNULL;
  1105.     ODPoint* v_last_i   = kODNULL;
  1106.  
  1107.     for (ODULong i = 0; i < v_count; i++)
  1108.     {
  1109.     if (i == 0)
  1110.         v_last_i = &target_contour->vertex[v_count-1];
  1111.     else
  1112.         v_last_i = v_i;
  1113.  
  1114.     v_i = &target_contour->vertex[i];
  1115.  
  1116.     if ((! v_last_i) || (! v_i))
  1117.     {
  1118.         area_x_minus2 = 0;
  1119.         break;
  1120.     }
  1121.  
  1122.     // convert from Fixed to long before trying to do
  1123.     // the cross product, to avoid overflow.
  1124.     // ----------------------------------------
  1125.     long x_last_i   = ODFixedRound(v_last_i->x);
  1126.     long y_last_i   = ODFixedRound(v_last_i->y);
  1127.     long x_i        = ODFixedRound(v_i->x);
  1128.     long y_i        = ODFixedRound(v_i->y);
  1129.  
  1130.     area_x_minus2 += (x_last_i * y_i) - (y_last_i * x_i);
  1131.     }
  1132.  
  1133.     if (area_x_minus2 == 0)
  1134.     {
  1135.         WARNMSG_DEBUG(WARN_INDEX(-1),"ODContour::IsPositive - contour has undefined area!\n");
  1136.         return kODFalse;
  1137.     }
  1138.     else
  1139.     {
  1140. // If _fIsPositive and _fSignKnown are added to ODContour for AIX:
  1141. //        _fIsPositive = (area_x_minus2 > 0);
  1142.         fIsPositive = (area_x_minus2 > 0);
  1143.     }
  1144.  
  1145. // If _fIsPositive and _fSignKnown are added to ODContour for AIX:
  1146. //    _fSignKnown = kODTrue;
  1147.  
  1148.     return fIsPositive;
  1149.  
  1150. }
  1151.  
  1152. WIN32_DLLEXPORT Region
  1153. ODPolygon::AsXRegion( ) const
  1154. {
  1155.     
  1156.     Region fRegion = XCreateRegion();
  1157.  
  1158.     // calculate Region if polygon data is available
  1159.     // ---------------------------------------------
  1160.     if ( (_buf) && 
  1161.          ((_buf->nContours > 0) && (_buf->firstContour.nVertices > 0)) ) 
  1162.     {
  1163.         ODContour* contour =  &_buf->firstContour;
  1164.  
  1165.         for (ODULong c = 0 ; c < _buf->nContours ; c++)
  1166.         {
  1167.             if (!contour) return kODNULL;
  1168.  
  1169.             Region subregion = DrawToXRegion(contour);
  1170.  
  1171.             if (IsPositive(contour)) 
  1172.                 XUnionRegion(fRegion, subregion, fRegion);
  1173.             else
  1174.                 XSubtractRegion(fRegion, subregion, fRegion);
  1175.  
  1176.             XDestroyRegion(subregion);
  1177.             contour =  contour->NextContour();
  1178.         }
  1179.     }
  1180.  
  1181.     return (Region) fRegion;
  1182.  
  1183. }
  1184. #endif // _PLATFORM_AIX_
  1185.  
  1186. WIN32_DLLEXPORT void
  1187. ODPolygon::Transform( Environment *ev, ODTransform *xform )
  1188. {
  1189.     if( this->HasData() ) {
  1190.         ODContour *c = &_buf->firstContour;
  1191.         for( ODSLong i=_buf->nContours; i>0; i-- ) {
  1192.             ODPoint *pt = c->vertex;
  1193.             for( ODSLong v=c->nVertices; v>0; v--, pt++ )
  1194.                 xform->TransformPoint(ev,pt);
  1195.             if( i>1 )
  1196.                 c = c->NextContour();
  1197.         }
  1198.     }
  1199. }
  1200.  
  1201.  
  1202. /******************************************************************************/
  1203. //**    CONTAINMENT TEST
  1204. /******************************************************************************/
  1205.  
  1206.  
  1207. //------------------------------------------------------------------------------
  1208. // ODPolygon::Contains
  1209. //
  1210. // Does a polygon contain a point?
  1211. // We determine this by drawing a ray from the point to the right towards
  1212. // infinity, and finding the polygon edges that intersect this ray. For each
  1213. // such edge, count it as 1 if its y value is increasing, -1 if decreasing.
  1214. // The sum of these values is 0 if the point is outside the polygon.
  1215. //------------------------------------------------------------------------------
  1216.  
  1217. #ifndef _PLATFORM_WIN32_
  1218. WIN32_DLLEXPORT ODSLong
  1219. ODPolygon::Contains( ODPoint point ) const
  1220. {
  1221.     if( !this->HasData() )
  1222.         return kODFalse;
  1223.  
  1224.     ODSLong count = 0;
  1225.     const ODPoint *pp1, *pp2;
  1226.     ODPoint p1, p2;
  1227.     ODPoint ray = point;
  1228.     
  1229.     for( PolyEdgeIterator polyIter (this); polyIter.IsNotComplete(); polyIter.Next() ) {
  1230.         polyIter.CurrentEdge(pp1,pp2);
  1231.         p1 = *pp1;
  1232.         p2 = *pp2;
  1233.         
  1234.         if( p1.y==p2.y ) {                                            // Horizontal line: ignore
  1235.             if( p1.y==point.y && InRange(point.x, p1.x,p2.x) ) {    // unless point is on it
  1236.                 return 0;
  1237.             }
  1238.         } else {
  1239.             ray.x = Max(p1.x,p2.x);
  1240.             ODPoint sect;
  1241.             if( ray.x >= point.x )
  1242.                 if( IntersectSegments(p1,p2, point,ray, §) ) {
  1243.                     if( WithinEpsilon(point.x,sect.x) && WithinEpsilon(point.y,sect.y) ) {
  1244.                         return 0;
  1245.                     }
  1246.                     if( p2.y > p1.y )
  1247.                         count++;
  1248.                     else
  1249.                         count--;
  1250.                 }
  1251.         }
  1252.     }
  1253.     
  1254.     return count;
  1255. }
  1256. #endif // _PLATFORM_WIN32_
  1257.  
  1258. #ifdef _PLATFORM_WIN32_
  1259.  
  1260. WIN32_DLLEXPORT ODSLong
  1261. ODPolygon::Contains( ODPoint point ) const
  1262. {
  1263.     ODRgnHandle rgn = this->AsWinRegion();
  1264.     ODBoolean b = kODFalse;
  1265.  
  1266.     if (rgn != kODNULL) 
  1267.     {
  1268.         Point pt = point.AsWinPoint();
  1269.  
  1270.         b = PtInRegion (rgn, pt.x, pt.y);
  1271.  
  1272.         DeleteObject (rgn);
  1273.     }
  1274.  
  1275.     return b;
  1276. }
  1277. #endif // _PLATFORM_WIN32_
  1278.  
  1279. /******************************************************************************/
  1280. //**    POLYGON EDGE ITERATOR
  1281. /******************************************************************************/
  1282.  
  1283.  
  1284. WIN32_DLLEXPORT PolyEdgeIterator::PolyEdgeIterator( const ODPolygon *poly )
  1285.     :fPoly (poly)
  1286. {
  1287.     fCurContour = poly->FirstContour();
  1288.     fCurContourIndex = 0;
  1289.     fCurVertex = 0;
  1290. }
  1291.  
  1292.  
  1293. WIN32_DLLEXPORT void
  1294. PolyEdgeIterator::CurrentEdge( const ODPoint* &v1, const ODPoint* &v2 )
  1295. {
  1296.     v1 = &fCurContour->vertex[fCurVertex];
  1297.     if( fCurVertex+1 < fCurContour->nVertices )
  1298.         v2 = v1+1;
  1299.     else
  1300.         v2 = &fCurContour->vertex[0];
  1301. }
  1302.  
  1303.  
  1304. #if ( (defined (_PLATFORM_WIN32_) || defined(_PLATFORM_OS2_))  \
  1305.        || defined(_PLATFORM_AIX_) )
  1306. WIN32_DLLEXPORT ODBoolean
  1307. #else
  1308. Boolean
  1309. #endif // _PLATFORM_WIN32_ || _PLATFORM_OS2_ || _PLATFORM_AIX_
  1310. PolyEdgeIterator::Next( )
  1311. {
  1312.     if( !fCurContour )                                    // Was already finished
  1313. #if ( (defined (_PLATFORM_WIN32_) || defined(_PLATFORM_OS2_))  \
  1314.        || defined(_PLATFORM_AIX_) )
  1315.         return kODFalse;
  1316. #else
  1317.         return false;
  1318. #endif // _PLATFORM_WIN32_ || _PLATFORM_OS2_ || _PLATFORM_AIX_
  1319.     if( ++fCurVertex >= fCurContour->nVertices )        // Next vertex; if past contour:
  1320.         if( ++fCurContourIndex >= fPoly->GetNContours() ) {        // Next contour; if past end:
  1321.             fCurContour = kODNULL;
  1322. #if ( (defined (_PLATFORM_WIN32_) || defined(_PLATFORM_OS2_))  \
  1323.        || defined(_PLATFORM_AIX_) )
  1324.             return kODFalse;        //...we're done.
  1325. #else
  1326.             return false;                                        //...we're done.
  1327. #endif // _PLATFORM_WIN32_ || _PLATFORM_OS2_ || _PLATFORM_AIX_
  1328.         } else {
  1329.             fCurContour = fCurContour->NextContour();            // Else go to start of contour
  1330.             fCurVertex = 0;
  1331.         }
  1332.     return kODTrue;
  1333. }
  1334.  
  1335.  
  1336. #if ( (defined (_PLATFORM_WIN32_) || defined(_PLATFORM_OS2_))  \
  1337.        || defined(_PLATFORM_AIX_) )
  1338. WIN32_DLLEXPORT ODBoolean
  1339. #else
  1340. Boolean
  1341. #endif // _PLATFORM_WIN32_ || _PLATFORM_OS2_ || _PLATFORM_AIX_
  1342. PolyEdgeIterator::IsNotComplete( )
  1343. {
  1344.     return fCurContour!=kODNULL;
  1345. }
  1346.  
  1347.  
  1348. #if ((defined (_PLATFORM_WIN32_) || defined (_PLATFORM_OS2_)) \
  1349.       || defined (_PLATFORM_AIX_) ) && defined(DEBUG)
  1350. // test programs begin here
  1351.  
  1352.  
  1353. WIN32_DLLEXPORT void ODPolygon::SelfTest()
  1354. {
  1355.  
  1356.   // let's first set up some Contour and PolygonData info
  1357.  
  1358.   ODCoordinate a1 = IntToFixed(0);
  1359.   ODCoordinate b1 = IntToFixed(20);
  1360.   ODCoordinate p1 = IntToFixed(10);
  1361.  
  1362.   ODCoordinate myLeft = IntToFixed(20);
  1363.   ODCoordinate myTop = IntToFixed(20);
  1364.   ODCoordinate myRight = IntToFixed(100);
  1365.   ODCoordinate myBottom = IntToFixed(100);
  1366.  
  1367.   ODPoint point1(a1,a1);
  1368.   ODPoint point2(b1,a1);
  1369.   ODPoint point3(b1,b1);
  1370.   ODPoint point4(a1,b1);
  1371.  
  1372.   ODPoint point5(p1,p1);
  1373.   ODRect rect2(myLeft, myTop, myRight, myBottom);
  1374.  
  1375.   MyContour *contour1 = new MyContour;
  1376.  
  1377.   contour1->nVertices = (ODSLong)4;
  1378.   contour1->vertex[0] = point1;
  1379.   contour1->vertex[1] = point2;
  1380.   contour1->vertex[2] = point3;
  1381.   contour1->vertex[3] = point4;
  1382.  
  1383.   MyPolygonData *polyData = new MyPolygonData;
  1384.   MyPolygonData *polyData2 = new MyPolygonData;
  1385.   MyPolygonData *polyData3 = new MyPolygonData;
  1386.   MyPolygonData *polyData4 = new MyPolygonData;
  1387.  
  1388.   polyData->nContours = (ODSLong)1;
  1389.   polyData->firstContour = *contour1;
  1390.  
  1391.   polyData2->nContours = (ODSLong)1;
  1392.   polyData2->firstContour = *contour1;
  1393.  
  1394.   polyData3->nContours = (ODSLong)1;
  1395.   polyData3->firstContour = *contour1;
  1396.  
  1397.   polyData4->nContours = (ODSLong)1;
  1398.   polyData4->firstContour = *contour1;
  1399.  
  1400.   // let's test!
  1401.   printf ("\n\nBEGIN ODPolygon::SelfTest\n\n");
  1402.  
  1403.  
  1404.   // testing ctor
  1405.   ODPolygon polygon1;
  1406.   ODPolygon polygon2;
  1407.   ODPolygon polygon3;
  1408.   ODPolygon *polygon4 = new ODPolygon;
  1409.  
  1410.   // test ::SetData
  1411.   // test ::HasData
  1412.   polygon1.SetData((ODPolygonData*)polyData);
  1413.   polygon1.PrintIt("polygon1: testing ::SetData() and ::HasData()");
  1414.   CHECKRES(polygon1.HasData());
  1415.  
  1416.   // test ::IsRectangular  
  1417.   polygon1.PrintIt("polygon1: testing ::IsRectangular()");
  1418.   CHECKRES(polygon1.IsRectangular());
  1419.  
  1420.   // test ::GetDataSize()
  1421.   ODULong dataSize = polygon1.GetDataSize();
  1422.   printf("polygon1 data size:[%ld]\n", dataSize);
  1423.   polygon1.PrintIt("testing ::GetDataSize()");
  1424.  
  1425.   // test ::GetData()
  1426.   ODPolygonData *myPolygonData = polygon1.GetData();
  1427.   polygon1.PrintIt("testing ::GetData()");
  1428.  
  1429.   // test  ::GetNContours()
  1430.   ODSLong numContours = polygon1.GetNContours();
  1431.   polygon1.PrintIt("testing ::GetNContours()");
  1432.   printf("polygon1 number contours:[%ld]\n", numContours);
  1433.  
  1434.   // test ::FirstContour() 
  1435.   ODContour* firstContour = polygon1.FirstContour(); 
  1436.   polygon1.PrintIt("testing ::FirstContour()");
  1437.  
  1438.   // test ::ComputeBoundingBox()
  1439.   ODRect* boundingBox = new ODRect;
  1440.   polygon1.ComputeBoundingBox(boundingBox);
  1441.   polygon1.PrintIt("testing ::ComputeBoundingBox(ODRect)");
  1442.   
  1443.   // test ::SetData()
  1444.   polygon3.SetData((ODPolygonData*)polyData3);
  1445.   polygon3.PrintIt("polygon3: after ::SetData()");
  1446.  
  1447.   // test ::Transform
  1448.   polygon3.PrintIt("about to run polygon3::Transform test!");
  1449.   // Create locale SOM environment to pass into
  1450.   // SOM class calls used in this method.
  1451.   Environment* ev = SOM_CreateLocalEnvironment();
  1452.   ODULong rc = FALSE;
  1453.   ODTransform* xform = kODNULL;
  1454.   ODPoint pt(IntToFixed(2), IntToFixed(2));
  1455.  
  1456.   try
  1457.     {
  1458.         xform = new ODTransform;
  1459.         xform->InitTransform(ev);
  1460.         xform->Reset(ev);
  1461.         xform->ScaleBy(ev, &pt);
  1462.  
  1463.         polygon3.Transform(ev, xform);
  1464.         polygon3.PrintIt("after running polygon3::Transform scale*2 test!");
  1465.         ODContour *transContour = polygon3.FirstContour();
  1466.         ODPoint *transPoint = transContour->vertex;
  1467.         for( ODSLong v=transContour->nVertices; 
  1468.              ((v>0) && (rc==FALSE)); v--, transPoint++ )
  1469.         {
  1470.          if (v==4) {
  1471.           if ((transPoint->x != IntToFixed(0 * 2)) ||
  1472.               (transPoint->y != IntToFixed(0 * 2)))
  1473.                 rc = TRUE;
  1474.           }
  1475.          if (v==3) {
  1476.           if ((transPoint->x != IntToFixed(20 * 2)) ||
  1477.               (transPoint->y != IntToFixed(0 * 2)))
  1478.                 rc = TRUE;
  1479.           }
  1480.          if (v==2) {
  1481.           if ((transPoint->x != IntToFixed(20 * 2)) ||
  1482.               (transPoint->y != IntToFixed(20 * 2)))
  1483.                 rc = TRUE;
  1484.           }
  1485.          if (v==1) {
  1486.           if ((transPoint->x != IntToFixed(0 * 2)) ||
  1487.               (transPoint->y != IntToFixed(20 * 2)))
  1488.                 rc = TRUE;
  1489.           }
  1490.         }
  1491.         if (rc == FALSE)
  1492.             printf("PASS\n");
  1493.         else
  1494.            {
  1495.                 printf("FAIL\n");
  1496.                 printf("Failing point: v== %d \n",(4-v));
  1497.                 printf("transPoint->x == %d \n",transPoint->x );
  1498.                 printf("transPoint->y == %d \n",transPoint->y );
  1499.            }
  1500.       }
  1501.       catch(ODException _exception)
  1502.       {
  1503.          printf("ODException occurred while testing ODPolygon::Transform \n");
  1504.          printf("FAIL\n");
  1505.          // Clear SOM Exception 
  1506.          SetErrorCode(kODNoError);
  1507.        } 
  1508.        // Destroy local SOM environment we created.
  1509.        SOM_DestroyLocalEnvironment(ev);
  1510.  
  1511.   printf("End of ODPolygon::Transform test.\n");
  1512.   
  1513.   // test ::operator==
  1514.   polygon2.SetData((ODPolygonData*)polyData2);
  1515.   polygon2.PrintIt("polygon2: after ::SetData()");
  1516.   polygon1.PrintIt("polygon1: testing ::operator==");
  1517.   CHECKRES(polygon1 == polygon2);
  1518.  
  1519.   // test ::operator!=
  1520.   polygon1.PrintIt("polygon1: testing ::operator!=");
  1521.   CHECKRES(!(polygon1 != polygon2));
  1522.  
  1523.   // test ::Contains()
  1524.   polygon1.PrintIt("polygon1: testing ::Contains(ODPoint)");
  1525.   CHECKRES(polygon1.Contains(point5));
  1526.  
  1527.   // test ::IsEmpty()
  1528.   polygon1.PrintIt("polygon1: testing ::IsEmpty()");
  1529.   CHECKRES(!(polygon1.IsEmpty()));
  1530.  
  1531.   // test ::AsRectangle()
  1532.   ODRect *rect1 = new ODRect;
  1533.   polygon1.PrintIt("polygon1: testing ::AsRect(ODRect*)");
  1534.   CHECKRES(polygon1.AsRectangle(rect1) );
  1535.  
  1536.   // test ::HasExactRegion()
  1537.   polygon1.PrintIt("polygon1: testing ::HasExactRegion");
  1538.   CHECKRES(polygon1.HasExactRegion() );
  1539.  
  1540. #ifdef _PLATFORM_WIN32_
  1541.   // test ::AsWinRegion()
  1542.   polygon1.PrintIt("polygon1: testing ::AsWinRegion");
  1543.   ODRgnHandle myRegion = polygon1.AsWinRegion();
  1544. #elif defined(_PLATFORM_OS2_)
  1545.   // test ::AsRegion()
  1546.   polygon1.PrintIt("polygon1: testing ::AsRegion");
  1547.   HPS hps;
  1548.   hps = WinGetPS(HWND_DESKTOP);
  1549.  
  1550.   ODRgnHandle myRegion = polygon1.AsRegion(hps);
  1551. #elif defined(_PLATFORM_AIX_)
  1552.   // test ::AsXRegion()
  1553.   polygon1.PrintIt("polygon1: testing ::AsXRegion");
  1554.  
  1555.   ODRgnHandle myRegion = polygon1.AsXRegion();
  1556.   polygon1.PrintIt("polygon1: after ::AsXRegion");
  1557. #endif
  1558.   CHECKRES(myRegion);
  1559.  
  1560.   // test ::SetNVertices()
  1561.   ODPolygon *copyPolygon1 = polygon1.Copy();
  1562.   copyPolygon1->PrintIt("copyPolygon1: after polygon1.Copy()");
  1563.   copyPolygon1->SetNVertices((ODSLong) 5);
  1564.   copyPolygon1->PrintIt("copyPolygon1: after ::SetNVertices");
  1565.   polygon1.PrintIt("polygon1: after ::copyPolygon1->SetNVertices");
  1566.  
  1567.   // test ::SetVertices()
  1568.   ODPoint *point6 = new ODPoint;
  1569.   point6->Set(b1,b1);
  1570.   polygon2.PrintIt("polygon2: before ::SetVertices");
  1571.   polygon2.SetVertices((ODSLong) 1 , point6);
  1572.   polygon2.PrintIt("polygon2: after  ::SetVertices");
  1573.  
  1574.   // test ::SetContours()
  1575.   ODSLong pointArray[4] = {(ODSLong)20,(ODSLong)20,(ODSLong)100,(ODSLong)100};
  1576.   polygon2.PrintIt("polygon2: before ::SetContours");
  1577.   polygon2.SetContours((ODSLong)1, pointArray);
  1578.   polygon2.PrintIt("polygon2: after  ::SetContours");
  1579.  
  1580.   polygon1.PrintIt("polygon1: before the Copy call!!");
  1581.   ODPolygon *copyPolygon = polygon1.Copy();
  1582.   copyPolygon->PrintIt("copyPolygon: after polygon1.Copy()");
  1583.   CHECKRES(polygon1 == *copyPolygon);
  1584.  
  1585.   // test ::SetRect()
  1586.   polygon2.SetRect(rect2);
  1587.   polygon2.PrintIt("polygon2: after ::SetRect(rect2)");
  1588.  
  1589.   // test ::MoveFrom()
  1590.   polygon1.MoveFrom(polygon2);
  1591.   polygon1.PrintIt("polygon1: after ::MoveFrom(polygon2)");
  1592.   CHECKRES( (polygon2.IsEmpty()) );
  1593.  
  1594.   // test ::SetData
  1595.   polygon4->SetData((ODPolygonData*)polyData4);
  1596.   polygon4->PrintIt("polygon4: testing ::SetData()");
  1597.  
  1598.   // Delete the MyPolygonData.  
  1599.   // Note: Can't call polygon1.Delete() since polygon1,2, & 3 are on the stack
  1600.   printf ("\n Deleting polyData and polygon4 \n");
  1601.   ODDisposePtr(polyData);
  1602.   ODDisposePtr(polyData2);
  1603.   ODDisposePtr(polyData3);
  1604.   polygon4->Delete();
  1605.  
  1606.   printf ("\n\nEND ODPolygon::SelfTest\n\n");
  1607.  
  1608.  
  1609. // STILL need to add test cases for these:
  1610.   // test ::ReadFrom()
  1611.   // test ::WriteTo()
  1612.  
  1613.  
  1614. }
  1615.  
  1616. WIN32_DLLEXPORT void ODPolygon::PrintIt(char *msg)
  1617. {
  1618.   printf ("-----------------------------------------------------\n");
  1619.   if(msg != NULL)
  1620.     printf ("%s\n",msg);
  1621.     if( this->HasData() ) {
  1622.       ODContour *c = &_buf->firstContour;
  1623.       for( ODSLong i=_buf->nContours; i>0; i-- ) {
  1624.         ODPoint *pt = c->vertex;
  1625.         for( ODSLong v=c->nVertices; v>0; v--, pt++ )
  1626.           printf("Point[%d]: %d,%d\n",(c->nVertices - v), pt->x, pt->y);
  1627.           if( i>1 )
  1628.             c = c->NextContour();
  1629.       } // for
  1630.     } // if
  1631. }
  1632. #endif // defined (_PLATFORM_WIN32_ || OS2 || AIX ) && defined(DEBUG)
  1633.