layout/style/nsStyleTransformMatrix.cpp

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

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

mercurial