LCOV - code coverage report
Current view: directory - layout/style - nsStyleTransformMatrix.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 270 0 0.0 %
Date: 2012-06-02 Functions: 29 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  *   Mozilla Corporation
      19                 :  *
      20                 :  * Contributor(s):
      21                 :  *   Keith Schwarz <kschwarz@mozilla.com> (original author)
      22                 :  *   Matt Woodrow <mwoodrow@mozilla.com>
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : /*
      39                 :  * A class used for intermediate representations of the -moz-transform property.
      40                 :  */
      41                 : 
      42                 : #include "nsStyleTransformMatrix.h"
      43                 : #include "nsAutoPtr.h"
      44                 : #include "nsCSSValue.h"
      45                 : #include "nsStyleContext.h"
      46                 : #include "nsPresContext.h"
      47                 : #include "nsRuleNode.h"
      48                 : #include "nsCSSKeywords.h"
      49                 : #include "nsMathUtils.h"
      50                 : #include "CSSCalc.h"
      51                 : #include "nsStyleAnimation.h"
      52                 : 
      53                 : namespace css = mozilla::css;
      54                 : 
      55                 : namespace nsStyleTransformMatrix {
      56                 : 
      57                 : /* Note on floating point precision: The transform matrix is an array
      58                 :  * of single precision 'float's, and so are most of the input values
      59                 :  * we get from the style system, but intermediate calculations
      60                 :  * involving angles need to be done in 'double'.
      61                 :  */
      62                 : 
      63                 : /* Force small values to zero.  We do this to avoid having sin(360deg)
      64                 :  * evaluate to a tiny but nonzero value.
      65                 :  */
      66               0 : static double FlushToZero(double aVal)
      67                 : {
      68               0 :   if (-FLT_EPSILON < aVal && aVal < FLT_EPSILON)
      69               0 :     return 0.0f;
      70                 :   else
      71               0 :     return aVal;
      72                 : }
      73                 : 
      74                 : /* Helper function to fill in an nscoord with the specified nsCSSValue. */
      75               0 : static nscoord CalcLength(const nsCSSValue &aValue,
      76                 :                           nsStyleContext* aContext,
      77                 :                           nsPresContext* aPresContext,
      78                 :                           bool &aCanStoreInRuleTree)
      79                 : {
      80               0 :   if (aValue.GetUnit() == eCSSUnit_Pixel ||
      81               0 :       aValue.GetUnit() == eCSSUnit_Number) {
      82                 :     // Handle this here (even though nsRuleNode::CalcLength handles it
      83                 :     // fine) so that callers are allowed to pass a null style context
      84                 :     // and pres context to SetToTransformFunction if they know (as
      85                 :     // nsStyleAnimation does) that all lengths within the transform
      86                 :     // function have already been computed to pixels and percents.
      87                 :     //
      88                 :     // Raw numbers are treated as being pixels.
      89               0 :     return nsPresContext::CSSPixelsToAppUnits(aValue.GetFloatValue());
      90                 :   }
      91                 :   return nsRuleNode::CalcLength(aValue, aContext, aPresContext,
      92               0 :                                 aCanStoreInRuleTree);
      93                 : }
      94                 : 
      95                 : static float
      96               0 : ProcessTranslatePart(const nsCSSValue& aValue,
      97                 :                      nsStyleContext* aContext,
      98                 :                      nsPresContext* aPresContext,
      99                 :                      bool& aCanStoreInRuleTree,
     100                 :                      nscoord aSize, float aAppUnitsPerMatrixUnit)
     101                 : {
     102               0 :   nscoord offset = 0;
     103               0 :   float percent = 0.0f;
     104                 : 
     105               0 :   if (aValue.GetUnit() == eCSSUnit_Percent) {
     106               0 :     percent = aValue.GetPercentValue();
     107               0 :   } else if (aValue.IsCalcUnit()) {
     108                 :     nsRuleNode::ComputedCalc result =
     109                 :       nsRuleNode::SpecifiedCalcToComputedCalc(aValue, aContext, aPresContext,
     110               0 :                                               aCanStoreInRuleTree);
     111               0 :     percent = result.mPercent;
     112               0 :     offset = result.mLength;
     113                 :   } else {
     114                 :     offset = CalcLength(aValue, aContext, aPresContext,
     115               0 :                          aCanStoreInRuleTree);
     116                 :   }
     117                 : 
     118               0 :   return (percent * NSAppUnitsToFloatPixels(aSize, aAppUnitsPerMatrixUnit)) + 
     119               0 :          NSAppUnitsToFloatPixels(offset, aAppUnitsPerMatrixUnit);
     120                 : }
     121                 : 
     122                 : /**
     123                 :  * Helper functions to process all the transformation function types.
     124                 :  *
     125                 :  * These take a matrix parameter to accumulate the current matrix.
     126                 :  */
     127                 : 
     128                 : /* Helper function to process a matrix entry. */
     129                 : static void
     130               0 : ProcessMatrix(gfx3DMatrix& aMatrix,
     131                 :               const nsCSSValue::Array* aData,
     132                 :               nsStyleContext* aContext,
     133                 :               nsPresContext* aPresContext,
     134                 :               bool& aCanStoreInRuleTree,
     135                 :               nsRect& aBounds, float aAppUnitsPerMatrixUnit)
     136                 : {
     137               0 :   NS_PRECONDITION(aData->Count() == 7, "Invalid array!");
     138                 : 
     139               0 :   gfxMatrix result;
     140                 : 
     141                 :   /* Take the first four elements out of the array as floats and store
     142                 :    * them.
     143                 :    */
     144               0 :   result.xx = aData->Item(1).GetFloatValue();
     145               0 :   result.yx = aData->Item(2).GetFloatValue();
     146               0 :   result.xy = aData->Item(3).GetFloatValue();
     147               0 :   result.yy = aData->Item(4).GetFloatValue();
     148                 : 
     149                 :   /* The last two elements have their length parts stored in aDelta
     150                 :    * and their percent parts stored in aX[0] and aY[1].
     151                 :    */
     152               0 :   result.x0 = ProcessTranslatePart(aData->Item(5),
     153                 :                                    aContext, aPresContext, aCanStoreInRuleTree,
     154               0 :                                    aBounds.Width(), aAppUnitsPerMatrixUnit);
     155               0 :   result.y0 = ProcessTranslatePart(aData->Item(6),
     156                 :                                    aContext, aPresContext, aCanStoreInRuleTree,
     157               0 :                                    aBounds.Height(), aAppUnitsPerMatrixUnit);
     158                 : 
     159               0 :   aMatrix.PreMultiply(result);
     160               0 : }
     161                 : 
     162                 : static void 
     163               0 : ProcessMatrix3D(gfx3DMatrix& aMatrix,
     164                 :                 const nsCSSValue::Array* aData,
     165                 :                 nsStyleContext* aContext,
     166                 :                 nsPresContext* aPresContext,
     167                 :                 bool& aCanStoreInRuleTree,
     168                 :                 nsRect& aBounds, float aAppUnitsPerMatrixUnit)
     169                 : {
     170               0 :   NS_PRECONDITION(aData->Count() == 17, "Invalid array!");
     171                 : 
     172               0 :   gfx3DMatrix temp;
     173                 : 
     174               0 :   temp._11 = aData->Item(1).GetFloatValue();
     175               0 :   temp._12 = aData->Item(2).GetFloatValue();
     176               0 :   temp._13 = aData->Item(3).GetFloatValue();
     177               0 :   temp._14 = aData->Item(4).GetFloatValue();
     178               0 :   temp._21 = aData->Item(5).GetFloatValue();
     179               0 :   temp._22 = aData->Item(6).GetFloatValue();
     180               0 :   temp._23 = aData->Item(7).GetFloatValue();
     181               0 :   temp._24 = aData->Item(8).GetFloatValue();
     182               0 :   temp._31 = aData->Item(9).GetFloatValue();
     183               0 :   temp._32 = aData->Item(10).GetFloatValue();
     184               0 :   temp._33 = aData->Item(11).GetFloatValue();
     185               0 :   temp._34 = aData->Item(12).GetFloatValue();
     186               0 :   temp._44 = aData->Item(16).GetFloatValue();
     187                 : 
     188               0 :   temp._41 = ProcessTranslatePart(aData->Item(13),
     189                 :                                   aContext, aPresContext, aCanStoreInRuleTree,
     190               0 :                                   aBounds.Width(), aAppUnitsPerMatrixUnit);
     191               0 :   temp._42 = ProcessTranslatePart(aData->Item(14),
     192                 :                                   aContext, aPresContext, aCanStoreInRuleTree,
     193               0 :                                   aBounds.Height(), aAppUnitsPerMatrixUnit);
     194               0 :   temp._43 = ProcessTranslatePart(aData->Item(15),
     195                 :                                   aContext, aPresContext, aCanStoreInRuleTree,
     196               0 :                                   aBounds.Height(), aAppUnitsPerMatrixUnit);
     197                 : 
     198               0 :   aMatrix.PreMultiply(temp);
     199               0 : }
     200                 : 
     201                 : /* Helper function to process two matrices that we need to interpolate between */
     202                 : static void
     203               0 : ProcessInterpolateMatrix(gfx3DMatrix& aMatrix,
     204                 :                          const nsCSSValue::Array* aData,
     205                 :                          nsStyleContext* aContext,
     206                 :                          nsPresContext* aPresContext,
     207                 :                          bool& aCanStoreInRuleTree,
     208                 :                          nsRect& aBounds, float aAppUnitsPerMatrixUnit)
     209                 : {
     210               0 :   NS_PRECONDITION(aData->Count() == 4, "Invalid array!");
     211                 : 
     212               0 :   gfx3DMatrix matrix1, matrix2;
     213               0 :   if (aData->Item(1).GetUnit() == eCSSUnit_List) {
     214               0 :     matrix1 = nsStyleTransformMatrix::ReadTransforms(aData->Item(1).GetListValue(),
     215                 :                              aContext, aPresContext,
     216                 :                              aCanStoreInRuleTree,
     217               0 :                              aBounds, aAppUnitsPerMatrixUnit);
     218                 :   }
     219               0 :   if (aData->Item(2).GetUnit() == eCSSUnit_List) {
     220               0 :     matrix2 = ReadTransforms(aData->Item(2).GetListValue(),
     221                 :                              aContext, aPresContext,
     222                 :                              aCanStoreInRuleTree,
     223               0 :                              aBounds, aAppUnitsPerMatrixUnit);
     224                 :   }
     225               0 :   double progress = aData->Item(3).GetPercentValue();
     226                 : 
     227               0 :   aMatrix = nsStyleAnimation::InterpolateTransformMatrix(matrix1, matrix2, progress) * aMatrix;
     228               0 : }
     229                 : 
     230                 : /* Helper function to process a translatex function. */
     231                 : static void
     232               0 : ProcessTranslateX(gfx3DMatrix& aMatrix, 
     233                 :                   const nsCSSValue::Array* aData,
     234                 :                   nsStyleContext* aContext,
     235                 :                   nsPresContext* aPresContext,
     236                 :                   bool& aCanStoreInRuleTree,
     237                 :                   nsRect& aBounds, float aAppUnitsPerMatrixUnit)
     238                 : {
     239               0 :   NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
     240                 : 
     241               0 :   gfxPoint3D temp;
     242                 : 
     243               0 :   temp.x = ProcessTranslatePart(aData->Item(1),
     244                 :                                 aContext, aPresContext, aCanStoreInRuleTree,
     245               0 :                                 aBounds.Width(), aAppUnitsPerMatrixUnit);
     246               0 :   aMatrix.Translate(temp);
     247               0 : }
     248                 : 
     249                 : /* Helper function to process a translatey function. */
     250                 : static void
     251               0 : ProcessTranslateY(gfx3DMatrix& aMatrix,
     252                 :                   const nsCSSValue::Array* aData,
     253                 :                   nsStyleContext* aContext,
     254                 :                   nsPresContext* aPresContext,
     255                 :                   bool& aCanStoreInRuleTree,
     256                 :                   nsRect& aBounds, float aAppUnitsPerMatrixUnit)
     257                 : {
     258               0 :   NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
     259                 : 
     260               0 :   gfxPoint3D temp;
     261                 : 
     262               0 :   temp.y = ProcessTranslatePart(aData->Item(1),
     263                 :                                 aContext, aPresContext, aCanStoreInRuleTree,
     264               0 :                                 aBounds.Height(), aAppUnitsPerMatrixUnit);
     265               0 :   aMatrix.Translate(temp);
     266               0 : }
     267                 : 
     268                 : static void 
     269               0 : ProcessTranslateZ(gfx3DMatrix& aMatrix,
     270                 :                   const nsCSSValue::Array* aData,
     271                 :                   nsStyleContext* aContext,
     272                 :                                           nsPresContext* aPresContext,
     273                 :                                           bool& aCanStoreInRuleTree,
     274                 :                                           float aAppUnitsPerMatrixUnit)
     275                 : {
     276               0 :   NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
     277                 : 
     278               0 :   gfxPoint3D temp;
     279                 : 
     280               0 :   temp.z = ProcessTranslatePart(aData->Item(1),
     281                 :                                 aContext, aPresContext, aCanStoreInRuleTree,
     282               0 :                                 0, aAppUnitsPerMatrixUnit);
     283               0 :   aMatrix.Translate(temp);
     284               0 : }
     285                 : 
     286                 : /* Helper function to process a translate function. */
     287                 : static void
     288               0 : ProcessTranslate(gfx3DMatrix& aMatrix,
     289                 :                  const nsCSSValue::Array* aData,
     290                 :                  nsStyleContext* aContext,
     291                 :                  nsPresContext* aPresContext,
     292                 :                  bool& aCanStoreInRuleTree,
     293                 :                  nsRect& aBounds, float aAppUnitsPerMatrixUnit)
     294                 : {
     295               0 :   NS_PRECONDITION(aData->Count() == 2 || aData->Count() == 3, "Invalid array!");
     296                 : 
     297               0 :   gfxPoint3D temp;
     298                 : 
     299               0 :   temp.x = ProcessTranslatePart(aData->Item(1),
     300                 :                                 aContext, aPresContext, aCanStoreInRuleTree,
     301               0 :                                 aBounds.Width(), aAppUnitsPerMatrixUnit);
     302                 : 
     303                 :   /* If we read in a Y component, set it appropriately */
     304               0 :   if (aData->Count() == 3) {
     305               0 :     temp.y = ProcessTranslatePart(aData->Item(2),
     306                 :                                   aContext, aPresContext, aCanStoreInRuleTree,
     307               0 :                                   aBounds.Height(), aAppUnitsPerMatrixUnit);
     308                 :   }
     309               0 :   aMatrix.Translate(temp);
     310               0 : }
     311                 : 
     312                 : static void
     313               0 : ProcessTranslate3D(gfx3DMatrix& aMatrix,
     314                 :                    const nsCSSValue::Array* aData,
     315                 :                    nsStyleContext* aContext,
     316                 :                    nsPresContext* aPresContext,
     317                 :                    bool& aCanStoreInRuleTree,
     318                 :                    nsRect& aBounds, float aAppUnitsPerMatrixUnit)
     319                 : {
     320               0 :   NS_PRECONDITION(aData->Count() == 4, "Invalid array!");
     321                 : 
     322               0 :   gfxPoint3D temp;
     323                 : 
     324               0 :   temp.x = ProcessTranslatePart(aData->Item(1),
     325                 :                                 aContext, aPresContext, aCanStoreInRuleTree,
     326               0 :                                 aBounds.Width(), aAppUnitsPerMatrixUnit);
     327                 : 
     328               0 :   temp.y = ProcessTranslatePart(aData->Item(2),
     329                 :                                 aContext, aPresContext, aCanStoreInRuleTree,
     330               0 :                                 aBounds.Height(), aAppUnitsPerMatrixUnit);
     331                 : 
     332               0 :   temp.z = ProcessTranslatePart(aData->Item(3),
     333                 :                                 aContext, aPresContext, aCanStoreInRuleTree,
     334               0 :                                 0, aAppUnitsPerMatrixUnit);
     335                 : 
     336               0 :   aMatrix.Translate(temp);
     337               0 : }
     338                 : 
     339                 : /* Helper function to set up a scale matrix. */
     340                 : static void
     341               0 : ProcessScaleHelper(gfx3DMatrix& aMatrix,
     342                 :                    float aXScale, 
     343                 :                    float aYScale, 
     344                 :                    float aZScale)
     345                 : {
     346               0 :   aMatrix.Scale(aXScale, aYScale, aZScale);
     347               0 : }
     348                 : 
     349                 : /* Process a scalex function. */
     350                 : static void
     351               0 : ProcessScaleX(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
     352                 : {
     353               0 :   NS_PRECONDITION(aData->Count() == 2, "Bad array!");
     354               0 :   ProcessScaleHelper(aMatrix, aData->Item(1).GetFloatValue(), 1.0f, 1.0f);
     355               0 : }
     356                 : 
     357                 : /* Process a scaley function. */
     358                 : static void
     359               0 : ProcessScaleY(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
     360                 : {
     361               0 :   NS_PRECONDITION(aData->Count() == 2, "Bad array!");
     362               0 :   ProcessScaleHelper(aMatrix, 1.0f, aData->Item(1).GetFloatValue(), 1.0f);
     363               0 : }
     364                 : 
     365                 : static void
     366               0 : ProcessScaleZ(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
     367                 : {
     368               0 :   NS_PRECONDITION(aData->Count() == 2, "Bad array!");
     369               0 :   ProcessScaleHelper(aMatrix, 1.0f, 1.0f, aData->Item(1).GetFloatValue());
     370               0 : }
     371                 : 
     372                 : static void
     373               0 : ProcessScale3D(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
     374                 : {
     375               0 :   NS_PRECONDITION(aData->Count() == 4, "Bad array!");
     376                 :   ProcessScaleHelper(aMatrix,
     377               0 :                      aData->Item(1).GetFloatValue(),
     378               0 :                      aData->Item(2).GetFloatValue(),
     379               0 :                      aData->Item(3).GetFloatValue());
     380               0 : }
     381                 : 
     382                 : /* Process a scale function. */
     383                 : static void
     384               0 : ProcessScale(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
     385                 : {
     386               0 :   NS_PRECONDITION(aData->Count() == 2 || aData->Count() == 3, "Bad array!");
     387                 :   /* We either have one element or two.  If we have one, it's for both X and Y.
     388                 :    * Otherwise it's one for each.
     389                 :    */
     390               0 :   const nsCSSValue& scaleX = aData->Item(1);
     391               0 :   const nsCSSValue& scaleY = (aData->Count() == 2 ? scaleX :
     392               0 :                               aData->Item(2));
     393                 : 
     394                 :   ProcessScaleHelper(aMatrix, 
     395                 :                      scaleX.GetFloatValue(),
     396                 :                      scaleY.GetFloatValue(),
     397               0 :                      1.0f);
     398               0 : }
     399                 : 
     400                 : /* Helper function that, given a set of angles, constructs the appropriate
     401                 :  * skew matrix.
     402                 :  */
     403                 : static void
     404               0 : ProcessSkewHelper(gfx3DMatrix& aMatrix, double aXAngle, double aYAngle)
     405                 : {
     406               0 :   aMatrix.SkewXY(aXAngle, aYAngle);
     407               0 : }
     408                 : 
     409                 : /* Function that converts a skewx transform into a matrix. */
     410                 : static void
     411               0 : ProcessSkewX(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
     412                 : {
     413               0 :   NS_ASSERTION(aData->Count() == 2, "Bad array!");
     414               0 :   ProcessSkewHelper(aMatrix, aData->Item(1).GetAngleValueInRadians(), 0.0);
     415               0 : }
     416                 : 
     417                 : /* Function that converts a skewy transform into a matrix. */
     418                 : static void
     419               0 : ProcessSkewY(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
     420                 : {
     421               0 :   NS_ASSERTION(aData->Count() == 2, "Bad array!");
     422               0 :   ProcessSkewHelper(aMatrix, 0.0, aData->Item(1).GetAngleValueInRadians());
     423               0 : }
     424                 : 
     425                 : /* Function that converts a skew transform into a matrix. */
     426                 : static void
     427               0 : ProcessSkew(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
     428                 : {
     429               0 :   NS_ASSERTION(aData->Count() == 2 || aData->Count() == 3, "Bad array!");
     430                 : 
     431               0 :   double xSkew = aData->Item(1).GetAngleValueInRadians();
     432               0 :   double ySkew = (aData->Count() == 2
     433               0 :                   ? 0.0 : aData->Item(2).GetAngleValueInRadians());
     434                 : 
     435               0 :   ProcessSkewHelper(aMatrix, xSkew, ySkew);
     436               0 : }
     437                 : 
     438                 : /* Function that converts a rotate transform into a matrix. */
     439                 : static void
     440               0 : ProcessRotateZ(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
     441                 : {
     442               0 :   NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
     443               0 :   double theta = aData->Item(1).GetAngleValueInRadians();
     444               0 :   aMatrix.RotateZ(theta);
     445               0 : }
     446                 : 
     447                 : static void
     448               0 : ProcessRotateX(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
     449                 : {
     450               0 :   NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
     451               0 :   double theta = aData->Item(1).GetAngleValueInRadians();
     452               0 :   aMatrix.RotateX(theta);
     453               0 : }
     454                 : 
     455                 : static void
     456               0 : ProcessRotateY(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
     457                 : {
     458               0 :   NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
     459               0 :   double theta = aData->Item(1).GetAngleValueInRadians();
     460               0 :   aMatrix.RotateY(theta);
     461               0 : }
     462                 : 
     463                 : static void
     464               0 : ProcessRotate3D(gfx3DMatrix& aMatrix, const nsCSSValue::Array* aData)
     465                 : {
     466               0 :   NS_PRECONDITION(aData->Count() == 5, "Invalid array!");
     467                 : 
     468                 :   /* We want our matrix to look like this:
     469                 :    * |       1 + (1-cos(angle))*(x*x-1)   -z*sin(angle)+(1-cos(angle))*x*y   y*sin(angle)+(1-cos(angle))*x*z   0 |
     470                 :    * |  z*sin(angle)+(1-cos(angle))*x*y         1 + (1-cos(angle))*(y*y-1)  -x*sin(angle)+(1-cos(angle))*y*z   0 |
     471                 :    * | -y*sin(angle)+(1-cos(angle))*x*z    x*sin(angle)+(1-cos(angle))*y*z        1 + (1-cos(angle))*(z*z-1)   0 |
     472                 :    * |                                0                                  0                                 0   1 |
     473                 :    * (see http://www.w3.org/TR/css3-3d-transforms/#transform-functions)
     474                 :    */
     475                 : 
     476                 :   /* The current spec specifies a matrix that rotates in the wrong direction. For now we just negate
     477                 :    * the angle provided to get the correct rotation direction until the spec is updated.
     478                 :    * See bug 704468.
     479                 :    */
     480               0 :   double theta = -aData->Item(4).GetAngleValueInRadians();
     481               0 :   float cosTheta = FlushToZero(cos(theta));
     482               0 :   float sinTheta = FlushToZero(sin(theta));
     483                 : 
     484               0 :   float x = aData->Item(1).GetFloatValue();
     485               0 :   float y = aData->Item(2).GetFloatValue();
     486               0 :   float z = aData->Item(3).GetFloatValue();
     487                 : 
     488                 :   /* Normalize [x,y,z] */
     489               0 :   float length = sqrt(x*x + y*y + z*z);
     490               0 :   if (length == 0.0) {
     491               0 :     return;
     492                 :   }
     493               0 :   x /= length;
     494               0 :   y /= length;
     495               0 :   z /= length;
     496                 : 
     497               0 :   gfx3DMatrix temp;
     498                 : 
     499                 :   /* Create our matrix */
     500               0 :   temp._11 = 1 + (1 - cosTheta) * (x * x - 1);
     501               0 :   temp._12 = -z * sinTheta + (1 - cosTheta) * x * y;
     502               0 :   temp._13 = y * sinTheta + (1 - cosTheta) * x * z;
     503               0 :   temp._14 = 0.0f;
     504               0 :   temp._21 = z * sinTheta + (1 - cosTheta) * x * y;
     505               0 :   temp._22 = 1 + (1 - cosTheta) * (y * y - 1);
     506               0 :   temp._23 = -x * sinTheta + (1 - cosTheta) * y * z;
     507               0 :   temp._24 = 0.0f;
     508               0 :   temp._31 = -y * sinTheta + (1 - cosTheta) * x * z;
     509               0 :   temp._32 = x * sinTheta + (1 - cosTheta) * y * z;
     510               0 :   temp._33 = 1 + (1 - cosTheta) * (z * z - 1);
     511               0 :   temp._34 = 0.0f;
     512               0 :   temp._41 = 0.0f;
     513               0 :   temp._42 = 0.0f;
     514               0 :   temp._43 = 0.0f;
     515               0 :   temp._44 = 1.0f;
     516                 : 
     517               0 :   aMatrix = temp * aMatrix;
     518                 : }
     519                 : 
     520                 : static void 
     521               0 : ProcessPerspective(gfx3DMatrix& aMatrix, 
     522                 :                    const nsCSSValue::Array* aData,
     523                 :                    nsStyleContext *aContext,
     524                 :                    nsPresContext *aPresContext,
     525                 :                    bool &aCanStoreInRuleTree,
     526                 :                    float aAppUnitsPerMatrixUnit)
     527                 : {
     528               0 :   NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
     529                 : 
     530               0 :   float depth = ProcessTranslatePart(aData->Item(1), aContext,
     531                 :                                      aPresContext, aCanStoreInRuleTree,
     532               0 :                                      0, aAppUnitsPerMatrixUnit);
     533               0 :   aMatrix.Perspective(depth);
     534               0 : }
     535                 : 
     536                 : 
     537                 : /**
     538                 :  * SetToTransformFunction is essentially a giant switch statement that fans
     539                 :  * out to many smaller helper functions.
     540                 :  */
     541                 : static void
     542               0 : MatrixForTransformFunction(gfx3DMatrix& aMatrix,
     543                 :                            const nsCSSValue::Array * aData,
     544                 :                            nsStyleContext* aContext,
     545                 :                            nsPresContext* aPresContext,
     546                 :                            bool& aCanStoreInRuleTree,
     547                 :                            nsRect& aBounds, 
     548                 :                            float aAppUnitsPerMatrixUnit)
     549                 : {
     550               0 :   NS_PRECONDITION(aData, "Why did you want to get data from a null array?");
     551                 :   // It's OK if aContext and aPresContext are null if the caller already
     552                 :   // knows that all length units have been converted to pixels (as
     553                 :   // nsStyleAnimation does).
     554                 : 
     555                 : 
     556                 :   /* Get the keyword for the transform. */
     557               0 :   switch (TransformFunctionOf(aData)) {
     558                 :   case eCSSKeyword_translatex:
     559                 :     ProcessTranslateX(aMatrix, aData, aContext, aPresContext,
     560               0 :                       aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
     561               0 :     break;
     562                 :   case eCSSKeyword_translatey:
     563                 :     ProcessTranslateY(aMatrix, aData, aContext, aPresContext,
     564               0 :                       aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
     565               0 :     break;
     566                 :   case eCSSKeyword_translatez:
     567                 :     ProcessTranslateZ(aMatrix, aData, aContext, aPresContext,
     568               0 :                       aCanStoreInRuleTree, aAppUnitsPerMatrixUnit);
     569               0 :     break;
     570                 :   case eCSSKeyword_translate:
     571                 :     ProcessTranslate(aMatrix, aData, aContext, aPresContext,
     572               0 :                      aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
     573               0 :     break;
     574                 :   case eCSSKeyword_translate3d:
     575                 :     ProcessTranslate3D(aMatrix, aData, aContext, aPresContext,
     576               0 :                        aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
     577               0 :     break;
     578                 :   case eCSSKeyword_scalex:
     579               0 :     ProcessScaleX(aMatrix, aData);
     580               0 :     break;
     581                 :   case eCSSKeyword_scaley:
     582               0 :     ProcessScaleY(aMatrix, aData);
     583               0 :     break;
     584                 :   case eCSSKeyword_scalez:
     585               0 :     ProcessScaleZ(aMatrix, aData);
     586               0 :     break;
     587                 :   case eCSSKeyword_scale:
     588               0 :     ProcessScale(aMatrix, aData);
     589               0 :     break;
     590                 :   case eCSSKeyword_scale3d:
     591               0 :     ProcessScale3D(aMatrix, aData);
     592               0 :     break;
     593                 :   case eCSSKeyword_skewx:
     594               0 :     ProcessSkewX(aMatrix, aData);
     595               0 :     break;
     596                 :   case eCSSKeyword_skewy:
     597               0 :     ProcessSkewY(aMatrix, aData);
     598               0 :     break;
     599                 :   case eCSSKeyword_skew:
     600               0 :     ProcessSkew(aMatrix, aData);
     601               0 :     break;
     602                 :   case eCSSKeyword_rotatex:
     603               0 :     ProcessRotateX(aMatrix, aData);
     604               0 :     break;
     605                 :   case eCSSKeyword_rotatey:
     606               0 :     ProcessRotateY(aMatrix, aData);
     607               0 :     break;
     608                 :   case eCSSKeyword_rotatez:
     609                 :   case eCSSKeyword_rotate:
     610               0 :     ProcessRotateZ(aMatrix, aData);
     611               0 :     break;
     612                 :   case eCSSKeyword_rotate3d:
     613               0 :     ProcessRotate3D(aMatrix, aData);
     614               0 :     break;
     615                 :   case eCSSKeyword_matrix:
     616                 :     ProcessMatrix(aMatrix, aData, aContext, aPresContext,
     617               0 :                   aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
     618               0 :     break;
     619                 :   case eCSSKeyword_matrix3d:
     620                 :     ProcessMatrix3D(aMatrix, aData, aContext, aPresContext,
     621               0 :                     aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
     622               0 :     break;
     623                 :   case eCSSKeyword_interpolatematrix:
     624                 :     ProcessInterpolateMatrix(aMatrix, aData, aContext, aPresContext,
     625               0 :                              aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
     626               0 :     break;
     627                 :   case eCSSKeyword_perspective:
     628                 :     ProcessPerspective(aMatrix, aData, aContext, aPresContext, 
     629               0 :                        aCanStoreInRuleTree, aAppUnitsPerMatrixUnit);
     630               0 :     break;
     631                 :   default:
     632               0 :     NS_NOTREACHED("Unknown transform function!");
     633                 :   }
     634               0 : }
     635                 : 
     636                 : /**
     637                 :  * Return the transform function, as an nsCSSKeyword, for the given
     638                 :  * nsCSSValue::Array from a transform list.
     639                 :  */
     640                 : nsCSSKeyword
     641               0 : TransformFunctionOf(const nsCSSValue::Array* aData)
     642                 : {
     643               0 :   nsAutoString keyword;
     644               0 :   aData->Item(0).GetStringValue(keyword);
     645               0 :   return nsCSSKeywords::LookupKeyword(keyword);
     646                 : }
     647                 : 
     648                 : gfx3DMatrix
     649               0 : ReadTransforms(const nsCSSValueList* aList,
     650                 :                nsStyleContext* aContext,
     651                 :                nsPresContext* aPresContext,
     652                 :                bool &aCanStoreInRuleTree,
     653                 :                nsRect& aBounds,
     654                 :                float aAppUnitsPerMatrixUnit)
     655                 : {
     656               0 :   gfx3DMatrix result;
     657                 : 
     658               0 :   for (const nsCSSValueList* curr = aList; curr != nsnull; curr = curr->mNext) {
     659               0 :     const nsCSSValue &currElem = curr->mValue;
     660               0 :     NS_ASSERTION(currElem.GetUnit() == eCSSUnit_Function,
     661                 :                  "Stream should consist solely of functions!");
     662               0 :     NS_ASSERTION(currElem.GetArrayValue()->Count() >= 1,
     663                 :                  "Incoming function is too short!");
     664                 : 
     665                 :     /* Read in a single transform matrix. */
     666               0 :     MatrixForTransformFunction(result, currElem.GetArrayValue(), aContext,
     667                 :                                aPresContext, aCanStoreInRuleTree,
     668               0 :                                aBounds, aAppUnitsPerMatrixUnit);
     669                 :   }
     670                 :   
     671                 :   return result;
     672                 : }
     673                 : 
     674                 : } // namespace nsStyleTransformMatrix

Generated by: LCOV version 1.7