Bug 1429298 - Part 6: Apply motion path transform matrix. r=nical

We implement the layout part of offset-path. Now we don't have
offset-distance, so use the default value, 0%, for it.

Note: rename mCombinedTransform as mIndividualTransform, which only
stores the combined individual transforms. We apply the individual
transforms, motion path transform, and specified transform in
ReadTransforms. (We have to follow the order, so we don't combine the
specified transform in FinishStyle.)

Depends on D2967

Differential Revision: https://phabricator.services.mozilla.com/D2968

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Boris Chiou 2018-08-22 01:22:28 +00:00
Родитель 3563363c59
Коммит bbea8d1bca
10 изменённых файлов: 239 добавлений и 58 удалений

Просмотреть файл

@ -81,6 +81,7 @@ EXPORTS.mozilla.dom += [
'SVGMatrix.h', 'SVGMatrix.h',
'SVGMetadataElement.h', 'SVGMetadataElement.h',
'SVGMPathElement.h', 'SVGMPathElement.h',
'SVGPathData.h',
'SVGPathElement.h', 'SVGPathElement.h',
'SVGPatternElement.h', 'SVGPatternElement.h',
'SVGPolygonElement.h', 'SVGPolygonElement.h',

Просмотреть файл

@ -76,6 +76,7 @@
#include "mozilla/dom/DOMRect.h" #include "mozilla/dom/DOMRect.h"
#include "mozilla/dom/DOMStringList.h" #include "mozilla/dom/DOMStringList.h"
#include "mozilla/dom/KeyframeEffect.h" #include "mozilla/dom/KeyframeEffect.h"
#include "mozilla/dom/SVGPathData.h"
#include "mozilla/layers/APZCCallbackHelper.h" #include "mozilla/layers/APZCCallbackHelper.h"
#include "imgIRequest.h" #include "imgIRequest.h"
#include "nsIImageLoadingContent.h" #include "nsIImageLoadingContent.h"
@ -10266,3 +10267,94 @@ nsLayoutUtils::StyleForScrollbar(nsIFrame* aScrollbarPart)
// held strongly by the element. // held strongly by the element.
return style.get(); return style.get();
} }
static float
ResolveTransformOrigin(const nsStyleCoord& aCoord,
TransformReferenceBox& aRefBox,
TransformReferenceBox::DimensionGetter aGetter)
{
float result = 0.0;
const float scale = mozilla::AppUnitsPerCSSPixel();
if (aCoord.GetUnit() == eStyleUnit_Calc) {
const nsStyleCoord::Calc *calc = aCoord.GetCalcValue();
result = NSAppUnitsToFloatPixels((aRefBox.*aGetter)(), scale) *
calc->mPercent +
NSAppUnitsToFloatPixels(calc->mLength, scale);
} else if (aCoord.GetUnit() == eStyleUnit_Percent) {
result = NSAppUnitsToFloatPixels((aRefBox.*aGetter)(), scale) *
aCoord.GetPercentValue();
} else {
MOZ_ASSERT(aCoord.GetUnit() == eStyleUnit_Coord, "unexpected unit");
result = NSAppUnitsToFloatPixels(aCoord.GetCoordValue(), scale);
}
return result;
}
/* static */ Maybe<MotionPathData>
nsLayoutUtils::ResolveMotionPath(const nsIFrame* aFrame)
{
MOZ_ASSERT(aFrame);
const nsStyleDisplay* display = aFrame->StyleDisplay();
if (!display->mMotion || !display->mMotion->HasPath()) {
return Nothing();
}
const UniquePtr<StyleMotion>& motion = display->mMotion;
// Bug 1429299 - Implement offset-distance for motion path. For now, we use
// the default value, i.e. 0%.
float distance = 0.0;
float angle = 0.0;
Point point;
if (motion->OffsetPath().GetType() == StyleShapeSourceType::Path) {
// Build the path and compute the point and angle for creating the
// equivalent translate and rotate.
// Here we only need to build a valid path for motion path, so
// using the default values of stroke-width, stoke-linecap, and fill-rule
// is fine for now because what we want is get the point and its normal
// vector along the path, instead of rendering it.
// FIXME: Bug 1484780, we should cache the path to avoid rebuilding it here
// at every restyle. (Caching the path avoids the cost of flattening it
// again each time.)
RefPtr<DrawTarget> drawTarget =
gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
RefPtr<PathBuilder> builder =
drawTarget->CreatePathBuilder(FillRule::FILL_WINDING);
RefPtr<gfx::Path> gfxPath =
SVGPathData::BuildPath(motion->OffsetPath().GetPath()->Path(),
builder,
NS_STYLE_STROKE_LINECAP_BUTT,
0.0);
if (!gfxPath) {
return Nothing();
}
float pathLength = gfxPath->ComputeLength();
float computedDistance = distance * pathLength;
Point tangent;
point = gfxPath->ComputePointAtLength(computedDistance, &tangent);
// Bug 1429301 - Implement offset-rotate for motion path.
// After implement offset-rotate, |angle| will be adjusted more.
// For now, the default value of offset-rotate is "auto", so we use the
// directional tangent vector.
angle = atan2(tangent.y, tangent.x);
} else {
// Bug 1480665: Implement ray() function.
NS_WARNING("Unsupported offset-path value");
}
// Compute the offset for motion path translate.
// We need to resolve transform-origin here to calculate the correct path
// translate. (i.e. Center transform-origin on the path.)
TransformReferenceBox refBox(aFrame);
Point origin(
ResolveTransformOrigin(display->mTransformOrigin[0],
refBox,
&TransformReferenceBox::Width),
ResolveTransformOrigin(display->mTransformOrigin[1],
refBox,
&TransformReferenceBox::Height)
);
// Bug 1186329: the translate parameters will be adjusted more after we
// implement offset-position and offset-anchor.
return Some(MotionPathData { point - origin, angle });
}

Просмотреть файл

@ -119,6 +119,11 @@ struct DisplayPortMarginsPropertyData {
uint32_t mPriority; uint32_t mPriority;
}; };
struct MotionPathData {
gfx::Point mTranslate;
float mRotate;
};
} // namespace mozilla } // namespace mozilla
// For GetDisplayPort // For GetDisplayPort
@ -3113,6 +3118,12 @@ public:
*/ */
static ComputedStyle* StyleForScrollbar(nsIFrame* aScrollbarPart); static ComputedStyle* StyleForScrollbar(nsIFrame* aScrollbarPart);
/**
* Generate the motion path transform result.
**/
static mozilla::Maybe<mozilla::MotionPathData>
ResolveMotionPath(const nsIFrame* aFrame);
private: private:
static uint32_t sFontSizeInflationEmPerLine; static uint32_t sFontSizeInflationEmPerLine;
static uint32_t sFontSizeInflationMinTwips; static uint32_t sFontSizeInflationMinTwips;

Просмотреть файл

@ -249,22 +249,30 @@ static void
IncrementScaleRestyleCountIfNeeded(nsIFrame* aFrame, LayerActivity* aActivity) IncrementScaleRestyleCountIfNeeded(nsIFrame* aFrame, LayerActivity* aActivity)
{ {
const nsStyleDisplay* display = aFrame->StyleDisplay(); const nsStyleDisplay* display = aFrame->StyleDisplay();
RefPtr<nsCSSValueSharedList> transformList = display->GetCombinedTransform(); if (!display->mSpecifiedTransform &&
if (!transformList) { !display->HasIndividualTransform() &&
!(display->mMotion && display->mMotion->HasPath())) {
// The transform was removed. // The transform was removed.
aActivity->mPreviousTransformScale = Nothing(); aActivity->mPreviousTransformScale = Nothing();
IncrementMutationCount(&aActivity->mRestyleCounts[LayerActivity::ACTIVITY_SCALE]); IncrementMutationCount(
&aActivity->mRestyleCounts[LayerActivity::ACTIVITY_SCALE]);
return; return;
} }
// Compute the new scale due to the CSS transform property. // Compute the new scale due to the CSS transform property.
bool dummyBool; bool dummyBool;
nsStyleTransformMatrix::TransformReferenceBox refBox(aFrame); nsStyleTransformMatrix::TransformReferenceBox refBox(aFrame);
Matrix4x4 transform = Matrix4x4 transform = nsStyleTransformMatrix::ReadTransforms(
nsStyleTransformMatrix::ReadTransforms(transformList->mHead, display->mIndividualTransform
refBox, ? display->mIndividualTransform->mHead
AppUnitsPerCSSPixel(), : nullptr,
&dummyBool); nsLayoutUtils::ResolveMotionPath(aFrame),
display->mSpecifiedTransform
? display->mSpecifiedTransform->mHead
: nullptr,
refBox,
AppUnitsPerCSSPixel(),
&dummyBool);
Matrix transform2D; Matrix transform2D;
if (!transform.Is2D(&transform2D)) { if (!transform.Is2D(&transform2D)) {
// We don't attempt to handle 3D transforms; just assume the scale changed. // We don't attempt to handle 3D transforms; just assume the scale changed.

Просмотреть файл

@ -7849,11 +7849,14 @@ nsDisplayTransform::ComputePerspectiveMatrix(const nsIFrame* aFrame,
return true; return true;
} }
nsDisplayTransform::FrameTransformProperties::FrameTransformProperties(const nsIFrame* aFrame, nsDisplayTransform::FrameTransformProperties::FrameTransformProperties(
float aAppUnitsPerPixel, const nsIFrame* aFrame,
const nsRect* aBoundsOverride) float aAppUnitsPerPixel,
const nsRect* aBoundsOverride)
: mFrame(aFrame) : mFrame(aFrame)
, mTransformList(aFrame->StyleDisplay()->GetCombinedTransform()) , mIndividualTransformList(aFrame->StyleDisplay()->mIndividualTransform)
, mMotion(nsLayoutUtils::ResolveMotionPath(aFrame))
, mTransformList(aFrame->StyleDisplay()->mSpecifiedTransform)
, mToTransformOrigin(GetDeltaToTransformOrigin(aFrame, aAppUnitsPerPixel, aBoundsOverride)) , mToTransformOrigin(GetDeltaToTransformOrigin(aFrame, aAppUnitsPerPixel, aBoundsOverride))
{ {
} }
@ -7922,10 +7925,16 @@ nsDisplayTransform::GetResultingTransformMatrixInternal(const FrameTransformProp
frame && frame->IsSVGTransformed(&svgTransform, frame && frame->IsSVGTransformed(&svgTransform,
&parentsChildrenOnlyTransform); &parentsChildrenOnlyTransform);
/* Transformed frames always have a transform, or are preserving 3d (and might still have perspective!) */ /* Transformed frames always have a transform, or are preserving 3d (and might still have perspective!) */
if (aProperties.mTransformList) { if (aProperties.HasTransform()) {
result = nsStyleTransformMatrix::ReadTransforms(aProperties.mTransformList->mHead, result = nsStyleTransformMatrix::ReadTransforms(
refBox, aAppUnitsPerPixel, aProperties.mIndividualTransformList
&dummyBool); ? aProperties.mIndividualTransformList->mHead
: nullptr,
aProperties.mMotion,
aProperties.mTransformList
? aProperties.mTransformList->mHead
: nullptr,
refBox, aAppUnitsPerPixel, &dummyBool);
} else if (hasSVGTransforms) { } else if (hasSVGTransforms) {
// Correct the translation components for zoom: // Correct the translation components for zoom:
float pixelsPerCSSPx = AppUnitsPerCSSPixel() / float pixelsPerCSSPx = AppUnitsPerCSSPixel() /

Просмотреть файл

@ -68,6 +68,7 @@ enum class nsDisplayOwnLayerFlags;
namespace mozilla { namespace mozilla {
class FrameLayerBuilder; class FrameLayerBuilder;
struct MotionPathData;
namespace layers { namespace layers {
class Layer; class Layer;
class ImageLayer; class ImageLayer;
@ -6577,6 +6578,11 @@ public:
FrameTransformProperties(const nsIFrame* aFrame, FrameTransformProperties(const nsIFrame* aFrame,
float aAppUnitsPerPixel, float aAppUnitsPerPixel,
const nsRect* aBoundsOverride); const nsRect* aBoundsOverride);
// This constructor is used on the compositor (for animations).
// Bug 1186329, Bug 1425837, If we want to support compositor animationsf
// or individual transforms and motion path, we may need to update this.
// For now, let mIndividualTransformList and mMotion as nullptr and
// Nothing().
FrameTransformProperties(RefPtr<const nsCSSValueSharedList>&& FrameTransformProperties(RefPtr<const nsCSSValueSharedList>&&
aTransformList, aTransformList,
const Point3D& aToTransformOrigin) const Point3D& aToTransformOrigin)
@ -6585,7 +6591,14 @@ public:
, mToTransformOrigin(aToTransformOrigin) , mToTransformOrigin(aToTransformOrigin)
{} {}
bool HasTransform() const
{
return mIndividualTransformList || mTransformList || mMotion.isSome();
}
const nsIFrame* mFrame; const nsIFrame* mFrame;
const RefPtr<const nsCSSValueSharedList> mIndividualTransformList;
const mozilla::Maybe<mozilla::MotionPathData> mMotion;
const RefPtr<const nsCSSValueSharedList> mTransformList; const RefPtr<const nsCSSValueSharedList> mTransformList;
const Point3D mToTransformOrigin; const Point3D mToTransformOrigin;
}; };

Просмотреть файл

@ -3636,10 +3636,10 @@ nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
, mSpecifiedRotate(aSource.mSpecifiedRotate) , mSpecifiedRotate(aSource.mSpecifiedRotate)
, mSpecifiedTranslate(aSource.mSpecifiedTranslate) , mSpecifiedTranslate(aSource.mSpecifiedTranslate)
, mSpecifiedScale(aSource.mSpecifiedScale) , mSpecifiedScale(aSource.mSpecifiedScale)
, mIndividualTransform(aSource.mIndividualTransform)
, mMotion(aSource.mMotion , mMotion(aSource.mMotion
? MakeUnique<StyleMotion>(*aSource.mMotion) ? MakeUnique<StyleMotion>(*aSource.mMotion)
: nullptr) : nullptr)
, mCombinedTransform(aSource.mCombinedTransform)
, mTransformOrigin{ aSource.mTransformOrigin[0], , mTransformOrigin{ aSource.mTransformOrigin[0],
aSource.mTransformOrigin[1], aSource.mTransformOrigin[1],
aSource.mTransformOrigin[2] } aSource.mTransformOrigin[2] }
@ -3704,9 +3704,8 @@ nsStyleDisplay::~nsStyleDisplay()
mSpecifiedTranslate); mSpecifiedTranslate);
ReleaseSharedListOnMainThread("nsStyleDisplay::mSpecifiedScale", ReleaseSharedListOnMainThread("nsStyleDisplay::mSpecifiedScale",
mSpecifiedScale); mSpecifiedScale);
ReleaseSharedListOnMainThread("nsStyleDisplay::mCombinedTransform", ReleaseSharedListOnMainThread("nsStyleDisplay::mIndividualTransform",
mCombinedTransform); mIndividualTransform);
MOZ_COUNT_DTOR(nsStyleDisplay); MOZ_COUNT_DTOR(nsStyleDisplay);
} }
@ -3734,7 +3733,7 @@ nsStyleDisplay::FinishStyle(
} }
} }
GenerateCombinedTransform(); GenerateCombinedIndividualTransform();
} }
static inline nsChangeHint static inline nsChangeHint
@ -4031,17 +4030,17 @@ nsStyleDisplay::CalcDifference(const nsStyleDisplay& aNewData) const
} }
void void
nsStyleDisplay::GenerateCombinedTransform() nsStyleDisplay::GenerateCombinedIndividualTransform()
{ {
// FIXME(emilio): This should probably be called from somewhere like what we // FIXME(emilio): This should probably be called from somewhere like what we
// do for image layers, instead of FinishStyle. // do for image layers, instead of FinishStyle.
// //
// This does and undoes the work a ton of times in Stylo. // This does and undoes the work a ton of times in Stylo.
mCombinedTransform = nullptr; mIndividualTransform = nullptr;
// Follow the order defined in the spec to append transform functions. // Follow the order defined in the spec to append transform functions.
// https://drafts.csswg.org/css-transforms-2/#ctm // https://drafts.csswg.org/css-transforms-2/#ctm
AutoTArray<nsCSSValueSharedList*, 4> shareLists; AutoTArray<nsCSSValueSharedList*, 3> shareLists;
if (mSpecifiedTranslate) { if (mSpecifiedTranslate) {
shareLists.AppendElement(mSpecifiedTranslate.get()); shareLists.AppendElement(mSpecifiedTranslate.get());
} }
@ -4051,24 +4050,20 @@ nsStyleDisplay::GenerateCombinedTransform()
if (mSpecifiedScale) { if (mSpecifiedScale) {
shareLists.AppendElement(mSpecifiedScale.get()); shareLists.AppendElement(mSpecifiedScale.get());
} }
if (mSpecifiedTransform) {
shareLists.AppendElement(mSpecifiedTransform.get());
}
if (shareLists.Length() == 0) { if (shareLists.Length() == 0) {
return; return;
} }
if (shareLists.Length() == 1) { if (shareLists.Length() == 1) {
mCombinedTransform = shareLists[0]; mIndividualTransform = shareLists[0];
return; return;
} }
// In common, we may have 3 transform functions(for rotate, translate and // In common, we may have 3 transform functions:
// scale) in mSpecifiedTransform, one rotate function in mSpecifiedRotate, // 1. one rotate function in mSpecifiedRotate,
// one translate function in mSpecifiedTranslate, and one scale function in // 2. one translate function in mSpecifiedTranslate,
// mSpecifiedScale. So 6 slots are enough for the most cases. // 3. one scale function in mSpecifiedScale.
AutoTArray<nsCSSValueList*, 6> valueLists; AutoTArray<nsCSSValueList*, 3> valueLists;
for (auto list: shareLists) { for (auto list: shareLists) {
if (list) { if (list) {
valueLists.AppendElement(list->mHead->Clone()); valueLists.AppendElement(list->mHead->Clone());
@ -4083,8 +4078,9 @@ nsStyleDisplay::GenerateCombinedTransform()
valueLists[i]->mNext = valueLists[i + 1]; valueLists[i]->mNext = valueLists[i + 1];
} }
mCombinedTransform = new nsCSSValueSharedList(valueLists[0]); mIndividualTransform = new nsCSSValueSharedList(valueLists[0]);
} }
// -------------------- // --------------------
// nsStyleVisibility // nsStyleVisibility
// //

Просмотреть файл

@ -2181,14 +2181,11 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay
RefPtr<nsCSSValueSharedList> mSpecifiedRotate; RefPtr<nsCSSValueSharedList> mSpecifiedRotate;
RefPtr<nsCSSValueSharedList> mSpecifiedTranslate; RefPtr<nsCSSValueSharedList> mSpecifiedTranslate;
RefPtr<nsCSSValueSharedList> mSpecifiedScale; RefPtr<nsCSSValueSharedList> mSpecifiedScale;
// Used to store the final combination of mSpecifiedRotate,
// mSpecifiedTranslate, and mSpecifiedScale.
RefPtr<nsCSSValueSharedList> mIndividualTransform;
mozilla::UniquePtr<mozilla::StyleMotion> mMotion; mozilla::UniquePtr<mozilla::StyleMotion> mMotion;
// Used to store the final combination of mSpecifiedTranslate,
// mSpecifiedRotate, mSpecifiedScale and mSpecifiedTransform.
// Use GetCombinedTransform() to get the final transform, instead of
// accessing mCombinedTransform directly.
RefPtr<nsCSSValueSharedList> mCombinedTransform;
nsStyleCoord mTransformOrigin[3]; // percent, coord, calc, 3rd param is coord, calc only nsStyleCoord mTransformOrigin[3]; // percent, coord, calc, 3rd param is coord, calc only
nsStyleCoord mChildPerspective; // none, coord nsStyleCoord mChildPerspective; // none, coord
nsStyleCoord mPerspectiveOrigin[2]; // percent, coord, calc nsStyleCoord mPerspectiveOrigin[2]; // percent, coord, calc
@ -2528,21 +2525,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay
inline bool IsFixedPosContainingBlockForTransformSupportingFrames() const; inline bool IsFixedPosContainingBlockForTransformSupportingFrames() const;
/** /**
* Returns the final combined transform. * Returns the final combined individual transform.
**/ **/
already_AddRefed<nsCSSValueSharedList> GetCombinedTransform() const { already_AddRefed<nsCSSValueSharedList> GetCombinedTransform() const
if (mCombinedTransform) { {
return do_AddRef(mCombinedTransform); return mIndividualTransform ? do_AddRef(mIndividualTransform) : nullptr;
}
// backward compatible to gecko-backed style system.
return mSpecifiedTransform ? do_AddRef(mSpecifiedTransform) : nullptr;
} }
private: private:
// Helpers for above functions, which do some but not all of the tests // Helpers for above functions, which do some but not all of the tests
// for them (since transform must be tested separately for each). // for them (since transform must be tested separately for each).
void GenerateCombinedTransform(); void GenerateCombinedIndividualTransform();
}; };
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTable struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTable

Просмотреть файл

@ -926,14 +926,12 @@ SetIdentityMatrix(nsCSSValue::Array* aMatrix)
} }
} }
Matrix4x4 static void
ReadTransforms(const nsCSSValueList* aList, ReadTransformsImpl(Matrix4x4& aMatrix,
TransformReferenceBox& aRefBox, const nsCSSValueList* aList,
float aAppUnitsPerMatrixUnit, TransformReferenceBox& aRefBox,
bool* aContains3dTransform) bool* aContains3dTransform)
{ {
Matrix4x4 result;
for (const nsCSSValueList* curr = aList; curr != nullptr; curr = curr->mNext) { for (const nsCSSValueList* curr = aList; curr != nullptr; curr = curr->mNext) {
const nsCSSValue &currElem = curr->mValue; const nsCSSValue &currElem = curr->mValue;
if (currElem.GetUnit() != eCSSUnit_Function) { if (currElem.GetUnit() != eCSSUnit_Function) {
@ -947,9 +945,55 @@ ReadTransforms(const nsCSSValueList* aList,
"Incoming function is too short!"); "Incoming function is too short!");
/* Read in a single transform matrix. */ /* Read in a single transform matrix. */
MatrixForTransformFunction(result, currElem.GetArrayValue(), aRefBox, MatrixForTransformFunction(aMatrix, currElem.GetArrayValue(), aRefBox,
aContains3dTransform); aContains3dTransform);
} }
}
Matrix4x4
ReadTransforms(const nsCSSValueList* aList,
TransformReferenceBox& aRefBox,
float aAppUnitsPerMatrixUnit,
bool* aContains3dTransform)
{
Matrix4x4 result;
ReadTransformsImpl(result, aList, aRefBox, aContains3dTransform);
float scale = float(AppUnitsPerCSSPixel()) / aAppUnitsPerMatrixUnit;
result.PreScale(1/scale, 1/scale, 1/scale);
result.PostScale(scale, scale, scale);
return result;
}
Matrix4x4
ReadTransforms(const nsCSSValueList* aIndividualTransforms,
const Maybe<MotionPathData>& aMotion,
const nsCSSValueList* aTransform,
TransformReferenceBox& aRefBox,
float aAppUnitsPerMatrixUnit,
bool* aContains3dTransform)
{
Matrix4x4 result;
if (aIndividualTransforms) {
ReadTransformsImpl(result, aIndividualTransforms, aRefBox,
aContains3dTransform);
}
if (aMotion.isSome()) {
// Create the equivalent translate and rotate function, according to the
// order in spec. We combine the translate and then the rotate.
// https://drafts.fxtf.org/motion-1/#calculating-path-transform
result.PreTranslate(aMotion->mTranslate.x, aMotion->mTranslate.y, 0.0);
if (aMotion->mRotate != 0.0) {
result.RotateZ(aMotion->mRotate);
}
}
if (aTransform) {
ReadTransformsImpl(result, aTransform, aRefBox, aContains3dTransform);
}
float scale = float(AppUnitsPerCSSPixel()) / aAppUnitsPerMatrixUnit; float scale = float(AppUnitsPerCSSPixel()) / aAppUnitsPerMatrixUnit;
result.PreScale(1/scale, 1/scale, 1/scale); result.PreScale(1/scale, 1/scale, 1/scale);

Просмотреть файл

@ -24,6 +24,10 @@ class nsPresContext;
struct gfxQuaternion; struct gfxQuaternion;
struct nsRect; struct nsRect;
namespace mozilla {
struct MotionPathData;
}
/** /**
* A helper to generate gfxMatrixes from css transform functions. * A helper to generate gfxMatrixes from css transform functions.
*/ */
@ -200,6 +204,16 @@ namespace nsStyleTransformMatrix {
float aAppUnitsPerMatrixUnit, float aAppUnitsPerMatrixUnit,
bool* aContains3dTransform); bool* aContains3dTransform);
// Generate the gfx::Matrix for CSS Transform Module Level 2.
// https://drafts.csswg.org/css-transforms-2/#ctm
mozilla::gfx::Matrix4x4
ReadTransforms(const nsCSSValueList* aIndividualTransforms,
const mozilla::Maybe<mozilla::MotionPathData>& aMotion,
const nsCSSValueList* aTransform,
TransformReferenceBox& aRefBox,
float aAppUnitsPerMatrixUnit,
bool* aContains3dTransform);
/** /**
* Given two nsStyleCoord values, compute the 2d position with respect to the * Given two nsStyleCoord values, compute the 2d position with respect to the
* given TransformReferenceBox that these values describe, in device pixels. * given TransformReferenceBox that these values describe, in device pixels.