From d3fd87344e138ad03f7127d2032b79cfab8fd044 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Sun, 10 Jun 2012 13:02:23 -0700 Subject: [PATCH] Do the necessary reflow when our font inflation data changes. (Bug 759755, patch 2) r=roc --- layout/generic/nsFontInflationData.cpp | 14 ++++- layout/generic/nsFontInflationData.h | 4 +- layout/generic/nsHTMLReflowState.cpp | 71 +++++++++++++++----------- 3 files changed, 55 insertions(+), 34 deletions(-) diff --git a/layout/generic/nsFontInflationData.cpp b/layout/generic/nsFontInflationData.cpp index 58ee4c14660a..2b63fdd37583 100644 --- a/layout/generic/nsFontInflationData.cpp +++ b/layout/generic/nsFontInflationData.cpp @@ -38,7 +38,7 @@ nsFontInflationData::FindFontInflationDataFor(const nsIFrame *aFrame) bfc->Properties().Get(FontInflationDataProperty())); } -/* static */ void +/* static */ bool nsFontInflationData::UpdateFontInflationDataWidthFor(const nsHTMLReflowState& aReflowState) { nsIFrame *bfc = aReflowState.frame; @@ -47,12 +47,22 @@ nsFontInflationData::UpdateFontInflationDataWidthFor(const nsHTMLReflowState& aR FrameProperties bfcProps(bfc->Properties()); nsFontInflationData *data = static_cast( bfcProps.Get(FontInflationDataProperty())); - if (!data) { + bool oldInflationEnabled; + nscoord oldNCAWidth; + if (data) { + oldNCAWidth = data->mNCAWidth; + oldInflationEnabled = data->mInflationEnabled; + } else { data = new nsFontInflationData(bfc); bfcProps.Set(FontInflationDataProperty(), data); + oldNCAWidth = -1; + oldInflationEnabled = true; /* not relevant */ } data->UpdateWidth(aReflowState); + + return oldNCAWidth != data->mNCAWidth || + oldInflationEnabled != data->mInflationEnabled; } /* static */ void diff --git a/layout/generic/nsFontInflationData.h b/layout/generic/nsFontInflationData.h index 7e89a369ccb1..b7378d93da92 100644 --- a/layout/generic/nsFontInflationData.h +++ b/layout/generic/nsFontInflationData.h @@ -20,7 +20,9 @@ public: static nsFontInflationData* FindFontInflationDataFor(const nsIFrame *aFrame); - static void + // Returns whether the effective width changed (which requires the + // caller to mark its descendants dirty + static bool UpdateFontInflationDataWidthFor(const nsHTMLReflowState& aReflowState); static void MarkFontInflationDataTextDirty(nsIFrame *aFrame); diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp index d4909c2db9f7..a3576436ee8b 100644 --- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -305,12 +305,6 @@ nsHTMLReflowState::Init(nsPresContext* aPresContext, "have unconstrained width; this should only result from " "very large sizes, not attempts at intrinsic width " "calculation"); - - if (frame->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT) { - // Create our font inflation data if we don't have it already, and - // give it our current width information. - nsFontInflationData::UpdateFontInflationDataWidthFor(*this); - } } void nsHTMLReflowState::InitCBReflowState() @@ -364,34 +358,49 @@ IsQuirkContainingBlockHeight(const nsHTMLReflowState* rs, nsIAtom* aFrameType) void nsHTMLReflowState::InitResizeFlags(nsPresContext* aPresContext, nsIAtom* aFrameType) { + if ((frame->GetStateBits() & NS_FRAME_FONT_INFLATION_FLOW_ROOT) && + nsLayoutUtils::FontSizeInflationEnabled(aPresContext)) { + // Create our font inflation data if we don't have it already, and + // give it our current width information. + bool dirty = nsFontInflationData::UpdateFontInflationDataWidthFor(*this); + if (dirty) { + // When font size inflation is enabled, the change in the width of a + // block (or anything that returns true in + // IsContainerForFontSizeInflation) needs to cause a dirty reflow + // since it changes the size of text, line-heights, etc. This is + // relatively similar to a classic case of style change reflow, + // except that because inflation doesn't affect the intrinsic sizing + // codepath, there's no need to invalidate intrinsic sizes. + // + // Note that this makes horizontal resizing a good bit more + // expensive. However, font size inflation is targeted at a set of + // devices (zoom-and-pan devices) where the main use case for + // horizontal resizing needing to be efficient (window resizing) is + // not present. It does still increase the cost of dynamic changes + // caused by script where a style or content change in one place + // causes a resize in another (e.g., rebalancing a table). + + // FIXME: This isn't so great for the cases where + // nsHTMLReflowState::SetComputedWidth is called, if the first time + // we go through InitResizeFlags we set mHResize to true, and then + // the second time we'd set it to false even without the + // NS_FRAME_IS_DIRTY bit already set. + if (frame->GetType() == nsGkAtoms::svgForeignObjectFrame) { + // Foreign object frames use dirty bits in a special way. + frame->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN); + nsIFrame *kid = frame->GetFirstPrincipalChild(); + if (kid) { + kid->AddStateBits(NS_FRAME_IS_DIRTY); + } + } else { + frame->AddStateBits(NS_FRAME_IS_DIRTY); + } + } + } + mFlags.mHResize = !(frame->GetStateBits() & NS_FRAME_IS_DIRTY) && frame->GetSize().width != mComputedWidth + mComputedBorderPadding.LeftRight(); - if (mFlags.mHResize && - nsLayoutUtils::FontSizeInflationEnabled(aPresContext)) { - // When font size inflation is enabled, the change in the width of a - // block (or anything that returns true in - // IsContainerForFontSizeInflation) needs to cause a dirty reflow - // since it changes the size of text, line-heights, etc. This is - // relatively similar to a classic case of style change reflow, - // except that because inflation doesn't affect the intrinsic sizing - // codepath, there's no need to invalidate intrinsic sizes. - // - // Note that this makes horizontal resizing a good bit more - // expensive. However, font size inflation is targeted at a set of - // devices (zoom-and-pan devices) where the main use case for - // horizontal resizing needing to be efficient (window resizing) is - // not present. It does still increase the cost of dynamic changes - // caused by script where a style or content change in one place - // causes a resize in another (e.g., rebalancing a table). - - // FIXME: This isn't so great for the cases where - // nsHTMLReflowState::SetComputedWith is called, if the first time - // we go through InitResizeFlags we set mHResize to true, and then - // the second time we'd set it to false even without the - // NS_FRAME_IS_DIRTY bit already set. - frame->AddStateBits(NS_FRAME_IS_DIRTY); - } // XXX Should we really need to null check mCBReflowState? (We do for // at least nsBoxFrame).