From 1ee66d0a5f4a5f91e6b9a1510baf6b444aaa27f7 Mon Sep 17 00:00:00 2001 From: Roy Tam Date: Thu, 13 Aug 2020 09:22:06 +0800 Subject: [PATCH 1/7] bump palemoon version --- application/palemoon/config/version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/palemoon/config/version.txt b/application/palemoon/config/version.txt index 7da4fc57ea..80701602f5 100644 --- a/application/palemoon/config/version.txt +++ b/application/palemoon/config/version.txt @@ -1 +1 @@ -28.10.1a1 \ No newline at end of file +28.10.2a1 \ No newline at end of file From be1f68f39eaadc1fc4ded32fd230d51bfec7e493 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 4 Aug 2020 13:54:01 -0700 Subject: [PATCH 2/7] Issue #1620 - Use Intrinsic Aspect Ratio for Images https://bugzilla.mozilla.org/show_bug.cgi?id=1547231 https://bugzilla.mozilla.org/show_bug.cgi?id=1559094 https://bugzilla.mozilla.org/show_bug.cgi?id=1633434 https://bugzilla.mozilla.org/show_bug.cgi?id=1565690 https://bugzilla.mozilla.org/show_bug.cgi?id=1602047 Make use of Aspect Ratios in Image frames before Images are loaded. - Check for width and height HTML properties and create a ratio with them. - Overwrite HTML size values with actual image dimensions on load. - Collapse any frames with srcless images. Comments: dom/html/nsGenericHTMLElement.cpp:1483 layout/generic/nsImageFrame.cpp:289 --- dom/html/HTMLImageElement.cpp | 2 +- dom/html/HTMLImageElement.h | 5 + dom/html/nsGenericHTMLElement.cpp | 60 +++- dom/html/nsGenericHTMLElement.h | 4 +- layout/generic/crashtests/1633434.html | 15 + layout/generic/crashtests/crashtests.list | 1 + layout/generic/nsImageFrame.cpp | 268 ++++++++++-------- layout/generic/nsImageFrame.h | 20 +- layout/style/nsCSSPropList.h | 11 + layout/style/nsRuleNode.cpp | 6 + layout/style/nsStyleStruct.cpp | 7 + layout/style/nsStyleStruct.h | 1 + layout/style/test/ListCSSProperties.cpp | 1 + modules/libpref/init/all.js | 6 + .../background-size-cover-003-ref.html | 21 ++ .../background-size-cover-003.html | 38 +++ .../img-aspect-ratio.html | 60 ++++ 17 files changed, 382 insertions(+), 144 deletions(-) create mode 100644 layout/generic/crashtests/1633434.html create mode 100644 testing/web-platform/tests/css-backgrounds/background-size-cover-003-ref.html create mode 100644 testing/web-platform/tests/css-backgrounds/background-size-cover-003.html create mode 100644 testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio.html diff --git a/dom/html/HTMLImageElement.cpp b/dom/html/HTMLImageElement.cpp index 444c352e2c..d042a9fe6f 100644 --- a/dom/html/HTMLImageElement.cpp +++ b/dom/html/HTMLImageElement.cpp @@ -325,7 +325,7 @@ HTMLImageElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes, nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData); nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aData); nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData); - nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData); + nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData, true); nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData); } diff --git a/dom/html/HTMLImageElement.h b/dom/html/HTMLImageElement.h index bb4a098824..23cac4afb9 100644 --- a/dom/html/HTMLImageElement.h +++ b/dom/html/HTMLImageElement.h @@ -196,6 +196,11 @@ public: return GetReferrerPolicyAsEnum(); } + bool IsAwaitingLoad() const + { + return !!mPendingImageLoadTask; + } + int32_t X(); int32_t Y(); // Uses XPCOM GetLowsrc. diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp index b52e61ce6e..afc76ee31c 100644 --- a/dom/html/nsGenericHTMLElement.cpp +++ b/dom/html/nsGenericHTMLElement.cpp @@ -1449,29 +1449,59 @@ nsGenericHTMLElement::MapImageMarginAttributeInto(const nsMappedAttributes* aAtt void nsGenericHTMLElement::MapImageSizeAttributesInto(const nsMappedAttributes* aAttributes, - nsRuleData* aData) + nsRuleData* aData, + bool aMapAspectRatio) { if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Position))) return; + auto* aWidth = aAttributes->GetAttr(nsGkAtoms::width); + auto* aHeight = aAttributes->GetAttr(nsGkAtoms::height); + // width: value - nsCSSValue* width = aData->ValueForWidth(); - if (width->GetUnit() == eCSSUnit_Null) { - const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width); - if (value && value->Type() == nsAttrValue::eInteger) - width->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel); - else if (value && value->Type() == nsAttrValue::ePercent) - width->SetPercentValue(value->GetPercentValue()); + if (aWidth) { + nsCSSValue* cWidth = aData->ValueForWidth(); + if (cWidth->GetUnit() == eCSSUnit_Null) { + if (aWidth->Type() == nsAttrValue::eInteger) + cWidth->SetFloatValue((float)aWidth->GetIntegerValue(), eCSSUnit_Pixel); + else if (aWidth->Type() == nsAttrValue::ePercent) + cWidth->SetPercentValue(aWidth->GetPercentValue()); + } } // height: value - nsCSSValue* height = aData->ValueForHeight(); - if (height->GetUnit() == eCSSUnit_Null) { - const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height); - if (value && value->Type() == nsAttrValue::eInteger) - height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel); - else if (value && value->Type() == nsAttrValue::ePercent) - height->SetPercentValue(value->GetPercentValue()); + if (aHeight) { + nsCSSValue* cHeight = aData->ValueForHeight(); + if (cHeight->GetUnit() == eCSSUnit_Null) { + if (aHeight->Type() == nsAttrValue::eInteger) + cHeight->SetFloatValue((float)aHeight->GetIntegerValue(), eCSSUnit_Pixel); + else if (aHeight->Type() == nsAttrValue::ePercent) + cHeight->SetPercentValue(aHeight->GetPercentValue()); + } + } + + // 2020-07-15 (RealityRipple) Much of this is a guess based on a few sources. + // Please go over this with a fine-tooth comb before production. + if (Preferences::GetBool("layout.css.width-and-height-map-to-aspect-ratio.enabled") && + aMapAspectRatio && aWidth && aHeight) { + Maybe w; + if (aWidth->Type() == nsAttrValue::eInteger) { + w.emplace(aWidth->GetIntegerValue()); + } else if (aWidth->Type() == nsAttrValue::eDoubleValue) { + w.emplace(aWidth->GetDoubleValue()); + } + + Maybe h; + if (aHeight->Type() == nsAttrValue::eInteger) { + h.emplace(aHeight->GetIntegerValue()); + } else if (aHeight->Type() == nsAttrValue::eDoubleValue) { + h.emplace(aHeight->GetDoubleValue()); + } + + if (w && h && *w != 0 && *h != 0) { + nsCSSValue* aspect_ratio = aData->ValueForAspectRatio(); + aspect_ratio->SetFloatValue((float(*w) / float(*h)), eCSSUnit_Number); + } } } diff --git a/dom/html/nsGenericHTMLElement.h b/dom/html/nsGenericHTMLElement.h index c9169df117..8412ea0dc8 100644 --- a/dom/html/nsGenericHTMLElement.h +++ b/dom/html/nsGenericHTMLElement.h @@ -702,10 +702,12 @@ public: * * @param aAttributes the list of attributes to map * @param aData the returned rule data [INOUT] + * @param aMapAspectRatio map width and height attributes on aspect-ratio * @see GetAttributeMappingFunction */ static void MapImageSizeAttributesInto(const nsMappedAttributes* aAttributes, - nsRuleData* aData); + nsRuleData* aData, + bool = false); /** * Helper to map the background attribute * into a style struct. diff --git a/layout/generic/crashtests/1633434.html b/layout/generic/crashtests/1633434.html new file mode 100644 index 0000000000..8a60b2072c --- /dev/null +++ b/layout/generic/crashtests/1633434.html @@ -0,0 +1,15 @@ + + + + + + diff --git a/layout/generic/crashtests/crashtests.list b/layout/generic/crashtests/crashtests.list index a6737fd7a4..d16e0984c2 100644 --- a/layout/generic/crashtests/crashtests.list +++ b/layout/generic/crashtests/crashtests.list @@ -644,3 +644,4 @@ load 1304441.html load 1316649.html load 1381134.html load 1381134-2.html +load 1633434.html diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 365b7810b3..3208a3233e 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -14,6 +14,7 @@ #include "mozilla/gfx/2D.h" #include "mozilla/gfx/Helpers.h" #include "mozilla/gfx/PathHelpers.h" +#include "mozilla/dom/HTMLImageElement.h" #include "mozilla/MouseEvents.h" #include "mozilla/Unused.h" @@ -229,26 +230,26 @@ nsImageFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext) { nsAtomicContainerFrame::DidSetStyleContext(aOldStyleContext); - if (!mImage) { - // We'll pick this change up whenever we do get an image. - return; - } - nsStyleImageOrientation newOrientation = StyleVisibility()->mImageOrientation; // We need to update our orientation either if we had no style context before // because this is the first time it's been set, or if the image-orientation // property changed from its previous value. bool shouldUpdateOrientation = - !aOldStyleContext || - aOldStyleContext->StyleVisibility()->mImageOrientation != newOrientation; + mImage && + (!aOldStyleContext || + aOldStyleContext->StyleVisibility()->mImageOrientation != newOrientation); if (shouldUpdateOrientation) { nsCOMPtr image(mImage->Unwrap()); mImage = nsLayoutUtils::OrientImage(image, newOrientation); - UpdateIntrinsicSize(mImage); - UpdateIntrinsicRatio(mImage); + UpdateIntrinsicSize(); + UpdateIntrinsicRatio(); + } else if (!aOldStyleContext || + aOldStyleContext->StylePosition()->mAspectRatio != + StylePosition()->mAspectRatio) { + UpdateIntrinsicRatio(); } } @@ -286,50 +287,114 @@ nsImageFrame::Init(nsIContent* aContent, p->AdjustPriority(-1); } -bool -nsImageFrame::UpdateIntrinsicSize(imgIContainer* aImage) +// 2020-07-14 (RealityRipple) Firefox is doing this completely differently +// because of loading="lazy" support and the StyleDisplay()->IsContainSize() +// property. Double-check all of this for problems. + +static IntrinsicSize +ComputeIntrinsicSize(imgIContainer* aImage, + bool aUseMappedRatio, + const nsImageFrame& aFrame) { - NS_PRECONDITION(aImage, "null image"); - if (!aImage) - return false; - - IntrinsicSize oldIntrinsicSize = mIntrinsicSize; - mIntrinsicSize = IntrinsicSize(); - - // Set intrinsic size to match aImage's reported intrinsic width & height. - nsSize intrinsicSize; - if (NS_SUCCEEDED(aImage->GetIntrinsicSize(&intrinsicSize))) { - // If the image has no intrinsic width, intrinsicSize.width will be -1, and - // we can leave mIntrinsicSize.width at its default value of eStyleUnit_None. - // Otherwise we use intrinsicSize.width. Height works the same way. - if (intrinsicSize.width != -1) - mIntrinsicSize.width.SetCoordValue(intrinsicSize.width); - if (intrinsicSize.height != -1) - mIntrinsicSize.height.SetCoordValue(intrinsicSize.height); - } else { - // Failure means that the image hasn't loaded enough to report a result. We - // treat this case as if the image's intrinsic size was 0x0. - mIntrinsicSize.width.SetCoordValue(0); - mIntrinsicSize.height.SetCoordValue(0); + // When 'contain: size' is implemented, make sure to check for it. +/* + const ComputedStyle& style = *aFrame.Style(); + if (style.StyleDisplay()->IsContainSize()) { + return AspectRatio(); + } + */ + nsSize size; + IntrinsicSize intrinsicSize; + if (aImage && NS_SUCCEEDED(aImage->GetIntrinsicSize(&size))) { + if (size.width != -1) + intrinsicSize.width.SetCoordValue(size.width); + if (size.height != -1) + intrinsicSize.height.SetCoordValue(size.height); + return intrinsicSize; } - return mIntrinsicSize != oldIntrinsicSize; + // If broken images should ever lose their size + /* + if (aFrame.ShouldShowBrokenImageIcon()) { + nscoord edgeLengthToUse = nsPresContext::CSSPixelsToAppUnits( + ICON_SIZE + (2 * (ICON_PADDING + ALT_BORDER_WIDTH))); + intrinsicSize.width.SetCoordValue(edgeLengthToUse); + intrinsicSize.height.SetCoordValue(edgeLengthToUse); + return intrinsicSize; + } + */ + + if (aUseMappedRatio && aFrame.StylePosition()->mAspectRatio != 0.0f) { + return IntrinsicSize(); + } + + intrinsicSize.width.SetCoordValue(0); + intrinsicSize.height.SetCoordValue(0); + return intrinsicSize; +} + +// For compat reasons, see bug 1602047, we don't use the intrinsic ratio from +// width="" and height="" for images with no src attribute (no request). +// +// If ever gets implemented, this will need to check for it. +bool nsImageFrame::ShouldUseMappedAspectRatio() const { + nsCOMPtr currentRequest; + nsCOMPtr imageLoader = do_QueryInterface(mContent); + if (imageLoader) { + imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST, + getter_AddRefs(currentRequest)); + } + if (!!currentRequest) { + return true; + } + // TODO(emilio): Investigate the compat situation of the above check, maybe we + // can just check for empty src attribute or something... + auto* image = static_cast(mContent); + return image && image->IsAwaitingLoad(); } bool -nsImageFrame::UpdateIntrinsicRatio(imgIContainer* aImage) +nsImageFrame::UpdateIntrinsicSize() { - NS_PRECONDITION(aImage, "null image"); + IntrinsicSize oldIntrinsicSize = mIntrinsicSize; + mIntrinsicSize = ComputeIntrinsicSize(mImage, ShouldUseMappedAspectRatio(), *this); + return mIntrinsicSize != oldIntrinsicSize; +} - if (!aImage) - return false; +static AspectRatio +ComputeAspectRatio(imgIContainer* aImage, + bool aUseMappedRatio, + const nsImageFrame& aFrame) +{ + // When 'contain: size' is implemented, make sure to check for it. +/* + const ComputedStyle& style = *aFrame.Style(); + if (style.StyleDisplay()->IsContainSize()) { + return AspectRatio(); + } + */ + if (aImage) { + AspectRatio fromImage; + if (NS_SUCCEEDED(aImage->GetIntrinsicRatio(&fromImage))) { + return fromImage; + } + } + if (aUseMappedRatio && aFrame.StylePosition()->mAspectRatio != 0.0f) { + return AspectRatio(aFrame.StylePosition()->mAspectRatio); + } + if (aFrame.ShouldShowBrokenImageIcon()) { + return AspectRatio(1.0f); + } + return AspectRatio(); +} + +bool +nsImageFrame::UpdateIntrinsicRatio() +{ AspectRatio oldIntrinsicRatio = mIntrinsicRatio; - - // Set intrinsic ratio to match aImage's reported intrinsic ratio. - if (NS_FAILED(aImage->GetIntrinsicRatio(&mIntrinsicRatio))) - mIntrinsicRatio = AspectRatio(); - + mIntrinsicRatio = + ComputeAspectRatio(mImage, ShouldUseMappedAspectRatio(), *this); return mIntrinsicRatio != oldIntrinsicRatio; } @@ -541,30 +606,38 @@ nsImageFrame::OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage) return NS_OK; } - bool intrinsicSizeChanged = false; + UpdateImage(aRequest, aImage); + return NS_OK; +} + +void nsImageFrame::UpdateImage(imgIRequest* aRequest, imgIContainer* aImage) { + MOZ_ASSERT(aRequest); if (SizeIsAvailable(aRequest)) { // This is valid and for the current request, so update our stored image // container, orienting according to our style. - mImage = nsLayoutUtils::OrientImage(aImage, StyleVisibility()->mImageOrientation); - - intrinsicSizeChanged = UpdateIntrinsicSize(mImage); - intrinsicSizeChanged = UpdateIntrinsicRatio(mImage) || intrinsicSizeChanged; + mImage = nsLayoutUtils::OrientImage(aImage, + StyleVisibility()->mImageOrientation); + MOZ_ASSERT(mImage); } else { // We no longer have a valid image, so release our stored image container. mImage = mPrevImage = nullptr; - - // Have to size to 0,0 so that GetDesiredSize recalculates the size. - mIntrinsicSize.width.SetCoordValue(0); - mIntrinsicSize.height.SetCoordValue(0); - mIntrinsicRatio = AspectRatio(); - intrinsicSizeChanged = true; + } + // NOTE(emilio): Intentionally using `|` instead of `||` to avoid + // short-circuiting. + bool intrinsicSizeChanged = + UpdateIntrinsicSize() | UpdateIntrinsicRatio(); + if (!(mState & IMAGE_GOTINITIALREFLOW)) { + return; } - if (intrinsicSizeChanged && (mState & IMAGE_GOTINITIALREFLOW)) { + // We're going to need to repaint now either way. + InvalidateFrame(); + + if (intrinsicSizeChanged) { // Now we need to reflow if we have an unconstrained size and have - // already gotten the initial reflow + // already gotten the initial reflow. if (!(mState & IMAGE_SIZECONSTRAINED)) { - nsIPresShell *presShell = presContext->GetPresShell(); + nsIPresShell *presShell = PresContext()->GetPresShell(); NS_ASSERTION(presShell, "No PresShell."); if (presShell) { presShell->FrameNeedsReflow(this, nsIPresShell::eStyleChange, @@ -578,8 +651,6 @@ nsImageFrame::OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage) mPrevImage = nullptr; } - - return NS_OK; } nsresult @@ -654,45 +725,9 @@ nsImageFrame::NotifyNewCurrentRequest(imgIRequest *aRequest, { nsCOMPtr image; aRequest->GetImage(getter_AddRefs(image)); - NS_ASSERTION(image || NS_FAILED(aStatus), "Successful load with no container?"); - - // May have to switch sizes here! - bool intrinsicSizeChanged = true; - if (NS_SUCCEEDED(aStatus) && image && SizeIsAvailable(aRequest)) { - // Update our stored image container, orienting according to our style. - mImage = nsLayoutUtils::OrientImage(image, StyleVisibility()->mImageOrientation); - - intrinsicSizeChanged = UpdateIntrinsicSize(mImage); - intrinsicSizeChanged = UpdateIntrinsicRatio(mImage) || intrinsicSizeChanged; - } else { - // We no longer have a valid image, so release our stored image container. - mImage = mPrevImage = nullptr; - - // Have to size to 0,0 so that GetDesiredSize recalculates the size - mIntrinsicSize.width.SetCoordValue(0); - mIntrinsicSize.height.SetCoordValue(0); - mIntrinsicRatio = AspectRatio(); - } - - if (mState & IMAGE_GOTINITIALREFLOW) { // do nothing if we haven't gotten the initial reflow yet - if (intrinsicSizeChanged) { - if (!(mState & IMAGE_SIZECONSTRAINED)) { - nsIPresShell *presShell = PresContext()->GetPresShell(); - if (presShell) { - presShell->FrameNeedsReflow(this, nsIPresShell::eStyleChange, - NS_FRAME_IS_DIRTY); - } - } else { - // We've already gotten the initial reflow, and our size hasn't changed, - // so we're ready to request a decode. - MaybeDecodeForPredictedSize(); - } - - mPrevImage = nullptr; - } - // Update border+content to account for image change - InvalidateFrame(); - } + NS_ASSERTION(image || NS_FAILED(aStatus), + "Successful load with no container?"); + UpdateImage(aRequest, image); } void @@ -786,32 +821,27 @@ bool nsImageFrame::ShouldShowBrokenImageIcon() const void nsImageFrame::EnsureIntrinsicSizeAndRatio() { + // When 'contain: size' is implemented, make sure to check for it. +/* + if (StyleDisplay()->IsContainSize()) { + // If we have 'contain:size', then our intrinsic size and ratio are 0,0 + // regardless of what our underlying image may think. + mIntrinsicSize = IntrinsicSize(0, 0); + mIntrinsicRatio = AspectRatio(); + return; + } + */ + // If mIntrinsicSize.width and height are 0, then we need to update from the // image container. - if (mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord && + if (!(mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord && mIntrinsicSize.width.GetCoordValue() == 0 && mIntrinsicSize.height.GetUnit() == eStyleUnit_Coord && - mIntrinsicSize.height.GetCoordValue() == 0) { - - if (mImage) { - UpdateIntrinsicSize(mImage); - UpdateIntrinsicRatio(mImage); - } else { - // Image request is null or image size not known. - if (!(GetStateBits() & NS_FRAME_GENERATED_CONTENT)) { - // Likely an invalid image. Check if we should display it as broken. - if (ShouldShowBrokenImageIcon()) { - // Invalid image specified. make the image big enough for the "broken" icon - nscoord edgeLengthToUse = - nsPresContext::CSSPixelsToAppUnits( - ICON_SIZE + (2 * (ICON_PADDING + ALT_BORDER_WIDTH))); - mIntrinsicSize.width.SetCoordValue(edgeLengthToUse); - mIntrinsicSize.height.SetCoordValue(edgeLengthToUse); - mIntrinsicRatio = AspectRatio(1.0f); - } - } - } + mIntrinsicSize.height.GetCoordValue() == 0)) { + return; } + UpdateIntrinsicSize(); + UpdateIntrinsicRatio(); } /* virtual */ diff --git a/layout/generic/nsImageFrame.h b/layout/generic/nsImageFrame.h index 2414d89dfc..5e9b672747 100644 --- a/layout/generic/nsImageFrame.h +++ b/layout/generic/nsImageFrame.h @@ -273,21 +273,19 @@ private: void GetDocumentCharacterSet(nsACString& aCharset) const; bool ShouldDisplaySelection(); + // Whether the image frame should use the mapped aspect ratio from width="" + // and height="". + bool ShouldUseMappedAspectRatio() const; + /** * Recalculate mIntrinsicSize from the image. - * - * @return whether aImage's size did _not_ - * match our previous intrinsic size. */ - bool UpdateIntrinsicSize(imgIContainer* aImage); + bool UpdateIntrinsicSize(); /** * Recalculate mIntrinsicRatio from the image. - * - * @return whether aImage's ratio did _not_ - * match our previous intrinsic ratio. */ - bool UpdateIntrinsicRatio(imgIContainer* aImage); + bool UpdateIntrinsicRatio(); /** * This function calculates the transform for converting between @@ -307,6 +305,12 @@ private: */ bool IsPendingLoad(imgIRequest* aRequest) const; + /** + * Updates mImage based on the current image request (cannot be null), and the + * image passed in (can be null), and invalidate layout and paint as needed. + */ + void UpdateImage(imgIRequest* aRequest, imgIContainer* aImage); + /** * Function to convert a dirty rect in the source image to a dirty * rect for the image frame. diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index 411f982a4e..44bd44cef4 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -470,6 +470,17 @@ CSS_PROP_DISPLAY( kAppearanceKTable, CSS_PROP_NO_OFFSET, eStyleAnimType_Discrete) +CSS_PROP_POSITION( + aspect-ratio, + aspect_ratio, + AspectRatio, + CSS_PROPERTY_INTERNAL | + CSS_PROPERTY_PARSE_INACCESSIBLE, + "", + VARIANT_NUMBER, + nullptr, + offsetof(nsStylePosition, mAspectRatio), + eStyleAnimType_None) CSS_PROP_DISPLAY( backface-visibility, backface_visibility, diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index a0f65c069c..1a451a2ef4 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -8544,6 +8544,12 @@ nsRuleNode::ComputePositionData(void* aStartStruct, SETCOORD_UNSET_INITIAL, aContext, mPresContext, conditions); + // aspect-ratio: float, initial + SetFactor(*aRuleData->ValueForAspectRatio(), + pos->mAspectRatio, conditions, + parentPos->mAspectRatio, 0.0f, + SETFCT_UNSET_INITIAL | SETFCT_POSITIVE | SETFCT_NONE); + // box-sizing: enum, inherit, initial SetValue(*aRuleData->ValueForBoxSizing(), pos->mBoxSizing, conditions, diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 9270f29600..3b19a44180 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -1408,6 +1408,7 @@ nsStylePosition::nsStylePosition(StyleStructContext aContext) , mGridAutoColumnsMax(eStyleUnit_Auto) , mGridAutoRowsMin(eStyleUnit_Auto) , mGridAutoRowsMax(eStyleUnit_Auto) + , mAspectRatio(0.0f) , mGridAutoFlow(NS_STYLE_GRID_AUTO_FLOW_ROW) , mBoxSizing(StyleBoxSizing::Content) , mAlignContent(NS_STYLE_ALIGN_NORMAL) @@ -1466,6 +1467,7 @@ nsStylePosition::nsStylePosition(const nsStylePosition& aSource) , mGridAutoColumnsMax(aSource.mGridAutoColumnsMax) , mGridAutoRowsMin(aSource.mGridAutoRowsMin) , mGridAutoRowsMax(aSource.mGridAutoRowsMax) + , mAspectRatio(aSource.mAspectRatio) , mGridAutoFlow(aSource.mGridAutoFlow) , mBoxSizing(aSource.mBoxSizing) , mAlignContent(aSource.mAlignContent) @@ -1636,6 +1638,11 @@ nsStylePosition::CalcDifference(const nsStylePosition& aNewData, if (isVertical ? heightChanged : widthChanged) { hint |= nsChangeHint_ReflowHintsForISizeChange; } + + if (mAspectRatio != aNewData.mAspectRatio) { + hint |= nsChangeHint_ReflowHintsForISizeChange | + nsChangeHint_ReflowHintsForBSizeChange; + } } else { if (widthChanged || heightChanged) { hint |= nsChangeHint_NeutralChange; diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index b257c6bb54..4bda817ddb 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -1815,6 +1815,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition nsStyleCoord mGridAutoColumnsMax; // [reset] coord, percent, enum, calc, flex nsStyleCoord mGridAutoRowsMin; // [reset] coord, percent, enum, calc, flex nsStyleCoord mGridAutoRowsMax; // [reset] coord, percent, enum, calc, flex + float mAspectRatio; // [reset] float uint8_t mGridAutoFlow; // [reset] enumerated. See nsStyleConsts.h mozilla::StyleBoxSizing mBoxSizing; // [reset] see nsStyleConsts.h diff --git a/layout/style/test/ListCSSProperties.cpp b/layout/style/test/ListCSSProperties.cpp index 718032f619..9f727104b6 100644 --- a/layout/style/test/ListCSSProperties.cpp +++ b/layout/style/test/ListCSSProperties.cpp @@ -106,6 +106,7 @@ const char *gInaccessibleProperties[] = { "-x-span", "-x-system-font", "-x-text-zoom", + "aspect-ratio", // for now. "-moz-control-character-visibility", "-moz-script-level", // parsed by UA sheets only "-moz-script-size-multiplier", diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 8cfac74a32..89da97f39f 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4819,6 +4819,12 @@ pref("media.ondevicechange.fakeDeviceChangeEvent.enabled", false); // those platforms we don't handle touch events anyway so it's conceptually // a no-op. pref("layout.css.touch_action.enabled", true); + +// WHATWG computed intrinsic aspect ratio for an img element +// https://html.spec.whatwg.org/multipage/rendering.html#attributes-for-embedded-content-and-images +// Are the width and height attributes on image-like elements mapped to the +// internal-for-now aspect-ratio property? +pref("layout.css.width-and-height-map-to-aspect-ratio.enabled", false); // Enables some assertions in nsStyleContext that are too expensive // for general use, but might be useful to enable for specific tests. diff --git a/testing/web-platform/tests/css-backgrounds/background-size-cover-003-ref.html b/testing/web-platform/tests/css-backgrounds/background-size-cover-003-ref.html new file mode 100644 index 0000000000..bd965cfecf --- /dev/null +++ b/testing/web-platform/tests/css-backgrounds/background-size-cover-003-ref.html @@ -0,0 +1,21 @@ + +CSS Test Reference + +
+
+
diff --git a/testing/web-platform/tests/css-backgrounds/background-size-cover-003.html b/testing/web-platform/tests/css-backgrounds/background-size-cover-003.html new file mode 100644 index 0000000000..4d2b6b125e --- /dev/null +++ b/testing/web-platform/tests/css-backgrounds/background-size-cover-003.html @@ -0,0 +1,38 @@ + +CSS Test: background-size: cover with zero-sized background positioning area. + + + + + + + +
+
+
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio.html new file mode 100644 index 0000000000..9ae87be9cd --- /dev/null +++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio.html @@ -0,0 +1,60 @@ + +Image width and height attributes are used to infer aspect-ratio + + + + + + + + + From c02e424911ee58eb6961149932bd6d47b5b5248f Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 7 Aug 2020 14:29:41 -0700 Subject: [PATCH 3/7] Issue #1620 - Remove Development Comments --- dom/html/nsGenericHTMLElement.cpp | 2 -- layout/generic/nsImageFrame.cpp | 4 ---- layout/svg/nsSVGOuterSVGFrame.cpp | 16 ++++------------ 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp index afc76ee31c..5af578b2d5 100644 --- a/dom/html/nsGenericHTMLElement.cpp +++ b/dom/html/nsGenericHTMLElement.cpp @@ -1480,8 +1480,6 @@ nsGenericHTMLElement::MapImageSizeAttributesInto(const nsMappedAttributes* aAttr } } - // 2020-07-15 (RealityRipple) Much of this is a guess based on a few sources. - // Please go over this with a fine-tooth comb before production. if (Preferences::GetBool("layout.css.width-and-height-map-to-aspect-ratio.enabled") && aMapAspectRatio && aWidth && aHeight) { Maybe w; diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 3208a3233e..d6f47f2e42 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -287,10 +287,6 @@ nsImageFrame::Init(nsIContent* aContent, p->AdjustPriority(-1); } -// 2020-07-14 (RealityRipple) Firefox is doing this completely differently -// because of loading="lazy" support and the StyleDisplay()->IsContainSize() -// property. Double-check all of this for problems. - static IntrinsicSize ComputeIntrinsicSize(imgIContainer* aImage, bool aUseMappedRatio, diff --git a/layout/svg/nsSVGOuterSVGFrame.cpp b/layout/svg/nsSVGOuterSVGFrame.cpp index d8cd2cb771..3f68245e22 100644 --- a/layout/svg/nsSVGOuterSVGFrame.cpp +++ b/layout/svg/nsSVGOuterSVGFrame.cpp @@ -234,22 +234,14 @@ nsSVGOuterSVGFrame::GetIntrinsicSize() /* virtual */ AspectRatio nsSVGOuterSVGFrame::GetIntrinsicRatio() -{ - // 2020-07-14 (RealityRipple) Firefox Uses a new IsReplacedAndContainSize(this) - // function call [Line 96-99 on trunk]. +{ + // When 'contain: size' is implemented, make sure to check for it. /* - static inline bool IsReplacedAndContainSize(const nsSVGOuterSVGFrame* aFrame) { - return aFrame->GetContent->GetParent() && - aFrame->StyleDisplay()->IsContainSize(); - } - */ - // but since contain: size doesn't exist in Pale Moon yet... -/* - if (IsReplacedAndContainSize(this)) { + if (this->GetContent->GetParent() && this->StyleDisplay()->IsContainSize()) { return AspectRatio(); } */ - + // We only have an intrinsic size/ratio if our width and height attributes // are both specified and set to non-percentage values, or we have a viewBox // rect: http://www.w3.org/TR/SVGMobile12/coords.html#IntrinsicSizing From 9f48a59946881ce7dd00981e8e04fa34087451a9 Mon Sep 17 00:00:00 2001 From: Andy Date: Fri, 7 Aug 2020 14:32:59 -0700 Subject: [PATCH 4/7] Issue #1620 - Enable Intrinsic Ratio by Default A simpler name feels so much cleaner. --- dom/html/nsGenericHTMLElement.cpp | 2 +- modules/libpref/init/all.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dom/html/nsGenericHTMLElement.cpp b/dom/html/nsGenericHTMLElement.cpp index 5af578b2d5..35ce8533bf 100644 --- a/dom/html/nsGenericHTMLElement.cpp +++ b/dom/html/nsGenericHTMLElement.cpp @@ -1480,7 +1480,7 @@ nsGenericHTMLElement::MapImageSizeAttributesInto(const nsMappedAttributes* aAttr } } - if (Preferences::GetBool("layout.css.width-and-height-map-to-aspect-ratio.enabled") && + if (Preferences::GetBool("layout.css.intrinsic-aspect-ratio.enabled") && aMapAspectRatio && aWidth && aHeight) { Maybe w; if (aWidth->Type() == nsAttrValue::eInteger) { diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 89da97f39f..75174b1f8c 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4824,7 +4824,7 @@ pref("layout.css.touch_action.enabled", true); // https://html.spec.whatwg.org/multipage/rendering.html#attributes-for-embedded-content-and-images // Are the width and height attributes on image-like elements mapped to the // internal-for-now aspect-ratio property? -pref("layout.css.width-and-height-map-to-aspect-ratio.enabled", false); +pref("layout.css.intrinsic-aspect-ratio.enabled", true); // Enables some assertions in nsStyleContext that are too expensive // for general use, but might be useful to enable for specific tests. From 07929daad2882f768f10fe03085fc58da0ad0489 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Mon, 10 Aug 2020 12:13:10 +0200 Subject: [PATCH 5/7] [CSS] Alias -webkit-appearance for compatibility reasons Since this is supported as an alias by Firefox and Edge for the same reasons and we have websites using this to (attempt to) override the system-provided styling with their own, leaving out the only supported keyword we'd otherwise have (with -moz- prefix) but still stating -webkit-. TODO: unprefix this completely and make the vendor prefixes aliases. --- layout/style/nsCSSPropAliasList.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/layout/style/nsCSSPropAliasList.h b/layout/style/nsCSSPropAliasList.h index f7938af9ed..9ec71b2cf8 100644 --- a/layout/style/nsCSSPropAliasList.h +++ b/layout/style/nsCSSPropAliasList.h @@ -264,6 +264,11 @@ CSS_PROP_ALIAS(-webkit-animation-timing-function, WebkitAnimationTimingFunction, WEBKIT_PREFIX_PREF) +CSS_PROP_ALIAS(-webkit-appearance, + appearance, + WebkitAppearance, + WEBKIT_PREFIX_PREF) + CSS_PROP_ALIAS(-webkit-filter, filter, WebkitFilter, From aa1210518c89a8ad270e68474fdab036ed5b71de Mon Sep 17 00:00:00 2001 From: Pale Moon Date: Sun, 9 Aug 2020 21:58:53 +0200 Subject: [PATCH 6/7] [Pale-Moon] Update user-agent overrides and reorganize. --- .../branding/shared/pref/uaoverrides.inc | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/application/palemoon/branding/shared/pref/uaoverrides.inc b/application/palemoon/branding/shared/pref/uaoverrides.inc index 44d4a4b80d..d6ba789edc 100644 --- a/application/palemoon/branding/shared/pref/uaoverrides.inc +++ b/application/palemoon/branding/shared/pref/uaoverrides.inc @@ -19,38 +19,30 @@ pref("@GUAO_PREF@.addons.mozilla.org","Mozilla/5.0 (%OS_SLICE% rv:@GRE_VERSION@) @GRE_DATE_SLICE@ @PM_SLICE@"); // Required for domains that are unresponsive to requests from users (or likely to be) -pref("@GUAO_PREF@.live.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)"); -pref("@GUAO_PREF@.msn.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)"); -pref("@GUAO_PREF@.bing.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)"); -pref("@GUAO_PREF@.outlook.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)"); -pref("@GUAO_PREF@.web.de","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)"); pref("@GUAO_PREF@.aol.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)"); -pref("@GUAO_PREF@.calendar.yahoo.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)"); +pref("@GUAO_PREF@.bing.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)"); +pref("@GUAO_PREF@.chase.com","Mozilla/5.0 (%OS_SLICE% rv:79.0) @GK_SLICE@ Firefox/79.0"); +pref("@GUAO_PREF@.dropbox.com","Mozilla/5.0 (%OS_SLICE% rv:99.9) @GK_SLICE@ Firefox/99.9 (Pale Moon)"); pref("@GUAO_PREF@.google.com","Mozilla/5.0 (%OS_SLICE% rv:71.0) @GK_SLICE@ Firefox/71.0 @PM_SLICE@"); pref("@GUAO_PREF@.googlevideos.com","Mozilla/5.0 (%OS_SLICE% rv:38.9) @GK_SLICE@ @GRE_VERSION_SLICE@ Firefox/38.9 @PM_SLICE@"); pref("@GUAO_PREF@.gstatic.com","Mozilla/5.0 (%OS_SLICE% rv:71.0) @GK_SLICE@ Firefox/71.0 @PM_SLICE@"); +pref("@GUAO_PREF@.live.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)"); +pref("@GUAO_PREF@.msn.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)"); +pref("@GUAO_PREF@.patientaccess.com","Mozilla/5.0 (%OS_SLICE% rv:60.0) @GK_SLICE@ Firefox/60.0 @PM_SLICE@"); +pref("@GUAO_PREF@.outlook.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)"); +pref("@GUAO_PREF@.web.de","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)"); pref("@GUAO_PREF@.yahoo.com","Mozilla/5.0 (%OS_SLICE% rv:99.9) @GK_SLICE@ Firefox/99.9 (Pale Moon)"); +pref("@GUAO_PREF@.calendar.yahoo.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)"); pref("@GUAO_PREF@.youtube.com","Mozilla/5.0 (%OS_SLICE% rv:60.0) @GK_SLICE@ Firefox/60.0 @PM_SLICE@"); pref("@GUAO_PREF@.gaming.youtube.com","Mozilla/5.0 (%OS_SLICE% rv:42.0) @GK_SLICE@ Firefox/42.0"); -pref("@GUAO_PREF@.dropbox.com","Mozilla/5.0 (%OS_SLICE% rv:99.9) @GK_SLICE@ Firefox/99.9 (Pale Moon)"); -pref("@GUAO_PREF@.patientaccess.com","Mozilla/5.0 (%OS_SLICE% rv:60.0) @GK_SLICE@ Firefox/60.0 @PM_SLICE@"); -pref("@GUAO_PREF@.players.brightcove.net","Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko"); - -// The never-ending Facebook debacle... -pref("@GUAO_PREF@.facebook.com","Mozilla/5.0 (%OS_SLICE% rv:99.9) @GK_SLICE@ Firefox/99.9 (Pale Moon)"); -pref("@GUAO_PREF@.fbcdn.net","Mozilla/5.0 (%OS_SLICE% rv:99.9) @GK_SLICE@ Firefox/99.9 (Pale Moon)"); - - -// UA-Sniffing domains below are pending responses from their operators - temp workaround -pref("@GUAO_PREF@.chase.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@"); // For Amazon Prime videos pref("@GUAO_PREF@.www.amazon.com","Mozilla/5.0 (%OS_SLICE% rv:45.9) @GK_SLICE@ Firefox/45.9 (Pale Moon)"); // Soundcloud uses Firefox-exclusive combinations of code. Never pass Firefox slice. pref("@GUAO_PREF@.soundcloud.com","Mozilla/5.0 (%OS_SLICE% rv:@GRE_VERSION@) @GRE_DATE_SLICE@ @PM_SLICE@"); // Daily motion only likes strict Firefox UAs pref("@GUAO_PREF@.dailymotion.com","Mozilla/5.0 (%OS_SLICE% rv:52.0) @GK_SLICE@ Firefox/52.0"); - +pref("@GUAO_PREF@.players.brightcove.net","Mozilla/5.0 (Windows NT 6.1; Trident/7.0; rv:11.0) like Gecko"); // The following requires native mode. Or it blocks.. "too old firefox", breakage, etc. pref("@GUAO_PREF@.deviantart.com","Mozilla/5.0 (%OS_SLICE% rv:@GRE_VERSION@) @GRE_DATE_SLICE@ @PM_SLICE@"); @@ -66,8 +58,8 @@ pref("@GUAO_PREF@.github.com","Mozilla/5.0 (%OS_SLICE% rv:@GRE_VERSION@) @GRE_DA pref("@GUAO_PREF@.humblebundle.com","Mozilla/5.0 (%OS_SLICE% rv:@GK_VERSION@) @GK_SLICE@ @FX_SLICE@ (Pale Moon)"); pref("@GUAO_PREF@.privat24.ua","Mozilla/5.0 (%OS_SLICE% rv:38.0) @GK_SLICE@ Firefox/38.0"); pref("@GUAO_PREF@.citi.com","Mozilla/5.0 (%OS_SLICE% rv:57.0) @GK_SLICE@ Firefox/57.0 (Pale Moon)"); -pref("@GUAO_PREF@.netflix.com","Mozilla/5.0 (%OS_SLICE% rv:45.9) @GK_SLICE@ Firefox/45.9"); -pref("@GUAO_PREF@.netflximg.net","Mozilla/5.0 (%OS_SLICE% rv:45.9) @GK_SLICE@ Firefox/45.9"); +pref("@GUAO_PREF@.netflix.com","Mozilla/5.0 (Windows NT 6.1; rv:45.9) @GK_SLICE@ Firefox/45.9"); +pref("@GUAO_PREF@.netflximg.net","Mozilla/5.0 (Windows NT 6.1; rv:45.9) @GK_SLICE@ Firefox/45.9"); // UA-sniffing domains that are "app/vendor-specific" and do not like Pale Moon pref("@GUAO_PREF@.web.whatsapp.com","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"); From 194f96855e54c068bcaaeb77d7cdf74a5ab0fc46 Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Tue, 11 Aug 2020 20:43:26 +0800 Subject: [PATCH 7/7] [Pale-Moon] Issue #1824 - Fix broken page style menu selection for alternative style sheets Missing `return` in anonymous function which checks if the given style sheet title is present in the document's style sheet array. --- application/palemoon/base/content/browser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/palemoon/base/content/browser.js b/application/palemoon/base/content/browser.js index 71e5320a75..bb5801f894 100644 --- a/application/palemoon/base/content/browser.js +++ b/application/palemoon/base/content/browser.js @@ -5637,7 +5637,7 @@ var gPageStyleMenu = { _stylesheetInFrame: function(frame, title) { return Array.some(frame.document.styleSheets, function(stylesheet) { - stylesheet.title == title + return stylesheet.title == title; }); },