/**
 * SetToTransformFunction is essentially a giant switch statement that fans
 * out to many smaller helper functions.
 */
void
nsStyleTransformMatrix::SetToTransformFunction(const nsCSSValue::Array * aData,
                                               nsStyleContext* aContext,
                                               nsPresContext* aPresContext,
                                               PRBool& aCanStoreInRuleTree)
{
  NS_PRECONDITION(aData, "Why did you want to get data from a null array?");
  NS_PRECONDITION(aContext, "Need a context for unit conversion!");
  NS_PRECONDITION(aPresContext, "Need a context for unit conversion!");
  
  /* Reset the matrix to the identity so that each subfunction can just
   * worry about its own components.
   */
  SetToIdentity();

  /* Get the keyword for the transform. */
  nsAutoString keyword;
  aData->Item(0).GetStringValue(keyword);
  switch (nsCSSKeywords::LookupKeyword(keyword)) {
  case eCSSKeyword_translatex:
    ProcessTranslateX(mDelta, mX, aData, aContext, aPresContext,
                      aCanStoreInRuleTree);
    break;
  case eCSSKeyword_translatey:
    ProcessTranslateY(mDelta, mY, aData, aContext, aPresContext,
                      aCanStoreInRuleTree);
    break;
  case eCSSKeyword_translate:
    ProcessTranslate(mDelta, mX, mY, aData, aContext, aPresContext,
                     aCanStoreInRuleTree);
    break;
  case eCSSKeyword_scalex:
    ProcessScaleX(mMain, aData);
    break;
  case eCSSKeyword_scaley:
    ProcessScaleY(mMain, aData);
    break;
  case eCSSKeyword_scale:
    ProcessScale(mMain, aData);
    break;
  case eCSSKeyword_skewx:
    ProcessSkewX(mMain, aData);
    break;
  case eCSSKeyword_skewy:
    ProcessSkewY(mMain, aData);
    break;
  case eCSSKeyword_skew:
    ProcessSkew(mMain, aData);
    break;
  case eCSSKeyword_rotate:
    ProcessRotate(mMain, aData);
    break;
  case eCSSKeyword_matrix:
    ProcessMatrix(mMain, mDelta, mX, mY, aData, aContext, aPresContext,
                  aCanStoreInRuleTree);
    break;
  default:
    NS_NOTREACHED("Unknown transform function!");
  }
}
/**
 * SetToTransformFunction is essentially a giant switch statement that fans
 * out to many smaller helper functions.
 */
gfx3DMatrix
nsStyleTransformMatrix::MatrixForTransformFunction(const nsCSSValue::Array * aData,
                                                   nsStyleContext* aContext,
                                                   nsPresContext* aPresContext,
                                                   PRBool& aCanStoreInRuleTree,
                                                   nsRect& aBounds, 
                                                   float aAppUnitsPerMatrixUnit)
{
  NS_PRECONDITION(aData, "Why did you want to get data from a null array?");
  // It's OK if aContext and aPresContext are null if the caller already
  // knows that all length units have been converted to pixels (as
  // nsStyleAnimation does).


  /* Get the keyword for the transform. */
  switch (TransformFunctionOf(aData)) {
  case eCSSKeyword_translatex:
    return ProcessTranslateX(aData, aContext, aPresContext,
                             aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
  case eCSSKeyword_translatey:
    return ProcessTranslateY(aData, aContext, aPresContext,
                             aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
  case eCSSKeyword_translatez:
    return ProcessTranslateZ(aData, aContext, aPresContext,
                             aCanStoreInRuleTree, aAppUnitsPerMatrixUnit);
  case eCSSKeyword_translate:
    return ProcessTranslate(aData, aContext, aPresContext,
                            aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
  case eCSSKeyword_translate3d:
    return ProcessTranslate3D(aData, aContext, aPresContext,
                              aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
  case eCSSKeyword_scalex:
    return ProcessScaleX(aData);
  case eCSSKeyword_scaley:
    return ProcessScaleY(aData);
  case eCSSKeyword_scalez:
    return ProcessScaleZ(aData);
  case eCSSKeyword_scale:
      return ProcessScale(aData);
  case eCSSKeyword_scale3d:
    return ProcessScale3D(aData);
  case eCSSKeyword_skewx:
    return ProcessSkewX(aData);
  case eCSSKeyword_skewy:
    return ProcessSkewY(aData);
  case eCSSKeyword_skew:
    return ProcessSkew(aData);
  case eCSSKeyword_rotatex:
    return ProcessRotateX(aData);
  case eCSSKeyword_rotatey:
    return ProcessRotateY(aData);
  case eCSSKeyword_rotatez:
  case eCSSKeyword_rotate:
      return ProcessRotateZ(aData);
  case eCSSKeyword_rotate3d:
    return ProcessRotate3D(aData);
  case eCSSKeyword_matrix:
    return ProcessMatrix(aData, aContext, aPresContext,
                         aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
  case eCSSKeyword_matrix3d:
    return ProcessMatrix3D(aData);
  case eCSSKeyword_interpolatematrix:
    return ProcessInterpolateMatrix(aData, aContext, aPresContext,
                                    aCanStoreInRuleTree, aBounds, aAppUnitsPerMatrixUnit);
  case eCSSKeyword_perspective:
    return ProcessPerspective(aData, aContext, aPresContext, 
                              aCanStoreInRuleTree, aAppUnitsPerMatrixUnit);
  default:
    NS_NOTREACHED("Unknown transform function!");
  }
  return gfx3DMatrix();
}
/**
 * SetToTransformFunction is essentially a giant switch statement that fans
 * out to many smaller helper functions.
 */
static void
MatrixForTransformFunction(Matrix4x4& aMatrix,
                           const nsCSSValue::Array * aData,
                           nsStyleContext* aContext,
                           nsPresContext* aPresContext,
                           RuleNodeCacheConditions& aConditions,
                           TransformReferenceBox& aRefBox,
                           bool* aContains3dTransform)
{
  MOZ_ASSERT(aContains3dTransform);
  NS_PRECONDITION(aData, "Why did you want to get data from a null array?");
  // It's OK if aContext and aPresContext are null if the caller already
  // knows that all length units have been converted to pixels (as
  // StyleAnimationValue does).


  /* Get the keyword for the transform. */
  switch (TransformFunctionOf(aData)) {
  case eCSSKeyword_translatex:
    ProcessTranslateX(aMatrix, aData, aContext, aPresContext,
                      aConditions, aRefBox);
    break;
  case eCSSKeyword_translatey:
    ProcessTranslateY(aMatrix, aData, aContext, aPresContext,
                      aConditions, aRefBox);
    break;
  case eCSSKeyword_translatez:
    *aContains3dTransform = true;
    ProcessTranslateZ(aMatrix, aData, aContext, aPresContext,
                      aConditions);
    break;
  case eCSSKeyword_translate:
    ProcessTranslate(aMatrix, aData, aContext, aPresContext,
                     aConditions, aRefBox);
    break;
  case eCSSKeyword_translate3d:
    *aContains3dTransform = true;
    ProcessTranslate3D(aMatrix, aData, aContext, aPresContext,
                       aConditions, aRefBox);
    break;
  case eCSSKeyword_scalex:
    ProcessScaleX(aMatrix, aData);
    break;
  case eCSSKeyword_scaley:
    ProcessScaleY(aMatrix, aData);
    break;
  case eCSSKeyword_scalez:
    *aContains3dTransform = true;
    ProcessScaleZ(aMatrix, aData);
    break;
  case eCSSKeyword_scale:
    ProcessScale(aMatrix, aData);
    break;
  case eCSSKeyword_scale3d:
    *aContains3dTransform = true;
    ProcessScale3D(aMatrix, aData);
    break;
  case eCSSKeyword_skewx:
    ProcessSkewX(aMatrix, aData);
    break;
  case eCSSKeyword_skewy:
    ProcessSkewY(aMatrix, aData);
    break;
  case eCSSKeyword_skew:
    ProcessSkew(aMatrix, aData);
    break;
  case eCSSKeyword_rotatex:
    *aContains3dTransform = true;
    ProcessRotateX(aMatrix, aData);
    break;
  case eCSSKeyword_rotatey:
    *aContains3dTransform = true;
    ProcessRotateY(aMatrix, aData);
    break;
  case eCSSKeyword_rotatez:
    *aContains3dTransform = true;
  case eCSSKeyword_rotate:
    ProcessRotateZ(aMatrix, aData);
    break;
  case eCSSKeyword_rotate3d:
    *aContains3dTransform = true;
    ProcessRotate3D(aMatrix, aData);
    break;
  case eCSSKeyword_matrix:
    ProcessMatrix(aMatrix, aData, aContext, aPresContext,
                  aConditions, aRefBox);
    break;
  case eCSSKeyword_matrix3d:
    *aContains3dTransform = true;
    ProcessMatrix3D(aMatrix, aData, aContext, aPresContext,
                    aConditions, aRefBox);
    break;
  case eCSSKeyword_interpolatematrix:
    ProcessInterpolateMatrix(aMatrix, aData, aContext, aPresContext,
                             aConditions, aRefBox,
                             aContains3dTransform);
    break;
  case eCSSKeyword_perspective:
    *aContains3dTransform = true;
    ProcessPerspective(aMatrix, aData, aContext, aPresContext, 
                       aConditions);
    break;
  default:
    NS_NOTREACHED("Unknown transform function!");
  }
}