From b241a84d884293e1ce49a79c75e362c02c0899f9 Mon Sep 17 00:00:00 2001 From: yami <34216515+kn-yami@users.noreply.github.com> Date: Sun, 16 Dec 2018 16:17:20 +0100 Subject: issue #908 - implement missing parts of CSS mask --- layout/base/nsLayoutUtils.cpp | 127 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 1 deletion(-) (limited to 'layout/base/nsLayoutUtils.cpp') diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 19200d5a7..f0341f9ef 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -117,6 +117,7 @@ #include "mozilla/StyleSetHandle.h" #include "mozilla/StyleSetHandleInlines.h" #include "RegionBuilder.h" +#include "SVGSVGElement.h" #ifdef MOZ_XUL #include "nsXULPopupManager.h" @@ -6935,7 +6936,7 @@ nsLayoutUtils::GetFrameTransparency(nsIFrame* aBackgroundFrame, const nsStyleBackground* bg = bgSC->StyleBackground(); if (NS_GET_A(bg->mBackgroundColor) < 255 || // bottom layer's clip is used for the color - bg->BottomLayer().mClip != NS_STYLE_IMAGELAYER_CLIP_BORDER) + bg->BottomLayer().mClip != StyleGeometryBox::Border) return eTransparencyTransparent; return eTransparencyOpaque; } @@ -9293,3 +9294,127 @@ nsLayoutUtils::IsInvisibleBreak(nsINode* aNode, nsIFrame** aNextLineFrame) return lineNonEmpty; } + +static nsRect +ComputeSVGReferenceRect(nsIFrame* aFrame, + StyleGeometryBox aGeometryBox) +{ + MOZ_ASSERT(aFrame->GetContent()->IsSVGElement()); + nsRect r; + + // For SVG elements without associated CSS layout box, the used value for + // content-box, padding-box, border-box and margin-box is fill-box. + switch (aGeometryBox) { + case StyleGeometryBox::Stroke: { + // XXX Bug 1299876 + // The size of srtoke-box is not correct if this graphic element has + // specific stroke-linejoin or stroke-linecap. + gfxRect bbox = nsSVGUtils::GetBBox(aFrame, + nsSVGUtils::eBBoxIncludeFill | nsSVGUtils::eBBoxIncludeStroke); + r = nsLayoutUtils::RoundGfxRectToAppRect(bbox, + nsPresContext::AppUnitsPerCSSPixel()); + break; + } + case StyleGeometryBox::View: { + nsIContent* content = aFrame->GetContent(); + nsSVGElement* element = static_cast(content); + SVGSVGElement* svgElement = element->GetCtx(); + MOZ_ASSERT(svgElement); + + if (svgElement && svgElement->HasViewBoxRect()) { + // If a ‘viewBox‘ attribute is specified for the SVG viewport creating + // element: + // 1. The reference box is positioned at the origin of the coordinate + // system established by the ‘viewBox‘ attribute. + // 2. The dimension of the reference box is set to the width and height + // values of the ‘viewBox‘ attribute. + nsSVGViewBox* viewBox = svgElement->GetViewBox(); + const nsSVGViewBoxRect& value = viewBox->GetAnimValue(); + r = nsRect(nsPresContext::CSSPixelsToAppUnits(value.x), + nsPresContext::CSSPixelsToAppUnits(value.y), + nsPresContext::CSSPixelsToAppUnits(value.width), + nsPresContext::CSSPixelsToAppUnits(value.height)); + } else { + // No viewBox is specified, uses the nearest SVG viewport as reference + // box. + svgFloatSize viewportSize = svgElement->GetViewportSize(); + r = nsRect(0, 0, + nsPresContext::CSSPixelsToAppUnits(viewportSize.width), + nsPresContext::CSSPixelsToAppUnits(viewportSize.height)); + } + + break; + } + case StyleGeometryBox::NoBox: + case StyleGeometryBox::Border: + case StyleGeometryBox::Content: + case StyleGeometryBox::Padding: + case StyleGeometryBox::Margin: + case StyleGeometryBox::Fill: { + gfxRect bbox = nsSVGUtils::GetBBox(aFrame, + nsSVGUtils::eBBoxIncludeFill); + r = nsLayoutUtils::RoundGfxRectToAppRect(bbox, + nsPresContext::AppUnitsPerCSSPixel()); + break; + } + default:{ + MOZ_ASSERT_UNREACHABLE("unknown StyleGeometryBox type"); + gfxRect bbox = nsSVGUtils::GetBBox(aFrame, + nsSVGUtils::eBBoxIncludeFill); + r = nsLayoutUtils::RoundGfxRectToAppRect(bbox, + nsPresContext::AppUnitsPerCSSPixel()); + break; + } + } + + return r; +} + +static nsRect +ComputeHTMLReferenceRect(nsIFrame* aFrame, + StyleGeometryBox aGeometryBox) +{ + nsRect r; + + // For elements with associated CSS layout box, the used value for fill-box, + // stroke-box and view-box is border-box. + switch (aGeometryBox) { + case StyleGeometryBox::Content: + r = aFrame->GetContentRectRelativeToSelf(); + break; + case StyleGeometryBox::Padding: + r = aFrame->GetPaddingRectRelativeToSelf(); + break; + case StyleGeometryBox::Margin: + r = aFrame->GetMarginRectRelativeToSelf(); + break; + case StyleGeometryBox::NoBox: + case StyleGeometryBox::Border: + case StyleGeometryBox::Fill: + case StyleGeometryBox::Stroke: + case StyleGeometryBox::View: + r = aFrame->GetRectRelativeToSelf(); + break; + default: + MOZ_ASSERT_UNREACHABLE("unknown StyleGeometryBox type"); + r = aFrame->GetRectRelativeToSelf(); + break; + } + + return r; +} + +/* static */ nsRect +nsLayoutUtils::ComputeGeometryBox(nsIFrame* aFrame, + StyleGeometryBox aGeometryBox) +{ + // We use ComputeSVGReferenceRect for all SVG elements, except + // element, which does have an associated CSS layout box. In this case we + // should still use ComputeHTMLReferenceRect for region computing. + nsRect r = aFrame->IsFrameOfType(nsIFrame::eSVG) && + (aFrame->GetType() != nsGkAtoms::svgOuterSVGFrame) + ? ComputeSVGReferenceRect(aFrame, aGeometryBox) + : ComputeHTMLReferenceRect(aFrame, aGeometryBox); + + return r; +} -- cgit v1.2.3