From 092c61f6e68971a62822532e12dc45ba54c9a713 Mon Sep 17 00:00:00 2001 From: janekptacijarabaci Date: Thu, 17 Aug 2017 21:08:44 +0200 Subject: CSS: inline-block with a display:block child element has a wrong baseline (HTML forms) --- image/DrawResult.h | 1 + layout/forms/nsFieldSetFrame.cpp | 71 +++++++++++---- layout/forms/nsFieldSetFrame.h | 9 +- layout/forms/nsHTMLButtonControlFrame.cpp | 41 +++++++++ layout/forms/nsHTMLButtonControlFrame.h | 7 ++ layout/forms/nsLegendFrame.h | 5 +- layout/forms/nsTextControlFrame.cpp | 11 +-- layout/forms/nsTextControlFrame.h | 35 ++++++++ layout/reftests/bugs/315920-17.html | 15 +++- .../forms/display-block-baselines-1-ref.html | 91 +++++++++++++++++++ .../reftests/forms/display-block-baselines-1.html | 92 +++++++++++++++++++ .../forms/display-block-baselines-2-ref.html | 100 +++++++++++++++++++++ .../reftests/forms/display-block-baselines-2.html | 100 +++++++++++++++++++++ .../forms/display-block-baselines-3-ref.html | 72 +++++++++++++++ .../reftests/forms/display-block-baselines-3.html | 73 +++++++++++++++ .../forms/display-block-baselines-4-ref.html | 73 +++++++++++++++ .../reftests/forms/display-block-baselines-4.html | 74 +++++++++++++++ .../forms/display-block-baselines-5-ref.html | 72 +++++++++++++++ .../reftests/forms/display-block-baselines-5.html | 72 +++++++++++++++ layout/reftests/forms/reftest.list | 5 ++ 20 files changed, 990 insertions(+), 29 deletions(-) create mode 100644 layout/reftests/forms/display-block-baselines-1-ref.html create mode 100644 layout/reftests/forms/display-block-baselines-1.html create mode 100644 layout/reftests/forms/display-block-baselines-2-ref.html create mode 100644 layout/reftests/forms/display-block-baselines-2.html create mode 100644 layout/reftests/forms/display-block-baselines-3-ref.html create mode 100644 layout/reftests/forms/display-block-baselines-3.html create mode 100644 layout/reftests/forms/display-block-baselines-4-ref.html create mode 100644 layout/reftests/forms/display-block-baselines-4.html create mode 100644 layout/reftests/forms/display-block-baselines-5-ref.html create mode 100644 layout/reftests/forms/display-block-baselines-5.html diff --git a/image/DrawResult.h b/image/DrawResult.h index 8240ede26..912f59dc3 100644 --- a/image/DrawResult.h +++ b/image/DrawResult.h @@ -6,6 +6,7 @@ #ifndef mozilla_image_DrawResult_h #define mozilla_image_DrawResult_h +#include // for uint8_t #include "mozilla/Attributes.h" #include "mozilla/Likely.h" diff --git a/layout/forms/nsFieldSetFrame.cpp b/layout/forms/nsFieldSetFrame.cpp index befd41ee2..fc9f0571b 100644 --- a/layout/forms/nsFieldSetFrame.cpp +++ b/layout/forms/nsFieldSetFrame.cpp @@ -5,26 +5,22 @@ #include "nsFieldSetFrame.h" +#include #include "mozilla/gfx/2D.h" +#include "mozilla/Likely.h" +#include "mozilla/Maybe.h" #include "nsCSSAnonBoxes.h" -#include "nsLayoutUtils.h" -#include "nsLegendFrame.h" #include "nsCSSRendering.h" -#include -#include "nsIFrame.h" -#include "nsPresContext.h" -#include "mozilla/RestyleManager.h" -#include "nsGkAtoms.h" -#include "nsStyleConsts.h" #include "nsDisplayList.h" +#include "nsGkAtoms.h" +#include "nsIFrameInlines.h" +#include "nsLayoutUtils.h" +#include "nsLegendFrame.h" #include "nsRenderingContext.h" -#include "nsIScrollableFrame.h" -#include "mozilla/Likely.h" -#include "mozilla/Maybe.h" +#include "nsStyleConsts.h" using namespace mozilla; using namespace mozilla::gfx; -using namespace mozilla::image; using namespace mozilla::layout; nsContainerFrame* @@ -126,7 +122,7 @@ void nsDisplayFieldSetBorderBackground::Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) { - DrawResult result = static_cast(mFrame)-> + image::DrawResult result = static_cast(mFrame)-> PaintBorder(aBuilder, *aCtx, ToReferenceFrame(), mVisibleRect); nsDisplayItemGenericImageGeometry::UpdateDrawResult(this, result); @@ -210,7 +206,7 @@ nsFieldSetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, contentDisplayItems.MoveTo(aLists); } -DrawResult +image::DrawResult nsFieldSetFrame::PaintBorder( nsDisplayListBuilder* aBuilder, nsRenderingContext& aRenderingContext, @@ -695,9 +691,50 @@ nsFieldSetFrame::AccessibleType() #endif nscoord -nsFieldSetFrame::GetLogicalBaseline(WritingMode aWritingMode) const +nsFieldSetFrame::GetLogicalBaseline(WritingMode aWM) const +{ + switch (StyleDisplay()->mDisplay) { + case mozilla::StyleDisplay::Grid: + case mozilla::StyleDisplay::InlineGrid: + case mozilla::StyleDisplay::Flex: + case mozilla::StyleDisplay::InlineFlex: + return BaselineBOffset(aWM, BaselineSharingGroup::eFirst, + AlignmentContext::eInline); + default: + return BSize(aWM) - BaselineBOffset(aWM, BaselineSharingGroup::eLast, + AlignmentContext::eInline); + } +} + +bool +nsFieldSetFrame::GetVerticalAlignBaseline(WritingMode aWM, + nscoord* aBaseline) const { nsIFrame* inner = GetInner(); - return inner->BStart(aWritingMode, GetParent()->GetSize()) + - inner->GetLogicalBaseline(aWritingMode); + MOZ_ASSERT(!inner->GetWritingMode().IsOrthogonalTo(aWM)); + if (!inner->GetVerticalAlignBaseline(aWM, aBaseline)) { + return false; + } + nscoord innerBStart = inner->BStart(aWM, GetSize()); + *aBaseline += innerBStart; + return true; +} + +bool +nsFieldSetFrame::GetNaturalBaselineBOffset(WritingMode aWM, + BaselineSharingGroup aBaselineGroup, + nscoord* aBaseline) const +{ + nsIFrame* inner = GetInner(); + MOZ_ASSERT(!inner->GetWritingMode().IsOrthogonalTo(aWM)); + if (!inner->GetNaturalBaselineBOffset(aWM, aBaselineGroup, aBaseline)) { + return false; + } + nscoord innerBStart = inner->BStart(aWM, GetSize()); + if (aBaselineGroup == BaselineSharingGroup::eFirst) { + *aBaseline += innerBStart; + } else { + *aBaseline += BSize(aWM) - (innerBStart + inner->BSize(aWM)); + } + return true; } diff --git a/layout/forms/nsFieldSetFrame.h b/layout/forms/nsFieldSetFrame.h index 54eaf678f..39d862278 100644 --- a/layout/forms/nsFieldSetFrame.h +++ b/layout/forms/nsFieldSetFrame.h @@ -7,7 +7,7 @@ #define nsFieldSetFrame_h___ #include "mozilla/Attributes.h" -#include "imgIContainer.h" +#include "DrawResult.h" #include "nsContainerFrame.h" class nsFieldSetFrame final : public nsContainerFrame @@ -46,6 +46,13 @@ public: const ReflowInput& aReflowInput, nsReflowStatus& aStatus) override; + nscoord GetLogicalBaseline(mozilla::WritingMode aWM) const override; + bool GetVerticalAlignBaseline(mozilla::WritingMode aWM, + nscoord* aBaseline) const override; + bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM, + BaselineSharingGroup aBaselineGroup, + nscoord* aBaseline) const override; + virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, const nsDisplayListSet& aLists) override; diff --git a/layout/forms/nsHTMLButtonControlFrame.cpp b/layout/forms/nsHTMLButtonControlFrame.cpp index ef9459ef2..2e4fa9f67 100644 --- a/layout/forms/nsHTMLButtonControlFrame.cpp +++ b/layout/forms/nsHTMLButtonControlFrame.cpp @@ -418,6 +418,47 @@ nsHTMLButtonControlFrame::ReflowButtonContents(nsPresContext* aPresContext, aButtonDesiredSize.SetOverflowAreasToDesiredBounds(); } +bool +nsHTMLButtonControlFrame::GetVerticalAlignBaseline(mozilla::WritingMode aWM, + nscoord* aBaseline) const +{ + nsIFrame* inner = mFrames.FirstChild(); + if (MOZ_UNLIKELY(inner->GetWritingMode().IsOrthogonalTo(aWM))) { + return false; + } + if (!inner->GetVerticalAlignBaseline(aWM, aBaseline)) { + // has an empty block frame as inner frame + *aBaseline = inner-> + SynthesizeBaselineBOffsetFromBorderBox(aWM, BaselineSharingGroup::eFirst); + } + nscoord innerBStart = inner->BStart(aWM, GetSize()); + *aBaseline += innerBStart; + return true; +} + +bool +nsHTMLButtonControlFrame::GetNaturalBaselineBOffset(mozilla::WritingMode aWM, + BaselineSharingGroup aBaselineGroup, + nscoord* aBaseline) const +{ + nsIFrame* inner = mFrames.FirstChild(); + if (MOZ_UNLIKELY(inner->GetWritingMode().IsOrthogonalTo(aWM))) { + return false; + } + if (!inner->GetNaturalBaselineBOffset(aWM, aBaselineGroup, aBaseline)) { + // has an empty block frame as inner frame + *aBaseline = inner-> + SynthesizeBaselineBOffsetFromBorderBox(aWM, aBaselineGroup); + } + nscoord innerBStart = inner->BStart(aWM, GetSize()); + if (aBaselineGroup == BaselineSharingGroup::eFirst) { + *aBaseline += innerBStart; + } else { + *aBaseline += BSize(aWM) - (innerBStart + inner->BSize(aWM)); + } + return true; +} + nsresult nsHTMLButtonControlFrame::SetFormProperty(nsIAtom* aName, const nsAString& aValue) { if (nsGkAtoms::value == aName) { diff --git a/layout/forms/nsHTMLButtonControlFrame.h b/layout/forms/nsHTMLButtonControlFrame.h index 96ad0f366..432afa12c 100644 --- a/layout/forms/nsHTMLButtonControlFrame.h +++ b/layout/forms/nsHTMLButtonControlFrame.h @@ -39,6 +39,13 @@ public: const ReflowInput& aReflowInput, nsReflowStatus& aStatus) override; + bool GetVerticalAlignBaseline(mozilla::WritingMode aWM, + nscoord* aBaseline) const override; + + bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM, + BaselineSharingGroup aBaselineGroup, + nscoord* aBaseline) const override; + virtual nsresult HandleEvent(nsPresContext* aPresContext, mozilla::WidgetGUIEvent* aEvent, nsEventStatus* aEventStatus) override; diff --git a/layout/forms/nsLegendFrame.h b/layout/forms/nsLegendFrame.h index 5f5e1e03e..a9e11cbbe 100644 --- a/layout/forms/nsLegendFrame.h +++ b/layout/forms/nsLegendFrame.h @@ -9,7 +9,8 @@ #include "mozilla/Attributes.h" #include "nsBlockFrame.h" -class nsLegendFrame : public nsBlockFrame { +class nsLegendFrame final : public nsBlockFrame +{ public: NS_DECL_QUERYFRAME_TARGET(nsLegendFrame) NS_DECL_QUERYFRAME @@ -30,7 +31,7 @@ public: virtual nsresult GetFrameName(nsAString& aResult) const override; #endif - int32_t GetLogicalAlign(WritingMode aCBWM); + int32_t GetLogicalAlign(mozilla::WritingMode aCBWM); }; diff --git a/layout/forms/nsTextControlFrame.cpp b/layout/forms/nsTextControlFrame.cpp index f85bc2a80..a7f7d40a8 100644 --- a/layout/forms/nsTextControlFrame.cpp +++ b/layout/forms/nsTextControlFrame.cpp @@ -106,6 +106,7 @@ private: nsTextControlFrame::nsTextControlFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) + , mFirstBaseline(NS_INTRINSIC_WIDTH_UNKNOWN) , mEditorHasBeenInitialized(false) , mIsProcessing(false) #ifdef DEBUG @@ -538,20 +539,20 @@ nsTextControlFrame::Reflow(nsPresContext* aPresContext, aReflowInput.ComputedLogicalBorderPadding().BStartEnd(wm)); aDesiredSize.SetSize(wm, finalSize); - // computation of the ascent wrt the input height + // Calculate the baseline and store it in mFirstBaseline. nscoord lineHeight = aReflowInput.ComputedBSize(); float inflation = nsLayoutUtils::FontSizeInflationFor(this); if (!IsSingleLineTextControl()) { lineHeight = ReflowInput::CalcLineHeight(GetContent(), StyleContext(), - NS_AUTOHEIGHT, inflation); + NS_AUTOHEIGHT, inflation); } RefPtr fontMet = nsLayoutUtils::GetFontMetricsForFrame(this, inflation); - // now adjust for our borders and padding - aDesiredSize.SetBlockStartAscent( + mFirstBaseline = nsLayoutUtils::GetCenteredFontBaseline(fontMet, lineHeight, wm.IsLineInverted()) + - aReflowInput.ComputedLogicalBorderPadding().BStart(wm)); + aReflowInput.ComputedLogicalBorderPadding().BStart(wm); + aDesiredSize.SetBlockStartAscent(mFirstBaseline); // overflow handling aDesiredSize.SetOverflowAreasToDesiredBounds(); diff --git a/layout/forms/nsTextControlFrame.h b/layout/forms/nsTextControlFrame.h index a76cba514..9d4d0b77c 100644 --- a/layout/forms/nsTextControlFrame.h +++ b/layout/forms/nsTextControlFrame.h @@ -62,6 +62,29 @@ public: const ReflowInput& aReflowInput, nsReflowStatus& aStatus) override; + bool GetVerticalAlignBaseline(mozilla::WritingMode aWM, + nscoord* aBaseline) const override + { + return GetNaturalBaselineBOffset(aWM, BaselineSharingGroup::eFirst, aBaseline); + } + + bool GetNaturalBaselineBOffset(mozilla::WritingMode aWM, + BaselineSharingGroup aBaselineGroup, + nscoord* aBaseline) const override + { + if (!IsSingleLineTextControl()) { + return false; + } + NS_ASSERTION(mFirstBaseline != NS_INTRINSIC_WIDTH_UNKNOWN, + "please call Reflow before asking for the baseline"); + if (aBaselineGroup == BaselineSharingGroup::eFirst) { + *aBaseline = mFirstBaseline; + } else { + *aBaseline = BSize(aWM) - mFirstBaseline; + } + return true; + } + virtual nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) override; virtual bool IsXULCollapsed() override; @@ -87,6 +110,14 @@ public: ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock)); } +#ifdef DEBUG + void MarkIntrinsicISizesDirty() override + { + // Need another Reflow to have a correct baseline value again. + mFirstBaseline = NS_INTRINSIC_WIDTH_UNKNOWN; + } +#endif + // nsIAnonymousContentCreator virtual nsresult CreateAnonymousContent(nsTArray& aElements) override; virtual void AppendAnonymousContentTo(nsTArray& aElements, @@ -300,6 +331,10 @@ private: } private: + // Our first baseline, or NS_INTRINSIC_WIDTH_UNKNOWN if we have a pending + // Reflow. + nscoord mFirstBaseline; + // these packed bools could instead use the high order bits on mState, saving 4 bytes bool mEditorHasBeenInitialized; bool mIsProcessing; diff --git a/layout/reftests/bugs/315920-17.html b/layout/reftests/bugs/315920-17.html index 1681754a5..6d9180144 100644 --- a/layout/reftests/bugs/315920-17.html +++ b/layout/reftests/bugs/315920-17.html @@ -1,5 +1,5 @@ - + - +

@@ -19,5 +17,14 @@
+ diff --git a/layout/reftests/forms/display-block-baselines-1-ref.html b/layout/reftests/forms/display-block-baselines-1-ref.html new file mode 100644 index 000000000..d01c086b5 --- /dev/null +++ b/layout/reftests/forms/display-block-baselines-1-ref.html @@ -0,0 +1,91 @@ + + + + + Reference: Testcase #1 for bug 1330962 + + + + +
+
+ A +
+ B +
+ +
+
+ A + +
+ B +
+ +
+
+ A
+
+
+ B +
+ +
+
+ A
+
+
+ B +
+ +
+
+ A
+
+
+ B +
+ +
+
+ A
+
+
+ B +
+ + + diff --git a/layout/reftests/forms/display-block-baselines-1.html b/layout/reftests/forms/display-block-baselines-1.html new file mode 100644 index 000000000..96ebdad71 --- /dev/null +++ b/layout/reftests/forms/display-block-baselines-1.html @@ -0,0 +1,92 @@ + + + + + Testcase #1 for bug 1330962 + + + + +
+
+ A + +
+ B +
+ +
+
+ A + +
+ B +
+ +
+
+ A + +
+ B +
+ +
+
+ A + +
+ B +
+ +
+
+ A + +
+ B +
+ +
+
+ A + +
+ B +
+ + + diff --git a/layout/reftests/forms/display-block-baselines-2-ref.html b/layout/reftests/forms/display-block-baselines-2-ref.html new file mode 100644 index 000000000..441a927b4 --- /dev/null +++ b/layout/reftests/forms/display-block-baselines-2-ref.html @@ -0,0 +1,100 @@ + + + + + Reference: Testcase #2 for bug 1330962 + + + + +
+
+ A
+
+
+ B +
+ +
+
+ A
+
+
+ B +
+ +
+
+ A
+
+
+ B +
+ +
+
+ A
+ +
+ B +
button-first
button-last
+
+ +
+
+ A
+ +
+ B +
button-firstbutton-last
+
+ +
+
+ A + +
+ B +
+ +
+
+ A + +
+ B +
+ + + diff --git a/layout/reftests/forms/display-block-baselines-2.html b/layout/reftests/forms/display-block-baselines-2.html new file mode 100644 index 000000000..78253fe4c --- /dev/null +++ b/layout/reftests/forms/display-block-baselines-2.html @@ -0,0 +1,100 @@ + + + + + Testcase #2 for bug 1330962 + + + + +
+
+ A + +
+ B +
+ +
+
+ A + +
+ B +
+ +
+
+ A + +
+ B +
+ +
+
+ A + +
+ B + +
+ +
+
+ A + +
+ B + +
+ +
+
+ A + +
+ B +
+ +
+
+ A + +
+ B +
+ + + diff --git a/layout/reftests/forms/display-block-baselines-3-ref.html b/layout/reftests/forms/display-block-baselines-3-ref.html new file mode 100644 index 000000000..ce277b50c --- /dev/null +++ b/layout/reftests/forms/display-block-baselines-3-ref.html @@ -0,0 +1,72 @@ + + + + + Reference: Testcase #3 for bug 1330962 + + + + +
+
+ A + +
+ B +
+ +
+
+ A + +
+ B +
+ +
+
+ A + +
+ B +
+ +
+
+ A
+
fieldset-first
fieldset-last
+
+ B +
+ + + diff --git a/layout/reftests/forms/display-block-baselines-3.html b/layout/reftests/forms/display-block-baselines-3.html new file mode 100644 index 000000000..9f3c2b110 --- /dev/null +++ b/layout/reftests/forms/display-block-baselines-3.html @@ -0,0 +1,73 @@ + + + + + Testcase #3 for bug 1330962 + + + + +
+
+ A + +
+ B +
+ +
+
+ A + +
+ B +
+ +
+
+ A + +
+ B +
+ +
+
+ A +
fieldset-first
fieldset-last
+
+ B +
+ + + + diff --git a/layout/reftests/forms/display-block-baselines-4-ref.html b/layout/reftests/forms/display-block-baselines-4-ref.html new file mode 100644 index 000000000..5015d50c4 --- /dev/null +++ b/layout/reftests/forms/display-block-baselines-4-ref.html @@ -0,0 +1,73 @@ + + + + + Reference: Testcase #4 for bug 1330962 + + + + +
+
+ A
+
legend +fieldset-first
fieldset-last
+
+ B +
+ +
+
+ A
+
grid-fieldset-firstgrid-fieldset-last
+
+ B +
+ +
+
+ A
+
fieldset-first
fieldset-last
+
+ B +
+ +
+
+ A
+
fieldset-first
fieldset-last
+
+ B +
+ + + diff --git a/layout/reftests/forms/display-block-baselines-4.html b/layout/reftests/forms/display-block-baselines-4.html new file mode 100644 index 000000000..1bfd344b0 --- /dev/null +++ b/layout/reftests/forms/display-block-baselines-4.html @@ -0,0 +1,74 @@ + + + + + Testcase #4 for bug 1330962 + + + + +
+
+ A +
legend +fieldset-first
fieldset-last
+
+ B +
+ +
+
+ A +
grid-fieldset-lastgrid-fieldset-first
+
+ B +
+ +
+
+ A +
fieldset-first
fieldset-last
+
+ B +
+ +
+
+ A +
fieldset-first
fieldset-last
+
+ B +
+ + + + diff --git a/layout/reftests/forms/display-block-baselines-5-ref.html b/layout/reftests/forms/display-block-baselines-5-ref.html new file mode 100644 index 000000000..0dce47f59 --- /dev/null +++ b/layout/reftests/forms/display-block-baselines-5-ref.html @@ -0,0 +1,72 @@ + + + + + Reference: Testcase #5 for bug 1330962 + + + + +
+
+ A
+ +
+ B +
+ +
+
+ A
+ +
+ B +
+ +
+
+ A
+ +
+ B +
+ +
+
+ A
+ +
+ B +
+ + + diff --git a/layout/reftests/forms/display-block-baselines-5.html b/layout/reftests/forms/display-block-baselines-5.html new file mode 100644 index 000000000..0359c8a6f --- /dev/null +++ b/layout/reftests/forms/display-block-baselines-5.html @@ -0,0 +1,72 @@ + + + + + Testcase #5 for bug 1330962 + + + + +
+
+ A + +
+ B +
+ +
+
+ A + +
+ B +
+ +
+
+ A + +
+ B +
+ +
+
+ A + +
+ B +
+ + + diff --git a/layout/reftests/forms/reftest.list b/layout/reftests/forms/reftest.list index d45db276f..c7532077b 100644 --- a/layout/reftests/forms/reftest.list +++ b/layout/reftests/forms/reftest.list @@ -1,4 +1,9 @@ fuzzy-if(skiaContent,1,10) HTTP(..) == text-control-baseline-1.html text-control-baseline-1-ref.html +fuzzy-if(cocoaWidget,16,64) fuzzy-if(Android,52,64) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu),104,224) fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),57,400) == display-block-baselines-1.html display-block-baselines-1-ref.html # anti-aliasing issues +== display-block-baselines-2.html display-block-baselines-2-ref.html +== display-block-baselines-3.html display-block-baselines-3-ref.html +== display-block-baselines-4.html display-block-baselines-4-ref.html +fuzzy-if(Android,4,8) == display-block-baselines-5.html display-block-baselines-5-ref.html # button element include button/reftest.list -- cgit v1.2.3