LCOV - app.info - layout/style/nsStyleTransformMatrix.cpp

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-04-21 | 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