--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -175,16 +175,20 @@ static void AddTransformFunctions(const
nsPresContext* aPresContext,
TransformReferenceBox& aRefBox,
InfallibleTArray<TransformFunction>& aFunctions)
{
if (aList->mValue.GetUnit() == eCSSUnit_None) {
return;
}
+ GeckoStyleContext* contextIfGecko = aContext
+ ? aContext->GetAsGecko()
+ : nullptr;
+
for (const nsCSSValueList* curr = aList; curr; curr = curr->mNext) {
const nsCSSValue& currElem = curr->mValue;
NS_ASSERTION(currElem.GetUnit() == eCSSUnit_Function,
"Stream should consist solely of functions!");
nsCSSValue::Array* array = currElem.GetArrayValue();
RuleNodeCacheConditions conditions;
switch (nsStyleTransformMatrix::TransformFunctionOf(array)) {
case eCSSKeyword_rotatex:
@@ -252,62 +256,62 @@ static void AddTransformFunctions(const
double y = array->Item(2).GetFloatValue();
double z = array->Item(3).GetFloatValue();
aFunctions.AppendElement(Scale(x, y, z));
break;
}
case eCSSKeyword_translatex:
{
double x = nsStyleTransformMatrix::ProcessTranslatePart(
- array->Item(1), aContext, aPresContext, conditions,
+ array->Item(1), contextIfGecko, aPresContext, conditions,
&aRefBox, &TransformReferenceBox::Width);
aFunctions.AppendElement(Translation(x, 0, 0));
break;
}
case eCSSKeyword_translatey:
{
double y = nsStyleTransformMatrix::ProcessTranslatePart(
- array->Item(1), aContext, aPresContext, conditions,
+ array->Item(1), contextIfGecko, aPresContext, conditions,
&aRefBox, &TransformReferenceBox::Height);
aFunctions.AppendElement(Translation(0, y, 0));
break;
}
case eCSSKeyword_translatez:
{
double z = nsStyleTransformMatrix::ProcessTranslatePart(
- array->Item(1), aContext, aPresContext, conditions,
+ array->Item(1), contextIfGecko, aPresContext, conditions,
nullptr);
aFunctions.AppendElement(Translation(0, 0, z));
break;
}
case eCSSKeyword_translate:
{
double x = nsStyleTransformMatrix::ProcessTranslatePart(
- array->Item(1), aContext, aPresContext, conditions,
+ array->Item(1), contextIfGecko, aPresContext, conditions,
&aRefBox, &TransformReferenceBox::Width);
// translate(x) is shorthand for translate(x, 0)
double y = 0;
if (array->Count() == 3) {
y = nsStyleTransformMatrix::ProcessTranslatePart(
- array->Item(2), aContext, aPresContext, conditions,
+ array->Item(2), contextIfGecko, aPresContext, conditions,
&aRefBox, &TransformReferenceBox::Height);
}
aFunctions.AppendElement(Translation(x, y, 0));
break;
}
case eCSSKeyword_translate3d:
{
double x = nsStyleTransformMatrix::ProcessTranslatePart(
- array->Item(1), aContext, aPresContext, conditions,
+ array->Item(1), contextIfGecko, aPresContext, conditions,
&aRefBox, &TransformReferenceBox::Width);
double y = nsStyleTransformMatrix::ProcessTranslatePart(
- array->Item(2), aContext, aPresContext, conditions,
+ array->Item(2), contextIfGecko, aPresContext, conditions,
&aRefBox, &TransformReferenceBox::Height);
double z = nsStyleTransformMatrix::ProcessTranslatePart(
- array->Item(3), aContext, aPresContext, conditions,
+ array->Item(3), contextIfGecko, aPresContext, conditions,
nullptr);
aFunctions.AppendElement(Translation(x, y, z));
break;
}
case eCSSKeyword_skewx:
{
CSSAngle x = MakeCSSAngle(array->Item(1));
@@ -375,30 +379,30 @@ static void AddTransformFunctions(const
aFunctions.AppendElement(TransformMatrix(matrix));
break;
}
case eCSSKeyword_interpolatematrix:
{
bool dummy;
Matrix4x4 matrix;
nsStyleTransformMatrix::ProcessInterpolateMatrix(matrix, array,
- aContext,
+ contextIfGecko,
aPresContext,
conditions,
aRefBox,
&dummy);
aFunctions.AppendElement(TransformMatrix(matrix));
break;
}
case eCSSKeyword_accumulatematrix:
{
bool dummy;
Matrix4x4 matrix;
nsStyleTransformMatrix::ProcessAccumulateMatrix(matrix, array,
- aContext,
+ contextIfGecko,
aPresContext,
conditions,
aRefBox,
&dummy);
aFunctions.AppendElement(TransformMatrix(matrix));
break;
}
case eCSSKeyword_perspective:
--- a/layout/style/nsStyleTransformMatrix.cpp
+++ b/layout/style/nsStyleTransformMatrix.cpp
@@ -131,17 +131,17 @@ TransformReferenceBox::Init(const nsSize
mY = 0;
mWidth = aDimensions.width;
mHeight = aDimensions.height;
mIsCached = true;
}
float
ProcessTranslatePart(const nsCSSValue& aValue,
- nsStyleContext* aContext,
+ GeckoStyleContext* aContext,
nsPresContext* aPresContext,
RuleNodeCacheConditions& aConditions,
TransformReferenceBox* aRefBox,
TransformReferenceBox::DimensionGetter aDimensionGetter)
{
nscoord offset = 0;
float percent = 0.0f;
@@ -155,49 +155,65 @@ ProcessTranslatePart(const nsCSSValue& a
// StyleAnimationValue does) that all lengths within the transform
// function have already been computed to pixels and percents.
//
// Raw numbers are treated as being pixels.
//
// Don't convert to aValue to AppUnits here to avoid precision issues.
return aValue.GetFloatValue();
} else if (aValue.IsCalcUnit()) {
- nsRuleNode::ComputedCalc result =
- nsRuleNode::SpecifiedCalcToComputedCalc(aValue, aContext, aPresContext,
- aConditions);
- percent = result.mPercent;
- offset = result.mLength;
+ if (aContext) {
+ // Gecko backend
+ nsRuleNode::ComputedCalc result =
+ nsRuleNode::SpecifiedCalcToComputedCalc(aValue, aContext, aPresContext,
+ aConditions);
+ percent = result.mPercent;
+ offset = result.mLength;
+ } else {
+ // Servo backend. We can retrieve the Calc value directly because it has
+ // been computed from Servo side and set by nsCSSValue::SetCalcValue().
+ // We don't use nsRuleNode::SpecifiedCalcToComputedCalc() because it
+ // asserts for null context and we always pass null context for Servo
+ // backend.
+ nsStyleCoord::CalcValue calc = aValue.GetCalcValue();
+ percent = calc.mPercent;
+ offset = calc.mLength;
+ }
} else {
+ // Note: The unit of nsCSSValue passed from Servo side would be number,
+ // pixel, percent, or eCSSUnit_Calc, so it is impossible to go into
+ // this branch.
+ MOZ_ASSERT(aContext, "We need a valid context to compute the length");
offset = nsRuleNode::CalcLength(aValue, aContext, aPresContext,
aConditions);
}
- float translation = NSAppUnitsToFloatPixels(offset,
- nsPresContext::AppUnitsPerCSSPixel());
+ float translation =
+ NSAppUnitsToFloatPixels(offset, nsPresContext::AppUnitsPerCSSPixel());
// We want to avoid calling aDimensionGetter if there's no percentage to be
// resolved (for performance reasons - see TransformReferenceBox).
if (percent != 0.0f && aRefBox && !aRefBox->IsEmpty()) {
- translation += percent *
- NSAppUnitsToFloatPixels((aRefBox->*aDimensionGetter)(),
- nsPresContext::AppUnitsPerCSSPixel());
+ translation +=
+ percent * NSAppUnitsToFloatPixels((aRefBox->*aDimensionGetter)(),
+ nsPresContext::AppUnitsPerCSSPixel());
}
return translation;
}
/**
* Helper functions to process all the transformation function types.
*
* These take a matrix parameter to accumulate the current matrix.
*/
/* Helper function to process a matrix entry. */
static void
ProcessMatrix(Matrix4x4& aMatrix,
const nsCSSValue::Array* aData,
- nsStyleContext* aContext,
+ GeckoStyleContext* aContext,
nsPresContext* aPresContext,
RuleNodeCacheConditions& aConditions,
TransformReferenceBox& aRefBox)
{
NS_PRECONDITION(aData->Count() == 7, "Invalid array!");
gfxMatrix result;
@@ -220,17 +236,17 @@ ProcessMatrix(Matrix4x4& aMatrix,
&aRefBox, &TransformReferenceBox::Height);
aMatrix = result * aMatrix;
}
static void
ProcessMatrix3D(Matrix4x4& aMatrix,
const nsCSSValue::Array* aData,
- nsStyleContext* aContext,
+ GeckoStyleContext* aContext,
nsPresContext* aPresContext,
RuleNodeCacheConditions& aConditions,
TransformReferenceBox& aRefBox)
{
NS_PRECONDITION(aData->Count() == 17, "Invalid array!");
Matrix4x4 temp;
@@ -463,17 +479,17 @@ OperateTransformMatrixByServo(const Matr
{
return Operator::operateByServo(aMatrix1, aMatrix2, aProgress);
}
template <typename Operator>
static void
ProcessMatrixOperator(Matrix4x4& aMatrix,
const nsCSSValue::Array* aData,
- nsStyleContext* aContext,
+ GeckoStyleContext* aContext,
nsPresContext* aPresContext,
RuleNodeCacheConditions& aConditions,
TransformReferenceBox& aRefBox,
bool* aContains3dTransform)
{
NS_PRECONDITION(aData->Count() == 4, "Invalid array!");
auto readTransform = [&](const nsCSSValue& aValue) -> Matrix4x4 {
@@ -509,61 +525,64 @@ ProcessMatrixOperator(Matrix4x4& aMatrix
aContains3dTransform);
return matrix;
};
Matrix4x4 matrix1 = readTransform(aData->Item(1));
Matrix4x4 matrix2 = readTransform(aData->Item(2));
double progress = aData->Item(3).GetPercentValue();
- if (aContext && aContext->IsServo()) {
+ // We cannot use GeckoStyleContext to check if we use Servo backend because
+ // it could be null in Gecko. Instead, use the unit of the nsCSSValue because
+ // we use eCSSUnit_SharedList for Servo backend.
+ if (aData->Item(1).GetUnit() == eCSSUnit_SharedList) {
aMatrix =
OperateTransformMatrixByServo<Operator>(matrix1, matrix2, progress)
* aMatrix;
return;
}
aMatrix =
OperateTransformMatrix<Operator>(matrix1, matrix2, progress) * aMatrix;
}
/* Helper function to process two matrices that we need to interpolate between */
void
ProcessInterpolateMatrix(Matrix4x4& aMatrix,
const nsCSSValue::Array* aData,
- nsStyleContext* aContext,
+ GeckoStyleContext* aContext,
nsPresContext* aPresContext,
RuleNodeCacheConditions& aConditions,
TransformReferenceBox& aRefBox,
bool* aContains3dTransform)
{
ProcessMatrixOperator<Interpolate>(aMatrix, aData, aContext, aPresContext,
aConditions, aRefBox,
aContains3dTransform);
}
void
ProcessAccumulateMatrix(Matrix4x4& aMatrix,
const nsCSSValue::Array* aData,
- nsStyleContext* aContext,
+ GeckoStyleContext* aContext,
nsPresContext* aPresContext,
RuleNodeCacheConditions& aConditions,
TransformReferenceBox& aRefBox,
bool* aContains3dTransform)
{
ProcessMatrixOperator<Accumulate>(aMatrix, aData, aContext, aPresContext,
aConditions, aRefBox,
aContains3dTransform);
}
/* Helper function to process a translatex function. */
static void
ProcessTranslateX(Matrix4x4& aMatrix,
const nsCSSValue::Array* aData,
- nsStyleContext* aContext,
+ GeckoStyleContext* aContext,
nsPresContext* aPresContext,
RuleNodeCacheConditions& aConditions,
TransformReferenceBox& aRefBox)
{
NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
Point3D temp;
@@ -572,17 +591,17 @@ ProcessTranslateX(Matrix4x4& aMatrix,
&aRefBox, &TransformReferenceBox::Width);
aMatrix.PreTranslate(temp);
}
/* Helper function to process a translatey function. */
static void
ProcessTranslateY(Matrix4x4& aMatrix,
const nsCSSValue::Array* aData,
- nsStyleContext* aContext,
+ GeckoStyleContext* aContext,
nsPresContext* aPresContext,
RuleNodeCacheConditions& aConditions,
TransformReferenceBox& aRefBox)
{
NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
Point3D temp;
@@ -590,17 +609,17 @@ ProcessTranslateY(Matrix4x4& aMatrix,
aContext, aPresContext, aConditions,
&aRefBox, &TransformReferenceBox::Height);
aMatrix.PreTranslate(temp);
}
static void
ProcessTranslateZ(Matrix4x4& aMatrix,
const nsCSSValue::Array* aData,
- nsStyleContext* aContext,
+ GeckoStyleContext* aContext,
nsPresContext* aPresContext,
RuleNodeCacheConditions& aConditions)
{
NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
Point3D temp;
temp.z = ProcessTranslatePart(aData->Item(1), aContext,
@@ -608,17 +627,17 @@ ProcessTranslateZ(Matrix4x4& aMatrix,
nullptr);
aMatrix.PreTranslate(temp);
}
/* Helper function to process a translate function. */
static void
ProcessTranslate(Matrix4x4& aMatrix,
const nsCSSValue::Array* aData,
- nsStyleContext* aContext,
+ GeckoStyleContext* aContext,
nsPresContext* aPresContext,
RuleNodeCacheConditions& aConditions,
TransformReferenceBox& aRefBox)
{
NS_PRECONDITION(aData->Count() == 2 || aData->Count() == 3, "Invalid array!");
Point3D temp;
@@ -633,17 +652,17 @@ ProcessTranslate(Matrix4x4& aMatrix,
&aRefBox, &TransformReferenceBox::Height);
}
aMatrix.PreTranslate(temp);
}
static void
ProcessTranslate3D(Matrix4x4& aMatrix,
const nsCSSValue::Array* aData,
- nsStyleContext* aContext,
+ GeckoStyleContext* aContext,
nsPresContext* aPresContext,
RuleNodeCacheConditions& aConditions,
TransformReferenceBox& aRefBox)
{
NS_PRECONDITION(aData->Count() == 4, "Invalid array!");
Point3D temp;
@@ -800,17 +819,17 @@ ProcessRotate3D(Matrix4x4& aMatrix, cons
temp.SetRotateAxisAngle(x, y, z, theta);
aMatrix = temp * aMatrix;
}
static void
ProcessPerspective(Matrix4x4& aMatrix,
const nsCSSValue::Array* aData,
- nsStyleContext *aContext,
+ GeckoStyleContext *aContext,
nsPresContext *aPresContext,
RuleNodeCacheConditions& aConditions)
{
NS_PRECONDITION(aData->Count() == 2, "Invalid array!");
float depth = ProcessTranslatePart(aData->Item(1), aContext,
aPresContext, aConditions, nullptr);
ApplyPerspectiveToMatrix(aMatrix, depth);
@@ -819,29 +838,28 @@ ProcessPerspective(Matrix4x4& aMatrix,
/**
* 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,
+ GeckoStyleContext* 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,
@@ -976,31 +994,34 @@ ReadTransforms(const nsCSSValueList* aLi
nsStyleContext* aContext,
nsPresContext* aPresContext,
RuleNodeCacheConditions& aConditions,
TransformReferenceBox& aRefBox,
float aAppUnitsPerMatrixUnit,
bool* aContains3dTransform)
{
Matrix4x4 result;
+ GeckoStyleContext* contextIfGecko = aContext
+ ? aContext->GetAsGecko()
+ : nullptr;
for (const nsCSSValueList* curr = aList; curr != nullptr; curr = curr->mNext) {
const nsCSSValue &currElem = curr->mValue;
if (currElem.GetUnit() != eCSSUnit_Function) {
NS_ASSERTION(currElem.GetUnit() == eCSSUnit_None &&
!aList->mNext,
"stream should either be a list of functions or a "
"lone None");
continue;
}
NS_ASSERTION(currElem.GetArrayValue()->Count() >= 1,
"Incoming function is too short!");
/* Read in a single transform matrix. */
- MatrixForTransformFunction(result, currElem.GetArrayValue(), aContext,
+ MatrixForTransformFunction(result, currElem.GetArrayValue(), contextIfGecko,
aPresContext, aConditions, aRefBox,
aContains3dTransform);
}
float scale = float(nsPresContext::AppUnitsPerCSSPixel()) / aAppUnitsPerMatrixUnit;
result.PreScale(1/scale, 1/scale, 1/scale);
result.PostScale(scale, scale, scale);