author | Ting-Yu Lin <tlin@mozilla.com> |
Thu, 16 Feb 2017 10:51:48 +0800 | |
changeset 343240 | 0058687f781389dad42c0e01f4117859e8496202 |
parent 343239 | f45cac0c1b91cb5220b74b1dd5b708a4154c9d1f |
child 343241 | 8a514a5851a4435f772ac5030f1ef4ed7303aa90 |
push id | 31372 |
push user | cbook@mozilla.com |
push date | Thu, 16 Feb 2017 12:16:10 +0000 |
treeherder | mozilla-central@2737f66ad6ac [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | dbaron |
bugs | 1326407 |
milestone | 54.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
layout/generic/nsFloatManager.cpp | file | annotate | diff | comparison | revisions | |
layout/generic/nsFloatManager.h | file | annotate | diff | comparison | revisions |
--- a/layout/generic/nsFloatManager.cpp +++ b/layout/generic/nsFloatManager.cpp @@ -531,89 +531,43 @@ nsFloatManager::ClearContinues(StyleClea ///////////////////////////////////////////////////////////////////////////// // BoxShapeInfo nscoord nsFloatManager::BoxShapeInfo::LineLeft(WritingMode aWM, const nscoord aBStart, const nscoord aBEnd) const { - nscoord radii[8]; - bool hasRadii = mFrame->GetShapeBoxBorderRadii(radii); - - if (!hasRadii) { + if (!mRadii) { return mShapeBoxRect.x; } - // Get the physical side for line-left since border-radii are in - // the physical axis. - mozilla::Side lineLeftSide = - aWM.PhysicalSide(aWM.LogicalSideForLineRelativeDir(eLineRelativeDirLeft)); - nscoord blockStartCornerRadiusL = - radii[SideToHalfCorner(lineLeftSide, true, false)]; - nscoord blockStartCornerRadiusB = - radii[SideToHalfCorner(lineLeftSide, true, true)]; - nscoord blockEndCornerRadiusL = - radii[SideToHalfCorner(lineLeftSide, false, false)]; - nscoord blockEndCornerRadiusB = - radii[SideToHalfCorner(lineLeftSide, false, true)]; - - if (aWM.IsLineInverted()) { - // This happens only when aWM is vertical-lr. Need to swap blockStart - // and blockEnd corners. - std::swap(blockStartCornerRadiusL, blockEndCornerRadiusL); - std::swap(blockStartCornerRadiusB, blockEndCornerRadiusB); - } - nscoord lineLeftDiff = ComputeEllipseLineInterceptDiff( mShapeBoxRect.y, mShapeBoxRect.YMost(), - blockStartCornerRadiusL, blockStartCornerRadiusB, - blockEndCornerRadiusL, blockEndCornerRadiusB, + mRadii[eCornerTopLeftX], mRadii[eCornerTopLeftY], + mRadii[eCornerBottomLeftX], mRadii[eCornerBottomLeftY], aBStart, aBEnd); return mShapeBoxRect.x + lineLeftDiff; } nscoord nsFloatManager::BoxShapeInfo::LineRight(WritingMode aWM, const nscoord aBStart, const nscoord aBEnd) const { - nscoord radii[8]; - bool hasRadii = mFrame->GetShapeBoxBorderRadii(radii); - - if (!hasRadii) { + if (!mRadii) { return mShapeBoxRect.XMost(); } - // Get the physical side for line-right since border-radii are in - // the physical axis. - mozilla::Side lineRightSide = - aWM.PhysicalSide(aWM.LogicalSideForLineRelativeDir(eLineRelativeDirRight)); - nscoord blockStartCornerRadiusL = - radii[SideToHalfCorner(lineRightSide, false, false)]; - nscoord blockStartCornerRadiusB = - radii[SideToHalfCorner(lineRightSide, false, true)]; - nscoord blockEndCornerRadiusL = - radii[SideToHalfCorner(lineRightSide, true, false)]; - nscoord blockEndCornerRadiusB = - radii[SideToHalfCorner(lineRightSide, true, true)]; - - if (aWM.IsLineInverted()) { - // This happens only when aWM is vertical-lr. Need to swap blockStart - // and blockEnd corners. - std::swap(blockStartCornerRadiusL, blockEndCornerRadiusL); - std::swap(blockStartCornerRadiusB, blockEndCornerRadiusB); - } - nscoord lineRightDiff = ComputeEllipseLineInterceptDiff( mShapeBoxRect.y, mShapeBoxRect.YMost(), - blockStartCornerRadiusL, blockStartCornerRadiusB, - blockEndCornerRadiusL, blockEndCornerRadiusB, + mRadii[eCornerTopRightX], mRadii[eCornerTopRightY], + mRadii[eCornerBottomRightX], mRadii[eCornerBottomRightY], aBStart, aBEnd); return mShapeBoxRect.XMost() - lineRightDiff; } ///////////////////////////////////////////////////////////////////////////// // EllipseShapeInfo nscoord nsFloatManager::EllipseShapeInfo::LineLeft(WritingMode aWM, @@ -668,19 +622,18 @@ nsFloatManager::FloatInfo::FloatInfo(nsI return; } // Initialize <shape-box>'s reference rect. LogicalRect shapeBoxRect = ShapeInfo::ComputeShapeBoxRect(shapeOutside, mFrame, aMarginRect, aWM); if (shapeOutside.GetType() == StyleShapeSourceType::Box) { - nsRect rect = ShapeInfo::ConvertToFloatLogical(shapeBoxRect, aWM, - aContainerSize); - mShapeInfo = MakeUnique<BoxShapeInfo>(rect, mFrame); + mShapeInfo = ShapeInfo::CreateShapeBox(mFrame, shapeBoxRect, aWM, + aContainerSize); } else if (shapeOutside.GetType() == StyleShapeSourceType::Shape) { StyleBasicShape* const basicShape = shapeOutside.GetBasicShape(); switch (basicShape->GetShapeType()) { case StyleBasicShapeType::Polygon: // Bug 1326409 - Implement the rendering of basic shape polygon() // for CSS shape-outside. return; @@ -836,16 +789,37 @@ nsFloatManager::ShapeInfo::ComputeShapeB "Box source type must have <shape-box> specified!"); break; } return rect; } /* static */ UniquePtr<nsFloatManager::ShapeInfo> +nsFloatManager::ShapeInfo::CreateShapeBox( + nsIFrame* const aFrame, + const LogicalRect& aShapeBoxRect, + WritingMode aWM, + const nsSize& aContainerSize) +{ + nsRect logicalShapeBoxRect + = ConvertToFloatLogical(aShapeBoxRect, aWM, aContainerSize); + + nscoord physicalRadii[8]; + bool hasRadii = aFrame->GetShapeBoxBorderRadii(physicalRadii); + if (!hasRadii) { + return MakeUnique<BoxShapeInfo>(logicalShapeBoxRect, + UniquePtr<nscoord[]>()); + } + + return MakeUnique<BoxShapeInfo>(logicalShapeBoxRect, + ConvertToFloatLogical(physicalRadii, aWM)); +} + +/* static */ UniquePtr<nsFloatManager::ShapeInfo> nsFloatManager::ShapeInfo::CreateCircleOrEllipse( StyleBasicShape* const aBasicShape, const LogicalRect& aShapeBoxRect, WritingMode aWM, const nsSize& aContainerSize) { // Use physical coordinates to compute the center of circle() or ellipse() // since the <position> keywords such as 'left', 'top', etc. are physical. @@ -963,16 +937,61 @@ nsFloatManager::ShapeInfo::ConvertToFloa WritingMode aWM, const nsSize& aContainerSize) { LogicalPoint logicalPoint(aWM, aPoint, aContainerSize); return nsPoint(logicalPoint.LineRelative(aWM, aContainerSize), logicalPoint.B(aWM)); } +/* static */ UniquePtr<nscoord[]> +nsFloatManager::ShapeInfo::ConvertToFloatLogical(const nscoord aRadii[8], + WritingMode aWM) +{ + UniquePtr<nscoord[]> logicalRadii(new nscoord[8]); + + // Get the physical side for line-left and line-right since border radii + // are on the physical axis. + Side lineLeftSide = + aWM.PhysicalSide(aWM.LogicalSideForLineRelativeDir(eLineRelativeDirLeft)); + logicalRadii[eCornerTopLeftX] = + aRadii[SideToHalfCorner(lineLeftSide, true, false)]; + logicalRadii[eCornerTopLeftY] = + aRadii[SideToHalfCorner(lineLeftSide, true, true)]; + logicalRadii[eCornerBottomLeftX] = + aRadii[SideToHalfCorner(lineLeftSide, false, false)]; + logicalRadii[eCornerBottomLeftY] = + aRadii[SideToHalfCorner(lineLeftSide, false, true)]; + + Side lineRightSide = + aWM.PhysicalSide(aWM.LogicalSideForLineRelativeDir(eLineRelativeDirRight)); + logicalRadii[eCornerTopRightX] = + aRadii[SideToHalfCorner(lineRightSide, false, false)]; + logicalRadii[eCornerTopRightY] = + aRadii[SideToHalfCorner(lineRightSide, false, true)]; + logicalRadii[eCornerBottomRightX] = + aRadii[SideToHalfCorner(lineRightSide, true, false)]; + logicalRadii[eCornerBottomRightY] = + aRadii[SideToHalfCorner(lineRightSide, true, true)]; + + if (aWM.IsLineInverted()) { + // When IsLineInverted() is true, i.e. aWM is vertical-lr, + // line-over/line-under are inverted from block-start/block-end. So the + // relationship reverses between which corner comes first going + // clockwise, and which corner is block-start versus block-end. We need + // to swap the values stored in top and bottom corners. + std::swap(logicalRadii[eCornerTopLeftX], logicalRadii[eCornerBottomLeftX]); + std::swap(logicalRadii[eCornerTopLeftY], logicalRadii[eCornerBottomLeftY]); + std::swap(logicalRadii[eCornerTopRightX], logicalRadii[eCornerBottomRightX]); + std::swap(logicalRadii[eCornerTopRightY], logicalRadii[eCornerBottomRightY]); + } + + return logicalRadii; +} + //---------------------------------------------------------------------- nsAutoFloatManager::~nsAutoFloatManager() { // Restore the old float manager in the reflow input if necessary. if (mNew) { #ifdef DEBUG if (nsBlockFrame::gNoisyFloatManager) {
--- a/layout/generic/nsFloatManager.h +++ b/layout/generic/nsFloatManager.h @@ -372,16 +372,22 @@ private: static nsRect ConvertToFloatLogical(const mozilla::LogicalRect& aRect, mozilla::WritingMode aWM, const nsSize& aContainerSize) { return nsRect(aRect.LineLeft(aWM, aContainerSize), aRect.BStart(aWM), aRect.ISize(aWM), aRect.BSize(aWM)); } + static mozilla::UniquePtr<ShapeInfo> CreateShapeBox( + nsIFrame* const aFrame, + const mozilla::LogicalRect& aShapeBoxRect, + mozilla::WritingMode aWM, + const nsSize& aContainerSize); + static mozilla::UniquePtr<ShapeInfo> CreateCircleOrEllipse( mozilla::StyleBasicShape* const aBasicShape, const mozilla::LogicalRect& aShapeBoxRect, mozilla::WritingMode aWM, const nsSize& aContainerSize); protected: // Compute the minimum line-axis difference between the bounding shape @@ -401,27 +407,33 @@ private: static nscoord XInterceptAtY(const nscoord aY, const nscoord aRadiusX, const nscoord aRadiusY); // Convert the physical point to the special logical coordinate space // used in float manager. static nsPoint ConvertToFloatLogical(const nsPoint& aPoint, mozilla::WritingMode aWM, const nsSize& aContainerSize); + + // Convert the half corner radii (nscoord[8]) to the special logical + // coordinate space used in float manager. + static mozilla::UniquePtr<nscoord[]> ConvertToFloatLogical( + const nscoord aRadii[8], + mozilla::WritingMode aWM); }; // Implements shape-outside: <shape-box>. class BoxShapeInfo final : public ShapeInfo { public: - BoxShapeInfo(const nsRect& aShapeBoxRect, nsIFrame* const aFrame) + BoxShapeInfo(const nsRect& aShapeBoxRect, + mozilla::UniquePtr<nscoord[]> aRadii) : mShapeBoxRect(aShapeBoxRect) - , mFrame(aFrame) - { - } + , mRadii(Move(aRadii)) + {} nscoord LineLeft(mozilla::WritingMode aWM, const nscoord aBStart, const nscoord aBEnd) const override; nscoord LineRight(mozilla::WritingMode aWM, const nscoord aBStart, const nscoord aBEnd) const override; nscoord BStart() const override { return mShapeBoxRect.y; } @@ -433,18 +445,20 @@ private: mShapeBoxRect.MoveBy(aLineLeft, aBlockStart); } private: // This is the reference box of css shape-outside if specified, which // implements the <shape-box> value in the CSS Shapes Module Level 1. // The coordinate space is the same as FloatInfo::mRect. nsRect mShapeBoxRect; - // The frame of the float. - nsIFrame* const mFrame; + // The half corner radii of the reference box. It's an nscoord[8] array + // in the float manager's coordinate space. If there are no radii, it's + // nullptr. + mozilla::UniquePtr<nscoord[]> mRadii; }; // Implements shape-outside: circle() and shape-outside: ellipse(). class EllipseShapeInfo : public ShapeInfo { public: EllipseShapeInfo(const nsPoint& aCenter, const nsSize& aRadii)