зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1846853 - Clamp negative outline-offset per spec r=emilio
A negative outline-offset value should be clamped per spec as to stop it from becoming invisible with large negative values. Spec ref: https://www.w3.org/TR/css-ui-4/#outline-offset Also added a new WPT reftest for this case as no tests existed prior, updated related WPT expectations, and updated a few old layout reftests. Differential Revision: https://phabricator.services.mozilla.com/D185357
This commit is contained in:
Родитель
846812dc70
Коммит
e115104963
|
@ -9880,16 +9880,17 @@ static void ComputeAndIncludeOutlineArea(nsIFrame* aFrame,
|
|||
innerRect);
|
||||
}
|
||||
|
||||
const nscoord offset = outline->mOutlineOffset.ToAppUnits();
|
||||
nsRect outerRect(innerRect);
|
||||
outerRect.Inflate(outline->EffectiveOffsetFor(outerRect));
|
||||
|
||||
if (outline->mOutlineStyle.IsAuto()) {
|
||||
nsPresContext* pc = aFrame->PresContext();
|
||||
outerRect.Inflate(offset);
|
||||
|
||||
pc->Theme()->GetWidgetOverflow(pc->DeviceContext(), aFrame,
|
||||
StyleAppearance::FocusOutline, &outerRect);
|
||||
} else {
|
||||
nscoord width = outline->GetOutlineWidth();
|
||||
outerRect.Inflate(width + offset);
|
||||
const nscoord width = outline->GetOutlineWidth();
|
||||
outerRect.Inflate(width);
|
||||
}
|
||||
|
||||
nsRect& vo = aOverflowAreas.InkOverflow();
|
||||
|
|
|
@ -962,9 +962,10 @@ nsCSSRendering::CreateBorderRendererForNonThemedOutline(
|
|||
return Nothing();
|
||||
}
|
||||
|
||||
const nscoord offset = ourOutline->mOutlineOffset.ToAppUnits();
|
||||
nsRect innerRect = aInnerRect;
|
||||
innerRect.Inflate(offset);
|
||||
|
||||
const nsSize effectiveOffset = ourOutline->EffectiveOffsetFor(innerRect);
|
||||
innerRect.Inflate(effectiveOffset);
|
||||
|
||||
// If the dirty rect is completely inside the border area (e.g., only the
|
||||
// content is being painted), then we can skip out now
|
||||
|
@ -975,7 +976,7 @@ nsCSSRendering::CreateBorderRendererForNonThemedOutline(
|
|||
return Nothing();
|
||||
}
|
||||
|
||||
nscoord width = ourOutline->GetOutlineWidth();
|
||||
const nscoord width = ourOutline->GetOutlineWidth();
|
||||
|
||||
StyleBorderStyle outlineStyle;
|
||||
// Themed outlines are handled by our callers, if supported.
|
||||
|
@ -1009,10 +1010,13 @@ nsCSSRendering::CreateBorderRendererForNonThemedOutline(
|
|||
RectCornerRadii innerRadii;
|
||||
ComputePixelRadii(twipsRadii, oneDevPixel, &innerRadii);
|
||||
|
||||
Float devPixelOffset = aPresContext->AppUnitsToFloatDevPixels(offset);
|
||||
const Float widths[4] = {
|
||||
outlineWidths[0] + devPixelOffset, outlineWidths[1] + devPixelOffset,
|
||||
outlineWidths[2] + devPixelOffset, outlineWidths[3] + devPixelOffset};
|
||||
const auto devPxOffset = LayoutDeviceSize::FromAppUnits(
|
||||
effectiveOffset, aPresContext->AppUnitsPerDevPixel());
|
||||
|
||||
const Float widths[4] = {outlineWidths[0] + devPxOffset.Height(),
|
||||
outlineWidths[1] + devPxOffset.Width(),
|
||||
outlineWidths[2] + devPxOffset.Height(),
|
||||
outlineWidths[3] + devPxOffset.Width()};
|
||||
nsCSSBorderRenderer::ComputeOuterRadii(innerRadii, widths, &outlineRadii);
|
||||
}
|
||||
|
||||
|
|
|
@ -4015,7 +4015,7 @@ void nsDisplayOutline::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) {
|
|||
nsRect rect = GetInnerRect() + ToReferenceFrame();
|
||||
nsPresContext* pc = mFrame->PresContext();
|
||||
if (IsThemedOutline()) {
|
||||
rect.Inflate(mFrame->StyleOutline()->mOutlineOffset.ToAppUnits());
|
||||
rect.Inflate(mFrame->StyleOutline()->EffectiveOffsetFor(rect));
|
||||
pc->Theme()->DrawWidgetBackground(aCtx, mFrame,
|
||||
StyleAppearance::FocusOutline, rect,
|
||||
GetPaintRect(aBuilder, aCtx));
|
||||
|
@ -4044,7 +4044,7 @@ bool nsDisplayOutline::CreateWebRenderCommands(
|
|||
nsPresContext* pc = mFrame->PresContext();
|
||||
nsRect rect = GetInnerRect() + ToReferenceFrame();
|
||||
if (IsThemedOutline()) {
|
||||
rect.Inflate(mFrame->StyleOutline()->mOutlineOffset.ToAppUnits());
|
||||
rect.Inflate(mFrame->StyleOutline()->EffectiveOffsetFor(rect));
|
||||
return pc->Theme()->CreateWebRenderCommandsForWidget(
|
||||
aBuilder, aResources, aSc, aManager, mFrame,
|
||||
StyleAppearance::FocusOutline, rect);
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
<style type="text/css">
|
||||
|
||||
* { -moz-outline-offset: -2px; outline-offset: -2px; }
|
||||
body > span { outline: 1px dotted black; }
|
||||
/* can't compare to border combined with negative margin because of
|
||||
margin collapsing */
|
||||
body > div { display: block; outline: 1px dotted black; width: 15em; }
|
||||
|
@ -17,7 +16,7 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<span></span><div>text<br>text<br>text</div>
|
||||
<div>text<br>text<br>text</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<span></span><div>text</div><span>Some words that must be wider than 10em</span><div>text</div>
|
||||
<div>text</div><span>Some words that must be wider than 10em</span><div>text</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -585,6 +585,18 @@ nsChangeHint nsStyleOutline::CalcDifference(
|
|||
return nsChangeHint(0);
|
||||
}
|
||||
|
||||
nsSize nsStyleOutline::EffectiveOffsetFor(const nsRect& aRect) const {
|
||||
const nscoord offset = mOutlineOffset.ToAppUnits();
|
||||
|
||||
if (offset >= 0) {
|
||||
// Fast path for non-negative offset values
|
||||
return nsSize(offset, offset);
|
||||
}
|
||||
|
||||
return nsSize(std::max(offset, -(aRect.Width() / 2)),
|
||||
std::max(offset, -(aRect.Height() / 2)));
|
||||
}
|
||||
|
||||
// --------------------
|
||||
// nsStyleList
|
||||
//
|
||||
|
|
|
@ -617,6 +617,8 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleOutline {
|
|||
return false;
|
||||
}
|
||||
|
||||
nsSize EffectiveOffsetFor(const nsRect& aRect) const;
|
||||
|
||||
protected:
|
||||
// The actual value of outline-width is the computed value (an absolute
|
||||
// length, forced to zero when outline-style is none) rounded to device
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[outline-013.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[outline-014.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[outline-015.html]
|
||||
expected: FAIL
|
|
@ -1,2 +0,0 @@
|
|||
[outline-016.html]
|
||||
expected: FAIL
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
div {
|
||||
border: 2px solid black;
|
||||
padding: 5px 0; /* No horizontal padding as outline-offset is not affected by it and span simulates it */
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
span {
|
||||
display: block;
|
||||
|
||||
/* 3/6px offset for border */
|
||||
height: 2px;
|
||||
width: calc(100% - 20em + 6px);
|
||||
margin: -1px calc(10em - 3px); /* -1px vertical to remove height of span from div height */
|
||||
background: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>PASS if there is a thin red line in the middle of the box.</p>
|
||||
<div>
|
||||
<span></span>
|
||||
</div>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://www.w3.org/TR/css-ui-4/#outline-offset">
|
||||
<link rel="match" href="negative-outline-offset-ref.html">
|
||||
<style>
|
||||
div {
|
||||
outline: 1px solid red;
|
||||
outline-offset: -10em;
|
||||
|
||||
border: 2px solid black;
|
||||
padding: 5px;
|
||||
font-size: 16px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>PASS if there is a thin red line in the middle of the box.</p>
|
||||
<div></div>
|
Загрузка…
Ссылка в новой задаче