home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / opendc12.zip / od124os2.exe / od12osr1.exe / src / CompShpe.cpp < prev    next >
C/C++ Source or Header  |  1997-03-21  |  21KB  |  859 lines

  1. /* @(#)Z 1.11 os2/src/imaging/realshps/CompShpe.cpp, odimaging, od96os2, odos29712d 97/03/21 17:38:18 (96/08/23 01:42:14) */
  2. //====START_GENERATED_PROLOG======================================
  3. //
  4. //
  5. //   COMPONENT_NAME: odimaging
  6. //
  7. //   CLASSES: none
  8. //
  9. //   ORIGINS: 82,27
  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:    CompShpe.cpp
  31.  
  32.   Contains:  CompositeShape class, private to ODShape.
  33.  
  34.   Written by:  Chuck Dumont
  35.  
  36. */
  37.  
  38. #ifdef _PLATFORM_OS2_
  39. #define INCL_GPI
  40. #define INCL_WIN
  41. #endif  // _PLATFORM_OS2_
  42.  
  43. #ifdef _PLATFORM_WIN32_
  44. #include <wtypes.h>
  45. #include <wingdi.h>
  46. #endif
  47.  
  48. #ifndef _ALTPOINT_
  49. #include "AltPoint.h"      // Use C++ savvy ODPoint and ODRect
  50. #endif
  51.  
  52. #ifndef _ALTPOLY_
  53. #include "AltPoly.h"
  54. #endif
  55.  
  56. #ifndef _ODTYPES_
  57. #include "ODTypes.h"
  58. #endif
  59.  
  60. #ifndef _PLATSHAPE_
  61. #include "PlatShpe.h"
  62. #endif
  63.  
  64. #ifndef _RECTSHPE_
  65. #include "RectShpe.h"
  66. #endif
  67.  
  68. #ifndef _RGNSHPE_
  69. #include "RgnShpe.h"
  70. #endif
  71.  
  72. #ifndef _COMPSHPE_
  73. #include "CompShpe.h"
  74. #endif
  75.  
  76.  
  77. #ifndef _POLYSHPE_
  78. #include "PolyShpe.h"
  79. #endif
  80.  
  81. #ifndef _POLYCLIP_
  82. #include "PolyClip.h"
  83. #endif
  84.  
  85. #ifndef SOM_ODTransform_xh
  86. #include "Trnsform.xh"
  87. #endif
  88.  
  89. #ifndef _RGN2PLYM_
  90. #include "Rgn2PlyM.h"
  91. #endif
  92.  
  93. #ifndef _EXCEPT_
  94. #include "Except.h"
  95. #endif
  96.  
  97. #ifndef _ODMEMORY_
  98. #include "ODMemory.h"
  99. #endif
  100.  
  101. #ifndef _ODDEBUG_
  102. #include "ODDebug.h"
  103. #endif
  104.  
  105.  
  106. void TransformRectangle(Environment* ev, ODTransform *xform, ODRect *r)
  107. {
  108. // This was ported directly from OS/2.  The cross-platform version
  109. // of OpenDoc still maintains TopLeft and BottomRight as member
  110. // functions of ODRect.  We'll keep this in the code just as a reference
  111. // until we're done with testing.  Ya never know when we might find this
  112. // useful.  jab - 05/20/96
  113. //    ODPoint botLeft = r->BotLeft();
  114. //    ODPoint topRight = r->TopRight();
  115. //    xform->TransformPoint(ev,&botLeft);  // [137664]
  116. //    xform->TransformPoint(ev,&topRight);
  117. //    *r = ODRect(botLeft,topRight);
  118.  
  119. #if defined(_PLATFORM_WIN32_) || defined(_PLATFORM_OS2_) || defined(_PLATFORM_UNIX_)
  120.     ODPoint topLeft = r->TopLeft();
  121.     ODPoint botRight = r->BotRight();
  122.     xform->TransformPoint( ev, &topLeft );  
  123.     xform->TransformPoint( ev, &botRight );
  124.     *r = ODRect( topLeft, botRight );
  125. #endif  // _PLATFORM_WIN32_
  126.  
  127. }
  128.  
  129. CompositeShape::CompositeShape( RealShape* shap1, RealShape* shap2, ODShapeOp oper )
  130.                               :  RealShape(GetMode(shap1, shap2 ) ) ,  fPolygon()
  131. {
  132. #if ODDebug
  133.    fType = 4;
  134. #endif
  135.    shape1 = shap1;
  136.    shape2 = shap2;
  137.    op = oper;
  138.    //fNumRects = 0;
  139.    bboxValid = 0;
  140.    bbox.Clear();
  141.    fRgnTransform = 0;
  142.    fPolygonTransform = 0;
  143. }
  144.  
  145.  
  146. CompositeShape::~CompositeShape( )
  147. {
  148.    delete shape1;
  149.    delete shape2;
  150.    fPolygon.Clear();
  151.    RealShape::Purge(0);
  152.    Environment *ev = somGetGlobalEnvironment(); // 137748 : AAA
  153.    if ( fPolygonTransform )
  154.       fPolygonTransform->Release( ev );
  155.    if ( fRgnTransform )
  156.       fRgnTransform->Release( ev );
  157.  
  158. }
  159.  
  160.  
  161. ODSize
  162. CompositeShape::Purge( ODSize requestedSize )
  163. {
  164.   if( fPolygon.HasData() ) {
  165.     ODSize size = fPolygon.GetDataSize();
  166.     fPolygon.Clear();
  167.     if (fPolygonTransform) {
  168.        delete fPolygonTransform;
  169.        fPolygonTransform = 0;
  170.     }
  171.     size += RealShape::Purge( requestedSize );
  172.     if ( fRgnTransform ) {
  173.        delete fRgnTransform;
  174.        fRgnTransform = 0;
  175.     }
  176.     size +=  shape1->Purge( requestedSize ) + shape2->Purge( requestedSize ) ;
  177.     return size;
  178.   } else
  179.     return 0;
  180. }
  181.  
  182.  
  183. const ODSLong kMaxLong  = 0x7FFFFFFF;
  184.  
  185. #if defined(_PLATFORM_UNIX_)
  186. #define max(a,b) (a)>(b) ? (a) : (b)
  187. #define min(a,b) (a)<(b) ? (a) : (b)
  188. #endif
  189.  
  190. void
  191. CompositeShape::GetBoundingBox( Environment* ev, ODRect *bounds )
  192. {
  193.    ODRect b1,b2;
  194.   if ( bboxValid ) {
  195.      *bounds = bbox;
  196.      return;
  197.   }
  198.   if ( op == kShapeUnion ) {
  199.     shape1->GetBoundingBox( ev, &b1 );
  200.     shape2->GetBoundingBox( ev, &b2 );
  201.     bbox.left = min( b1.left, b2.left );
  202.     bbox.bottom = min( b1.bottom, b2.bottom );
  203.     bbox.right = max( b1.right, b2.right );
  204.     bbox.top = max( b1.top, b2.top );
  205.   } else {
  206.     shape1->GetPesimisticBoundingBox( ev, &b1 );
  207.     shape2->GetPesimisticBoundingBox( ev, &b2 );
  208.     if( !b1.Intersects(b2) ) {
  209.        if( op == kShapeIntersection ) 
  210.           bbox.Clear();
  211.        else if( op == kShapeDifference ) 
  212.           shape1->GetBoundingBox( ev, &bbox );
  213.        else { 
  214.           WARNMSG_DEBUG( WARN_INDEX(-1), "Bogus ShapeOp in GetBoundingBox" );
  215.           THROW( kODErrInvalidParameter );
  216.        }
  217.     }
  218.     else {
  219.             if( fMode == kODLoseGeometry ) {
  220.  
  221. #ifdef _PLATFORM_OS2_
  222.                if( !fQDRegion ) 
  223.                   GetPlatformShape( ev, kODQuickDraw );
  224.                RECTL box;
  225.                HPS hps = GetPresSpace();
  226.                GpiQueryRegionBox(hps, fQDRegion, &box);
  227.                ReleasePresSpace(hps);
  228. #endif  // _PLATFORM_OS2_
  229.  
  230. #ifdef _PLATFORM_WIN32_
  231.                if( !fQDRegion ) 
  232.                   GetPlatformShape( ev, kODWin32 );
  233.                Rect box;
  234.                LONG lComplexity = GetRgnBox( fQDRegion, &box );
  235. #endif  // _PLATFORM_WIN32_
  236.  
  237. #ifdef _PLATFORM_AIX_
  238.                if( !fQDRegion ) 
  239.                   GetPlatformShape( ev, kODAIX );
  240.                Rect box;
  241.                XClipBox(fQDRegion, &box);
  242. #endif  // _PLATFORM_AIX_
  243.  
  244.                bbox = box;
  245.             }
  246.             else {
  247.               this->InitQDPoly( ev );
  248.               fPolygon.ComputeBoundingBox( &bbox );
  249. // AL: commented out the next two lines because InitQDPoly will take care of the transform
  250. //            if ( fPolygonTransform )
  251. //                        fPolygonTransform->TransformRectangles( ev, &bbox, 1 );
  252.             }
  253.      }
  254.   }
  255.   *bounds = bbox;
  256.    bboxValid = kODTrue;
  257. }
  258.  
  259. void
  260. CompositeShape::GetPesimisticBoundingBox( Environment* ev, ODRect *bounds )
  261. {
  262.    ODRect b1,b2;
  263.   if ( bboxValid ) {
  264.      *bounds = bbox;
  265.      return;
  266.   }
  267.   if ( op == kShapeUnion ) {
  268.     shape1->GetPesimisticBoundingBox( ev, &b1 );
  269.     shape2->GetPesimisticBoundingBox( ev, &b2 );
  270.         b1 |= b2;
  271.   } else if( op == kShapeIntersection ) {
  272.     shape1->GetPesimisticBoundingBox( ev, &b1 );
  273.     shape2->GetPesimisticBoundingBox( ev, &b2 );
  274.         b1 &= b2;
  275.   }
  276.   else if( op == kShapeDifference ) {
  277.      shape1->GetPesimisticBoundingBox( ev,&b1 );
  278.   }
  279.   else {
  280.         WARNMSG_DEBUG( WARN_INDEX(-1), "Bogus ShapeOp in GetPessimisticBoundingBox" );
  281.         THROW( kODErrInvalidParameter );
  282.   }
  283.   *bounds = b1;
  284. }
  285.  
  286.  
  287. RealShape*
  288. CompositeShape::SetRectangle( const ODRect *r )
  289. {
  290.   RealShape *rect = new RectShape ( fMode , *r ) ;
  291.   delete this;
  292.   return rect;
  293. }
  294.  
  295.  
  296. RealShape*
  297. CompositeShape::Clear( )
  298. {
  299.   ODRect empty;
  300.   empty.Clear();
  301.   RealShape *s = new RectShape( fMode,empty );
  302.   delete this;
  303.   return s;
  304. }
  305.  
  306. void
  307. CompositeShape::InitQDPoly( Environment* ev )
  308.  
  309. {
  310.    if( !fPolygon.HasData() ){
  311.       ODTempPolygon shapePoly1,shapePoly2;
  312.       shape1->CopyPolygon( ev, shapePoly1 );
  313.       shape2->CopyPolygon( ev, shapePoly2 );
  314.       ODPolygon* poly[2];
  315.       poly[0] = &shapePoly1;
  316.       poly[1] = &shapePoly2;
  317.  
  318.       TRY{
  319.          PolyClip( 2, (const ODPolygon**)poly, op, fPolygon );
  320.       }CATCH_ALL{
  321.          shapePoly1.Clear();
  322.          shapePoly2.Clear();
  323.          RERAISE;
  324.       }ENDTRY
  325.    }
  326.    else {
  327.       if( fPolygonTransform ) fPolygon.Transform( ev, fPolygonTransform );
  328.    }
  329.    if ( fPolygonTransform ) {
  330.       delete fPolygonTransform;
  331.       fPolygonTransform = 0;
  332.    }
  333. }
  334.  
  335.  
  336. void
  337. CompositeShape::CopyPolygon( Environment* ev, ODPolygon &result )
  338. {
  339.    this->InitQDPoly(ev);
  340. // AL: don't need the next if statement; it has been already taken care of
  341. /*
  342.    if ( fPolygonTransform ) {
  343.       fPolygon.Transform( ev, fPolygonTransform );
  344.       delete fPolygonTransform;
  345.       fPolygonTransform = 0;
  346.    }
  347. */
  348.    result.CopyFrom( fPolygon );
  349. }
  350.  
  351.  
  352. RealShape*
  353. CompositeShape::SetPolygon( const ODPolygon &poly)
  354. {
  355.    RealShape  *p;
  356.  
  357.    p   = new PolygonShape( fMode );
  358.    p = p->SetPolygon( poly );
  359.    delete this;
  360.    return p;
  361. }
  362.  
  363.  
  364. void
  365. CompositeShape::InitQDRegion( Environment* ev )
  366. {
  367. }
  368.  
  369.  
  370.  
  371. #ifdef _PLATFORM_OS2_
  372.  
  373. ODPlatformShape CompositeShape::GetPlatformShape( Environment*ev, ODGraphicsSystem system )
  374. {
  375.   if( system == kODQuickDraw ) {
  376.      if (fQDRegion && (!fRgnTransform || fRgnTransform && fRgnTransform->GetType(ev) == kODIdentityXform));
  377.      else if (fQDRegion && fRgnTransform && fRgnTransform->GetType(ev) == kODTranslateXform) {
  378.         fQDRegion.Unlink();
  379.         HPS hps = GetPresSpace();
  380.         ODPoint offset;
  381.         fRgnTransform->GetOffset(ev, &offset);
  382.         POINTL ptlOffset = offset.AsPOINTL();
  383.         GpiOffsetRegion(hps, fQDRegion, &ptlOffset);
  384.         ReleasePresSpace(hps);
  385.      }
  386.      else {
  387.     // Either we have no region, or the region transform is > translation.
  388.     HPS hps = GetPresSpace();
  389.  
  390.     if (fQDRegion)
  391.         fQDRegion.Unlink();
  392.     else
  393.         fQDRegion.InitRegion(GpiCreateRegion(hps, 0, 0));
  394.  
  395.     HRGN hrgn1,hrgn2;
  396.     LONG IMode;
  397.  
  398.     hrgn1 = shape1->GetPlatformShape( ev, kODPM );
  399.     hrgn2 = shape2->GetPlatformShape( ev, kODPM );
  400.  
  401.     switch(this->op) {
  402.         case kShapeIntersection:
  403.             IMode = CRGN_AND;
  404.             break;
  405.         case kShapeUnion:
  406.             IMode = CRGN_OR;
  407.             break;
  408.         case kShapeDifference:
  409.             IMode = CRGN_DIFF;
  410.             break;
  411.         default:
  412.                         WARNMSG_DEBUG( WARN_INDEX(-1), "Bogus ShapeOp to Combine" );
  413.             THROW( kODErrInvalidParameter );
  414.             break;
  415.     }
  416.     GpiCombineRegion(hps,fQDRegion,hrgn1,hrgn2,IMode);
  417.     ReleasePresSpace(hps);
  418.      }  
  419.      if(fRgnTransform) {
  420.     fRgnTransform->Release(ev); // 137748: AAA
  421.     fRgnTransform = 0;
  422.      }
  423.      return fQDRegion;
  424.   }
  425.   else {
  426.      THROW(kODErrInvalidGraphicsSystem);
  427.      return kODNULL;
  428.   }
  429. }
  430.  
  431. #endif  // _PLATFORM_OS2_
  432.  
  433.  
  434. #ifdef _PLATFORM_WIN32_
  435.  
  436. ODPlatformShape CompositeShape::GetPlatformShape( Environment*ev, ODGraphicsSystem system )
  437. {
  438.   if( ( system == kODWin32 ) || ( system == kODWinNT ) || ( system == kODWin95 ) ) {
  439.      if ( fQDRegion && ( !fRgnTransform || fRgnTransform && fRgnTransform->GetType(ev) == kODIdentityXform ) );
  440.      else if ( fQDRegion && fRgnTransform && fRgnTransform->GetType(ev) == kODTranslateXform ) {
  441.         fQDRegion.Unlink();
  442.         ODPoint offset;
  443.         fRgnTransform->GetOffset( ev, &offset );
  444.         Point ptOffset = offset.AsWinPoint();
  445.         OffsetRgn( fQDRegion, ptOffset.x, ptOffset.y );
  446.      }
  447.      else {
  448.     // Either we have no region, or the region transform is > translation.
  449.  
  450.     if (fQDRegion)
  451.         fQDRegion.Unlink();
  452.     else
  453.         fQDRegion.InitRegion( CreateRectRgn( 0, 0, 0, 0 ) );
  454.  
  455.     HRGN hrgn1,hrgn2;
  456.     LONG IMode;
  457.  
  458.     hrgn1 = shape1->GetPlatformShape( ev, kODWin32 );
  459.     hrgn2 = shape2->GetPlatformShape( ev, kODWin32 );
  460.  
  461.     switch(this->op) {
  462.         case kShapeIntersection:
  463.             IMode = RGN_AND;
  464.             break;
  465.         case kShapeUnion:
  466.             IMode = RGN_OR;
  467.             break;
  468.         case kShapeDifference:
  469.             IMode = RGN_DIFF;
  470.             break;
  471.         default:
  472.                         WARNMSG_DEBUG( WARN_INDEX(-1), "Bogus ShapeOp to combine" );
  473.             THROW( kODErrInvalidParameter );
  474.             break;
  475.     }
  476.     CombineRgn( fQDRegion, hrgn1, hrgn2, IMode );
  477.      }  
  478.      if(fRgnTransform) {
  479.     fRgnTransform->Release(ev); // 137748: AAA
  480.     fRgnTransform = 0;
  481.      }
  482.      return fQDRegion;
  483.   }
  484.   else {
  485.      THROW( kODErrInvalidGraphicsSystem );
  486.      return kODNULL;
  487.   }
  488. }
  489.  
  490. #endif  // _PLATFORM_WIN32_
  491.  
  492.  
  493. #ifdef _PLATFORM_AIX_
  494.  
  495. ODPlatformShape CompositeShape::GetPlatformShape( Environment*ev, ODGraphicsSystem system )
  496. {
  497.   if( system == kODAIX ) {
  498.      if ( fQDRegion && ( !fRgnTransform || fRgnTransform && fRgnTransform->GetType(ev) == kODIdentityXform ) );
  499.      else if ( fQDRegion && fRgnTransform && fRgnTransform->GetType(ev) == kODTranslateXform ) {
  500.         fQDRegion.Unlink();
  501.         ODPoint offset;
  502.         fRgnTransform->GetOffset( ev, &offset );
  503.         Point ptOffset = offset.AsXPoint();
  504.         OffsetRgn( fQDRegion, ptOffset.x, ptOffset.y );
  505.      }
  506.      else {
  507.     // Either we have no region, or the region transform is > translation.
  508.  
  509.     if (fQDRegion)
  510.         fQDRegion.Unlink();
  511.     else
  512.         fQDRegion.InitRegion( ODNewRgn() );
  513.  
  514.     ODRgnHandle hrgn1,hrgn2;
  515.  
  516.     hrgn1 = shape1->GetPlatformShape( ev, kODAIX );
  517.     hrgn2 = shape2->GetPlatformShape( ev, kODAIX );
  518.  
  519.     switch(this->op) {
  520.         case kShapeIntersection:
  521.             SectRgn(hrgn1, hrgn2, fQDRegion);
  522.             break;
  523.         case kShapeUnion:
  524.                         UnionRgn(hrgn1, hrgn2, fQDRegion);
  525.             break;
  526.         case kShapeDifference:
  527.                         DiffRgn(hrgn1, hrgn2, fQDRegion);
  528.             break;
  529.         default:
  530.                         WARNMSG_DEBUG( WARN_INDEX(-1), "Bogus ShapeOp to combine" );
  531.             THROW( kODErrInvalidParameter );
  532.             break;
  533.     }
  534.      }  
  535.      if(fRgnTransform) {
  536.     fRgnTransform->Release(ev); // 137748: AAA
  537.     fRgnTransform = 0;
  538.      }
  539.      return fQDRegion;
  540.   }
  541.   else {
  542.      THROW( kODErrInvalidGraphicsSystem );
  543.      return kODNULL;
  544.   }
  545. }
  546.  
  547. #endif  // _PLATFORM_AIX_
  548.  
  549.  
  550.  
  551.  
  552. ODBoolean
  553. CompositeShape::IsSameAs( Environment* ev, RealShape *shape )
  554. {
  555.    ODBoolean empty1,empty2;
  556.  
  557.    if( shape == this )
  558.       return kODTrue;
  559.  
  560.    empty1 = this->IsObviousEmpty( ev );
  561.    empty2 = shape->IsObviousEmpty( ev );
  562.  
  563.    if( empty1 && empty2 ) 
  564.       return kODTrue;
  565.  
  566.    if( fMode == kODNeedsGeometry ) {
  567.       if( !shape->HasGeometry() ) 
  568.          return kODFalse;
  569.       this->InitQDPoly( ev );
  570.       ODPolygon poly;
  571.       shape->CopyPolygon( ev, poly );
  572.       return( fPolygon == poly );
  573.    }
  574. #ifdef _PLATFORM_OS2_
  575.    return EqualRgn( this->GetPlatformShape( ev, kODPM ), (ODRgnHandle)shape->GetPlatformShape( ev, kODPM ) );
  576. #endif  // _PLATFORM_OS2_
  577.  
  578. #ifdef _PLATFORM_WIN32_
  579.    return EqualRgn( this->GetPlatformShape( ev, kODWin32 ), (ODRgnHandle)shape->GetPlatformShape( ev, kODWin32 ) );
  580. #endif  // _PLATFORM_Win32_
  581.  
  582. #ifdef _PLATFORM_AIX_
  583.    return EqualRgn( this->GetPlatformShape( ev, kODAIX ), (ODRgnHandle)shape->GetPlatformShape( ev, kODAIX ) );
  584.   return kODTrue;
  585. #endif  // _PLATFORM_AIX_
  586. }
  587.  
  588.  
  589. ODBoolean
  590. CompositeShape::IsEmpty( Environment* ev )
  591. {
  592.    ODRect box;
  593.  
  594.    if( this->IsObviousEmpty(ev) ) 
  595.       return kODTrue;
  596.    this->GetBoundingBox( ev, &box );
  597.  
  598.    return box.IsEmpty();
  599. }
  600.  
  601.  
  602. ODBoolean
  603. CompositeShape::IsObviousEmpty( Environment* ev )
  604. {
  605.   ODRect box;
  606.  
  607.   this->GetPesimisticBoundingBox( ev, &box );
  608.   return box.IsEmpty();
  609. }
  610.  
  611.  
  612. ODBoolean
  613. CompositeShape::ContainsPoint( Environment* ev, ODPoint point )
  614. {
  615.    if(fQDRegion)  {
  616.       ODPoint pt = point;
  617.       if ( fRgnTransform && fRgnTransform->GetType(ev) != kODIdentityXform  )
  618.            fRgnTransform->InvertPoint( ev, &pt );  // [137664]
  619. #ifdef _PLATFORM_OS2
  620.       return PtInRgn( pt.AsQDPoint(), fQDRegion );
  621. #endif 
  622.  
  623. #ifdef _PLATFORM_WIN32_
  624.       return PtInRgn( pt.AsWinPoint(), fQDRegion );
  625. #endif
  626.  
  627. #ifdef _PLATFORM_UNIX_
  628.       return PtInRgn( pt.AsXPoint(), fQDRegion );
  629. #endif
  630.    }
  631.  
  632.    switch(this->op){
  633.  
  634.    case kShapeIntersection:
  635.        return ( shape1->ContainsPoint( ev, point ) && shape2->ContainsPoint( ev, point ) );
  636.  
  637.    case kShapeUnion:
  638.        return ( shape1->ContainsPoint( ev, point ) || shape2->ContainsPoint( ev, point ) );
  639.  
  640.    case kShapeDifference:
  641.        return ( shape1->ContainsPoint( ev, point ) && !shape2->ContainsPoint( ev, point ) );
  642.  
  643.    default:
  644.        WARNMSG_DEBUG( WARN_INDEX(-1), "Bogus ShapeOp to combine" );
  645.        THROW( kODErrInvalidParameter );
  646.        break;
  647.    }
  648.    return kODFalse;
  649. }
  650.  
  651.  
  652. ODBoolean
  653. CompositeShape::IsRectangular( Environment* ev )
  654. {
  655.    ODRect box;
  656.    ODBoolean empty = kODFalse;
  657.  
  658.    this->GetBoundingBox( ev, &box );
  659.    RealShape* tempShape = (RealShape*) new RectShape( fMode, box );
  660.    tempShape->Subtract( ev, this) ;
  661.    empty = tempShape->IsEmpty( ev );
  662.    delete tempShape;
  663.    return empty;
  664. }
  665.  
  666.  
  667. ODBoolean
  668. CompositeShape::IsObviousRectangular( Environment* ev )
  669. {
  670.    ODRect box1,box2;
  671.    ODBoolean empty = kODFalse;
  672.    ODBoolean isrect1, isrect2;
  673.  
  674.    isrect1 = shape1->IsObviousRectangular( ev );
  675.    isrect2 =  shape2->IsObviousRectangular( ev );
  676.  
  677.    if( !isrect1 || !isrect2 ) 
  678.       return kODFalse;
  679.  
  680.    if( op == kShapeIntersection ) 
  681.       return kODTrue;
  682.  
  683.    shape1->GetPesimisticBoundingBox( ev, &box1 );
  684.    shape2->GetPesimisticBoundingBox( ev, &box2 );
  685.  
  686.    if( box1.IsEmpty() || box2.IsEmpty() ) 
  687.       return kODTrue;
  688.  
  689.    if( box2.Contains( box1 ) ) 
  690.       return kODTrue;
  691.  
  692.    if( box1.Contains( box2 ) ) {
  693.       if( op == kShapeDifference ) 
  694.          return kODFalse;
  695.       else 
  696.          return kODTrue;
  697.    }
  698.  
  699.    if( box1.Intersects( box2 ) ) 
  700.       return kODFalse;
  701.    else if( op == kShapeDifference ) 
  702.       return kODTrue;
  703.  
  704.    return(kODFalse);
  705. }
  706.  
  707.  
  708. ODBoolean
  709. CompositeShape::HasGeometry( )
  710. {
  711.    return ( shape1->HasGeometry() && shape2->HasGeometry() );
  712. }
  713.  
  714.  
  715. RealShape*
  716. CompositeShape::Copy( Environment* ev )
  717. {
  718.    ODPolygon result;
  719.    ODRgnHandle newRgn = 0;
  720.  
  721.    RealShape* newshap1 = shape1->Copy( ev );
  722.    RealShape* newshap2 = shape2->Copy( ev );
  723.    CompositeShape* newShape = new CompositeShape( newshap1, newshap2, op );
  724.  
  725.    if( fQDRegion ) {
  726.       newShape->fQDRegion = fQDRegion;
  727.    }
  728.  
  729.    if ( fRgnTransform )
  730.       newShape->fRgnTransform = fRgnTransform->Copy( ev );
  731.  
  732.    newShape->fPolygon.CopyFrom( fPolygon );
  733.  
  734.    if ( fPolygonTransform )
  735.       newShape->fPolygonTransform = fPolygonTransform->Copy( ev );
  736.  
  737.    if ( bboxValid ) {
  738.      newShape->bbox = bbox;
  739.      newShape->bboxValid = kODTrue;
  740.    }
  741.    return (RealShape *)newShape;
  742. }
  743.  
  744.  
  745. ODGeometryMode  GetMode( RealShape* shap1, RealShape* shap2 )
  746. {
  747. /*
  748.   if ( shap1->HasGeometry() && shap2->HasGeometry()  )
  749.     return kODPreserveGeometry;
  750.   else
  751.     return kODLoseGeometry;
  752. */
  753.    ODGeometryMode mode1 = shap1->GetGeometryMode();
  754.    ODGeometryMode mode2 = shap2->GetGeometryMode();
  755.  
  756.    if( mode1 == kODLoseGeometry || mode2 == kODLoseGeometry ) {
  757.       if( mode1 == kODNeedsGeometry )
  758.          THROW( kODErrNoShapeGeometry );
  759.       return kODLoseGeometry;
  760.    }
  761.    return mode1;
  762. }
  763.  
  764.  
  765. RealShape*
  766. CompositeShape::Transform( Environment *ev, ODTransform *xform )
  767. {
  768.    if ( xform->GetType(ev) != kODIdentityXform ) {
  769.       shape1 = shape1->Transform( ev,xform );
  770.       shape2 = shape2->Transform( ev,xform );
  771.  
  772.       if ( fPolygon.HasData() ) {
  773.          if ( !fPolygonTransform )
  774.             fPolygonTransform = xform->Copy( ev );
  775.          else
  776.             fPolygonTransform->PostCompose( ev, xform );
  777.       }
  778.  
  779.       if ( fQDRegion ) {
  780.          if ( !fRgnTransform )
  781.             fRgnTransform = xform->Copy( ev );
  782.          else
  783.             fRgnTransform->PostCompose( ev, xform );
  784.       }
  785.  
  786.       if ( bboxValid ) {
  787. // AL: I've commented out the next line and replaced it with the code that follows :
  788. //         xform->TransformRectangles(ev, &bbox, 1);
  789.  
  790.          if( xform->GetType(ev) > kODScaleTranslateXform ) 
  791.             bboxValid = kODFalse;                   // cannot transform bounding box, invalidate
  792.          else 
  793.             TransformRectangle( ev, xform, &bbox );
  794.       }
  795.  
  796. //    RealShape::Purge(0);
  797.  
  798.    }
  799.    return this;
  800. }
  801.  
  802.  
  803. RealShape*
  804. CompositeShape::Outset( Environment* ev, ODCoordinate distance )
  805. {
  806.    shape1->Outset( ev, distance );
  807.    if( op == kShapeDifference ) 
  808.       shape2->Outset( ev, -distance );
  809.    else 
  810.       shape2->Outset( ev, distance );
  811.  
  812.    RealShape::Purge( 0 );  // flush the region
  813.    fPolygon.Clear();     // and the polygon
  814.  
  815.    if( fPolygonTransform ) {
  816.       delete fPolygonTransform;
  817.       fPolygonTransform = 0;
  818.    }
  819.    if( fRgnTransform ) {
  820.       delete fRgnTransform;
  821.       fRgnTransform = 0;
  822.    }
  823.    if( bboxValid ) {
  824.       if( !bbox.IsEmpty() ) 
  825.          bbox.Inset( -distance, -distance );
  826.    }
  827.    return this;
  828. }
  829.  
  830.  
  831. RealShape*
  832. CompositeShape::Subtract( Environment* ev, RealShape *shape )
  833. {
  834.   if( shape==this )
  835.     return this->Clear();
  836.   else
  837.     return this->Promote( ev, kShapeDifference, shape );
  838. }
  839.  
  840.  
  841. RealShape*
  842. CompositeShape::Intersect( Environment* ev, RealShape *shape )
  843. {
  844.   if( shape==this )
  845.     return this;
  846.   else
  847.     return this->Promote( ev, kShapeIntersection, shape );
  848. }
  849.  
  850.  
  851. RealShape*
  852. CompositeShape::Union( Environment* ev, RealShape *shape )
  853. {
  854.   if( shape==this )
  855.     return this;
  856.   else
  857.     return this->Promote( ev, kShapeUnion,shape );
  858. }
  859.