home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc Source Code / Imaging / TrnsfrmB.cpp < prev   
Encoding:
Text File  |  1996-04-22  |  27.7 KB  |  961 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        TrnsfrmB.cp
  3.  
  4.     Contains:    Implementation of ODBaseTransform
  5.  
  6.     Owned by:    Jens Alfke
  7.  
  8.     Copyright:    © 1993-94 Apple Computer, Inc. All rights reserved.
  9.  
  10.     Change History (most recent first):
  11.     
  12.          <2>     1/15/96    TJ        Cleaned Up
  13.         <18>     10/8/95    TJ        Fixes Recomended by Refball
  14.         <17>     9/13/95    DM        1277216 GM:API return no ODPoints nor
  15.                                     ODPolygons
  16.         <16>      9/8/95    jpa        Use SET_SOM_EXCEPTION [1281031]
  17.         <15>     8/18/95    NP        1274946:
  18.                                     kODErrInvalidParameter->kODErrIllegalNullIn
  19.                                     put
  20.         <14>     8/16/95    jpa        Use ODGet/SetMatrixProp in ReadFrom/WriteTo
  21.                                     [1276814]
  22.         <13>     8/12/95    TÇ        1276808 Call ODReleaseObject instead of
  23.                                     ODDeleteObject on shapes & transforms
  24.         <12>      8/3/95    RR        #1257260: Collapse B classes. Remove
  25.                                     somInit methods. Don't call IsInitialized
  26.                                     or SubclassResponsibility
  27.         <11>     3/20/95    jpa        SOM_CATCH --> SOM_TRY [1224355]
  28.         <10>    12/20/94    VL        1195012: Make Storage calls be
  29.                                     marshallable.
  30.          <9>    12/20/94    jpa        Added composite xform support [1205794]
  31.          <8>     12/5/94    jpa        Code-review fixes, error handling & such.
  32.                                     [1203923]
  33.          <7>     9/29/94    RA        1189812: Mods for 68K build.
  34.          <6>      9/9/94    jpa        Added Release method, and verify refcnt in
  35.                                     somUninit. [1185660]
  36.          <5>     8/17/94    jpa        Function prefixes. [1181512]
  37.          <4>      8/8/94    jpa        Added NewTransform [1179574]
  38.          <3>     7/15/94    jpa        CopyFrom now calls InitBaseTransform in
  39.                                     case caller had just created the object.
  40.          <2>     6/30/94    jpa        Ported implementation to SOM.
  41.          <1>     6/15/94    jpa        first checked in (stubs)
  42.          ---------------------------Moved to ODSOM project.
  43.          <6>     5/27/94    jpa        Fixed bug in ScaleBy, noticed while copying
  44.                                     code over to SOM.
  45.          <5>      5/9/94    jpa        Use new built-in matrix code. [1162092]
  46.          <4>     3/25/94    JA        Rewrote & changed API to support scaling
  47.                                     for QD parts. (1153438)
  48.          <3>     3/15/94    MB        Changes to support SCpp/ASLM builds,
  49.                                     #1150864.
  50.          <2>     2/16/94    JA        Include new AltPoint.h.
  51.         <15>      2/7/94    JA        Further tigerings.
  52.         <14>      2/3/94    JA        Tiger Team Makeover!
  53.         <13>     12/3/93    TÇ        Stop including ODError.h, it is included
  54.                                     as ErrorDef.h inside Except.h
  55.         <12>    11/23/93    JA        Minor tweaks.
  56.         <11>    10/14/93    JA        No more copying in get/setters.
  57.          <9>     10/6/93    JA        Use new fixed-point ODPoint.
  58.          <8>     9/23/93    JA        Restored MoveBy. Added Mac-specific
  59.                                     convenience methods.
  60.          <7>     9/22/93    JA        Oops! Removed leftover line of test code.
  61.          <6>     9/22/93    JA        Updated ASSERTs for new macro.
  62.          <5>     9/20/93    JA        Post-brownies: Okay, REALLY fixed
  63.                                     ReadPlatformTransform.
  64.          <4>     9/17/93    TÇ        fixed ReadPlatformTransform
  65.          <3>     9/16/93    JA        Added Read/WritePlatformTransform. Removed
  66.                                     constructor w/params. Use copy-in, copy-out
  67.                                     semantics.
  68.          <2>     9/07/93    jpa        Fleshed out class, cleverly letting GX do the matrix grunge.
  69.          <1>     8/18/93    TÇ        first checked in
  70.          <0>     8/18/93    JBS        created
  71.     
  72.     Theory Of Operation:
  73.     
  74.         An ODBaseTransform is mostly a holder for an ODMatrix. It also caches an
  75.         inverse of its matrix for use in InvertPoint and Invert operations.
  76.         Since it is possible for subclasses of ODBaseTransform to exist that do not
  77.         use matrices (nonlinear transforms like morphs or spherizers), it must be
  78.         able to coexist with these. They can be detected by sending them a
  79.         HasMatrix message. The major problem arises when I'm asked to compose
  80.         myself with one of these; matrix multiplication is right out, so I have
  81.         to keep around a copy of the other transform and do manual composition. In
  82.         fact I have to keep around two potential transforms, one for pre-composi-
  83.         tion and one for post-composition.
  84.         It is illegal to externalize a composite transform, since this would be
  85.         difficult to implement. In practice the only transforms that get extern-
  86.         alized are frames' internal transforms, which are probably not composite.
  87.         
  88.         Anyone wanting to implement nonlinear transforms needs to subclass
  89.         ODBaseTransform and override at least the following methods:
  90.             GetMatrix    [need to throw ODErrTransformErr]
  91.             HasMatrix    [need to return false]
  92.             Reset
  93.             Copy
  94.             CopyFrom
  95.             Invert
  96.             PreCompose
  97.             PostCompose
  98.             TransformPoint
  99.             InvertPoint
  100.             TransformShape
  101.             InvertShape
  102.             WriteTo
  103.             ReadFrom
  104.  
  105.     To Do:
  106.     In Progress:
  107.         
  108. */
  109.  
  110. #ifndef _PLFMDEF_
  111. #include "PlfmDef.h"
  112. #endif
  113.  
  114. #ifndef _ALTPOINT_
  115. #include "AltPoint.h"            /* Use C++ savvy ODPoint and ODRect*/
  116. #endif
  117.  
  118.  
  119. #define ODBaseTransform_Class_Source
  120. #define VARIABLE_MACROS
  121. #include <TrnsfrmB.xih>
  122.  
  123.  
  124. #ifndef SOM_ODTransform_xh
  125. #include "Trnsform.xh"
  126. #endif
  127.  
  128. #ifndef _MATRIX_
  129. #include "Matrix.h"
  130. #endif
  131.  
  132. #ifndef _ODMATH_
  133. #include "ODMath.h"
  134. #endif
  135.  
  136. #ifndef SOM_ODShape_xh
  137. #include <Shape.xh>
  138. #endif
  139.  
  140. #ifndef _ODUTILS_
  141. #include <ODUtils.h>
  142. #endif
  143.  
  144. #ifndef _EXCEPT_
  145. #include "Except.h"
  146. #endif
  147.  
  148. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  149. #include <StdTypes.xh>
  150. #endif
  151.  
  152. #ifndef SOM_ODStorageUnit_xh
  153. #include <StorageU.xh>
  154. #endif
  155.  
  156. #ifndef _ODDEBUG_
  157. #include "ODDebug.h"
  158. #endif
  159.  
  160. #ifndef _LINEOPS_
  161. #include "LineOps.h"                    /* For kFixedEpsilon */
  162. #endif
  163.  
  164. #ifndef _STDTYPIO_
  165. #include <StdTypIO.h>
  166. #endif
  167.  
  168. #ifndef _STORUTIL_
  169. #include <StorUtil.h>
  170. #endif
  171.  
  172.  
  173. #define BAIL_IF_NULL(PARAM,VAL) \
  174.             if( (PARAM)!=kODNULL ) ; else {                        \
  175.                 WARN("Invalid NULL parameter " #PARAM);            \
  176.                 ODSetSOMException(ev, kODErrIllegalNullInput);    \
  177.                 return VAL;                                        \
  178.             }
  179. #define VOID /**/
  180.  
  181.  
  182. #pragma segment ODTransform
  183.  
  184.  
  185. //==============================================================================
  186. // HOUSEKEEPING
  187. //==============================================================================
  188.  
  189.  
  190. //------------------------------------------------------------------------------
  191. //    somUninit
  192. //------------------------------------------------------------------------------
  193.  
  194. SOM_Scope void  SOMLINK ODBaseTransform__somUninit(ODBaseTransform *somSelf)
  195. {
  196.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  197.     ODBaseTransformMethodDebug("ODBaseTransform","somUninit");
  198.    
  199.     ODDeleteObject(_fInverseMatrix);
  200.     ODSafeReleaseObject(_fPreTransform);
  201.     ODSafeReleaseObject(_fPostTransform);
  202.     
  203.     ODBaseTransform_parents_somUninit(somSelf);
  204.  
  205. }
  206.  
  207. //------------------------------------------------------------------------------
  208. //    InitBaseTransform
  209. //------------------------------------------------------------------------------
  210.  
  211. SOM_Scope void  SOMLINK ODBaseTransform__InitBaseTransform(ODBaseTransform *somSelf, Environment *ev)
  212. {
  213.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  214.     ODBaseTransformMethodDebug("ODBaseTransform","ODBaseTransformInitBaseTransform");
  215.  
  216.     SOM_TRY
  217.     
  218.     /* Moved from somInit. SOM itself sets fields to zero
  219.     _fInverseMatrix = kODNULL;
  220.     _fPreTransform = kODNULL;
  221.     _fPostTransform = kODNULL;
  222.     */
  223.     _fType = kODIdentityXform;
  224.     _fMatrix = kODIdentityMatrix;
  225.     
  226.     somSelf->InitRefCntObject(ev);
  227.     
  228.     SOM_CATCH_ALL
  229.     SOM_ENDTRY
  230. }
  231.  
  232. //------------------------------------------------------------------------------
  233. //    Release
  234. //------------------------------------------------------------------------------
  235.  
  236. SOM_Scope void  SOMLINK ODBaseTransform__Release(ODBaseTransform *somSelf, Environment *ev)
  237. {
  238. //    ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  239.     ODBaseTransformMethodDebug("ODBaseShape","Release");
  240.  
  241.     SOM_TRY
  242.  
  243.     ODBaseTransform_parents_Release(somSelf,ev);
  244.     
  245.     // Delete myself when my refCount goes to zero:
  246.     if( somSelf->GetRefCount(ev) < 1 )
  247.         delete somSelf;
  248.  
  249.     SOM_CATCH_ALL
  250.     SOM_ENDTRY
  251. }
  252.  
  253. //------------------------------------------------------------------------------
  254. //    Purge
  255. //------------------------------------------------------------------------------
  256.  
  257. SOM_Scope ODSize  SOMLINK ODBaseTransform__Purge(ODBaseTransform *somSelf, Environment *ev,
  258.         ODSize size)
  259. {
  260.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  261.     ODBaseTransformMethodDebug("ODBaseTransform","Purge");
  262.  
  263.     ODSize purged = 0;
  264.     ODVolatile(purged);
  265.     
  266.     SOM_TRY
  267.     
  268.         if( _fInverseMatrix ) {
  269.             ODDeleteObject(_fInverseMatrix);
  270.             purged = sizeof(ODMatrix);
  271.         }
  272.         else
  273.             purged = 0;
  274.  
  275.         purged += parent_Purge(somSelf,ev,size);
  276.     
  277.     SOM_CATCH_ALL
  278.         WARN("Error %ld trying to purge in ODBaseTransform__Purge",ErrorCode());
  279.         SetErrorCode(kODNoError);        // dh - Eat the exception; Purge should not 
  280.                                         // propagate it because clients function
  281.                                         // fine whether memory was purged or not.
  282.     SOM_ENDTRY
  283.  
  284.     return purged;
  285. }
  286.  
  287.  
  288. //==============================================================================
  289. // GETTERS
  290. //==============================================================================
  291.  
  292.  
  293. //------------------------------------------------------------------------------
  294. //    GetType
  295. //------------------------------------------------------------------------------
  296.  
  297. SOM_Scope ODTransformType SOMLINK ODBaseTransform__GetType(ODBaseTransform *somSelf, Environment *ev)
  298. {
  299.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  300.     ODBaseTransformMethodDebug("ODBaseTransform","GetType");
  301.  
  302.     if( _fPreTransform || _fPostTransform )
  303.         return kODUnknownXform;
  304.     else
  305.         return _fType;
  306. }
  307.  
  308. //------------------------------------------------------------------------------
  309. //    GetMatrix
  310. //------------------------------------------------------------------------------
  311.  
  312. SOM_Scope void SOMLINK ODBaseTransform__GetMatrix(ODBaseTransform *somSelf, Environment *ev,
  313.          ODMatrix *m )
  314. {
  315.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  316.     ODBaseTransformMethodDebug("ODBaseTransform","GetMatrix");
  317.  
  318.     BAIL_IF_NULL(m,VOID);
  319.     *m = _fMatrix;
  320.     if( _fPreTransform || _fPostTransform )
  321.         ODSetSOMException(ev,kODErrTransformErr);
  322. }
  323.  
  324. //------------------------------------------------------------------------------
  325. //    HasMatrix
  326. //------------------------------------------------------------------------------
  327.  
  328. SOM_Scope ODBoolean SOMLINK ODBaseTransform__HasMatrix(ODBaseTransform *somSelf, Environment *ev)
  329. {
  330.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  331.     ODBaseTransformMethodDebug("ODBaseTransform","HasMatrix");
  332.  
  333.     return _fPreTransform==kODNULL && _fPostTransform==kODNULL;
  334. }
  335.  
  336. //------------------------------------------------------------------------------
  337. //    GetOffset
  338. //------------------------------------------------------------------------------
  339.  
  340. SOM_Scope void SOMLINK ODBaseTransform__GetOffset(ODBaseTransform *somSelf, Environment *ev,
  341.          ODPoint *p )
  342. {
  343.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  344.     ODBaseTransformMethodDebug("ODBaseTransform","GetOffset");
  345.  
  346.     BAIL_IF_NULL(p,VOID);
  347.     p->x = ODFractDivide(_fMatrix.m[2][0], _fMatrix.m[2][2]);
  348.     p->y = ODFractDivide(_fMatrix.m[2][1], _fMatrix.m[2][2]);
  349. }
  350.  
  351. //------------------------------------------------------------------------------
  352. //    GetScale
  353. //------------------------------------------------------------------------------
  354.  
  355. SOM_Scope void SOMLINK ODBaseTransform__GetScale(ODBaseTransform *somSelf, Environment *ev,
  356.          ODPoint *scale )
  357. {
  358.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  359.     ODBaseTransformMethodDebug("ODBaseTransform","GetScale");
  360.  
  361.     BAIL_IF_NULL(scale,VOID);
  362.     scale->x = ODFractDivide(_fMatrix.m[0][0], _fMatrix.m[2][2]);
  363.     scale->y = ODFractDivide(_fMatrix.m[1][1], _fMatrix.m[2][2]);
  364. }
  365.  
  366. //------------------------------------------------------------------------------
  367. //    GetPreScaleOffset
  368. //------------------------------------------------------------------------------
  369.  
  370. SOM_Scope void SOMLINK ODBaseTransform__GetPreScaleOffset(ODBaseTransform *somSelf, Environment *ev,
  371.          ODPoint *offset )
  372. {
  373.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  374.     ODBaseTransformMethodDebug("ODBaseTransform","GetPreScaleOffset");
  375.  
  376.     // This returns the offset to use if you are going to apply the offset
  377.     // _before_ scaling. Just divide the translation elements by the scales.
  378.     
  379.     BAIL_IF_NULL(offset,VOID);
  380.     offset->x = ODFixedDivide(_fMatrix.m[2][0],_fMatrix.m[0][0]);
  381.     offset->y = ODFixedDivide(_fMatrix.m[2][1],_fMatrix.m[1][1]);
  382.     
  383.     if( offset->x==kODFixedInfinity || offset->x==kODFixedMinusInfinity
  384.       ||offset->y==kODFixedInfinity || offset->y==kODFixedMinusInfinity )
  385.             ODSetSOMException(ev,kODErrTransformErr);
  386. }
  387.  
  388. //------------------------------------------------------------------------------
  389. //    IsSameAs
  390. //------------------------------------------------------------------------------
  391.  
  392. static ODBoolean Neq( ODFixed a, ODFixed b )
  393. {
  394.     return (a-b > kFixedEpsilon) || (a-b < -kFixedEpsilon);
  395. }
  396.  
  397. SOM_Scope ODBoolean SOMLINK ODBaseTransform__IsSameAs(ODBaseTransform *somSelf, Environment *ev,
  398.          ODTransform *xform )
  399. {
  400.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  401.     ODBaseTransformMethodDebug("ODBaseTransform","IsSameAs");
  402.  
  403.     SOM_TRY
  404.     
  405.     BAIL_IF_NULL(xform,kODFalse);
  406.     
  407.     if( _fPreTransform || _fPostTransform )
  408.         return kODFalse;                    // ????? What else can I do??
  409.  
  410.     if( (ODBaseTransform*)xform != somSelf) {
  411.         ODMatrix m0, m1, *mp;
  412.         xform->GetMatrix(ev,&m1);
  413.         
  414.         if(_fMatrix.m[2][2]!=kODFract1 ) {
  415.             m0 = _fMatrix;
  416.             MxNormalize(&m0);                // Normalize my matrix
  417.             mp = &m0;
  418.         } else
  419.             mp = &_fMatrix;
  420.         if(m1.m[2][2]!=kODFract1 )
  421.             MxNormalize(&m1);                // Normalize other matrix
  422.             
  423.         for( long i=8; i>=0; i-- )
  424.             if( Neq(mp->m[0][i],m1.m[0][i]) )    // Compare matrices
  425.                 return kODFalse;
  426.     }
  427.     return kODTrue;
  428.  
  429.     SOM_CATCH_ALL
  430.     SOM_ENDTRY
  431.     return kODFalse;
  432. }
  433.  
  434.  
  435. //==============================================================================
  436. // SETTERS
  437. //==============================================================================
  438.  
  439.  
  440. //------------------------------------------------------------------------------
  441. //    SetMatrix
  442. //------------------------------------------------------------------------------
  443.  
  444. SOM_Scope ODTransform* SOMLINK ODBaseTransform__SetMatrix(ODBaseTransform *somSelf, Environment *ev,
  445.          ODMatrix *m )
  446. {
  447.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  448.     ODBaseTransformMethodDebug("ODBaseTransform","SetMatrix");
  449.  
  450.     SOM_TRY
  451.     
  452.     if( m == kODNULL )
  453.         somSelf->Reset(ev);
  454.     else {
  455.         ODTransformType type = MxType(m);
  456.         if( type==kODUnknownXform )
  457.             THROW(kODErrTransformErr);
  458.         _fMatrix = *m;
  459.         _fType = type;
  460.         ODDeleteObject(_fInverseMatrix);
  461.         ODReleaseObject(ev,_fPreTransform);
  462.         ODReleaseObject(ev,_fPostTransform);
  463.     }
  464.  
  465.     SOM_CATCH_ALL
  466.     SOM_ENDTRY
  467.     return (ODTransform*) somSelf;
  468. }
  469.  
  470. //------------------------------------------------------------------------------
  471. //    Reset
  472. //------------------------------------------------------------------------------
  473.  
  474. SOM_Scope ODTransform* SOMLINK ODBaseTransform__Reset(ODBaseTransform *somSelf, Environment *ev)
  475. {
  476.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  477.     ODBaseTransformMethodDebug("ODBaseTransform","Reset");
  478.  
  479.     _fMatrix = kODIdentityMatrix;
  480.     _fType = kODIdentityXform;
  481.     ODDeleteObject(_fInverseMatrix);
  482.     ODSafeReleaseObject(_fPreTransform);    _fPreTransform = kODNULL;
  483.     ODSafeReleaseObject(_fPostTransform);_fPostTransform= kODNULL;
  484.     return (ODTransform*) somSelf;
  485. }
  486.  
  487. //------------------------------------------------------------------------------
  488. //    NewTransform
  489. //------------------------------------------------------------------------------
  490.  
  491. SOM_Scope ODTransform*  SOMLINK ODBaseTransform__NewTransform(ODBaseTransform *somSelf, Environment *ev)
  492. {
  493. //    ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  494.     ODBaseTransformMethodDebug("ODBaseTransform","NewTransform");
  495.     
  496.     ODTransform *x = new ODTransform;
  497.     if( !x )
  498.         ODSetSOMException(ev,kODErrOutOfMemory);
  499.     else {
  500.         TRY{
  501.             x->InitTransform(ev);
  502.         }CATCH_ALL{
  503.             ODSafeReleaseObject(x);
  504.             SET_SOM_EXCEPTION(ev);
  505.         }ENDTRY
  506.     }
  507.     return x;
  508. }
  509.  
  510. //------------------------------------------------------------------------------
  511. //    Copy
  512. //------------------------------------------------------------------------------
  513.  
  514. SOM_Scope ODTransform* SOMLINK ODBaseTransform__Copy(ODBaseTransform *somSelf, Environment *ev )
  515. {
  516.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  517.     ODBaseTransformMethodDebug("ODBaseTransform","Copy");
  518.  
  519.     ODTransform *x = kODNULL; ODVolatile(x);
  520.     
  521.     SOM_TRY
  522.     
  523.         x = new ODTransform;
  524.         THROW_IF_NULL(x);
  525.         x->InitTransform(ev);
  526.         x->SetMatrix(ev,&_fMatrix);
  527.         if( _fPreTransform ) {
  528.             ODTransform *t = _fPreTransform->Copy(ev);
  529.             x->PreCompose(ev,t);
  530.             t->Release(ev);
  531.         }
  532.         if( _fPostTransform ) {
  533.             ODTransform *t = _fPostTransform->Copy(ev);
  534.             x->PostCompose(ev,t);
  535.             t->Release(ev);
  536.         }
  537.     
  538.     SOM_CATCH_ALL
  539.         ODSafeReleaseObject(x);
  540.         x = kODNULL;
  541.     SOM_ENDTRY
  542.     return x;
  543. }
  544.  
  545. //------------------------------------------------------------------------------
  546. //    CopyFrom
  547. //------------------------------------------------------------------------------
  548.  
  549. SOM_Scope ODTransform* SOMLINK ODBaseTransform__CopyFrom(ODBaseTransform *somSelf, Environment *ev,
  550.          ODTransform *xform )
  551. {
  552.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  553.     ODBaseTransformMethodDebug("ODBaseTransform","CopyFrom");
  554.  
  555.     SOM_TRY
  556.     
  557.     BAIL_IF_NULL(xform,kODNULL);
  558.  
  559.     if( xform->HasMatrix(ev) ) {
  560.         xform->GetMatrix(ev,&_fMatrix);
  561.         _fType = xform->GetType(ev);
  562.         ODDeleteObject(_fInverseMatrix);
  563.     } else {
  564.         somSelf->Reset(ev);
  565.         _fPreTransform = xform->Copy(ev);
  566.     }
  567.  
  568.     SOM_CATCH_ALL
  569.     SOM_ENDTRY
  570.     return (ODTransform*) somSelf;
  571. }
  572.  
  573.  
  574. //==============================================================================
  575. // MATRIX TRANSFORMATIONS
  576. //==============================================================================
  577.  
  578.  
  579. //------------------------------------------------------------------------------
  580. //    SetOffset
  581. //------------------------------------------------------------------------------
  582.  
  583. SOM_Scope ODTransform* SOMLINK ODBaseTransform__SetOffset(ODBaseTransform *somSelf, Environment *ev,
  584.          ODPoint *offset )
  585. {
  586.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  587.     ODBaseTransformMethodDebug("ODBaseTransform","SetOffset");
  588.  
  589.     SOM_TRY
  590.     
  591.     somSelf->Reset(ev);
  592.     _fMatrix.m[2][0] = offset->x;
  593.     _fMatrix.m[2][1] = offset->y;
  594.     _fType = kODTranslateXform;
  595.  
  596.     SOM_CATCH_ALL
  597.     SOM_ENDTRY
  598.     return (ODTransform*) somSelf;
  599. }
  600.  
  601. //------------------------------------------------------------------------------
  602. //    MoveBy
  603. //------------------------------------------------------------------------------
  604.  
  605. SOM_Scope ODTransform* SOMLINK ODBaseTransform__MoveBy(ODBaseTransform *somSelf, Environment *ev,
  606.          ODPoint *offset )
  607. {
  608.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  609.     ODBaseTransformMethodDebug("ODBaseTransform","MoveBy");
  610.  
  611.     SOM_TRY
  612.     
  613.     ODMatrix m = _fMatrix;
  614.     if( MxMove(&m,_fType,offset->x,offset->y) )
  615.         THROW(kODErrTransformErr);
  616.     somSelf->SetMatrix(ev, &m);
  617.  
  618.     SOM_CATCH_ALL
  619.     SOM_ENDTRY
  620.     return (ODTransform*) somSelf;
  621. }
  622.  
  623. //------------------------------------------------------------------------------
  624. //    ScaleBy
  625. //------------------------------------------------------------------------------
  626.  
  627. SOM_Scope ODTransform* SOMLINK ODBaseTransform__ScaleBy(ODBaseTransform *somSelf, Environment *ev,
  628.          ODPoint *scale )
  629. {
  630.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  631.     ODBaseTransformMethodDebug("ODBaseTransform","ScaleBy");
  632.  
  633.     SOM_TRY
  634.     
  635.     ODMatrix m = _fMatrix;
  636.     if( MxScale(&m,scale->x,scale->y) )
  637.         THROW(kODErrTransformErr);
  638.     somSelf->SetMatrix(ev, &m);
  639.  
  640.     SOM_CATCH_ALL
  641.     SOM_ENDTRY
  642.     return (ODTransform*) somSelf;
  643. }
  644.  
  645. //------------------------------------------------------------------------------
  646. //    ScaleDownBy
  647. //------------------------------------------------------------------------------
  648.  
  649. SOM_Scope ODTransform* SOMLINK ODBaseTransform__ScaleDownBy(ODBaseTransform *somSelf, Environment *ev,
  650.          ODPoint *scale )
  651. {
  652.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  653.     ODBaseTransformMethodDebug("ODBaseTransform","ScaleDownBy");
  654.  
  655.     SOM_TRY
  656.     
  657.     if( scale->x==0 || scale->y==0 )
  658.         THROW(kODErrTransformErr);
  659.     ODPoint s;
  660.     s.x = ODFixedDivide(kODFixed1,scale->x);
  661.     s.y = ODFixedDivide(kODFixed1,scale->y);
  662.     somSelf->ScaleBy(ev, &s);
  663.  
  664.     SOM_CATCH_ALL
  665.     SOM_ENDTRY
  666.     return (ODTransform*) somSelf;
  667. }
  668.  
  669. //------------------------------------------------------------------------------
  670. //    BuildInverse
  671. //------------------------------------------------------------------------------
  672.  
  673. SOM_Scope void SOMLINK ODBaseTransform__BuildInverse(ODBaseTransform *somSelf, Environment *ev)
  674. {
  675.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  676.     ODBaseTransformMethodDebug("ODBaseTransform","BuildInverse");
  677.  
  678.     SOM_TRY
  679.     
  680.     WASSERT(!_fInverseMatrix);
  681.     _fInverseMatrix = new ODMatrix;
  682.     if( MxInverse(&_fMatrix,_fType, _fInverseMatrix) ) {
  683.         ODDeleteObject(_fInverseMatrix);
  684.         THROW(kODErrTransformErr);
  685.     }
  686.     
  687.     SOM_CATCH_ALL
  688.     SOM_ENDTRY
  689. }
  690.  
  691. //------------------------------------------------------------------------------
  692. //    Invert
  693. //------------------------------------------------------------------------------
  694.  
  695. SOM_Scope ODTransform* SOMLINK ODBaseTransform__Invert(ODBaseTransform *somSelf, Environment *ev )
  696. {
  697.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  698.     ODBaseTransformMethodDebug("ODBaseTransform","Invert");
  699.     
  700.     SOM_TRY
  701.  
  702.     if( !_fInverseMatrix )
  703.         somSelf->BuildInverse(ev);
  704.     
  705.     if( _fPreTransform || _fPostTransform ) {
  706.         // When inverting, switch pre with post and invert each one.
  707.         ODBaseTransform *pre = _fPreTransform;
  708.         _fPreTransform = _fPostTransform ?_fPostTransform->Invert(ev) :kODNULL;
  709.         _fPostTransform = pre ?pre->Invert(ev) :kODNULL;
  710.     }
  711.     
  712.     // Swap matrix with inverse:
  713.     ODFixed *a = &_fMatrix.m[0][0];
  714.     ODFixed *b = &_fInverseMatrix->m[0][0];
  715.     for( ODSLong i=9; i>0; i-- ) {
  716.         register ODFixed temp = *a;
  717.         *(a++) = *b;
  718.         *(b++) = temp;
  719.     }
  720.     
  721.     // No need to change _fType, since matrix and inverse have same type.
  722.     
  723.     SOM_CATCH_ALL
  724.     SOM_ENDTRY
  725.     return (ODTransform*) somSelf;
  726. }
  727.  
  728. //------------------------------------------------------------------------------
  729. //    PreCompose
  730. //------------------------------------------------------------------------------
  731.  
  732. SOM_Scope ODTransform* SOMLINK ODBaseTransform__PreCompose(ODBaseTransform *somSelf, Environment *ev,
  733.          ODTransform *t )
  734. {
  735.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  736.     ODBaseTransformMethodDebug("ODBaseTransform","PreCompose");
  737.  
  738.     SOM_TRY
  739.     BAIL_IF_NULL(t,kODNULL);
  740.     
  741.     if( _fPreTransform )
  742.         _fPreTransform->PreCompose(ev,t);
  743.     else if( !t->HasMatrix(ev) )
  744.         _fPreTransform = t->Copy(ev);
  745.     else {
  746.         ODMatrix m;
  747.         t->GetMatrix(ev,&m);
  748.         if( MxConcat( &_fMatrix,_fType, &m,t->GetType(ev) ) )    // m = m * _fMatrix
  749.             THROW(kODErrTransformErr);
  750.         somSelf->SetMatrix(ev, &m);
  751.     }
  752.  
  753.     SOM_CATCH_ALL
  754.     SOM_ENDTRY
  755.     return (ODTransform*) somSelf;
  756. }
  757.  
  758. //------------------------------------------------------------------------------
  759. //    PostCompose
  760. //------------------------------------------------------------------------------
  761.  
  762. SOM_Scope ODTransform* SOMLINK ODBaseTransform__PostCompose(ODBaseTransform *somSelf, Environment *ev,
  763.          ODTransform *t )
  764. {
  765.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  766.     ODBaseTransformMethodDebug("ODBaseTransform","PostCompose");
  767.  
  768.     SOM_TRY
  769.     BAIL_IF_NULL(t,kODNULL);
  770.     
  771.     if( _fPostTransform )
  772.         _fPostTransform->PostCompose(ev,t);
  773.     else if( !t->HasMatrix(ev) )
  774.         _fPostTransform = t->Copy(ev);
  775.     else {
  776.         ODMatrix m;
  777.         ODMatrix me = _fMatrix;
  778.         t->GetMatrix(ev,&m);
  779.         if( MxConcat( &m,t->GetType(ev), &me,_fType) )                // me = me * m
  780.             THROW(kODErrTransformErr);
  781.         somSelf->SetMatrix(ev, &me);
  782.     }
  783.  
  784.     SOM_CATCH_ALL
  785.     SOM_ENDTRY
  786.     return (ODTransform*) somSelf;
  787. }
  788.  
  789. //------------------------------------------------------------------------------
  790. //    TransformPoint
  791. //------------------------------------------------------------------------------
  792.  
  793. SOM_Scope void SOMLINK ODBaseTransform__TransformPoint(ODBaseTransform *somSelf, Environment *ev,
  794.          ODPoint *pt )
  795. {
  796.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  797.     ODBaseTransformMethodDebug("ODBaseTransform","TransformPoint");
  798.     
  799.     ODPoint xp = *pt;
  800.     
  801.     SOM_TRY
  802.  
  803.     if( _fPreTransform )
  804.         _fPreTransform->TransformPoint(ev,&xp);
  805.     if( MxMul(&_fMatrix,_fType, &xp,1) )
  806.         THROW(kODErrTransformErr);
  807.     if( _fPostTransform )
  808.         _fPostTransform->TransformPoint(ev,&xp);
  809.  
  810.     *pt = xp;
  811.     
  812.     SOM_CATCH_ALL
  813.     SOM_ENDTRY
  814. }
  815.  
  816. //------------------------------------------------------------------------------
  817. //    InvertPoint
  818. //------------------------------------------------------------------------------
  819.  
  820. SOM_Scope void SOMLINK ODBaseTransform__InvertPoint(ODBaseTransform *somSelf, Environment *ev,
  821.          ODPoint *pt )
  822. {
  823.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  824.     ODBaseTransformMethodDebug("ODBaseTransform","InvertPoint");
  825.  
  826.     ODPoint inv = *pt;
  827.  
  828.     SOM_TRY
  829.  
  830.     if( !_fInverseMatrix )
  831.         somSelf->BuildInverse(ev);
  832.     
  833.     if( _fPostTransform )
  834.         _fPostTransform->InvertPoint(ev,&inv);
  835.     if( MxMul(_fInverseMatrix,_fType, &inv,1) )
  836.         THROW(kODErrTransformErr);
  837.     if( _fPreTransform )
  838.         _fPreTransform->InvertPoint(ev,&inv);
  839.         
  840.     *pt = inv;
  841.  
  842.     SOM_CATCH_ALL
  843.     SOM_ENDTRY
  844. }
  845.  
  846. //------------------------------------------------------------------------------
  847. //    TransformShape
  848. //------------------------------------------------------------------------------
  849.  
  850. SOM_Scope void SOMLINK ODBaseTransform__TransformShape(ODBaseTransform *somSelf, Environment *ev,
  851.          ODShape *shape )
  852. {
  853.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  854.     ODBaseTransformMethodDebug("ODBaseTransform","TransformShape");
  855.  
  856.     SOM_TRY
  857.     
  858.     BAIL_IF_NULL(shape,VOID);
  859.     if( _fPreTransform )
  860.         _fPreTransform->TransformShape(ev,shape);
  861.     shape->Transform(ev, (ODTransform*)somSelf);
  862.     if( _fPostTransform )
  863.         _fPostTransform->TransformShape(ev,shape);
  864.     
  865.     /*    This call is (a) a convenience for clients and (b) provided for
  866.         implementations of non-affine transformations, i.e. transformations
  867.         that do not map straight lines onto straight lines. ODShapes trans-
  868.         form themselves by running all their control points through the
  869.         transform. For a non-affine transformation this is not sufficient
  870.         and the transform itself will have to do the work. In fact, if
  871.         the transform has no matrix (HasMatrix()==false), then the body of
  872.         this method must _not_ call ODShape::Transform(somSelf) or an endless
  873.         recursion will result! (Look at ODShape::Transform to see why.)
  874.     */
  875.  
  876.     SOM_CATCH_ALL
  877.     SOM_ENDTRY
  878. }
  879.  
  880. //------------------------------------------------------------------------------
  881. //    InvertShape
  882. //------------------------------------------------------------------------------
  883.  
  884. SOM_Scope void SOMLINK ODBaseTransform__InvertShape(ODBaseTransform *somSelf, Environment *ev,
  885.          ODShape *shape )
  886. {
  887.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  888.     ODBaseTransformMethodDebug("ODBaseTransform","InvertShape");
  889.  
  890.     SOM_TRY
  891.     
  892.     BAIL_IF_NULL(shape,VOID);
  893.     if( _fPostTransform )
  894.         _fPostTransform->TransformShape(ev,shape);
  895.     shape->InverseTransform(ev, (ODTransform*)somSelf);
  896.     if( _fPreTransform )
  897.         _fPreTransform->TransformShape(ev,shape);
  898.     
  899.     // See above comment in TransformShape.
  900.  
  901.     SOM_CATCH_ALL
  902.     SOM_ENDTRY
  903. }
  904.  
  905.  
  906. //==============================================================================
  907. // INPUT / OUTPUT
  908. //==============================================================================
  909.  
  910.  
  911. //------------------------------------------------------------------------------
  912. // WriteTo
  913. //------------------------------------------------------------------------------
  914.  
  915. SOM_Scope void SOMLINK ODBaseTransform__WriteTo(ODBaseTransform *somSelf, Environment *ev,
  916.          ODStorageUnit *su )
  917. {
  918.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  919.     ODBaseTransformMethodDebug("ODBaseTransform","WriteTo");
  920.     
  921.     SOM_TRY
  922.     BAIL_IF_NULL(su,VOID);
  923.     
  924.     if( _fPreTransform || _fPostTransform) {
  925.         WARN("Tried to externalize composite transform %p",somSelf);
  926.     }
  927.     
  928.     ODSUForceFocus(ev,su,kODNULL,kODTransform);
  929.     ODULong size = su->GetSize(ev);
  930.     if( size!=0 )
  931.         su->DeleteValue(ev,size);        // Nuke previous contents
  932.     ODSetMatrixProp(ev, su, kODNULL,kODNULL, &_fMatrix);
  933.  
  934.     SOM_CATCH_ALL
  935.     SOM_ENDTRY
  936. }
  937.  
  938. //------------------------------------------------------------------------------
  939. // ReadFrom
  940. //------------------------------------------------------------------------------
  941.  
  942. SOM_Scope void SOMLINK ODBaseTransform__ReadFrom(ODBaseTransform *somSelf, Environment *ev,
  943.          ODStorageUnit *su )
  944. {
  945.     ODBaseTransformData *somThis = ODBaseTransformGetData(somSelf);
  946.     ODBaseTransformMethodDebug("ODBaseTransform","ReadFrom");
  947.  
  948.     SOM_TRY
  949.     
  950.     ODReleaseObject(ev,_fPreTransform);
  951.     ODReleaseObject(ev,_fPostTransform);
  952.     
  953.     BAIL_IF_NULL(su,VOID);
  954.     ODMatrix m;
  955.     ODGetMatrixProp(ev, su, kODNULL, kODTransform, &m);
  956.     somSelf->SetMatrix(ev, &m);
  957.  
  958.     SOM_CATCH_ALL
  959.     SOM_ENDTRY
  960. }
  961.