Do the necessary reflow when our font inflation data changes. (Bug 759755, patch 2) r=roc/bzbarsky

This commit is contained in:
L. David Baron 2012-06-11 13:57:35 -07:00
parent 614bdba9ff
commit 5cfd6386f6
3 changed files with 60 additions and 35 deletions

View File

@ -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<nsFontInflationData*>(
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

View File

@ -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);

View File

@ -308,12 +308,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()
@ -367,35 +361,54 @@ IsQuirkContainingBlockHeight(const nsHTMLReflowState* rs, nsIAtom* aFrameType)
void
nsHTMLReflowState::InitResizeFlags(nsPresContext* aPresContext, nsIAtom* aFrameType)
{
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).
bool isHResize = frame->GetSize().width !=
mComputedWidth + mComputedBorderPadding.LeftRight();
// 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);
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 || (!frame->GetParent() && isHResize)) {
// When font size inflation is enabled, a change in either:
// * the effective width of a font inflation flow root
// * the width of the frame
// needs to cause a dirty reflow since they change the font size
// inflation calculations, which in turn change 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) &&
isHResize;
// XXX Should we really need to null check mCBReflowState? (We do for
// at least nsBoxFrame).
if (IS_TABLE_CELL(aFrameType) &&