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

  1. /* @(#)Z 1.8 com/src/imaging/Matrix.cpp, odimaging, od96os2, odos29712d 97/03/21 17:18:18 (96/10/29 09:25:06) */
  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. /*  Licensed Materials - Property of IBM                            */
  31. /*                                                                  */
  32. /*                                                                  */
  33. /* Copyright (C) International Business Machines Corp., 1994.       */
  34. /* Copyright (C) Apple Computer, Inc., 1994                         */
  35. /*                                                                  */
  36. /*  US Government Users Restricted Rights -                         */
  37. /*  Use, duplication, or disclosure restricted                      */
  38. /*  by GSA ADP Schedule Contract with IBM Corp.                     */
  39. /*                                                                  */
  40. /*  IBM Change History (most recent first):                         */
  41. /*          3/18/96 jab  Merge OS/2 Feb. 13 drop with DR4.          */
  42. /*  117544  4/3/95  MAP  Replace definitions of true/false          */
  43. /*  <OS2>   8/27/94 MAP  Port A8C3                                  */
  44. /*                                                                  */
  45. /********************************************************************/
  46. /*
  47.     File:        Matrix.cpp
  48.  
  49.     Contains:    Matrix math for ODTransforms.
  50.  
  51.     Owned by:    Jens Alfke
  52.     Owned by:    Cary Clark, Michael Fairman, Robert Johnson, Keith McGreggor,
  53.                 Oliver Steele, David Van Brink, Jens Alfke
  54.     Based on:    QuickDraw GX "matrixMath.c" and "math.c" sources
  55.  
  56.     Copyright:    ⌐ 1994 - 1995 by Apple Computer, Inc., all rights reserved.
  57.  
  58.     Change History (most recent first):
  59.     
  60.          <2>     5/25/95    jpa        Renamed some routines that conflict with GX
  61.                                     exports. [1241078, 1253324]
  62.          <1>     6/15/94    jpa        first checked in
  63.          ---------------------------Moved to ODSOM project.
  64.          <2>     5/10/94    jpa        Replaced a too-complex typecast to appease
  65.                                     %$*# cfront.
  66.          <1>      5/9/94    jpa        first checked in
  67.     To Do:
  68.         * I have no idea whether this code will work on little-endian CPUs.
  69.           It _should_, but who knows?
  70.     In Progress:
  71.         
  72. */
  73.  
  74.  
  75. #ifdef _PLATFORM_MACINTOSH_
  76. #pragma segment ODTransform
  77. #endif
  78.  
  79.  
  80. #ifndef _MATRIX_
  81. #include "Matrix.h"
  82. #endif
  83.  
  84.  
  85. #if defined(_PLATFORM_OS2_) || defined(_PLATFORM_WIN32_)
  86. #ifndef _PAGETUNING_OFF_
  87. #include <ODPagtun.h>
  88. #endif 
  89. #endif   // IBM Platforms
  90.  
  91. #ifndef _ODMATH_
  92. #include "ODMath.h"
  93. #endif
  94.  
  95. #if  defined(_PLATFORM_OS2_) || defined(_PLATFORM_WIN32_) || defined(_PLATFORM_UNIX_)
  96. #define FracDiv ODFractDivide
  97. #define FracMul ODFractMultiply
  98. #endif
  99.  
  100. //=============================================================================
  101. // Constants & Types
  102. //=============================================================================
  103.  
  104. // defect 117544
  105. #if defined(_PLATFORM_OS2_) || defined(_PLATFORM_WIN32_) || defined(_PLATFORM_UNIX_)
  106. #define true  kODTrue
  107. #define false kODFalse
  108. #endif
  109.  
  110. #define wideSize        64                        /* bit sizes */
  111. #define longSize        32
  112. #define fractPrecision    30                        /* fixed ODPoint precisions */
  113. #define fixedPrecision    16
  114.  
  115.  
  116. typedef int fastInt;
  117.  
  118.  
  119. const ODMatrix kODIdentityMatrix = {{{kODFixed1, 0, 0},
  120.                      {0, kODFixed1, 0},
  121.                      {0,  0, kODFract1}}};
  122.  
  123.  
  124. //=============================================================================
  125. // Math Subroutines
  126. //=============================================================================
  127.  
  128. // MyWideScale is the same as GX's WideScale.
  129.  
  130. static ODSShort
  131. MyWideScale( const ODWide *wide )    // JPA: I wrote this from scratch
  132. {
  133.     ODWide temp = *wide;
  134. #if !defined(_PLATFORM_UNIX_)
  135.     if (temp.hi < 0)
  136.         ODWideNegate(&temp);
  137.     if (temp.hi)
  138.         return ODFirstBit(temp.hi) + longSize;
  139.     else
  140.         return ODFirstBit(temp.lo);
  141. #else // defined(_PLATFORM_UNIX_)
  142.     if (temp < 0)
  143.         temp = -temp;
  144.     return ODWideFirstBit(temp);
  145. #endif // !defined(_PLATFORM_UNIX_)
  146. }
  147.  
  148.  
  149. #if PLATFORM_MACINTOSH && USES68KINLINES
  150.     /* an inline macro version of overflow checking: */
  151.     extern "C" {
  152.         #pragma parameter __D0 FixAddCheck(__D0, __A0)
  153.         extern ODBoolean FixAddCheck( ODFixed a, ODFixed *b ) = {
  154.             0xD190,        // ADD.L    D0,(A0)
  155.             0x58C0,        // SVC        D0        0 if overflow, 0xff if no overflow
  156.             0x5200      // ADDQ.B    #$1,D0    1 if overflow, 0 if no overflow
  157.         };
  158.     }
  159. #else
  160.     static ODBoolean
  161.     FixAddCheck( ODFixed a, ODFixed *b )
  162.     {
  163.         register ODFixed temp = *b;
  164.         
  165.         *b += a;
  166.         if (*b < temp ^ a < 0)
  167.             return true;
  168.         else
  169.             return false;
  170.     }
  171. #endif
  172.  
  173.  
  174. static ODBoolean
  175. FixMulCheck( ODFixed a, ODFixed b, ODFixed *result )
  176. {
  177.     *result = ODFixedMultiply(a,b);
  178.     return (*result==kODFixedInfinity || *result==kODFixedMinusInfinity);
  179. }
  180.  
  181.  
  182. static ODBoolean
  183. FixDivCheck( ODFixed a, ODFixed b, ODFixed *result )
  184. {
  185.     *result = ODFixedDivide(a,b);
  186.     return (*result==kODFixedInfinity || *result==kODFixedMinusInfinity);
  187. }
  188.  
  189.  
  190. static ODBoolean
  191. FixMulAddCheck(register ODFixed a, register ODFixed b, register ODFixed *c)
  192. {
  193.     ODWide temp;
  194.     ODWideShift(ODWideMultiply(a, b, &temp), fixedPrecision);
  195. #if !defined(_PLATFORM_UNIX_)
  196.     if (*c < 0) --temp.hi;
  197.     temp.lo += *c;
  198.     if (temp.lo < *c) ++temp.hi;
  199.     *c = temp.lo;
  200. #else // defined(_PLATFORM_UNIX_)
  201.     temp += *c;
  202.     *c = (ODFixed)temp;
  203. #endif // !defined(_PLATFORM_UNIX_)
  204.     return !ODWideIsLong(&temp);
  205. }
  206.  
  207.  
  208. static ODBoolean
  209. MulMulAddCheck( long a1, long b1, long a2, long b2, short bias, long *dest )
  210. {
  211.     ODWide temp1, temp2;
  212.     ODWideShift(ODWideAdd(ODWideMultiply(a1, b1, &temp1),
  213.                              ODWideMultiply(a2, b2, &temp2)),
  214.                  bias);
  215. #if !defined(_PLATFORM_UNIX_)
  216.     if (*dest < 0) --temp1.hi;
  217.     if ((temp1.lo += *dest) < *dest) ++temp1.hi;
  218.     *dest = temp1.lo;
  219. #else // defined(_PLATFORM_UNIX_)
  220.     temp1 += *dest;
  221.     *dest = (long)temp1;
  222. #endif // !defined(_PLATFORM_UNIX_)
  223.     return !ODWideIsLong(&temp1);
  224. }
  225.  
  226.  
  227. static ODBoolean
  228. FracDivCheck(register ODFixed dividend, register ODFixed divisor, register ODFixed *dest)
  229. {
  230.     ODWide temp;
  231. #if !defined(_PLATFORM_UNIX_)
  232.     temp.hi = dividend; temp.lo = 0;
  233. #else // defined(_PLATFORM_UNIX_)
  234.     temp = (ODWide)dividend << sizeof(long);
  235. #endif // !defined(_PLATFORM_UNIX_)
  236.     *dest = ODWideDivide(ODWideShift(&temp, longSize-fractPrecision), divisor, kODIgnoreRemainder);
  237.     return *dest == kODFixedMinusInfinity;
  238. }
  239.  
  240.  
  241. static ODBoolean
  242. FracMulAddCheck(register ODFixed a, register ODFixed b, register ODFixed *c)
  243. {
  244.     ODWide temp;
  245.     ODWideShift(ODWideMultiply(a, b, &temp), fractPrecision);
  246. #if !defined(_PLATFORM_UNIX_)
  247.     if (*c < 0) --temp.hi;
  248.     temp.lo += *c;
  249.     if (temp.lo < *c) ++temp.hi;
  250.     *c = temp.lo;
  251. #else // defined(_PLATFORM_UNIX_)
  252.     temp += *c;
  253.     *c = (long)temp;
  254. #endif // !defined(_PLATFORM_UNIX_)
  255.     return !ODWideIsLong(&temp);
  256. }
  257.  
  258.  
  259. static ODBoolean
  260. FracDivAddCheck(register ODFixed a, register ODFixed b, register ODFixed *c)
  261. {
  262.     ODFixed d;
  263.     return FracDivCheck(a, b, &d) || FixAddCheck(d, c);
  264. }
  265.  
  266.  
  267. // MyVectorMultiply is the same as GX's VectorMultiply. Ditto the ...Divide variant.
  268.  
  269. static ODWide*
  270. MyVectorMultiply(register long count, register const long *vector1, register long step1,
  271.                 register const long *vector2, register long step2, register ODWide *dot)
  272. {
  273.     short flags = count >= 0;
  274. #if !defined(_PLATFORM_UNIX_)
  275.     dot->hi = dot->lo = 0;
  276. #else // defined(_PLATFORM_UNIX_)
  277.     *dot = 0;
  278. #endif // !defined(_PLATFORM_UNIX_)
  279.     if (!flags)
  280.         count = -count;
  281.     while (count--)
  282.     {    ODWide temp;
  283.         if (flags ^= 2)
  284.             ODWideAdd(dot, ODWideMultiply(*vector1, *vector2, &temp));
  285.         else
  286.             ODWideSubtract(dot, ODWideMultiply(*vector1, *vector2, &temp));
  287.         vector1 += step1;
  288.         vector2 += step2;
  289.     }
  290.     return dot;
  291. }
  292.  
  293.  
  294. static long
  295. MyVectorMultiplyDivide(long count, const long *vector1, long step1,
  296.                                  const long *vector2, long step2, long scalar)
  297. {
  298.     ODWide temp;
  299.     return ODWideDivide(MyVectorMultiply(count, vector1, step1, vector2, step2, &temp), scalar, 0);
  300. }
  301.  
  302.  
  303.  
  304. //=============================================================================
  305. // Matrix Math
  306. //=============================================================================
  307.  
  308.  
  309. //
  310. // IBM Platforms
  311. //
  312. #if defined(_PLATFORM_OS2_) || defined(_PLATFORM_WIN32_) || defined(_PLATFORM_UNIX_) // [122017]
  313.  
  314. const ODFixed kFixedEpsilon= 0x00000007;  // Amt by which fixeds can differ and be "equal"
  315.  
  316. inline ODBoolean Neq( ODFixed a, ODFixed b )
  317. {
  318.   return (a-b > kFixedEpsilon) || (a-b < -kFixedEpsilon);
  319. }
  320.  
  321. ODTransformType
  322. MxType(const ODMatrix *matrix)
  323. {
  324.   register ODSShort translate;
  325.  
  326.   if (matrix->m[0][2] == 0 && matrix->m[1][2] == 0 && matrix->m[2][2] <= 0)
  327.     return kODInvalidXform;
  328.   if (Neq(matrix->m[0][2],0) || Neq(matrix->m[1][2],0) || Neq(matrix->m[2][2],kODFract1))
  329.     return kODPerspectiveXform;
  330.   if (Neq(matrix->m[2][0],0) || Neq(matrix->m[2][1],0))
  331.     translate = kODTranslateXform;
  332.   else
  333.     translate = kODIdentityXform;
  334.   if (Neq(matrix->m[0][1],0) || Neq(matrix->m[1][0],0))
  335.     return (ODTransformType)( (ODSShort)kODLinearXform + translate );
  336.   if (Neq(matrix->m[0][0],kODFixed1) || Neq(matrix->m[1][1],kODFixed1))
  337.     return (ODTransformType)( (ODSShort)kODScaleXform + translate );
  338.   return (ODTransformType)translate;
  339. }
  340.  
  341. #endif  // IBM Platforms
  342.  
  343.  
  344. //
  345. // Macintosh specific code
  346. //
  347. #ifdef _PLATFORM_MACINTOSH_
  348.  
  349. ODTransformType
  350. MxType(const ODMatrix *matrix)
  351. {
  352.   register ODSShort translate;
  353.  
  354.   if (matrix->m[0][2] == 0 && matrix->m[1][2] == 0 && matrix->m[2][2] <= 0)
  355.     return kODInvalidXform;
  356.   if (matrix->m[0][2] || matrix->m[1][2] || matrix->m[2][2] != kODFract1)
  357.     return kODPerspectiveXform;
  358.   if (matrix->m[2][0] || matrix->m[2][1])
  359.     translate = kODTranslateXform;
  360.   else
  361.     translate = kODIdentityXform;
  362.   if (matrix->m[0][1] || matrix->m[1][0])
  363.     return (ODTransformType)( (ODSShort)kODLinearXform + translate );
  364.   if (matrix->m[0][0] != kODFixed1 || matrix->m[1][1] != kODFixed1)
  365.     return (ODTransformType)( (ODSShort)kODScaleXform + translate );
  366.   return (ODTransformType)translate;
  367. }
  368.  
  369. #endif // _PLATFORM_MACINTOSH_
  370.  
  371. ODBoolean
  372. MxNormalize(ODMatrix *map)
  373. {
  374.     unsigned long norm[3][3];
  375.     register fastInt shift, count;
  376.     register ODFixed *src;
  377.     register unsigned long *dst;
  378.     ODTransformType state = MxType(map);
  379.  
  380.     if (state == kODInvalidXform) return true;
  381.     if (state != kODPerspectiveXform) return false;            /* map is already normalized */
  382.  
  383.     {    register unsigned long mask = 0;
  384.         src = &map->m[0][0]; dst = &norm[0][0];
  385.         count = 9;
  386.         do
  387.         {    register ODFixed temp;
  388.             if ((temp = *src++) < 0) temp = -temp;
  389.             mask |= *dst++ = temp;
  390.         } while (--count);
  391.         shift = ODFirstBit(mask) - fractPrecision;            /* find the scale of greatest element */
  392.     }
  393.  
  394.     src = &map->m[0][0];
  395.     {    register unsigned long sum;
  396.         register ODFract w;
  397.         if ( (sum = norm[0][2] + norm[1][2]) != 0 )                /* map is truly perspective */
  398.         {    count = ODFirstBit(sum) - (fractPrecision - 1);
  399.             if (count >= 0 ? sum > kODFract1 - kODFixed1 << count : sum << -count > kODFract1 - kODFixed1) ++count;
  400.             if (count > shift) shift = count;
  401.         }
  402.         else                                        /* map is pathologically affine */
  403.         {    w = map->m[2][2];                    /* must be > 0 or map would be invalid */
  404.             if (w & w - 1)                            /* if it's not a power of 2, try to divide by w */
  405.             {    count = 3;
  406.                 dst = &norm[0][0];
  407.                 do                                /* check if map can be divided by w */
  408.                 {    if (*dst++ >> 1 >= w ) break;        /* is the x-coefficient too big? */
  409.                     if (*dst++ >> 1 >= w ) break;        /* is the y-coefficient too big? */
  410.                 } while (++dst, --count);
  411.                 if (count == 0)                        /* no coefficients were too big */
  412.                 {    count = 3;
  413.                     do
  414.                     {    *src = FracDiv(*src, w); ++src;    /* divide the x-coefficient by w */
  415.                         *src = FracDiv(*src, w); ++src;    /* divide the y-coefficient by w */
  416.                     } while (++src, --count);
  417.                     map->m[2][2] = kODFract1;
  418.                     return false;
  419.                 }
  420.             }
  421.         }
  422.     }
  423.  
  424.     /*    if map is truly perspective, w is a power of 2, or map cannot be divided by w,
  425.         shift map so that either the scale of some element is fractPrecision or
  426.         the L1 norm of u and v does not exceed kODFract1 - kODFixed1.  This insures that
  427.             FractMultiply(u, x) + FractMultiply(v, y) + FractToFixed(w)
  428.         never overflows.
  429.     */
  430.     count = 9;
  431.     if (shift > 0)
  432.     {    register ODFixed round = 1 << shift - 1;
  433.         do *src = *src + round >> shift;
  434.         while (++src, --count);
  435.     }
  436.     else if ( (shift = -shift) != 0 )
  437.         do *src <<= shift;
  438.         while (++src, --count);
  439.     return false;
  440. }
  441.  
  442.  
  443. typedef struct
  444. {    char bits[2][2];
  445. } bias;
  446.  
  447.  
  448. #if !defined(_PLATFORM_UNIX_)
  449. static ODBoolean
  450. MxWideNorm(ODWide src[3][3], ODMatrix *dst, register bias *delta)
  451. {
  452.     ODWide norm[3][3];
  453.     register fastInt shift;
  454.     register long hi;
  455.     register unsigned long lo;
  456.     register long *srcPtr, *dstPtr;
  457.  
  458.     {    register fastInt count;
  459.  
  460.                 /* Compute the absolute values of src */
  461.         srcPtr = (long *)&src[0][0]; dstPtr = (long *)&norm[0][0];
  462.         count = 9;
  463.         do
  464.         {    hi = *srcPtr++; lo = *srcPtr++;
  465.             if (hi < 0)
  466.                 (lo = -lo)!=0 ? (hi = ~hi) : (hi = -hi);
  467.             *dstPtr++ = hi; *dstPtr++ = lo;
  468.         } while (--count);
  469.  
  470.                 /* Find the scale of a, b, c, and d */
  471.         if ( (hi = norm[0][0].hi | norm[0][1].hi | norm[1][0].hi | norm[1][1].hi) != 0 )
  472.             shift = ODFirstBit(hi) + longSize - fractPrecision - delta->bits[0][0];
  473.         else if ( (lo = norm[0][0].lo | norm[0][1].lo | norm[1][0].lo | norm[1][1].lo) != 0 )
  474.             shift = ODFirstBit(lo) - fractPrecision - delta->bits[0][0];
  475.         else shift = -wideSize;
  476.  
  477.                 /* Find the scale of u and v */
  478.         if ( (hi = norm[0][2].hi | norm[1][2].hi) != 0 )
  479.             count = ODFirstBit(hi) + longSize - fractPrecision - delta->bits[0][1];
  480.         else if ( (lo = norm[0][2].lo | norm[1][2].lo) != 0 )
  481.             count = ODFirstBit(lo) - fractPrecision - delta->bits[0][1];
  482.         else count = -wideSize;
  483.         if (count > shift) shift = count;
  484.  
  485.                 /* Find the scale of h and k */
  486.         if ( (hi = norm[2][0].hi | norm[2][1].hi) != 0 )
  487.             count = ODFirstBit(hi) + longSize - fractPrecision - delta->bits[1][0];
  488.         else if ( (lo = norm[2][0].lo | norm[2][1].lo) != 0 )
  489.             count = ODFirstBit(lo) - fractPrecision - delta->bits[1][0];
  490.         else count = -wideSize;
  491.         if (count > shift) shift = count;
  492.  
  493.                 /* Find the scale of w */
  494.         if ( (hi = norm[2][2].hi) != 0 )
  495.             count = ODFirstBit(hi) + longSize - fractPrecision - delta->bits[1][1];
  496.         else if ( (lo = norm[2][2].lo) != 0 )
  497.             count = ODFirstBit(lo) - fractPrecision - delta->bits[1][1];
  498.         else count = -wideSize;
  499.         if (count > shift) shift = count;
  500.     }
  501.  
  502.     {    register fastInt i, j;
  503.  
  504.                 /* Execute the shift */
  505.         srcPtr = (long *)&src[0][0]; dstPtr = &dst->m[0][0];
  506.         for (i = 3; i--; )
  507.             for (j = 3; j--; )
  508.             {    ODWide temp;
  509.                 temp.hi = *srcPtr++; temp.lo = *srcPtr++;
  510.                 ODWideShift(&temp, shift + delta->bits[!i ][!j]);
  511.                 *dstPtr++ = temp.lo;
  512.             }
  513.     }
  514.     return MxNormalize(dst);
  515. }
  516. #else // defined(_PLATFORM_UNIX_)
  517. static ODBoolean
  518. MxWideNorm(ODWide src[3][3], ODMatrix *dst, register bias *delta)
  519. {
  520.     ODWide norm[3][3];
  521.     register fastInt shift;
  522.     ODWide *srcPtr, *tNormPtr, temp;
  523.     register long *dstPtr;
  524.  
  525.     {
  526.         register fastInt count;
  527.  
  528.                 /* Compute the absolute values of src */
  529.         count = 9;
  530.         srcPtr = &src[0][0]; tNormPtr = &norm[0][0];
  531.         do
  532.         {
  533.             if (*srcPtr < 0)
  534.                 *tNormPtr++ = *srcPtr++;
  535.             else
  536.                 *tNormPtr++ = -*srcPtr++;
  537.         } while (--count);
  538.  
  539.                 /* Find the scale of a, b, c, and d */
  540.         temp = norm[0][0] | norm[0][1] | norm[1][0] | norm[1][1];
  541.         if (temp)
  542.             shift = ODFirstBit(temp) - fractPrecision - delta->bits[0][0];
  543.         else shift = -wideSize;
  544.  
  545.                 /* Find the scale of u and v */
  546.         temp = norm[0][2] | norm[1][2];
  547.         if (temp)
  548.             count = ODFirstBit(temp) - fractPrecision - delta->bits[0][1];
  549.         else count = -wideSize;
  550.         if (count > shift) shift = count;
  551.  
  552.                 /* Find the scale of h and k */
  553.         temp = norm[2][0] | norm[2][1];
  554.         if (temp)
  555.             count = ODFirstBit(temp) - fractPrecision - delta->bits[1][0];
  556.         else count = -wideSize;
  557.         if (count > shift) shift = count;
  558.  
  559.                 /* Find the scale of w */
  560.         temp = norm[2][2];
  561.         if (temp)
  562.             count = ODFirstBit(temp) - fractPrecision - delta->bits[1][1];
  563.         else count = -wideSize;
  564.         if (count > shift) shift = count;
  565.     }
  566.  
  567.     {
  568.         register fastInt i, j;
  569.         
  570.                 /* Execute the shift */
  571.         srcPtr = &src[0][0]; dstPtr = &dst->m[0][0];
  572.         for (i = 3; i--; )
  573.             for (j = 3; j--; )
  574.             {
  575.                 temp = *srcPtr++;
  576.                 ODWideShift(&temp, shift + delta->bits[!i ][!j]);
  577.                 *dstPtr++ = (unsigned long)temp;
  578.             }
  579.     }
  580.     return MxNormalize(dst);
  581. }
  582. #endif // !defined(_PLATFORM_UNIX_)
  583.  
  584.  
  585. /*    MxInverse - Computes the inverse of the given matrix, placing it in the destination (second) matrix. */
  586. ODBoolean
  587. MxInverse(const ODMatrix *matrix, register ODTransformType flags, ODMatrix *imatrix)
  588. {
  589.     register ODFixed *im = &imatrix->m[0][0];
  590.     register const ODFixed *m0 = &matrix->m[0][0];
  591.  
  592.     switch(flags) {
  593.         case kODIdentityXform:
  594.             *imatrix = *matrix;                /* do nothing but copy if identity */
  595.         break;
  596.         case kODTranslateXform:
  597.         {
  598.             *im++ = *m0++;                                            /* a = 1.0 */
  599.             *im++ = *m0++;                                            /* b = 0.0 */
  600.             *im++ = *m0++;                                            /* u = 0.0 */
  601.             *im++ = *m0++;                                            /* c = 0.0 */
  602.             *im++ = *m0++;                                            /* d = 1.0 */
  603.             *im++ = *m0++;                                            /* v = 0.0 */
  604.             *im++ = -*m0++;                                            /* h = -h */
  605.             *im++ = -*m0++;                                            /* k = -k */
  606.             *im = *m0;                                                /* w = 1.0 */
  607.         }
  608.         break;
  609.         case kODScaleXform:
  610.         case kODScaleXform+kODTranslateXform:
  611.         {    ODFixed temp;
  612.             register ODFixed a, d;
  613.             if (FixDivCheck(kODFixed1, a = *m0++, &temp)) return true; *im++ = temp;    /* a = 1/a */
  614.             *im++ = *m0++;                                            /* b = 0.0 */
  615.             *im++ = *m0++;                                            /* u = 0.0 */
  616.             *im++ = *m0++;                                            /* c = 0.0 */
  617.             if (FixDivCheck(kODFixed1, d = *m0++, &temp)) return true; *im++ = temp;    /* d = 1/d */
  618.             *im++ = *m0++;                                            /* v = 0.0 */
  619.             if (flags & kODTranslateXform)
  620.             {    if (FixDivCheck(*m0++, a, &temp)) return true; *im++ = -temp;    /* h = -h/a */
  621.                 if (FixDivCheck(*m0++, d, &temp)) return true; *im++ = -temp;    /* k = -k/d */
  622.             }
  623.             else
  624.             {    *im++ = *m0++;                                        /* h = 0.0 */
  625.                 *im++ = *m0++;                                        /* k = 0.0 */
  626.             }
  627.             *im = *m0;                                                /* w = 1.0 */
  628.         }
  629.         break;
  630. #if !defined(_PLATFORM_UNIX_)
  631.         case kODLinearXform:
  632.         case kODLinearXform+kODTranslateXform:
  633.         {    ODWide det, temp, tmp;
  634.             register short shift;
  635.  
  636.             /* compute the determinant */
  637.             ODWideSubtract(ODWideMultiply(matrix->m[0][0], matrix->m[1][1], &det),
  638.                     ODWideMultiply(matrix->m[1][0], matrix->m[0][1], &temp));
  639.             if ((shift = MyWideScale(&det) - (longSize - 2)) > 0)
  640.                 ODWideShift(&det, shift);
  641.             else
  642.                 shift = 0;
  643.  
  644.             temp.hi = matrix->m[1][1]; temp.lo = 0;
  645.             if ((*im++ = ODWideDivide(ODWideShift(&temp, shift), det.lo, kODIgnoreRemainder)) == kODFixedMinusInfinity)
  646.                 return true;
  647.             temp.hi = -matrix->m[0][1]; temp.lo = 0;
  648.             if ((*im++ = ODWideDivide(ODWideShift(&temp, shift), det.lo, kODIgnoreRemainder)) == kODFixedMinusInfinity)
  649.                 return true;
  650.             *im++ = 0;
  651.             temp.hi = -matrix->m[1][0]; temp.lo = 0;
  652.             if ((*im++ = ODWideDivide(ODWideShift(&temp, shift), det.lo, kODIgnoreRemainder)) == kODFixedMinusInfinity)
  653.                 return true;
  654.             temp.hi = matrix->m[0][0]; temp.lo = 0;
  655.             if ((*im++ = ODWideDivide(ODWideShift(&temp, shift), det.lo, kODIgnoreRemainder)) == kODFixedMinusInfinity)
  656.                 return true;
  657.             *im++ = 0;
  658.             if (flags & kODTranslateXform)
  659.             {    shift -= fixedPrecision;
  660.                 ODWideSubtract(ODWideMultiply(matrix->m[1][0], matrix->m[2][1], &temp), ODWideMultiply(matrix->m[2][0], matrix->m[1][1], &tmp));
  661.                 if (shift < MyWideScale(&temp) - (wideSize - 2))
  662.                     return true;
  663.                 if ((*im++ = ODWideDivide(ODWideShift(&temp, shift), det.lo, kODIgnoreRemainder)) == kODFixedMinusInfinity)
  664.                     return true;
  665.                 ODWideSubtract(ODWideMultiply(matrix->m[0][1], matrix->m[2][0], &temp), ODWideMultiply(matrix->m[2][1], matrix->m[0][0], &tmp));
  666.                 if (shift < MyWideScale(&temp) - (wideSize - 2))
  667.                     return true;
  668.                 if ((*im++ = ODWideDivide(ODWideShift(&temp, shift), det.lo, kODIgnoreRemainder)) == kODFixedMinusInfinity)
  669.                     return true;
  670.             }
  671.             else
  672.             {    *im++ = 0;
  673.                 *im++ = 0;
  674.             }
  675.             *im++ = kODFract1;
  676.         }
  677.         break;
  678.         case kODPerspectiveXform:
  679.         {    ODWide inv[3][3];
  680.             ODWide temp;
  681.             bias delta = { 30, 16, 16, 2 };
  682.  
  683.             ODWideSubtract(ODWideMultiply(m0[4], m0[8], &inv[0][0]), ODWideMultiply(m0[5], m0[7], &temp));
  684.             ODWideSubtract(ODWideMultiply(m0[2], m0[7], &inv[0][1]), ODWideMultiply(m0[1], m0[8], &temp));
  685.             ODWideSubtract(ODWideMultiply(m0[1], m0[5], &inv[0][2]), ODWideMultiply(m0[2], m0[4], &temp));
  686.             ODWideSubtract(ODWideMultiply(m0[5], m0[6], &inv[1][0]), ODWideMultiply(m0[3], m0[8], &temp));
  687.             ODWideSubtract(ODWideMultiply(m0[0], m0[8], &inv[1][1]), ODWideMultiply(m0[6], m0[2], &temp));
  688.             ODWideSubtract(ODWideMultiply(m0[2], m0[3], &inv[1][2]), ODWideMultiply(m0[0], m0[5], &temp));
  689.             ODWideSubtract(ODWideMultiply(m0[3], m0[7], &inv[2][0]), ODWideMultiply(m0[6], m0[4], &temp));
  690.             ODWideSubtract(ODWideMultiply(m0[6], m0[1], &inv[2][1]), ODWideMultiply(m0[0], m0[7], &temp));
  691.             ODWideSubtract(ODWideMultiply(m0[0], m0[4], &inv[2][2]), ODWideMultiply(m0[3], m0[1], &temp));
  692.  
  693.             return MxWideNorm(inv, imatrix, &delta);
  694.         }
  695. #else // defined(_PLATFORM_UNIX_)
  696.         case kODLinearXform:
  697.         case kODLinearXform+kODTranslateXform:
  698.         {    ODWide det, temp;
  699.             register short shift;
  700.  
  701.             /* compute the determinant */
  702.             det = (ODWide)matrix->m[0][0] * (ODWide)matrix->m[1][1];
  703.             temp = (ODWide)matrix->m[1][0] * (ODWide)matrix->m[0][1];
  704.             det -= temp;
  705.             if ((shift = MyWideScale(&det) - (longSize - 2)) > 0)
  706.                 ODWideShift(&det, shift);
  707.             else
  708.                 shift = 0;
  709.  
  710.             temp = ((ODWide)matrix->m[1][1]) << sizeof(long);
  711.             if ((*im++ = ODWideDivide(ODWideShift(&temp, shift), (unsigned long)det, kODIgnoreRemainder)) == kODFixedMinusInfinity)
  712.                 return true;
  713.             temp = ((ODWide)-matrix->m[0][1]) << sizeof(long);
  714.             if ((*im++ = ODWideDivide(ODWideShift(&temp, shift), (unsigned long)det, kODIgnoreRemainder)) == kODFixedMinusInfinity)
  715.                 return true;
  716.             *im++ = 0;
  717.             temp = ((ODWide)-matrix->m[1][0]) << sizeof(long);
  718.             if ((*im++ = ODWideDivide(ODWideShift(&temp, shift), (unsigned long)det, kODIgnoreRemainder)) == kODFixedMinusInfinity)
  719.                 return true;
  720.             temp = ((ODWide)matrix->m[0][0]) << sizeof(long);
  721.             if ((*im++ = ODWideDivide(ODWideShift(&temp, shift), (unsigned long)det, kODIgnoreRemainder)) == kODFixedMinusInfinity)
  722.                 return true;
  723.             *im++ = 0;
  724.             if (flags & kODTranslateXform)
  725.             {    shift -= fixedPrecision;
  726.                 temp = (ODWide)matrix->m[1][0] * (ODWide)matrix->m[2][1] - (ODWide)matrix->m[2][0] * (ODWide)matrix->m[1][1];
  727.                 if (shift < MyWideScale(&temp) - (wideSize - 2))
  728.                     return true;
  729.                 if ((*im++ = ODWideDivide(ODWideShift(&temp, shift), (unsigned long)det, kODIgnoreRemainder)) == kODFixedMinusInfinity)
  730.                     return true;
  731.                 temp  = (ODWide)matrix->m[0][1] * (ODWide)matrix->m[2][0] - (ODWide)matrix->m[2][1] * (ODWide)matrix->m[0][0];
  732.                 if (shift < MyWideScale(&temp) - (wideSize - 2))
  733.                     return true;
  734.                 if ((*im++ = ODWideDivide(ODWideShift(&temp, shift), (unsigned long)det, kODIgnoreRemainder)) == kODFixedMinusInfinity)
  735.                     return true;
  736.             }
  737.             else
  738.             {    *im++ = 0;
  739.                 *im++ = 0;
  740.             }
  741.             *im++ = kODFract1;
  742.         }
  743.         break;
  744.         case kODPerspectiveXform:
  745.         {    ODWide inv[3][3];
  746.             bias delta = { 30, 16, 16, 2 };
  747.  
  748.             inv[0][0] = (ODWide)m0[4] * (ODWide)m0[8] - (ODWide)m0[5] * (ODWide)m0[7];
  749.             inv[0][1] = (ODWide)m0[2] * (ODWide)m0[7] - (ODWide)m0[1] * (ODWide)m0[8];
  750.             inv[0][2] = (ODWide)m0[1] * (ODWide)m0[5] - (ODWide)m0[2] * (ODWide)m0[4];
  751.             inv[1][0] = (ODWide)m0[5] * (ODWide)m0[6] - (ODWide)m0[3] * (ODWide)m0[8];
  752.             inv[1][1] = (ODWide)m0[0] * (ODWide)m0[8] - (ODWide)m0[6] * (ODWide)m0[2];
  753.             inv[1][2] = (ODWide)m0[2] * (ODWide)m0[3] - (ODWide)m0[0] * (ODWide)m0[5];
  754.             inv[2][0] = (ODWide)m0[3] * (ODWide)m0[7] - (ODWide)m0[6] * (ODWide)m0[4];
  755.             inv[2][1] = (ODWide)m0[6] * (ODWide)m0[1] - (ODWide)m0[0] * (ODWide)m0[7];
  756.             inv[2][2] = (ODWide)m0[0] * (ODWide)m0[4] - (ODWide)m0[3] * (ODWide)m0[1];
  757.  
  758.             return MxWideNorm(inv, imatrix, &delta);
  759.         }
  760. #endif // !defined(_PLATFORM_UNIX_)
  761.         break;
  762.         case kODUnknownXform:
  763.         case kODInvalidXform:
  764.             return true;
  765.     }
  766.     return false;
  767. }
  768.  
  769.  
  770. /*    MxMul multiples a list of vectors by the given matrix and returns the result in place.
  771.     ( x1 y1 1 ) = ( x0 y0 1 ) * matrix;    */
  772. ODBoolean
  773. MxMul(const ODMatrix *matrix, ODTransformType flags, ODPoint *vector, ODSLong cnt)
  774. {
  775.     register const ODFixed *m0 = matrix->m[0];
  776.     register ODFixed *vectorPtr = &vector->x;
  777.     register ODSLong count = cnt;
  778.     
  779.     switch(flags) {  /* do nothing if identity matrix */
  780.         case kODTranslateXform:
  781.             m0 += 6;  /* advance to x translate */
  782.             {    register ODFixed x = *m0++;  /* x translation */
  783.                 register ODFixed y = *m0;  /* y translation */
  784.                     
  785.                 while (count--)
  786.                 {    if (FixAddCheck(x, vectorPtr))
  787.                         goto MxMulError;
  788.                     ++vectorPtr;
  789.                     if (FixAddCheck(y, vectorPtr))
  790.                         goto MxMulError;
  791.                     ++vectorPtr;
  792.                 }
  793.             }
  794.         break;
  795.         case kODScaleXform:
  796.             {    register ODFixed xScale = *m0; 
  797.                 register ODFixed yScale = *(m0 + 4);
  798.                     
  799.                 while (count--)
  800.                 {    ODFixed temp;
  801.                 
  802.                     if (FixMulCheck(*vectorPtr, xScale, &temp))
  803.                         goto MxMulError;
  804.                     *vectorPtr++ = temp;
  805.                     if (FixMulCheck(*vectorPtr, yScale, &temp))
  806.                         goto MxMulError;
  807.                     *vectorPtr++ = temp;
  808.                 }
  809.             }
  810.         break;
  811.         case kODTranslateXform + kODScaleXform:
  812.             {    register ODFixed xScale = *m0;
  813.                 register ODFixed yScale = *(m0 + 4);
  814.                 register ODFixed x, y;
  815.                     
  816.                 m0 += 6;  /* advance to x translate */
  817.                 x = *m0++;  /* x translation */
  818.                 y = *m0;  /* y translation */
  819.                 while (count--)
  820.                 {    ODFixed tempX = *vectorPtr, tempY = *(vectorPtr + 1);
  821.                     *vectorPtr = x;
  822.                     if (FixMulAddCheck(xScale, tempX, vectorPtr))
  823.                         goto MxMulError;
  824.                     *++vectorPtr = y;
  825.                     if (FixMulAddCheck(yScale, tempY, vectorPtr))
  826.                         goto MxMulError;
  827.                     ++vectorPtr;
  828.                 }
  829.             }
  830.         break;
  831.         case kODLinearXform:
  832.         case kODLinearXform + kODTranslateXform:
  833.             {    register const ODFixed *m1;    /* will ODPoint at y translation vector */
  834.                 register ODFixed xScale = *m0;
  835.                 register ODFixed alpha = *(m0 += 1);
  836.                 register ODFixed beta = *(m0 += 2);
  837.                 register ODFixed yScale = *(m0 += 1);
  838.                 register ODFixed xTemp, yTemp;
  839.                 
  840.                 m0 += 2; /* ODPoint at x translation vector */
  841.                 m1 = m0 + 1;
  842.                 
  843.                 while (count--)
  844.                 {    xTemp = *vectorPtr, yTemp = *(vectorPtr + 1);
  845.                     *vectorPtr = *m0;
  846.                     if (MulMulAddCheck(xTemp, xScale, yTemp, beta, fixedPrecision, vectorPtr))
  847.                         goto MxMulError;
  848.                     *++vectorPtr = *m1;
  849.                     if (MulMulAddCheck(xTemp, alpha, yTemp, yScale, fixedPrecision, vectorPtr))
  850.                         goto MxMulError;
  851.                     ++vectorPtr;
  852.                 }
  853.             }
  854.         break;
  855.         case kODPerspectiveXform:
  856.             {    register ODFixed *dst = vectorPtr;
  857.                 register ODFixed m, divisor;
  858.                 register ODFract u, v;
  859.                 ODFixed cpy[3];
  860.                 cpy[2] = kODFixed1;
  861.                 u = m0[2];
  862.                 v = m0[5];
  863.                 m = ODFractToFixed(m0[8]);
  864.                 while (count--)
  865.                 {    divisor = FracMul(u, vectorPtr[0]) + FracMul(v, vectorPtr[1]) + m;
  866.                     if (divisor <= 0)
  867.                         goto MxMulError;
  868.                     cpy[0] = *vectorPtr++;
  869.                     cpy[1] = *vectorPtr++;
  870.                     *dst++ = MyVectorMultiplyDivide(3, cpy, 1, m0, 3, divisor);
  871.                     *dst++ = MyVectorMultiplyDivide(3, cpy, 1, m0+1, 3, divisor);
  872.                 }
  873.             }
  874.         break;
  875.         case kODUnknownXform:
  876.         case kODInvalidXform:
  877.         MxMulError:
  878.             return true;
  879.     }  /* end of switch */
  880.     return false;
  881. }
  882.  
  883.  
  884. /*    MxMulOffset - Multiples a list of vectors by the given matrix and returns the result in place.
  885.     ( x1 y1 1 ) = ( x0-hOffset y0-vOffset 1 ) * matrix;    */
  886. static ODBoolean
  887. MxMulOffset(const ODMatrix *matrix, ODTransformType flags, ODPoint *vector, ODSLong cnt, ODFixed hOffset, ODFixed vOffset)
  888. {
  889.     register ODFixed *vectorPtr = &vector->x;
  890.     register ODFixed h = hOffset, v = vOffset;
  891.  
  892.     if (h || v)
  893.     {    ODMatrix translation;
  894.         ODBoolean error;
  895.         translation.m[2][0] = -h;
  896.         translation.m[2][1] = -v;
  897.         error = MxMul(&translation, kODTranslateXform, vector, cnt);
  898.         if( error ) return error;
  899.     }
  900.     return MxMul(matrix, flags, vector, cnt);
  901. }
  902.  
  903.  
  904. /* MxConcat - Postmultiplies matrix B by matrix A.
  905.     B = B * A;
  906.      returns true if error occurs (either invalid matrix or overflow in calculation)
  907.  */
  908. ODBoolean
  909. MxConcat(register const ODMatrix *a, register ODTransformType aFlags,
  910.          register ODMatrix *b, register ODTransformType bFlags)
  911. {
  912.     ODBoolean savedB = false;
  913.     ODMatrix oldB;
  914.  
  915.     if (aFlags == kODUnknownXform && (aFlags = MxType(a)) == kODInvalidXform)
  916.         return true;
  917.     if (bFlags == kODUnknownXform && (bFlags = MxType(b)) == kODInvalidXform)
  918.         return true;
  919.     if (aFlags == kODIdentityXform)
  920.         return false;
  921.     if (bFlags == kODIdentityXform)
  922.     {    *b = *a;
  923.         return false;
  924.     }
  925.     if (bFlags != kODPerspectiveXform && aFlags < kODScaleXform)
  926.     {    ODPoint hk = *(ODPoint *)&b->m[2][0];
  927.         if (FixAddCheck(a->m[2][0], &b->m[2][0]) || FixAddCheck(a->m[2][1], &b->m[2][1]))
  928.         {    *(ODPoint *)&b->m[2][0] = hk;
  929.             goto rangeError;
  930.         }
  931.         return false;
  932.     }
  933.     if (aFlags < kODLinearXform)
  934.     {    register fastInt i, j;
  935.         oldB = *b;
  936.         savedB = true;
  937.         for (i = 3; i--; )
  938.             for (j = 2; j--; )
  939.             {    if (aFlags >= kODScaleXform)
  940.                     if (FixMulCheck(b->m[i][j], a->m[j][j], &b->m[i][j]))
  941.                         goto rangeError;
  942.                 if (aFlags & kODTranslateXform)
  943.                     if (i == 2) {
  944.                         if (bFlags == kODPerspectiveXform) {
  945.                             if (FracMulAddCheck(b->m[2][2], a->m[2][j], &b->m[2][j]))
  946.                                 goto rangeError;
  947.                         } else if (FixAddCheck(a->m[2][j], &b->m[2][j]))
  948.                             goto rangeError;
  949.                     } else if (bFlags == kODPerspectiveXform)
  950.                         if (FracMulAddCheck(b->m[i][2], a->m[2][j], &b->m[i][j]))
  951.                             goto rangeError;
  952.             }
  953.         return false;
  954.     }
  955.     if (aFlags < kODPerspectiveXform)
  956.     {    
  957.         ODMatrix c;
  958.         register fastInt i, j;
  959.         for (i = 3; i--; )
  960.         {    c.m[i][2] = b->m[i][2];
  961.             for (j = 2; j--; )
  962.             {    if (aFlags >= kODScaleXform)
  963.                 {    if (FixMulCheck(b->m[i][j], a->m[j][j], &c.m[i][j]))
  964.                         goto rangeError;
  965.                     if (aFlags >= kODLinearXform)
  966.                         if (FixMulAddCheck(b->m[i][1-j], a->m[1-j][j], &c.m[i][j]))
  967.                             goto rangeError;
  968.                 }
  969.                 else
  970.                     c.m[i][j] = b->m[i][j];
  971.                 if (aFlags & kODTranslateXform)
  972.                     if (i == 2) {
  973.                         if (bFlags == kODPerspectiveXform) {
  974.                             if (FracMulAddCheck(b->m[2][2], a->m[2][j], &c.m[2][j]))
  975.                                 goto rangeError;
  976.                         } else
  977.                             if (FixAddCheck(a->m[2][j], &c.m[2][j]))
  978.                                 goto rangeError;
  979.                     } 
  980.                       else if (bFlags == kODPerspectiveXform)
  981.                         if (FracMulAddCheck(b->m[i][2], a->m[2][j], &c.m[i][j]))
  982.                             goto rangeError;
  983.             }
  984.         }
  985.         *b = c;
  986.         return false;
  987.     }
  988. perspectiveCase:    /* aFlags == kODPerspectiveXform */
  989.     {    ODWide c[3][3];
  990.         register fastInt i, j;
  991.         bias delta = { 16, 16, 16, 16 };
  992.         for (i = 3; i--; )
  993.             for (j = 3; j--; )
  994.             {    ODWide temp;
  995.                 ODWideShift(ODWideMultiply(b->m[i][2], a->m[2][j], &c[i][j]), fractPrecision - fixedPrecision);
  996.                 ODWideAdd(&c[i][j], ODWideMultiply(b->m[i][1], a->m[1][j], &temp));
  997.                 ODWideAdd(&c[i][j], ODWideMultiply(b->m[i][0], a->m[0][j], &temp));
  998.             }
  999.         return MxWideNorm(c, b, &delta);
  1000.     }
  1001.  
  1002. rangeError:
  1003.     if (savedB) *b = oldB;
  1004.     goto perspectiveCase;
  1005. }
  1006.  
  1007.  
  1008. /*                                        |  1   0   0    |
  1009.     currentMatrix =  currentMatrix *    |  0   1   0    |
  1010.                                         |  tx  ty  1    |
  1011. */
  1012. ODBoolean
  1013. MxMove(ODMatrix *currentMatrix, ODTransformType flags, register ODFixed tx, register ODFixed ty)
  1014. {
  1015.     if (flags == kODPerspectiveXform)
  1016.     {    register ODFixed *fixPtr = ¤tMatrix->m[0][0];
  1017.         register ODFract *fracPtr = ¤tMatrix->m[0][2];
  1018.         register fastInt counter = 3;
  1019.         
  1020.         do
  1021.         {    register ODFract u = fracPtr[0];
  1022.         
  1023.             if (FracMulAddCheck(u, tx, &fixPtr[0]) || FracMulAddCheck(u, ty, &fixPtr[1]))
  1024.                 return true;
  1025.             fracPtr += 3;
  1026.             fixPtr += 3;
  1027.         } while (--counter);
  1028.     } else if (FixAddCheck(tx, ¤tMatrix->m[2][0]) || FixAddCheck(ty, ¤tMatrix->m[2][1]))
  1029.         return true;
  1030.     return false;
  1031. }
  1032.  
  1033.  
  1034. ODBoolean
  1035. MxMoveTo(register ODMatrix *currentMatrix, ODTransformType flags, ODFixed x, ODFixed y)
  1036. {
  1037.     if (flags == kODPerspectiveXform)
  1038.     {    register ODFract u = currentMatrix->m[2][2];
  1039.         
  1040.         if (FracDivAddCheck(-currentMatrix->m[2][0], u, &x) ||
  1041.             FracDivAddCheck(-currentMatrix->m[2][1], u, &y))
  1042.         {
  1043.             return true;
  1044.         } 
  1045.         return MxMove(currentMatrix, kODPerspectiveXform, x, y);
  1046.     } else
  1047.     {    register ODFixed *fixPtr = ¤tMatrix->m[2][0];
  1048.     
  1049.         *fixPtr++ = x;
  1050.         *fixPtr = y;
  1051.     }
  1052.     return false;
  1053. }
  1054.  
  1055. /*
  1056.  * scales a matrix by sx and sy.
  1057.  *
  1058.  *                                | sx 0   0    |
  1059.  *    currentMx =  currentMx *    | 0   sy 0    |;
  1060.  *                                | 0   0  1    |
  1061.  *
  1062.  */
  1063. ODBoolean
  1064. MxScale(ODMatrix *currentMatrix, register ODFixed sx, register ODFixed sy)
  1065. {    
  1066.     register ODFixed *m = currentMatrix->m[0];
  1067.     
  1068.     if (FixMulCheck( sx, *m, m))
  1069.         return true;
  1070.     m++;
  1071.     if (FixMulCheck( sy, *m, m))
  1072.         return true;
  1073.     m += 2;
  1074.     if (FixMulCheck( sx, *m, m))
  1075.         return true;
  1076.     m++;
  1077.     if (FixMulCheck( sy, *m, m))
  1078.         return true;
  1079.     m += 2;
  1080.     if (FixMulCheck( sx, *m, m))
  1081.         return true;
  1082.     m++;
  1083.     if (FixMulCheck( sy, *m, m))
  1084.         return true;
  1085.     return false;
  1086. }
  1087.  
  1088.  
  1089. /*                                        | 1            ySkew     0    |
  1090.     currentMatrix =  currentMatrix *    | xSkew     1        0   |
  1091.                                         | 0            0        1   |    */
  1092. ODBoolean
  1093. MxSkew(ODMatrix *currentMatrix, register ODFixed xSkew, register ODFixed ySkew)
  1094. {
  1095.     register ODFixed *matrixPtr = currentMatrix->m[0];
  1096.     register fastInt counter = 3;
  1097.     
  1098.     do
  1099.     {    register ODFixed temp = *matrixPtr;
  1100.         
  1101.         if (xSkew)
  1102.             if (FixMulAddCheck(*(matrixPtr+1), xSkew, matrixPtr))
  1103.                 return true;
  1104.         matrixPtr += 1;
  1105.         if (ySkew)
  1106.             if (FixMulAddCheck(temp, ySkew, matrixPtr))
  1107.                 return true;
  1108.         matrixPtr += 2;
  1109.     } while (--counter);
  1110.     return false;
  1111. }
  1112.  
  1113.  
  1114. /*                                    | cosine    sine      0    |
  1115.     currentMatrix = currentMatrix *    | -sine        cosine  0    | 
  1116.                                     | 0            0        1    |    */
  1117. /* note that while this would almost never fail, in extreme pathological cases, it could , for */
  1118. /* instance if the ODMatrix [0][0] and [0][1] are both > ff(23200) */
  1119. ODBoolean
  1120. MxRotate(ODMatrix *currentMatrix, ODFixed angle)
  1121. {
  1122.     ODFract cos;
  1123.     register ODFract s = ODFractSinCos(angle, &cos);
  1124.     register ODFract c = cos;
  1125.     register ODFixed *src = currentMatrix->m[0];
  1126.     register ODFixed *dst = src;
  1127.     register fastInt counter = 3;    
  1128.  
  1129.     do
  1130.     {    register ODFixed x = *src++;
  1131.         register ODFixed y = *src;
  1132.         
  1133.         src += 2;
  1134.         *dst = FracMul(x, c);
  1135.         if (FracMulAddCheck(y, -s, dst++))
  1136.             return true;
  1137.         *dst = FracMul(x, s);
  1138.         if (FracMulAddCheck(y, c, dst)) 
  1139.             return true;
  1140.         dst += 2;
  1141.     } while (--counter);
  1142.     return false;
  1143. }
  1144.