From 23dffd4efe8a56825c22620a65935e20918834e0 Mon Sep 17 00:00:00 2001 From: Scott Johnson Date: Tue, 15 Nov 2011 10:59:19 +1300 Subject: [PATCH 01/34] Bug 682077 - Remove nsITreeImageListener interface to make inheritance hierarchy more clear. r=neil, sr=bz --HG-- extra : rebase_source : 37becb5bb6a987fafb90a340284d284614dc64ae --- .../base/src/tree/src/nsITreeImageListener.h | 64 ------------------- .../xul/base/src/tree/src/nsTreeBodyFrame.cpp | 8 ++- .../xul/base/src/tree/src/nsTreeBodyFrame.h | 1 - .../base/src/tree/src/nsTreeImageListener.cpp | 6 +- .../base/src/tree/src/nsTreeImageListener.h | 5 +- 5 files changed, 9 insertions(+), 75 deletions(-) delete mode 100644 layout/xul/base/src/tree/src/nsITreeImageListener.h diff --git a/layout/xul/base/src/tree/src/nsITreeImageListener.h b/layout/xul/base/src/tree/src/nsITreeImageListener.h deleted file mode 100644 index 7fe9538eeb10..000000000000 --- a/layout/xul/base/src/tree/src/nsITreeImageListener.h +++ /dev/null @@ -1,64 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 2011 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Dave Hyatt (Original Author) - * Jan Varga - * Scott Johnson , Mozilla Corporation - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef nsITreeImageListener_h__ -#define nsITreeImageListener_h__ - -// The interface for our image listener. -// {90586540-2D50-403e-8DCE-981CAA778444} -#define NS_ITREEIMAGELISTENER_IID \ -{ 0x90586540, 0x2d50, 0x403e, { 0x8d, 0xce, 0x98, 0x1c, 0xaa, 0x77, 0x84, 0x44 } } - -class nsITreeImageListener : public nsISupports -{ -public: - NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITREEIMAGELISTENER_IID) - - NS_IMETHOD AddCell(PRInt32 aIndex, nsITreeColumn* aCol) = 0; - - /** - * Clear the internal frame pointer to prevent dereferencing an object - * that no longer exists. - */ - NS_IMETHOD ClearFrame() = 0; -}; - -NS_DEFINE_STATIC_IID_ACCESSOR(nsITreeImageListener, NS_ITREEIMAGELISTENER_IID) - -#endif diff --git a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp index 73e635e6d8b4..8e3c73aac7d3 100644 --- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp +++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp @@ -2157,9 +2157,11 @@ nsTreeBodyFrame::GetImage(PRInt32 aRowIndex, nsTreeColumn* aCol, bool aUseContex // We either aren't done loading, or we're animating. Add our row as a listener for invalidations. nsCOMPtr obs; imgReq->GetDecoderObserver(getter_AddRefs(obs)); - nsCOMPtr listener(do_QueryInterface(obs)); - if (listener) - listener->AddCell(aRowIndex, aCol); + + if (obs) { + static_cast (obs.get())->AddCell(aRowIndex, aCol); + } + return NS_OK; } } diff --git a/layout/xul/base/src/tree/src/nsTreeBodyFrame.h b/layout/xul/base/src/tree/src/nsTreeBodyFrame.h index 4a0bfea577d8..69127614a90b 100644 --- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.h +++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.h @@ -61,7 +61,6 @@ #include "nsScrollbarFrame.h" #include "nsThreadUtils.h" #include "mozilla/LookAndFeel.h" -#include "nsITreeImageListener.h" class nsOverflowChecker; class nsTreeImageListener; diff --git a/layout/xul/base/src/tree/src/nsTreeImageListener.cpp b/layout/xul/base/src/tree/src/nsTreeImageListener.cpp index eb16264847e1..3155f5d9224f 100644 --- a/layout/xul/base/src/tree/src/nsTreeImageListener.cpp +++ b/layout/xul/base/src/tree/src/nsTreeImageListener.cpp @@ -42,7 +42,7 @@ #include "imgIRequest.h" #include "imgIContainer.h" -NS_IMPL_ISUPPORTS3(nsTreeImageListener, imgIDecoderObserver, imgIContainerObserver, nsITreeImageListener) +NS_IMPL_ISUPPORTS2(nsTreeImageListener, imgIDecoderObserver, imgIContainerObserver) nsTreeImageListener::nsTreeImageListener(nsTreeBodyFrame* aTreeFrame) : mTreeFrame(aTreeFrame), @@ -92,7 +92,7 @@ NS_IMETHODIMP nsTreeImageListener::FrameChanged(imgIContainer *aContainer, } -NS_IMETHODIMP +void nsTreeImageListener::AddCell(PRInt32 aIndex, nsITreeColumn* aCol) { if (!mInvalidationArea) { @@ -114,8 +114,6 @@ nsTreeImageListener::AddCell(PRInt32 aIndex, nsITreeColumn* aCol) mInvalidationArea->AddRow(aIndex); } } - - return NS_OK; } diff --git a/layout/xul/base/src/tree/src/nsTreeImageListener.h b/layout/xul/base/src/tree/src/nsTreeImageListener.h index c32501b38cfa..e0beba4d915b 100644 --- a/layout/xul/base/src/tree/src/nsTreeImageListener.h +++ b/layout/xul/base/src/tree/src/nsTreeImageListener.h @@ -45,10 +45,9 @@ #include "nsITreeColumns.h" #include "nsStubImageDecoderObserver.h" #include "nsTreeBodyFrame.h" -#include "nsITreeImageListener.h" // This class handles image load observation. -class nsTreeImageListener : public nsStubImageDecoderObserver, public nsITreeImageListener +class nsTreeImageListener : public nsStubImageDecoderObserver { public: nsTreeImageListener(nsTreeBodyFrame *aTreeFrame); @@ -64,7 +63,6 @@ public: NS_IMETHOD FrameChanged(imgIContainer *aContainer, const nsIntRect *aDirtyRect); - NS_IMETHOD AddCell(PRInt32 aIndex, nsITreeColumn* aCol); NS_IMETHOD ClearFrame(); friend class nsTreeBodyFrame; @@ -72,6 +70,7 @@ public: protected: void UnsuppressInvalidation() { mInvalidationSuppressed = false; } void Invalidate(); + void AddCell(PRInt32 aIndex, nsITreeColumn* aCol); private: nsTreeBodyFrame* mTreeFrame; From 25e07cffd050415affefcaf3e013b2ca0570c291 Mon Sep 17 00:00:00 2001 From: Scott Johnson Date: Tue, 15 Nov 2011 15:45:43 +1300 Subject: [PATCH 02/34] Bug 702503 - Remove PR_TRUE/PR_FALSE added with bug 666446 and replace with bool values. r=dholbert --HG-- extra : rebase_source : 6156ccbce49e7eeeb38488802a6f100d419b8335 --- image/src/RasterImage.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index 8c730cf238ca..3b656ce3aa21 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -346,7 +346,7 @@ RasterImage::AdvanceFrame(TimeStamp aTime, nsIntRect* aDirtyRect) // If animation mode is "loop once", it's time to stop animating if (mAnimationMode == kLoopOnceAnimMode || mLoopCount == 0) { - mAnimationFinished = PR_TRUE; + mAnimationFinished = true; EvaluateAnimation(); } @@ -383,7 +383,7 @@ RasterImage::AdvanceFrame(TimeStamp aTime, nsIntRect* aDirtyRect) } if (!(timeout > 0)) { - mAnimationFinished = PR_TRUE; + mAnimationFinished = true; EvaluateAnimation(); } @@ -404,13 +404,13 @@ RasterImage::AdvanceFrame(TimeStamp aTime, nsIntRect* aDirtyRect) nextFrame, nextFrameIndex))) { // something went wrong, move on to next NS_WARNING("RasterImage::AdvanceFrame(): Compositing of frame failed"); - nextFrame->SetCompositingFailed(PR_TRUE); + nextFrame->SetCompositingFailed(true); mAnim->currentAnimationFrameIndex = nextFrameIndex; mAnim->currentAnimationFrameTime = aTime; return false; } - nextFrame->SetCompositingFailed(PR_FALSE); + nextFrame->SetCompositingFailed(false); } // Set currentAnimationFrameIndex at the last possible moment From 34e1635026f70a239465fbc09bab938197d83455 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:00 +1300 Subject: [PATCH 03/34] Add support for -moz-text-size-adjust CSS property. (Bug 627842, patch 1) r=bzbarsky This property is analogous to the -webkit-text-size-adjust property (and *maybe* also the -ms-text-size-adjust property). It allows pages to opt out of text size adjustments performed on mobile devices by specifying -moz-text-size-adjust: none. --- dom/interfaces/css/nsIDOMCSS2Properties.idl | 5 ++++- layout/base/nsStyleConsts.h | 4 ++++ layout/style/nsCSSPropList.h | 9 +++++++++ layout/style/nsComputedDOMStyle.cpp | 19 +++++++++++++++++++ layout/style/nsComputedDOMStyle.h | 1 + layout/style/nsRuleNode.cpp | 9 +++++++++ layout/style/nsStyleStruct.cpp | 3 +++ layout/style/nsStyleStruct.h | 1 + layout/style/test/property_database.js | 8 ++++++++ 9 files changed, 58 insertions(+), 1 deletion(-) diff --git a/dom/interfaces/css/nsIDOMCSS2Properties.idl b/dom/interfaces/css/nsIDOMCSS2Properties.idl index 2a968befb870..2942e572dfe7 100644 --- a/dom/interfaces/css/nsIDOMCSS2Properties.idl +++ b/dom/interfaces/css/nsIDOMCSS2Properties.idl @@ -51,7 +51,7 @@ * http://www.w3.org/TR/DOM-Level-2-Style */ -[builtinclass, scriptable, uuid(519ae4fa-0fee-4aaa-bcb9-34b503236801)] +[builtinclass, scriptable, uuid(0a6fc4c6-a62a-4f52-9ab6-3d398b958843)] interface nsIDOMCSS2Properties : nsISupports { attribute DOMString background; @@ -764,4 +764,7 @@ interface nsIDOMCSS2Properties : nsISupports attribute DOMString MozAnimation; // raises(DOMException) on setting + + attribute DOMString MozTextSizeAdjust; + // raises(DOMException) on setting }; diff --git a/layout/base/nsStyleConsts.h b/layout/base/nsStyleConsts.h index 68985b6471dd..7b0cec3c2199 100644 --- a/layout/base/nsStyleConsts.h +++ b/layout/base/nsStyleConsts.h @@ -713,6 +713,10 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) { #define NS_STYLE_HYPHENS_MANUAL 1 #define NS_STYLE_HYPHENS_AUTO 2 +// See nsStyleText +#define NS_STYLE_TEXT_SIZE_ADJUST_NONE 0 +#define NS_STYLE_TEXT_SIZE_ADJUST_AUTO 1 + // See nsStyleText #define NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT 0 diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h index a075798442f8..69268eee5a4a 100644 --- a/layout/style/nsCSSPropList.h +++ b/layout/style/nsCSSPropList.h @@ -2235,6 +2235,15 @@ CSS_PROP_TEXT( nsnull, offsetof(nsStyleText, mTextShadow), eStyleAnimType_Shadow) +CSS_PROP_TEXT( + -moz-text-size-adjust, + text_size_adjust, + CSS_PROP_DOMPROP_PREFIXED(TextSizeAdjust), + CSS_PROPERTY_PARSE_VALUE, + VARIANT_AUTO | VARIANT_NONE | VARIANT_INHERIT, + nsnull, + CSS_PROP_NO_OFFSET, + eStyleAnimType_None) CSS_PROP_TEXT( text-transform, text_transform, diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 5363e010fbe8..a0eebfff5439 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -2643,6 +2643,24 @@ nsComputedDOMStyle::DoGetHyphens() return val; } +nsIDOMCSSValue* +nsComputedDOMStyle::DoGetTextSizeAdjust() +{ + nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue(); + switch (GetStyleText()->mTextSizeAdjust) { + default: + NS_NOTREACHED("unexpected value"); + // fall through + case NS_STYLE_TEXT_SIZE_ADJUST_AUTO: + val->SetIdent(eCSSKeyword_auto); + break; + case NS_STYLE_TEXT_SIZE_ADJUST_NONE: + val->SetIdent(eCSSKeyword_none); + break; + } + return val; +} + nsIDOMCSSValue* nsComputedDOMStyle::DoGetPointerEvents() { @@ -4579,6 +4597,7 @@ nsComputedDOMStyle::GetQueryablePropertyMap(PRUint32* aLength) COMPUTED_STYLE_MAP_ENTRY(text_decoration_color, MozTextDecorationColor), COMPUTED_STYLE_MAP_ENTRY(text_decoration_line, MozTextDecorationLine), COMPUTED_STYLE_MAP_ENTRY(text_decoration_style, MozTextDecorationStyle), + COMPUTED_STYLE_MAP_ENTRY(text_size_adjust, TextSizeAdjust), COMPUTED_STYLE_MAP_ENTRY_LAYOUT(_moz_transform, MozTransform), COMPUTED_STYLE_MAP_ENTRY_LAYOUT(_moz_transform_origin, MozTransformOrigin), COMPUTED_STYLE_MAP_ENTRY(transform_style, MozTransformStyle), diff --git a/layout/style/nsComputedDOMStyle.h b/layout/style/nsComputedDOMStyle.h index 37e95178631b..d1a432136bdd 100644 --- a/layout/style/nsComputedDOMStyle.h +++ b/layout/style/nsComputedDOMStyle.h @@ -322,6 +322,7 @@ private: nsIDOMCSSValue* DoGetWordWrap(); nsIDOMCSSValue* DoGetHyphens(); nsIDOMCSSValue* DoGetMozTabSize(); + nsIDOMCSSValue* DoGetTextSizeAdjust(); /* Visibility properties */ nsIDOMCSSValue* DoGetOpacity(); diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 27336bf8ea5b..2e7a332edad0 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -3398,6 +3398,15 @@ nsRuleNode::ComputeTextData(void* aStartStruct, SETDSC_ENUMERATED, parentText->mHyphens, NS_STYLE_HYPHENS_MANUAL, 0, 0, 0, 0); + // text-size-adjust: none, auto, inherit, initial + SetDiscrete(*aRuleData->ValueForTextSizeAdjust(), text->mTextSizeAdjust, + canStoreInRuleTree, SETDSC_NONE | SETDSC_AUTO, + parentText->mTextSizeAdjust, + NS_STYLE_TEXT_SIZE_ADJUST_AUTO, // initial value + NS_STYLE_TEXT_SIZE_ADJUST_AUTO, // auto value + NS_STYLE_TEXT_SIZE_ADJUST_NONE, // none value + 0, 0); + COMPUTE_END_INHERITED(Text, text) } diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index 988070a0bd26..559b45d60caa 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -2800,6 +2800,7 @@ nsStyleText::nsStyleText(void) mWhiteSpace = NS_STYLE_WHITESPACE_NORMAL; mWordWrap = NS_STYLE_WORDWRAP_NORMAL; mHyphens = NS_STYLE_HYPHENS_MANUAL; + mTextSizeAdjust = NS_STYLE_TEXT_SIZE_ADJUST_AUTO; mLetterSpacing.SetNormalValue(); mLineHeight.SetNormalValue(); @@ -2816,6 +2817,7 @@ nsStyleText::nsStyleText(const nsStyleText& aSource) mWhiteSpace(aSource.mWhiteSpace), mWordWrap(aSource.mWordWrap), mHyphens(aSource.mHyphens), + mTextSizeAdjust(aSource.mTextSizeAdjust), mTabSize(aSource.mTabSize), mLetterSpacing(aSource.mLetterSpacing), mLineHeight(aSource.mLineHeight), @@ -2843,6 +2845,7 @@ nsChangeHint nsStyleText::CalcDifference(const nsStyleText& aOther) const (mWhiteSpace != aOther.mWhiteSpace) || (mWordWrap != aOther.mWordWrap) || (mHyphens != aOther.mHyphens) || + (mTextSizeAdjust != aOther.mTextSizeAdjust) || (mLetterSpacing != aOther.mLetterSpacing) || (mLineHeight != aOther.mLineHeight) || (mTextIndent != aOther.mTextIndent) || diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 332b089d570c..d8114caec12c 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -1280,6 +1280,7 @@ struct nsStyleText { PRUint8 mWhiteSpace; // [inherited] see nsStyleConsts.h PRUint8 mWordWrap; // [inherited] see nsStyleConsts.h PRUint8 mHyphens; // [inherited] see nsStyleConsts.h + PRUint8 mTextSizeAdjust; // [inherited] see nsStyleConsts.h PRInt32 mTabSize; // [inherited] see nsStyleConsts.h nsStyleCoord mLetterSpacing; // [inherited] coord, normal diff --git a/layout/style/test/property_database.js b/layout/style/test/property_database.js index 1e20b45c21bf..7d7f231f5667 100644 --- a/layout/style/test/property_database.js +++ b/layout/style/test/property_database.js @@ -925,6 +925,14 @@ var gCSSProperties = { other_values: [ "0", "3", "99", "12000" ], invalid_values: [ "-1", "-808", "3.0", "17.5" ] }, + "-moz-text-size-adjust": { + domProp: "MozTextSizeAdjust", + inherited: true, + type: CSS_TYPE_LONGHAND, + initial_values: [ "auto" ], + other_values: [ "none" ], + invalid_values: [ "-5%", "0", "100", "0%", "50%", "100%", "220.3%" ] + }, "-moz-transform": { domProp: "MozTransform", inherited: false, From 4aff8b6cdff94c6bf612e50a57972e69e96248b0 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:00 +1300 Subject: [PATCH 04/34] Set an NS_FRAME_IN_CONSTRAINED_HEIGHT state bit on frames that are in a constrained space. (Bug 627842, patch 2) r=roc --- layout/generic/nsHTMLReflowState.cpp | 13 +++++++++++++ layout/generic/nsIFrame.h | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp index 58d22c684a34..a1d5b79a7c49 100644 --- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -289,6 +289,19 @@ nsHTMLReflowState::Init(nsPresContext* aPresContext, InitResizeFlags(aPresContext, type); + nsIFrame *parent = frame->GetParent(); + if (parent && + (parent->GetStateBits() & NS_FRAME_IN_CONSTRAINED_HEIGHT) && + !(parent->GetType() == nsGkAtoms::scrollFrame && + parent->GetStyleDisplay()->mOverflowY != NS_STYLE_OVERFLOW_HIDDEN)) { + frame->AddStateBits(NS_FRAME_IN_CONSTRAINED_HEIGHT); + } else if (mStylePosition->mHeight.GetUnit() != eStyleUnit_Auto || + mStylePosition->mMaxHeight.GetUnit() != eStyleUnit_None) { + frame->AddStateBits(NS_FRAME_IN_CONSTRAINED_HEIGHT); + } else { + frame->RemoveStateBits(NS_FRAME_IN_CONSTRAINED_HEIGHT); + } + NS_WARN_IF_FALSE((mFrameType == NS_CSS_FRAME_TYPE_INLINE && !frame->IsFrameOfType(nsIFrame::eReplaced)) || type == nsGkAtoms::textFrame || diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 470b21aab8df..a57fa31fc7a4 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -293,6 +293,10 @@ typedef PRUint64 nsFrameState; // A display item for this frame has been painted as part of a ThebesLayer. #define NS_FRAME_PAINTED_THEBES NS_FRAME_STATE_BIT(38) +// Frame is or is a descendant of something with a fixed height, and +// has no closer ancestor that is overflow:auto or overflow:scroll. +#define NS_FRAME_IN_CONSTRAINED_HEIGHT NS_FRAME_STATE_BIT(39) + // The lower 20 bits and upper 32 bits of the frame state are reserved // by this API. #define NS_FRAME_RESERVED ~NS_FRAME_IMPL_RESERVED From 01956a72c7e2fa68262c49c10427bdb2b3c49b3b Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:00 +1300 Subject: [PATCH 05/34] When reflowing a frame (such as text controls) that jumps from HTML layout into XUL layout and then jumps back to HTML on the child frame, link the parent reflow state chain correctly. (Bug 627842, patch 3) r=roc --- layout/generic/nsFrame.cpp | 17 +++++++++++++++-- layout/xul/base/src/nsBoxFrame.cpp | 2 +- layout/xul/base/src/nsBoxLayoutState.cpp | 3 +++ layout/xul/base/src/nsBoxLayoutState.h | 10 +++++++++- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index dec6ab3fc65d..34460fe9ecc6 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -7510,8 +7510,21 @@ nsFrame::BoxReflow(nsBoxLayoutState& aState, // Construct the parent chain manually since constructing it normally // messes up dimensions. - reflowState.parentReflowState = &parentReflowState; - reflowState.mCBReflowState = &parentReflowState; + const nsHTMLReflowState *outerReflowState = aState.OuterReflowState(); + NS_ASSERTION(!outerReflowState || outerReflowState->frame != this, + "in and out of XUL on a single frame?"); + if (outerReflowState && outerReflowState->frame == parentFrame) { + // We're a frame (such as a text control frame) that jumps into + // box reflow and then straight out of it on the child frame. + // This means we actually have a real parent reflow state. + // nsLayoutUtils::InflationMinFontSizeFor needs this to be linked + // up correctly for text control frames, so do so here). + reflowState.parentReflowState = outerReflowState; + reflowState.mCBReflowState = outerReflowState; + } else { + reflowState.parentReflowState = &parentReflowState; + reflowState.mCBReflowState = &parentReflowState; + } reflowState.mReflowDepth = aState.GetReflowDepth(); // mComputedWidth and mComputedHeight are content-box, not diff --git a/layout/xul/base/src/nsBoxFrame.cpp b/layout/xul/base/src/nsBoxFrame.cpp index f775d061f847..254aec7c00e0 100644 --- a/layout/xul/base/src/nsBoxFrame.cpp +++ b/layout/xul/base/src/nsBoxFrame.cpp @@ -676,7 +676,7 @@ nsBoxFrame::Reflow(nsPresContext* aPresContext, // create the layout state nsBoxLayoutState state(aPresContext, aReflowState.rendContext, - aReflowState.mReflowDepth); + &aReflowState, aReflowState.mReflowDepth); nsSize computedSize(aReflowState.ComputedWidth(),aReflowState.ComputedHeight()); diff --git a/layout/xul/base/src/nsBoxLayoutState.cpp b/layout/xul/base/src/nsBoxLayoutState.cpp index 8e8b19397d31..f72a11375c1f 100644 --- a/layout/xul/base/src/nsBoxLayoutState.cpp +++ b/layout/xul/base/src/nsBoxLayoutState.cpp @@ -46,9 +46,11 @@ nsBoxLayoutState::nsBoxLayoutState(nsPresContext* aPresContext, nsRenderingContext* aRenderingContext, + const nsHTMLReflowState* aOuterReflowState, PRUint16 aReflowDepth) : mPresContext(aPresContext) , mRenderingContext(aRenderingContext) + , mOuterReflowState(aOuterReflowState) , mLayoutFlags(0) , mReflowDepth(aReflowDepth) , mPaintingDisabled(false) @@ -59,6 +61,7 @@ nsBoxLayoutState::nsBoxLayoutState(nsPresContext* aPresContext, nsBoxLayoutState::nsBoxLayoutState(const nsBoxLayoutState& aState) : mPresContext(aState.mPresContext) , mRenderingContext(aState.mRenderingContext) + , mOuterReflowState(aState.mOuterReflowState) , mLayoutFlags(aState.mLayoutFlags) , mReflowDepth(aState.mReflowDepth + 1) , mPaintingDisabled(aState.mPaintingDisabled) diff --git a/layout/xul/base/src/nsBoxLayoutState.h b/layout/xul/base/src/nsBoxLayoutState.h index 3bec5e05930d..452e30f2a39d 100644 --- a/layout/xul/base/src/nsBoxLayoutState.h +++ b/layout/xul/base/src/nsBoxLayoutState.h @@ -59,7 +59,10 @@ class nsHTMLReflowCommand; class NS_STACK_CLASS nsBoxLayoutState { public: - nsBoxLayoutState(nsPresContext* aPresContext, nsRenderingContext* aRenderingContext = nsnull, + nsBoxLayoutState(nsPresContext* aPresContext, + nsRenderingContext* aRenderingContext = nsnull, + // see OuterReflowState() below + const nsHTMLReflowState* aOuterReflowState = nsnull, PRUint16 aReflowDepth = 0) NS_HIDDEN; nsBoxLayoutState(const nsBoxLayoutState& aState) NS_HIDDEN; @@ -84,11 +87,16 @@ public: void* AllocateStackMemory(size_t aSize) { return PresShell()->AllocateStackMemory(aSize); } + // The HTML reflow state that lives outside the box-block boundary. + // May not be set reliably yet. + const nsHTMLReflowState* OuterReflowState() { return mOuterReflowState; } + PRUint16 GetReflowDepth() { return mReflowDepth; } private: nsRefPtr mPresContext; nsRenderingContext *mRenderingContext; + const nsHTMLReflowState *mOuterReflowState; PRUint32 mLayoutFlags; PRUint16 mReflowDepth; bool mPaintingDisabled; From f3569b9305bc88d2efde6d496fed2288d7cca813 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:00 +1300 Subject: [PATCH 06/34] Don't duplicate frame state bits, so that we can assert about NS_FRAME_IN_REFLOW during painting. (Bug 627842, patch 3.5) r=roc --- layout/generic/nsIFrame.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index a57fa31fc7a4..eeca38cd295b 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -160,9 +160,6 @@ typedef PRUint64 nsFrameState; #define NS_FRAME_IN_REFLOW NS_FRAME_STATE_BIT(0) -// This is only set during painting -#define NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO NS_FRAME_STATE_BIT(0) - // This bit is set when a frame is created. After it has been reflowed // once (during the DidReflow with a finished state) the bit is // cleared. @@ -297,8 +294,10 @@ typedef PRUint64 nsFrameState; // has no closer ancestor that is overflow:auto or overflow:scroll. #define NS_FRAME_IN_CONSTRAINED_HEIGHT NS_FRAME_STATE_BIT(39) -// The lower 20 bits and upper 32 bits of the frame state are reserved -// by this API. +// This is only set during painting +#define NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO NS_FRAME_STATE_BIT(40) + +// Bits 0-19 and bits 32-59 of the frame state are reserved by this API. #define NS_FRAME_RESERVED ~NS_FRAME_IMPL_RESERVED // Box layout bits From ae36de8162dde4f12b05a84123c2df329dc16c3b Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:00 +1300 Subject: [PATCH 07/34] Don't construct cell reflow states with a row group reflow state as their parent; instead, always link in a table row reflow state as appropriate. (Bug 627842, patch 3.875) r=roc Fixes assertion on layout/reftests/bugs/409084-1a.html once the rest of the inflation patches land. --- layout/tables/nsTableRowGroupFrame.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp index 4f50057e5aed..c6c64f49bc23 100644 --- a/layout/tables/nsTableRowGroupFrame.cpp +++ b/layout/tables/nsTableRowGroupFrame.cpp @@ -951,6 +951,8 @@ nsTableRowGroupFrame::SplitSpanningCells(nsPresContext& aPresContext, aFirstTruncatedRow = nsnull; aDesiredHeight = 0; + bool borderCollapse = + static_cast(aTable.GetFirstInFlow())->IsBorderCollapse(); PRInt32 lastRowIndex = aLastRow.GetRowIndex(); bool wasLast = false; // Iterate the rows between aFirstRow and aLastRow @@ -970,7 +972,21 @@ nsTableRowGroupFrame::SplitSpanningCells(nsPresContext& aPresContext, nscoord cellAvailHeight = aSpanningRowBottom - rowPos.y; NS_ASSERTION(cellAvailHeight >= 0, "No space for cell?"); bool isTopOfPage = (row == &aFirstRow) && aFirstRowIsTopOfPage; - nscoord cellHeight = row->ReflowCellFrame(&aPresContext, aReflowState, + + nsRect rowRect = row->GetRect(); + nsSize rowAvailSize(aReflowState.availableWidth, + NS_MAX(aReflowState.availableHeight - rowRect.y, + 0)); + // don't let the available height exceed what + // CalculateRowHeights set for it + rowAvailSize.height = NS_MIN(rowAvailSize.height, rowRect.height); + nsHTMLReflowState rowReflowState(&aPresContext, aReflowState, + row, rowAvailSize, + -1, -1, false); + InitChildReflowState(aPresContext, borderCollapse, rowReflowState); + rowReflowState.mFlags.mIsTopOfPage = isTopOfPage; // set top of page + + nscoord cellHeight = row->ReflowCellFrame(&aPresContext, rowReflowState, isTopOfPage, cell, cellAvailHeight, status); aDesiredHeight = NS_MAX(aDesiredHeight, rowPos.y + cellHeight); From c346e00fe20baeb70ebd67f36a8ba0c2a260531d Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:00 +1300 Subject: [PATCH 08/34] Implement computation of font size inflation for improved readibility of text on mobile devices. (Bug 627842, patch 4) r=roc This implements computation of the font size inflation factor for a given frame. Since Fennec does layout using a fake viewport whose width represents a typical viewport width on the desktop and then allows users to pan and zoom, fonts are not always readable even when zoomed. The goal of this font size inflation is to ensure that when a block of text is zoomed to fill the width of the device, the fonts are large enough to read. We do this by increasing the font sizes in the page. Since this increase is a function of the width of the text's container, the inflation must be performed (in later patches in this series) after style data computation and after intrinsic width computation. The font size inflation factor does not vary *within* a block. Since sync uses a whitelist (the services.sync.prefs.sync.* prefs) for preferences (i.e., preferences are not synced by default), this patch does not make any changes relating to sync, since we do not want the inflation preferences synced across devices (since preferred settings are likely to be device-specific). --- layout/base/nsLayoutUtils.cpp | 319 +++++++++++++++++++++++++++++++ layout/base/nsLayoutUtils.h | 53 +++++ layout/build/nsLayoutStatics.cpp | 1 + mobile/app/mobile.js | 2 + modules/libpref/src/init/all.js | 23 +++ 5 files changed, 398 insertions(+) diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 546abc05996c..795dc1f5539a 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -128,6 +128,9 @@ bool nsLayoutUtils::gPreventAssertInCompareTreePosition = false; typedef gfxPattern::GraphicsFilter GraphicsFilter; typedef FrameMetrics::ViewID ViewID; +static PRUint32 sFontSizeInflationEmPerLine; +static PRUint32 sFontSizeInflationMinTwips; + static ViewID sScrollIdCounter = FrameMetrics::START_SCROLL_ID; typedef nsDataHashtable ContentMap; @@ -4317,6 +4320,16 @@ nsLayoutUtils::GetTextRunMemoryForFrames(nsIFrame* aFrame, PRUint64* aTotal) return NS_OK; } +/* static */ +void +nsLayoutUtils::Initialize() +{ + mozilla::Preferences::AddUintVarCache(&sFontSizeInflationEmPerLine, + "font.size.inflation.emPerLine"); + mozilla::Preferences::AddUintVarCache(&sFontSizeInflationMinTwips, + "font.size.inflation.minTwips"); +} + /* static */ void nsLayoutUtils::Shutdown() @@ -4479,3 +4492,309 @@ nsReflowFrameRunnable::Run() } return NS_OK; } + +/** + * Compute the minimum font size inside of a container with the given + * width, such that **when the user zooms the container to fill the full + * width of the device**, the fonts satisfy our minima. + */ +static nscoord +MinimumFontSizeFor(nsPresContext* aPresContext, nscoord aContainerWidth) +{ + if (sFontSizeInflationEmPerLine == 0 && sFontSizeInflationMinTwips == 0) { + return 0; + } + nscoord byLine = 0, byInch = 0; + if (sFontSizeInflationEmPerLine != 0) { + byLine = aContainerWidth / sFontSizeInflationEmPerLine; + } + if (sFontSizeInflationMinTwips != 0) { + // REVIEW: Is this giving us app units and sizes *not* counting + // viewport scaling? + nsDeviceContext *dx = aPresContext->DeviceContext(); + nsRect clientRect; + dx->GetClientRect(clientRect); // FIXME: GetClientRect looks expensive + float deviceWidthInches = + float(clientRect.width) / float(dx->AppUnitsPerPhysicalInch()); + byInch = NSToCoordRound(aContainerWidth / + (deviceWidthInches * 1440 / + sFontSizeInflationMinTwips )); + } + return NS_MAX(byLine, byInch); +} + +/* static */ float +nsLayoutUtils::FontSizeInflationInner(const nsIFrame *aFrame, + nscoord aMinFontSize) +{ + // Note that line heights should be inflated by the same ratio as the + // font size of the same text; thus we operate only on the font size + // even when we're scaling a line height. + nscoord styleFontSize = aFrame->GetStyleFont()->mFont.size; + if (styleFontSize <= 0) { + // Never scale zero font size. + return 1.0; + } + + if (aMinFontSize <= 0) { + // No need to scale. + return 1.0; + } + + // Scale everything from 0-1.5 times min to instead fit in the range + // 1-1.5 times min, so that we still show some distinction rather than + // just enforcing a minimum. + // FIXME: Fiddle with this algorithm; maybe have prefs to control it? + float ratio = float(styleFontSize) / float(aMinFontSize); + if (ratio >= 1.5f) { + // If we're already at 1.5 or more times the minimum, don't scale. + return 1.0; + } + + // To scale 0-1.5 times min to instead be 1-1.5 times min, we want + // to the desired multiple of min to be 1 + (ratio/3) (where ratio + // is our input's multiple of min). The scaling needed to produce + // that is that divided by |ratio|, or: + return (1.0f / ratio) + (1.0f / 3.0f); +} + +/* static */ bool +nsLayoutUtils::IsContainerForFontSizeInflation(const nsIFrame *aFrame) +{ + /* + * Font size inflation is build around the idea that we're inflating + * the fonts for a pan-and-zoom UI so that when the user scales up a + * block or other container to fill the width of the device, the fonts + * will be readable. To do this, we need to pick what counts as a + * container. + * + * From a code perspective, the only hard requirement is that frames + * that are line participants + * (nsIFrame::IsFrameOfType(nsIFrame::eLineParticipant)) are never + * containers, since line layout assumes that the inflation is + * consistent within a line. + * + * This is not an imposition, since we obviously want a bunch of text + * (possibly with inline elements) flowing within a block to count the + * block (or higher) as its container. + * + * We also want form controls, including the text in the anonymous + * content inside of them, to match each other and the text next to + * them, so they and their anonymous content should also not be a + * container. + * + * There are contexts where it would be nice if some blocks didn't + * count as a container, so that, for example, an indented quotation + * didn't end up with a smaller font size. However, it's hard to + * distinguish these situations where we really do want the indented + * thing to count as a container, so we don't try, and blocks are + * always containers. + */ + bool isInline = aFrame->GetStyleDisplay()->mDisplay == + NS_STYLE_DISPLAY_INLINE || + aFrame->GetContent()->IsInNativeAnonymousSubtree(); + NS_ASSERTION(!aFrame->IsFrameOfType(nsIFrame::eLineParticipant) || isInline, + "line participants must not be containers"); + return !isInline; +} + +static bool +ShouldInflateFontsForContainer(const nsIFrame *aFrame) +{ + // We only want to inflate fonts for text that is in a place + // with room to expand. The question is what the best heuristic for + // that is... + // For now, we're going to use NS_FRAME_IN_CONSTRAINED_HEIGHT, which + // indicates whether the frame is inside something with a constrained + // height (propagating down the tree), but the propagation stops when + // we hit overflow-y: scroll or auto. + return aFrame->GetStyleText()->mTextSizeAdjust != + NS_STYLE_TEXT_SIZE_ADJUST_NONE && + !(aFrame->GetStateBits() & NS_FRAME_IN_CONSTRAINED_HEIGHT); +} + +nscoord +nsLayoutUtils::InflationMinFontSizeFor(const nsHTMLReflowState &aReflowState) +{ +#ifdef DEBUG + { + const nsHTMLReflowState *rs = &aReflowState; + const nsIFrame *f = aReflowState.frame; + for (; rs; rs = rs->parentReflowState, f = f->GetParent()) { + NS_ABORT_IF_FALSE(rs->frame == f, + "reflow state parentage must match frame parentage"); + } + } +#endif + + if (!FontSizeInflationEnabled(aReflowState.frame->PresContext())) { + return 0; + } + + nsIFrame *reflowRoot = nsnull; + for (const nsHTMLReflowState *rs = &aReflowState; rs; + reflowRoot = rs->frame, rs = rs->parentReflowState) { + if (IsContainerForFontSizeInflation(rs->frame)) { + if (!ShouldInflateFontsForContainer(rs->frame)) { + return 0; + } + + NS_ABORT_IF_FALSE(rs->ComputedWidth() != NS_INTRINSICSIZE, + "must have a computed width"); + return MinimumFontSizeFor(aReflowState.frame->PresContext(), + rs->ComputedWidth()); + } + } + + // We've hit the end of the reflow state chain. There are two + // possibilities now: we're either at a reflow root or we're crossing + // into flexbox layout. (Note that sometimes we cross into and out of + // flexbox layout on the same frame, e.g., for nsTextControlFrame, + // which breaks the reflow state parentage chain.) + // This code depends on: + // * When we cross from HTML to XUL and then on the child jump back + // to HTML again, we link the reflow states correctly (see hack in + // nsFrame::BoxReflow setting reflowState.parentReflowState). + // * For any other cases, the XUL frame is a font size inflation + // container, so we won't cross back into HTML (see the conditions + // under which we test the assertion in + // InflationMinFontSizeFor(const nsIFrame *). + + return InflationMinFontSizeFor(reflowRoot->GetParent()); +} + +nscoord +nsLayoutUtils::InflationMinFontSizeFor(const nsIFrame *aFrame) +{ +#ifdef DEBUG + // Check that neither this frame nor any of its ancestors are + // currently being reflowed. + // It's ok for box frames (but not arbitrary ancestors of box frames) + // since they set their size before reflow. + if (!(aFrame->IsBoxFrame() && IsContainerForFontSizeInflation(aFrame))) { + for (const nsIFrame *f = aFrame; f; f = f->GetParent()) { + NS_ABORT_IF_FALSE(!(f->GetStateBits() & NS_FRAME_IN_REFLOW), + "must call nsHTMLReflowState& version during reflow"); + } + } + // It's ok if frames are dirty, or even if they've never been + // reflowed, since they will be eventually and then we'll get the + // right size. +#endif + + if (!FontSizeInflationEnabled(aFrame->PresContext())) { + return 0; + } + + for (const nsIFrame *f = aFrame; f; f = f->GetParent()) { + if (IsContainerForFontSizeInflation(f)) { + if (!ShouldInflateFontsForContainer(f)) { + return 0; + } + + return MinimumFontSizeFor(aFrame->PresContext(), + f->GetContentRect().width); + } + } + + NS_ABORT_IF_FALSE(false, "root should always be container"); + + return 0; +} + +/* static */ nscoord +nsLayoutUtils::InflationMinFontSizeFor(const nsIFrame *aFrame, + nscoord aInflationContainerWidth) +{ + if (!FontSizeInflationEnabled(aFrame->PresContext())) { + return 0; + } + + for (const nsIFrame *f = aFrame; f; f = f->GetParent()) { + if (IsContainerForFontSizeInflation(f)) { + if (!ShouldInflateFontsForContainer(f)) { + return 0; + } + + // The caller is (sketchily) asserting that it picked the right + // container when passing aInflationContainerWidth. We only do + // this for text inputs and a few other limited situations. + return MinimumFontSizeFor(aFrame->PresContext(), + aInflationContainerWidth); + } + } + + NS_ABORT_IF_FALSE(false, "root should always be container"); + + return 0; +} + +float +nsLayoutUtils::FontSizeInflationFor(const nsHTMLReflowState &aReflowState) +{ +#ifdef DEBUG + { + const nsHTMLReflowState *rs = &aReflowState; + const nsIFrame *f = aReflowState.frame; + for (; rs; rs = rs->parentReflowState, f = f->GetParent()) { + NS_ABORT_IF_FALSE(rs->frame == f, + "reflow state parentage must match frame parentage"); + } + } +#endif + + if (!FontSizeInflationEnabled(aReflowState.frame->PresContext())) { + return 1.0; + } + + return FontSizeInflationInner(aReflowState.frame, + InflationMinFontSizeFor(aReflowState)); +} + +float +nsLayoutUtils::FontSizeInflationFor(const nsIFrame *aFrame) +{ +#ifdef DEBUG + // Check that neither this frame nor any of its ancestors are + // currently being reflowed. + // It's ok for box frames (but not arbitrary ancestors of box frames) + // since they set their size before reflow. + if (!(aFrame->IsBoxFrame() && IsContainerForFontSizeInflation(aFrame))) { + for (const nsIFrame *f = aFrame; f; f = f->GetParent()) { + NS_ABORT_IF_FALSE(!(f->GetStateBits() & NS_FRAME_IN_REFLOW), + "must call nsHTMLReflowState& version during reflow"); + } + } + // It's ok if frames are dirty, or even if they've never been + // reflowed, since they will be eventually and then we'll get the + // right size. +#endif + + if (!FontSizeInflationEnabled(aFrame->PresContext())) { + return 1.0; + } + + return FontSizeInflationInner(aFrame, + InflationMinFontSizeFor(aFrame)); +} + +/* static */ float +nsLayoutUtils::FontSizeInflationFor(const nsIFrame *aFrame, + nscoord aInflationContainerWidth) +{ + if (!FontSizeInflationEnabled(aFrame->PresContext())) { + return 1.0; + } + + return FontSizeInflationInner(aFrame, + InflationMinFontSizeFor(aFrame, + aInflationContainerWidth)); +} + +/* static */ bool +nsLayoutUtils::FontSizeInflationEnabled(nsPresContext *aPresContext) +{ + return (sFontSizeInflationEmPerLine != 0 || + sFontSizeInflationMinTwips != 0) && + !aPresContext->IsChrome(); +} diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 623bacb78f67..ae925a6e8df4 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -1452,6 +1452,59 @@ public: */ static bool Are3DTransformsEnabled(); + /** + * Return whether this is a frame whose width is used when computing + * the font size inflation of its descendants. + */ + static bool IsContainerForFontSizeInflation(const nsIFrame *aFrame); + + /** + * Return the font size inflation *ratio* for a given frame. This is + * the factor by which font sizes should be inflated; it is never + * smaller than 1. + * + * There are three variants: pass a reflow state if the frame or any + * of its ancestors are currently being reflowed and a frame + * otherwise, or, if you know the width of the inflation container (a + * somewhat sketchy assumption), its width. + */ + static float FontSizeInflationFor(const nsHTMLReflowState &aReflowState); + static float FontSizeInflationFor(const nsIFrame *aFrame); + static float FontSizeInflationFor(const nsIFrame *aFrame, + nscoord aInflationContainerWidth); + + /** + * Perform the first half of the computation of FontSizeInflationFor + * (see above). + * This includes determining whether inflation should be performed + * within this container and returning 0 if it should not be. + * + * The result is guaranteed not to vary between line participants + * (inlines, text frames) within a line. + * + * The result should not be used directly since font sizes slightly + * above the minimum should always be adjusted as done by + * FontSizeInflationInner. + */ + static nscoord InflationMinFontSizeFor(const nsHTMLReflowState + &aReflowState); + static nscoord InflationMinFontSizeFor(const nsIFrame *aFrame); + static nscoord InflationMinFontSizeFor(const nsIFrame *aFrame, + nscoord aInflationContainerWidth); + + /** + * Perform the second half of the computation done by + * FontSizeInflationFor (see above). + * + * aMinFontSize must be the result of one of the + * InflationMinFontSizeFor methods above. + */ + static float FontSizeInflationInner(const nsIFrame *aFrame, + nscoord aMinFontSize); + + static bool FontSizeInflationEnabled(nsPresContext *aPresContext); + + static void Initialize(); static void Shutdown(); /** diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index 645d48eee0da..3fa323e25ca0 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -258,6 +258,7 @@ nsLayoutStatics::Initialize() nsContentSink::InitializeStatics(); nsHtml5Module::InitializeStatics(); + nsLayoutUtils::Initialize(); nsIPresShell::InitializeStatics(); nsRefreshDriver::InitializeStatics(); diff --git a/mobile/app/mobile.js b/mobile/app/mobile.js index b49fd031cf3b..5271c1534bba 100644 --- a/mobile/app/mobile.js +++ b/mobile/app/mobile.js @@ -419,6 +419,8 @@ pref("browser.ui.zoom.animationDuration", 200); // ms duration of double-tap zoo pref("browser.ui.zoom.reflow", false); // Change text wrapping on double-tap pref("browser.ui.zoom.reflow.fontSize", 720); +pref("font.size.inflation.minTwips", 160); + // pinch gesture pref("browser.ui.pinch.maxGrowth", 150); // max pinch distance growth pref("browser.ui.pinch.maxShrink", 200); // max pinch distance shrinkage diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 22d65a43ad80..89030231cc1e 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -1538,6 +1538,29 @@ pref("font.minimum-size.x-western", 0); pref("font.minimum-size.x-unicode", 0); pref("font.minimum-size.x-user-def", 0); +/* + * A value greater than zero enables font size inflation for + * pan-and-zoom UIs, so that the fonts in a block are at least the size + * that, if a block's width is scaled to match the device's width, the + * fonts in the block are big enough that at most the pref value ems of + * text fit in *the width of the device*. + * + * When both this pref and the next are set, the larger inflation is + * used. + */ +pref("font.size.inflation.emPerLine", 0); +/* + * A value greater than zero enables font size inflation for + * pan-and-zoom UIs, so that if a block's width is scaled to match the + * device's width, the fonts in a block are at least the font size + * given. The value given is in twips, i.e., 1/20 of a point, or 1/1440 + * of an inch. + * + * When both this pref and the previous are set, the larger inflation is + * used. + */ +pref("font.size.inflation.minTwips", 0); + #ifdef XP_WIN pref("font.name.serif.ar", "Times New Roman"); From b5f3e65d175cb1b0cdeef5f6539045fe72da7b34 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:00 +1300 Subject: [PATCH 09/34] When font size inflation is enabled, horizontal resizes of blocks must cause a full dirty reflow. (Bug 627842, patch 5) r=bzbarsky This change is sufficient because the places that set mHResize to true other than InitResizeFlags and nsFrame::BoxReflow aren't a problem because they're in table code whose goal is to force the reflow to propagate down to the cell, and once we reach the cell we'll hit the code we've added here. --- layout/generic/nsFrame.cpp | 10 +++++++++- layout/generic/nsHTMLReflowState.cpp | 25 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 34460fe9ecc6..85fa63a9c663 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -7569,8 +7569,16 @@ nsFrame::BoxReflow(nsBoxLayoutState& aState, // mLastSize before calling Reflow and then switching it back, but // However, mLastSize can also be the size passed to BoxReflow by // RefreshSizeCache, so that doesn't really make sense. - if (metrics->mLastSize.width != aWidth) + if (metrics->mLastSize.width != aWidth) { reflowState.mFlags.mHResize = true; + + // When font size inflation is enabled, a horizontal resize + // requires a full reflow. See nsHTMLReflowState::InitResizeFlags + // for more details. + if (nsLayoutUtils::FontSizeInflationEnabled(aPresContext)) { + AddStateBits(NS_FRAME_IS_DIRTY); + } + } if (metrics->mLastSize.height != aHeight) reflowState.mFlags.mVResize = true; diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp index a1d5b79a7c49..63bc722097cc 100644 --- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -365,6 +365,31 @@ nsHTMLReflowState::InitResizeFlags(nsPresContext* aPresContext, nsIAtom* aFrameT 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). From c8a116a10b07a65c4d270dabc7bc4aad3bc6105e Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:00 +1300 Subject: [PATCH 10/34] Add inflation parameter to nsLayoutUtils::GetFontMetricsFor* methods. (Bug 627842, patch 6) r=roc --- layout/base/nsLayoutUtils.cpp | 14 +++++++++----- layout/base/nsLayoutUtils.h | 8 ++++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 795dc1f5539a..e39dd12af704 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1928,22 +1928,26 @@ nsLayoutUtils::GetTextShadowRectsUnion(const nsRect& aTextAndDecorationsRect, nsresult nsLayoutUtils::GetFontMetricsForFrame(const nsIFrame* aFrame, - nsFontMetrics** aFontMetrics) + nsFontMetrics** aFontMetrics, + float aInflation) { return nsLayoutUtils::GetFontMetricsForStyleContext(aFrame->GetStyleContext(), - aFontMetrics); + aFontMetrics, + aInflation); } nsresult nsLayoutUtils::GetFontMetricsForStyleContext(nsStyleContext* aStyleContext, - nsFontMetrics** aFontMetrics) + nsFontMetrics** aFontMetrics, + float aInflation) { // pass the user font set object into the device context to pass along to CreateFontGroup gfxUserFontSet* fs = aStyleContext->PresContext()->GetUserFontSet(); + nsFont font = aStyleContext->GetStyleFont()->mFont; + font.size = NSToCoordRound(font.size * aInflation); return aStyleContext->PresContext()->DeviceContext()->GetMetricsFor( - aStyleContext->GetStyleFont()->mFont, - aStyleContext->GetStyleVisibility()->mLanguage, + font, aStyleContext->GetStyleVisibility()->mLanguage, fs, *aFontMetrics); } diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index ae925a6e8df4..ecd6d66528d4 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -742,19 +742,23 @@ public: * Get the font metrics corresponding to the frame's style data. * @param aFrame the frame * @param aFontMetrics the font metrics result + * @param aSizeInflation number to multiply font size by * @return success or failure code */ static nsresult GetFontMetricsForFrame(const nsIFrame* aFrame, - nsFontMetrics** aFontMetrics); + nsFontMetrics** aFontMetrics, + float aSizeInflation = 1.0f); /** * Get the font metrics corresponding to the given style data. * @param aStyleContext the style data * @param aFontMetrics the font metrics result + * @param aSizeInflation number to multiply font size by * @return success or failure code */ static nsresult GetFontMetricsForStyleContext(nsStyleContext* aStyleContext, - nsFontMetrics** aFontMetrics); + nsFontMetrics** aFontMetrics, + float aSizeInflation = 1.0f); /** * Find the immediate child of aParent whose frame subtree contains From 718291d781ede173bcc41a380d3ea48dd935024b Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:01 +1300 Subject: [PATCH 11/34] Use the text run's font group for the tab width instead of recomputing it from the frame. (Bug 627842, patch 7) r=roc --- layout/generic/nsTextFrameThebes.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index f7868013594d..9c6970e781e8 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -2757,8 +2757,7 @@ ComputeTabWidthAppUnits(nsIFrame* aFrame, gfxTextRun* aTextRun) // Round the space width when converting to appunits the same way // textruns do gfxFloat spaceWidthAppUnits = - NS_round(GetFirstFontMetrics( - GetFontGroupForFrame(aFrame)).spaceWidth * + NS_round(GetFirstFontMetrics(aTextRun->GetFontGroup()).spaceWidth * aTextRun->GetAppUnitsPerDevUnit()); return textStyle->mTabSize * spaceWidthAppUnits; } From e369aa454d4ebd9ac6607d88dfd57ab4ad422de2 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:01 +1300 Subject: [PATCH 12/34] Pass block's reflow state to nsTextFrame::UnionAdditionalOverflow. (Bug 627842, patch 8) r=roc --- layout/generic/nsLineLayout.cpp | 2 +- layout/generic/nsLineLayout.h | 3 +++ layout/generic/nsTextFrame.h | 4 +++- layout/generic/nsTextFrameThebes.cpp | 10 ++++++---- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp index 33bcafda658e..83bd073fccbb 100644 --- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -2619,7 +2619,7 @@ nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsOverflowAreas& aOverflo if (pfd->GetFlag(PFD_RECOMPUTEOVERFLOW) || frame->GetStyleContext()->HasTextDecorationLines()) { nsTextFrame* f = static_cast(frame); - r = f->RecomputeOverflow(); + r = f->RecomputeOverflow(*mBlockReflowState); } frame->FinishAndStoreOverflow(r, frame->GetSize()); } diff --git a/layout/generic/nsLineLayout.h b/layout/generic/nsLineLayout.h index 91eb19a61e37..9a42d97d8933 100644 --- a/layout/generic/nsLineLayout.h +++ b/layout/generic/nsLineLayout.h @@ -369,6 +369,9 @@ public: * context (e.g. MathML or floating first-letter). */ nsIFrame* GetLineContainerFrame() const { return mBlockReflowState->frame; } + const nsHTMLReflowState* GetLineContainerRS() const { + return mBlockReflowState; + } const nsLineList::iterator* GetLine() const { return GetFlag(LL_GOTLINEBOX) ? &mLineBox : nsnull; } diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index d522ffcc8ae0..ad18f1ccb3cc 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -264,7 +264,8 @@ public: PRUint32 aSkippedStartOffset = 0, PRUint32 aSkippedMaxLength = PR_UINT32_MAX); - nsOverflowAreas RecomputeOverflow(); + nsOverflowAreas + RecomputeOverflow(const nsHTMLReflowState& aBlockReflowState); void AddInlineMinWidthForFlow(nsRenderingContext *aRenderingContext, nsIFrame::InlineMinWidthData *aData); @@ -434,6 +435,7 @@ protected: SelectionDetails* GetSelectionDetails(); void UnionAdditionalOverflow(nsPresContext* aPresContext, + const nsHTMLReflowState& aBlockReflowState, PropertyProvider& aProvider, nsRect* aVisualOverflowRect, bool aIncludeTextDecorations); diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 9c6970e781e8..566713f5c161 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -4375,6 +4375,7 @@ nsTextFrame::GetTextDecorations(nsPresContext* aPresContext, void nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext, + const nsHTMLReflowState& aBlockReflowState, PropertyProvider& aProvider, nsRect* aVisualOverflowRect, bool aIncludeTextDecorations) @@ -7306,8 +7307,8 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, // When we have text decorations, we don't need to compute their overflow now // because we're guaranteed to do it later // (see nsLineLayout::RelativePositionFrames) - UnionAdditionalOverflow(presContext, provider, &aMetrics.VisualOverflow(), - false); + UnionAdditionalOverflow(presContext, *aLineLayout.GetLineContainerRS(), + provider, &aMetrics.VisualOverflow(), false); ///////////////////////////////////////////////////////////////////// // Clean up, update state @@ -7544,7 +7545,7 @@ nsTextFrame::TrimTrailingWhiteSpace(nsRenderingContext* aRC) } nsOverflowAreas -nsTextFrame::RecomputeOverflow() +nsTextFrame::RecomputeOverflow(const nsHTMLReflowState& aBlockReflowState) { nsRect bounds(nsPoint(0, 0), GetSize()); nsOverflowAreas result(bounds, bounds); @@ -7563,7 +7564,8 @@ nsTextFrame::RecomputeOverflow() &provider); nsRect &vis = result.VisualOverflow(); vis.UnionRect(vis, RoundOut(textMetrics.mBoundingBox) + nsPoint(0, mAscent)); - UnionAdditionalOverflow(PresContext(), provider, &vis, true); + UnionAdditionalOverflow(PresContext(), aBlockReflowState, provider, + &vis, true); return result; } static PRUnichar TransformChar(const nsStyleText* aStyle, gfxTextRun* aTextRun, From 37e8b4fd87dc3a773730c716ebee7ed7324ea0f6 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:01 +1300 Subject: [PATCH 13/34] Apply font size inflation to text. (Bug 627842, patch 9) r=roc This applies the font size inflation to reflow and painting of text frames. However, it does not (by design) apply to intrinsic width computation, since the inflation is itself a function of the containers width, which can depend on the intrinsic width. --- content/base/src/nsRange.cpp | 6 +- layout/base/nsLayoutUtils.cpp | 19 +- layout/generic/nsTextFrame.h | 67 +++- layout/generic/nsTextFrameThebes.cpp | 437 +++++++++++++++++++-------- 4 files changed, 382 insertions(+), 147 deletions(-) diff --git a/content/base/src/nsRange.cpp b/content/base/src/nsRange.cpp index 30d2e9245af4..49fb52ae3d2b 100644 --- a/content/base/src/nsRange.cpp +++ b/content/base/src/nsRange.cpp @@ -2167,9 +2167,9 @@ static nsresult GetPartialTextRect(nsLayoutUtils::RectCallback* aCallback, continue; // overlapping with the offset we want - f->EnsureTextRun(); - NS_ENSURE_TRUE(f->GetTextRun(), NS_ERROR_OUT_OF_MEMORY); - bool rtl = f->GetTextRun()->IsRightToLeft(); + f->EnsureTextRun(nsTextFrame::eInflated); + NS_ENSURE_TRUE(f->GetTextRun(nsTextFrame::eInflated), NS_ERROR_OUT_OF_MEMORY); + bool rtl = f->GetTextRun(nsTextFrame::eInflated)->IsRightToLeft(); nsRect r(f->GetOffsetTo(relativeTo), f->GetSize()); if (fstart < aStartOffset) { // aStartOffset is within this frame diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index e39dd12af704..17ca9bc52c56 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -4275,8 +4275,8 @@ nsLayoutUtils::GetFontFacesForText(nsIFrame* aFrame, } // overlapping with the offset we want - gfxSkipCharsIterator iter = curr->EnsureTextRun(); - gfxTextRun* textRun = curr->GetTextRun(); + gfxSkipCharsIterator iter = curr->EnsureTextRun(nsTextFrame::eInflated); + gfxTextRun* textRun = curr->GetTextRun(nsTextFrame::eInflated); NS_ENSURE_TRUE(textRun, NS_ERROR_OUT_OF_MEMORY); PRUint32 skipStart = iter.ConvertOriginalToSkipped(fstart); @@ -4299,12 +4299,15 @@ nsLayoutUtils::GetTextRunMemoryForFrames(nsIFrame* aFrame, PRUint64* aTotal) if (aFrame->GetType() == nsGkAtoms::textFrame) { nsTextFrame* textFrame = static_cast(aFrame); - gfxTextRun *run = textFrame->GetTextRun(); - if (run) { - if (aTotal) { - run->AccountForSize(aTotal); - } else { - run->ClearSizeAccounted(); + for (PRUint32 i = 0; i < 2; ++i) { + gfxTextRun *run = textFrame->GetTextRun( + (i != 0) ? nsTextFrame::eInflated : nsTextFrame::eNotInflated); + if (run) { + if (aTotal) { + run->AccountForSize(aTotal); + } else { + run->ClearSizeAccounted(); + } } } return NS_OK; diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index ad18f1ccb3cc..36463cdadfb3 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -65,13 +65,16 @@ class PropertyProvider; // reflow #define TEXT_HAS_NONCOLLAPSED_CHARACTERS NS_FRAME_STATE_BIT(31) +#define TEXT_HAS_FONT_INFLATION NS_FRAME_STATE_BIT(61) + class nsTextFrame : public nsFrame { public: NS_DECL_FRAMEARENA_HELPERS friend class nsContinuingTextFrame; - nsTextFrame(nsStyleContext* aContext) : nsFrame(aContext) + nsTextFrame(nsStyleContext* aContext) + : nsFrame(aContext) { NS_ASSERTION(mContentOffset == 0, "Bogus content offset"); } @@ -225,7 +228,13 @@ public: #ifdef ACCESSIBILITY virtual already_AddRefed CreateAccessible(); #endif - + + float GetFontSizeInflation() const; + bool HasFontSizeInflation() const { + return (GetStateBits() & TEXT_HAS_FONT_INFLATION) != 0; + } + void SetFontSizeInflation(float aInflation); + virtual void MarkIntrinsicWidthsDirty(); virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext); virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext); @@ -366,6 +375,16 @@ public: // boundary. PRInt32 GetInFlowContentLength(); + enum TextRunType { + // Anything in reflow (but not intrinsic width calculation) or + // painting should use the inflated text run (i.e., with font size + // inflation applied). + eInflated, + // Intrinsic width calculation should use the non-inflated text run. + // When there is font size inflation, it will be different. + eNotInflated + }; + /** * Acquires the text run for this content, if necessary. * @param aRC the rendering context to use as a reference for creating @@ -378,19 +397,49 @@ public: * to offsets into the textrun; its initial offset is set to this frame's * content offset */ - gfxSkipCharsIterator EnsureTextRun(gfxContext* aReferenceContext = nsnull, + gfxSkipCharsIterator EnsureTextRun(TextRunType aWhichTextRun, + float aInflation, + gfxContext* aReferenceContext = nsnull, nsIFrame* aLineContainer = nsnull, const nsLineList::iterator* aLine = nsnull, PRUint32* aFlowEndInTextRun = nsnull); + // Since we can't reference |this| in default arguments: + gfxSkipCharsIterator EnsureTextRun(TextRunType aWhichTextRun) { + return EnsureTextRun(aWhichTextRun, + (aWhichTextRun == eInflated) + ? GetFontSizeInflation() : 1.0f); + } - gfxTextRun* GetTextRun() { return mTextRun; } - void SetTextRun(gfxTextRun* aTextRun) { mTextRun = aTextRun; } + + gfxTextRun* GetTextRun(TextRunType aWhichTextRun) { + if (aWhichTextRun == eInflated || !HasFontSizeInflation()) + return mTextRun; + return GetUninflatedTextRun(); + } + gfxTextRun* GetUninflatedTextRun(); + void SetTextRun(gfxTextRun* aTextRun, TextRunType aWhichTextRun, + float aInflation); /** - * Clears out |mTextRun| from all frames that hold a reference to it, - * starting at |aStartContinuation|, or if it's nsnull, starting at |this|. - * Deletes |mTextRun| if all references were cleared and it's not cached. + * Notify the frame that it should drop its pointer to a text run. + * Returns whether the text run was removed (i.e., whether it was + * associated with this frame, either as its inflated or non-inflated + * text run. */ - void ClearTextRun(nsTextFrame* aStartContinuation); + bool RemoveTextRun(gfxTextRun* aTextRun); + /** + * Clears out |mTextRun| (or the uninflated text run, when aInflated + * is nsTextFrame::eNotInflated and there is inflation) from all frames that hold a + * reference to it, starting at |aStartContinuation|, or if it's + * nsnull, starting at |this|. Deletes the text run if all references + * were cleared and it's not cached. + */ + void ClearTextRun(nsTextFrame* aStartContinuation, + TextRunType aWhichTextRun); + + void ClearTextRuns() { + ClearTextRun(nsnull, nsTextFrame::eInflated); + ClearTextRun(nsnull, nsTextFrame::eNotInflated); + } // Get the DOM content range mapped by this frame after excluding // whitespace subject to start-of-line and end-of-line trimming. diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 566713f5c161..1800cc367a0f 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -187,6 +187,11 @@ NS_DECLARE_FRAME_PROPERTY(TabWidthProperty, DestroyTabWidth) NS_DECLARE_FRAME_PROPERTY(OffsetToFrameProperty, nsnull) +// text runs are destroyed by the text run cache +NS_DECLARE_FRAME_PROPERTY(UninflatedTextRunProperty, nsnull) + +NS_DECLARE_FRAME_PROPERTY(FontSizeInflationProperty, nsnull) + // The following flags are set during reflow // This bit is set on the first frame in a continuation indicating @@ -231,6 +236,7 @@ NS_DECLARE_FRAME_PROPERTY(OffsetToFrameProperty, nsnull) // nsTextFrame.h has // #define TEXT_HAS_NONCOLLAPSED_CHARACTERS NS_FRAME_STATE_BIT(31) +// #define TEXT_HAS_FONT_INFLATION NS_FRAME_STATE_BIT(61) // If true, then this frame is being removed due to a SetLength() on a // previous continuation and the style context of that previous @@ -427,8 +433,10 @@ ClearAllTextRunReferences(nsTextFrame* aFrame, gfxTextRun* aTextRun, { NS_PRECONDITION(aFrame, ""); NS_PRECONDITION(!aStartContinuation || - !aStartContinuation->GetTextRun() || - aStartContinuation->GetTextRun() == aTextRun, + (!aStartContinuation->GetTextRun(nsTextFrame::eInflated) || + aStartContinuation->GetTextRun(nsTextFrame::eInflated) == aTextRun) || + (!aStartContinuation->GetTextRun(nsTextFrame::eNotInflated) || + aStartContinuation->GetTextRun(nsTextFrame::eNotInflated) == aTextRun), "wrong aStartContinuation for this text run"); if (!aStartContinuation || aStartContinuation == aFrame) { @@ -442,9 +450,8 @@ ClearAllTextRunReferences(nsTextFrame* aFrame, gfxTextRun* aTextRun, bool found = aStartContinuation == aFrame; while (aFrame) { NS_ASSERTION(aFrame->GetType() == nsGkAtoms::textFrame, "Bad frame"); - if (aFrame->GetTextRun() != aTextRun) + if (!aFrame->RemoveTextRun(aTextRun)) break; - aFrame->SetTextRun(nsnull); aFrame = static_cast(aFrame->GetNextContinuation()); } NS_POSTCONDITION(!found || aStartContinuation, "how did we find null?"); @@ -805,12 +812,15 @@ IsAllWhitespace(const nsTextFragment* aFrag, bool aAllowNewline) class BuildTextRunsScanner { public: BuildTextRunsScanner(nsPresContext* aPresContext, gfxContext* aContext, - nsIFrame* aLineContainer) : + nsIFrame* aLineContainer, nsTextFrame::TextRunType aWhichTextRun, + float aInflation) : mCurrentFramesAllSameTextRun(nsnull), mContext(aContext), mLineContainer(aLineContainer), + mInflation(aInflation), mBidiEnabled(aPresContext->BidiEnabled()), mSkipIncompleteTextRuns(false), + mWhichTextRun(aWhichTextRun), mNextRunContextInfo(nsTextFrameUtils::INCOMING_NONE), mCurrentRunContextInfo(nsTextFrameUtils::INCOMING_NONE) { ResetRunInfo(); @@ -965,11 +975,13 @@ private: // mMaxTextLength is an upper bound on the size of the text in all mapped frames // The value PR_UINT32_MAX represents overflow; text will be discarded PRUint32 mMaxTextLength; + float mInflation; bool mDoubleByteText; bool mBidiEnabled; bool mStartOfLine; bool mSkipIncompleteTextRuns; bool mCanStopOnThisLine; + nsTextFrame::TextRunType mWhichTextRun; PRUint8 mNextRunContextInfo; PRUint8 mCurrentRunContextInfo; }; @@ -1174,7 +1186,8 @@ BuildTextRunsScanner::FindBoundaries(nsIFrame* aFrame, FindBoundaryState* aState static void BuildTextRuns(gfxContext* aContext, nsTextFrame* aForFrame, nsIFrame* aLineContainer, - const nsLineList::iterator* aForFrameLine) + const nsLineList::iterator* aForFrameLine, + nsTextFrame::TextRunType aWhichTextRun, float aInflation) { NS_ASSERTION(aForFrame || aLineContainer, "One of aForFrame or aLineContainer must be set!"); @@ -1192,7 +1205,8 @@ BuildTextRuns(gfxContext* aContext, nsTextFrame* aForFrame, } nsPresContext* presContext = aLineContainer->PresContext(); - BuildTextRunsScanner scanner(presContext, aContext, aLineContainer); + BuildTextRunsScanner scanner(presContext, aContext, aLineContainer, + aWhichTextRun, aInflation); nsBlockFrame* block = nsLayoutUtils::GetAsBlock(aLineContainer); @@ -1458,7 +1472,7 @@ void BuildTextRunsScanner::AccumulateRunInfo(nsTextFrame* aFrame) mappedFlow->GetContentEnd() == aFrame->GetContentOffset(), "Overlapping or discontiguous frames => BAD"); mappedFlow->mEndFrame = static_cast(aFrame->GetNextContinuation()); - if (mCurrentFramesAllSameTextRun != aFrame->GetTextRun()) { + if (mCurrentFramesAllSameTextRun != aFrame->GetTextRun(mWhichTextRun)) { mCurrentFramesAllSameTextRun = nsnull; } @@ -1489,6 +1503,12 @@ HasTerminalNewline(const nsTextFrame* aFrame) bool BuildTextRunsScanner::ContinueTextRunAcrossFrames(nsTextFrame* aFrame1, nsTextFrame* aFrame2) { + // We don't need to check font size inflation, since + // |FindLineContainer| above (via |nsIFrame::CanContinueTextRun|) + // ensures that text runs never cross block boundaries. This means + // that the font size inflation on all text frames in the text run is + // already guaranteed to be the same as each other (and for the line + // container). if (mBidiEnabled && NS_GET_EMBEDDING_LEVEL(aFrame1) != NS_GET_EMBEDDING_LEVEL(aFrame2)) return false; @@ -1573,7 +1593,7 @@ void BuildTextRunsScanner::ScanFrame(nsIFrame* aFrame) AccumulateRunInfo(frame); if (mMappedFlows.Length() == 1) { - mCurrentFramesAllSameTextRun = frame->GetTextRun(); + mCurrentFramesAllSameTextRun = frame->GetTextRun(mWhichTextRun); mCurrentRunContextInfo = mNextRunContextInfo; } return; @@ -1628,14 +1648,15 @@ GetSpacingFlags(nscoord spacing) } static gfxFontGroup* -GetFontGroupForFrame(nsIFrame* aFrame, +GetFontGroupForFrame(nsIFrame* aFrame, float aFontSizeInflation, nsFontMetrics** aOutFontMetrics = nsnull) { if (aOutFontMetrics) *aOutFontMetrics = nsnull; nsRefPtr metrics; - nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(metrics)); + nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(metrics), + aFontSizeInflation); if (!metrics) return nsnull; @@ -1875,7 +1896,7 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer) // Now build the textrun nsTextFrame* firstFrame = mMappedFlows[0].mStartFrame; - gfxFontGroup* fontGroup = GetFontGroupForFrame(firstFrame); + gfxFontGroup* fontGroup = GetFontGroupForFrame(firstFrame, mInflation); if (!fontGroup) { DestroyUserData(userDataToDestroy); return nsnull; @@ -2164,8 +2185,8 @@ BuildTextRunsScanner::AssignTextRun(gfxTextRun* aTextRun) for (f = startFrame; f != endFrame; f = static_cast(f->GetNextContinuation())) { #ifdef DEBUG_roc - if (f->GetTextRun()) { - gfxTextRun* textRun = f->GetTextRun(); + if (f->GetTextRun(mWhichTextRun)) { + gfxTextRun* textRun = f->GetTextRun(mWhichTextRun); if (textRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) { if (mMappedFlows[0].mStartFrame != static_cast(textRun->GetUserData())) { NS_WARNING("REASSIGNING SIMPLE FLOW TEXT RUN!"); @@ -2183,7 +2204,7 @@ BuildTextRunsScanner::AssignTextRun(gfxTextRun* aTextRun) } #endif - gfxTextRun* oldTextRun = f->GetTextRun(); + gfxTextRun* oldTextRun = f->GetTextRun(mWhichTextRun); if (oldTextRun) { nsTextFrame* firstFrame = nsnull; PRUint32 startOffset = 0; @@ -2214,10 +2235,10 @@ BuildTextRunsScanner::AssignTextRun(gfxTextRun* aTextRun) PRUint32 textRunOffset = iter.ConvertOriginalToSkipped(f->GetContentOffset()); clearFrom = textRunOffset == oldTextRun->GetLength() ? f : nsnull; } - f->ClearTextRun(clearFrom); + f->ClearTextRun(clearFrom, mWhichTextRun); #ifdef DEBUG - if (firstFrame && !firstFrame->GetTextRun()) { + if (firstFrame && !firstFrame->GetTextRun(mWhichTextRun)) { // oldTextRun was destroyed - assert that we don't reference it. for (PRUint32 i = 0; i < mBreakSinks.Length(); ++i) { NS_ASSERTION(oldTextRun != mBreakSinks[i]->mTextRun, @@ -2226,7 +2247,7 @@ BuildTextRunsScanner::AssignTextRun(gfxTextRun* aTextRun) } #endif } - f->SetTextRun(aTextRun); + f->SetTextRun(aTextRun, mWhichTextRun, mInflation); } // Set this bit now; we can't set it any earlier because // f->ClearTextRun() might clear it out. @@ -2235,13 +2256,17 @@ BuildTextRunsScanner::AssignTextRun(gfxTextRun* aTextRun) } gfxSkipCharsIterator -nsTextFrame::EnsureTextRun(gfxContext* aReferenceContext, nsIFrame* aLineContainer, +nsTextFrame::EnsureTextRun(TextRunType aWhichTextRun, + float aInflation, + gfxContext* aReferenceContext, + nsIFrame* aLineContainer, const nsLineList::iterator* aLine, PRUint32* aFlowEndInTextRun) { - if (mTextRun && (!aLine || !(*aLine)->GetInvalidateTextRuns())) { - if (mTextRun->GetExpirationState()->IsTracked()) { - gTextRuns->MarkUsed(mTextRun); + gfxTextRun *textRun = GetTextRun(aWhichTextRun); + if (textRun && (!aLine || !(*aLine)->GetInvalidateTextRuns())) { + if (textRun->GetExpirationState()->IsTracked()) { + gTextRuns->MarkUsed(textRun); } } else { nsRefPtr ctx = aReferenceContext; @@ -2249,9 +2274,11 @@ nsTextFrame::EnsureTextRun(gfxContext* aReferenceContext, nsIFrame* aLineContain ctx = GetReferenceRenderingContext(this, nsnull); } if (ctx) { - BuildTextRuns(ctx, this, aLineContainer, aLine); + BuildTextRuns(ctx, this, aLineContainer, aLine, aWhichTextRun, + aInflation); } - if (!mTextRun) { + textRun = GetTextRun(aWhichTextRun); + if (!textRun) { // A text run was not constructed for this frame. This is bad. The caller // will check mTextRun. static const gfxSkipChars emptySkipChars; @@ -2259,29 +2286,29 @@ nsTextFrame::EnsureTextRun(gfxContext* aReferenceContext, nsIFrame* aLineContain } } - if (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) { + if (textRun->GetFlags() & nsTextFrameUtils::TEXT_IS_SIMPLE_FLOW) { if (aFlowEndInTextRun) { - *aFlowEndInTextRun = mTextRun->GetLength(); + *aFlowEndInTextRun = textRun->GetLength(); } - return gfxSkipCharsIterator(mTextRun->GetSkipChars(), 0, mContentOffset); + return gfxSkipCharsIterator(textRun->GetSkipChars(), 0, mContentOffset); } - TextRunUserData* userData = static_cast(mTextRun->GetUserData()); + TextRunUserData* userData = static_cast(textRun->GetUserData()); TextRunMappedFlow* flow = FindFlowForContent(userData, mContent); if (flow) { // Since textruns can only contain one flow for a given content element, // this must be our flow. PRUint32 flowIndex = flow - userData->mMappedFlows; userData->mLastFlowIndex = flowIndex; - gfxSkipCharsIterator iter(mTextRun->GetSkipChars(), + gfxSkipCharsIterator iter(textRun->GetSkipChars(), flow->mDOMOffsetToBeforeTransformOffset, mContentOffset); if (aFlowEndInTextRun) { if (flowIndex + 1 < userData->mMappedFlowCount) { - gfxSkipCharsIterator end(mTextRun->GetSkipChars()); + gfxSkipCharsIterator end(textRun->GetSkipChars()); *aFlowEndInTextRun = end.ConvertOriginalToSkipped( flow[1].mStartFrame->GetContentOffset() + flow[1].mDOMOffsetToBeforeTransformOffset); } else { - *aFlowEndInTextRun = mTextRun->GetLength(); + *aFlowEndInTextRun = textRun->GetLength(); } } return iter; @@ -2459,7 +2486,8 @@ public: const nsTextFragment* aFrag, nsTextFrame* aFrame, const gfxSkipCharsIterator& aStart, PRInt32 aLength, nsIFrame* aLineContainer, - nscoord aOffsetFromBlockOriginForTabs) + nscoord aOffsetFromBlockOriginForTabs, + nsTextFrame::TextRunType aWhichTextRun) : mTextRun(aTextRun), mFontGroup(nsnull), mTextStyle(aTextStyle), mFrag(aFrag), mLineContainer(aLineContainer), @@ -2471,7 +2499,8 @@ public: mJustificationSpacing(0), mHyphenWidth(-1), mOffsetFromBlockOriginForTabs(aOffsetFromBlockOriginForTabs), - mReflowing(true) + mReflowing(true), + mWhichTextRun(aWhichTextRun) { NS_ASSERTION(mStart.IsInitialized(), "Start not initialized?"); } @@ -2481,8 +2510,9 @@ public: * have other data around. Gets everything from the frame. EnsureTextRun * *must* be called before this!!! */ - PropertyProvider(nsTextFrame* aFrame, const gfxSkipCharsIterator& aStart) - : mTextRun(aFrame->GetTextRun()), mFontGroup(nsnull), + PropertyProvider(nsTextFrame* aFrame, const gfxSkipCharsIterator& aStart, + nsTextFrame::TextRunType aWhichTextRun) + : mTextRun(aFrame->GetTextRun(aWhichTextRun)), mFontGroup(nsnull), mTextStyle(aFrame->GetStyleText()), mFrag(aFrame->GetContent()->GetText()), mLineContainer(nsnull), @@ -2494,7 +2524,8 @@ public: mJustificationSpacing(0), mHyphenWidth(-1), mOffsetFromBlockOriginForTabs(0), - mReflowing(false) + mReflowing(false), + mWhichTextRun(aWhichTextRun) { NS_ASSERTION(mTextRun, "Textrun not initialized!"); } @@ -2558,7 +2589,10 @@ protected: void SetupJustificationSpacing(); void InitFontGroupAndFontMetrics() { - mFontGroup = GetFontGroupForFrame(mFrame, getter_AddRefs(mFontMetrics)); + float inflation = (mWhichTextRun == nsTextFrame::eInflated) + ? mFrame->GetFontSizeInflation() : 1.0f; + mFontGroup = GetFontGroupForFrame(mFrame, inflation, + getter_AddRefs(mFontMetrics)); } gfxTextRun* mTextRun; @@ -2584,6 +2618,7 @@ protected: gfxFloat mHyphenWidth; gfxFloat mOffsetFromBlockOriginForTabs; bool mReflowing; + nsTextFrame::TextRunType mWhichTextRun; }; PRUint32 @@ -3684,7 +3719,7 @@ nsTextFrame::DestroyFrom(nsIFrame* aDestructRoot) // We might want to clear NS_CREATE_FRAME_IF_NON_WHITESPACE or // NS_REFRAME_IF_WHITESPACE on mContent here, since our parent frame // type might be changing. Not clear whether it's worth it. - ClearTextRun(nsnull); + ClearTextRuns(); if (mNextContinuation) { mNextContinuation->SetPrevInFlow(nsnull); } @@ -3772,9 +3807,18 @@ nsContinuingTextFrame::Init(nsIContent* aContent, if (prev->GetStyleContext() != GetStyleContext()) { // We're taking part of prev's text, and its style may be different // so clear its textrun which may no longer be valid (and don't set ours) - prev->ClearTextRun(nsnull); + prev->ClearTextRuns(); } else { - mTextRun = prev->GetTextRun(); + float inflation = prev->GetFontSizeInflation(); + SetFontSizeInflation(inflation); + mTextRun = prev->GetTextRun(nsTextFrame::eInflated); + if (inflation != 1.0f) { + gfxTextRun *uninflatedTextRun = + prev->GetTextRun(nsTextFrame::eNotInflated); + if (uninflatedTextRun) { + SetTextRun(uninflatedTextRun, nsTextFrame::eNotInflated, 1.0f); + } + } } #ifdef IBMBIDI if (aPrevInFlow->GetStateBits() & NS_FRAME_IS_BIDI) { @@ -3826,11 +3870,13 @@ nsContinuingTextFrame::DestroyFrom(nsIFrame* aDestructRoot) !(GetStateBits() & TEXT_STYLE_MATCHES_PREV_CONTINUATION)) || (mPrevContinuation && mPrevContinuation->GetStyleContext() != GetStyleContext())) { - ClearTextRun(nsnull); + ClearTextRuns(); // Clear the previous continuation's text run also, so that it can rebuild // the text run to include our text. if (mPrevContinuation) { - (static_cast(mPrevContinuation))->ClearTextRun(nsnull); + nsTextFrame *prevContinuationText = + static_cast(mPrevContinuation); + prevContinuationText->ClearTextRuns(); } } nsSplittableFrame::RemoveFromFlow(this); @@ -4010,12 +4056,69 @@ nsTextFrame::GetLastContinuation() const return lastInFlow; } +gfxTextRun* +nsTextFrame::GetUninflatedTextRun() +{ + return static_cast( + Properties().Get(UninflatedTextRunProperty())); +} + void -nsTextFrame::ClearTextRun(nsTextFrame* aStartContinuation) +nsTextFrame::SetTextRun(gfxTextRun* aTextRun, TextRunType aWhichTextRun, + float aInflation) +{ + NS_ASSERTION(aTextRun, "must have text run"); + + // Our inflated text run is always stored in mTextRun. In the cases + // where our current inflation is not 1.0, however, we store two text + // runs, and the uninflated one goes in a frame property. We never + // store a single text run in both. + if (aWhichTextRun == eInflated) { + if (HasFontSizeInflation() && aInflation == 1.0f) { + // FIXME: Probably shouldn't do this within each SetTextRun + // method, but it doesn't hurt. + ClearTextRun(nsnull, nsTextFrame::eNotInflated); + } + SetFontSizeInflation(aInflation); + } else { + NS_ABORT_IF_FALSE(aInflation == 1.0f, "unexpected inflation"); + if (HasFontSizeInflation()) { + Properties().Set(UninflatedTextRunProperty(), aTextRun); + return; + } + // fall through to setting mTextRun + } + + mTextRun = aTextRun; + + // FIXME: Add assertions testing the relationship between + // GetFontSizeInflation() and whether we have an uninflated text run + // (but be aware that text runs can go away). +} + +bool +nsTextFrame::RemoveTextRun(gfxTextRun* aTextRun) +{ + if (aTextRun == mTextRun) { + mTextRun = nsnull; + return true; + } + FrameProperties props = Properties(); + if ((GetStateBits() & TEXT_HAS_FONT_INFLATION) && + props.Get(UninflatedTextRunProperty()) == aTextRun) { + props.Delete(UninflatedTextRunProperty()); + return true; + } + return false; +} + +void +nsTextFrame::ClearTextRun(nsTextFrame* aStartContinuation, + TextRunType aWhichTextRun) { // save textrun because ClearAllTextRunReferences may clear ours - gfxTextRun* textRun = mTextRun; - + gfxTextRun* textRun = GetTextRun(aWhichTextRun); + if (!textRun) return; @@ -4067,7 +4170,7 @@ nsTextFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo) // textFrame contained deleted text (or the insertion point, // if this was a pure insertion). textFrame->mState &= ~TEXT_WHITESPACE_FLAGS; - textFrame->ClearTextRun(nsnull); + textFrame->ClearTextRuns(); if (!lastDirtiedFrame || lastDirtiedFrame->GetParent() != textFrame->GetParent()) { // Ask the parent frame to reflow me. @@ -4107,7 +4210,7 @@ nsTextFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo) textFrame->mContentOffset += sizeChange; // XXX we could rescue some text runs by adjusting their user data // to reflect the change in DOM offsets - textFrame->ClearTextRun(nsnull); + textFrame->ClearTextRuns(); textFrame = static_cast(textFrame->GetNextContinuation()); } } @@ -4119,7 +4222,7 @@ nsTextFrame::CharacterDataChanged(CharacterDataChangeInfo* aInfo) nsTextFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext) { nsFrame::DidSetStyleContext(aOldStyleContext); - ClearTextRun(nsnull); + ClearTextRuns(); } class nsDisplayText : public nsCharClipDisplayItem { @@ -4402,6 +4505,9 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext, TextDecorations textDecs; GetTextDecorations(aPresContext, textDecs); if (textDecs.HasDecorationLines()) { + nscoord inflationMinFontSize = + nsLayoutUtils::InflationMinFontSizeFor(aBlockReflowState); + const nscoord width = GetSize().width; const gfxFloat appUnitsPerDevUnit = aPresContext->AppUnitsPerDevPixel(), gfxWidth = width / appUnitsPerDevUnit, @@ -4412,8 +4518,10 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext, for (PRUint32 i = 0; i < textDecs.mUnderlines.Length(); ++i) { const LineDecoration& dec = textDecs.mUnderlines[i]; + float inflation = nsLayoutUtils::FontSizeInflationInner(dec.mFrame, + inflationMinFontSize); const gfxFont::Metrics metrics = - GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame)); + GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation)); const nsRect decorationRect = nsCSSRendering::GetTextDecorationRect(aPresContext, @@ -4428,8 +4536,10 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext, for (PRUint32 i = 0; i < textDecs.mOverlines.Length(); ++i) { const LineDecoration& dec = textDecs.mOverlines[i]; + float inflation = nsLayoutUtils::FontSizeInflationInner(dec.mFrame, + inflationMinFontSize); const gfxFont::Metrics metrics = - GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame)); + GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation)); const nsRect decorationRect = nsCSSRendering::GetTextDecorationRect(aPresContext, @@ -4444,8 +4554,10 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext, for (PRUint32 i = 0; i < textDecs.mStrikes.Length(); ++i) { const LineDecoration& dec = textDecs.mStrikes[i]; + float inflation = nsLayoutUtils::FontSizeInflationInner(dec.mFrame, + inflationMinFontSize); const gfxFont::Metrics metrics = - GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame)); + GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation)); const nsRect decorationRect = nsCSSRendering::GetTextDecorationRect(aPresContext, @@ -5113,8 +5225,8 @@ nsTextFrame::GetCaretColorAt(PRInt32 aOffset) { NS_PRECONDITION(aOffset >= 0, "aOffset must be positive"); - gfxSkipCharsIterator iter = EnsureTextRun(); - PropertyProvider provider(this, iter); + gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated); + PropertyProvider provider(this, iter, nsTextFrame::eInflated); PRInt32 contentOffset = provider.GetStart().GetOriginalOffset(); PRInt32 contentLength = provider.GetOriginalLength(); NS_PRECONDITION(aOffset >= contentOffset && @@ -5168,11 +5280,11 @@ nsTextFrame::MeasureCharClippedText(gfxContext* aCtx, // Don't pass in aRenderingContext here, because we need a *reference* // context and aRenderingContext might have some transform in it // XXX get the block and line passed to us somehow! This is slow! - gfxSkipCharsIterator iter = EnsureTextRun(); + gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated); if (!mTextRun) return false; - PropertyProvider provider(this, iter); + PropertyProvider provider(this, iter, nsTextFrame::eInflated); // Trim trailing whitespace provider.InitializeForDisplay(true); @@ -5272,11 +5384,11 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt, // Don't pass in aRenderingContext here, because we need a *reference* // context and aRenderingContext might have some transform in it // XXX get the block and line passed to us somehow! This is slow! - gfxSkipCharsIterator iter = EnsureTextRun(); + gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated); if (!mTextRun) return; - PropertyProvider provider(this, iter); + PropertyProvider provider(this, iter, nsTextFrame::eInflated); // Trim trailing whitespace provider.InitializeForDisplay(true); @@ -5387,12 +5499,17 @@ nsTextFrame::DrawTextRunAndDecorations( gfxRect dirtyRect(aDirtyRect.x / app, aDirtyRect.y / app, aDirtyRect.Width() / app, aDirtyRect.Height() / app); + nscoord inflationMinFontSize = + nsLayoutUtils::InflationMinFontSizeFor(this); + // Underlines for (PRUint32 i = aDecorations.mUnderlines.Length(); i-- > 0; ) { const LineDecoration& dec = aDecorations.mUnderlines[i]; + float inflation = nsLayoutUtils::FontSizeInflationInner(dec.mFrame, + inflationMinFontSize); const gfxFont::Metrics metrics = - GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame)); + GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation)); decSize.height = metrics.underlineSize; decPt.y = (frameTop - dec.mBaselineOffset) / app; @@ -5406,8 +5523,10 @@ nsTextFrame::DrawTextRunAndDecorations( for (PRUint32 i = aDecorations.mOverlines.Length(); i-- > 0; ) { const LineDecoration& dec = aDecorations.mOverlines[i]; + float inflation = nsLayoutUtils::FontSizeInflationInner(dec.mFrame, + inflationMinFontSize); const gfxFont::Metrics metrics = - GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame)); + GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation)); decSize.height = metrics.underlineSize; decPt.y = (frameTop - dec.mBaselineOffset) / app; @@ -5426,8 +5545,10 @@ nsTextFrame::DrawTextRunAndDecorations( for (PRUint32 i = aDecorations.mStrikes.Length(); i-- > 0; ) { const LineDecoration& dec = aDecorations.mStrikes[i]; + float inflation = nsLayoutUtils::FontSizeInflationInner(dec.mFrame, + inflationMinFontSize); const gfxFont::Metrics metrics = - GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame)); + GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation)); decSize.height = metrics.strikeoutSize; decPt.y = (frameTop - dec.mBaselineOffset) / app; @@ -5557,11 +5678,11 @@ nsTextFrame::GetCharacterOffsetAtFramePointInternal(const nsPoint &aPoint, { ContentOffsets offsets; - gfxSkipCharsIterator iter = EnsureTextRun(); + gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated); if (!mTextRun) return offsets; - PropertyProvider provider(this, iter); + PropertyProvider provider(this, iter, nsTextFrame::eInflated); // Trim leading but not trailing whitespace if possible provider.InitializeForDisplay(false); gfxFloat width = mTextRun->IsRightToLeft() ? mRect.width - aPoint.x : aPoint.x; @@ -5789,11 +5910,11 @@ nsTextFrame::GetPointFromOffset(PRInt32 inOffset, return NS_OK; } - gfxSkipCharsIterator iter = EnsureTextRun(); + gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated); if (!mTextRun) return NS_ERROR_FAILURE; - PropertyProvider properties(this, iter); + PropertyProvider properties(this, iter, nsTextFrame::eInflated); // Don't trim trailing whitespace, we want the caret to appear in the right // place if it's positioned there properties.InitializeForDisplay(false); @@ -5914,7 +6035,7 @@ nsTextFrame::PeekOffsetNoAmount(bool aForward, PRInt32* aOffset) { NS_ASSERTION(aOffset && *aOffset <= GetContentLength(), "aOffset out of range"); - gfxSkipCharsIterator iter = EnsureTextRun(); + gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated); if (!mTextRun) return false; @@ -5996,7 +6117,7 @@ nsTextFrame::PeekOffsetCharacter(bool aForward, PRInt32* aOffset, if (selectStyle == NS_STYLE_USER_SELECT_ALL) return false; - gfxSkipCharsIterator iter = EnsureTextRun(); + gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated); if (!mTextRun) return false; @@ -6075,7 +6196,7 @@ ClusterIterator::NextCluster() { if (!mDirection) return false; - gfxTextRun* textRun = mTextFrame->GetTextRun(); + gfxTextRun* textRun = mTextFrame->GetTextRun(nsTextFrame::eInflated); mHaveWordBreak = false; while (true) { @@ -6110,8 +6231,8 @@ ClusterIterator::ClusterIterator(nsTextFrame* aTextFrame, PRInt32 aPosition, PRInt32 aDirection, nsString& aContext) : mTextFrame(aTextFrame), mDirection(aDirection), mCharIndex(-1) { - mIterator = aTextFrame->EnsureTextRun(); - if (!aTextFrame->GetTextRun()) { + mIterator = aTextFrame->EnsureTextRun(nsTextFrame::eInflated); + if (!aTextFrame->GetTextRun(nsTextFrame::eInflated)) { mDirection = 0; // signal failure return; } @@ -6338,10 +6459,45 @@ FindStartAfterSkippingWhitespace(PropertyProvider* aProvider, return aIterator->GetSkippedOffset(); } +union VoidPtrOrFloat { + VoidPtrOrFloat() : p(nsnull) {} + + void *p; + float f; +}; + +float +nsTextFrame::GetFontSizeInflation() const +{ + if (!HasFontSizeInflation()) { + return 1.0f; + } + VoidPtrOrFloat u; + u.p = Properties().Get(FontSizeInflationProperty()); + return u.f; +} + +void +nsTextFrame::SetFontSizeInflation(float aInflation) +{ + if (aInflation == 1.0f) { + if (HasFontSizeInflation()) { + RemoveStateBits(TEXT_HAS_FONT_INFLATION); + Properties().Delete(FontSizeInflationProperty()); + } + return; + } + + AddStateBits(TEXT_HAS_FONT_INFLATION); + VoidPtrOrFloat u; + u.f = aInflation; + Properties().Set(FontSizeInflationProperty(), u.p); +} + /* virtual */ void nsTextFrame::MarkIntrinsicWidthsDirty() { - ClearTextRun(nsnull); + ClearTextRuns(); nsFrame::MarkIntrinsicWidthsDirty(); } @@ -6354,8 +6510,10 @@ nsTextFrame::AddInlineMinWidthForFlow(nsRenderingContext *aRenderingContext, PRUint32 flowEndInTextRun; gfxContext* ctx = aRenderingContext->ThebesContext(); gfxSkipCharsIterator iter = - EnsureTextRun(ctx, aData->lineContainer, aData->line, &flowEndInTextRun); - if (!mTextRun) + EnsureTextRun(nsTextFrame::eNotInflated, 1.0f, ctx, aData->lineContainer, + aData->line, &flowEndInTextRun); + gfxTextRun *textRun = GetTextRun(nsTextFrame::eNotInflated); + if (!textRun) return; // Pass null for the line container. This will disable tab spacing, but that's @@ -6369,14 +6527,14 @@ nsTextFrame::AddInlineMinWidthForFlow(nsRenderingContext *aRenderingContext, bool hyphenating = frag->GetLength() > 0 && (textStyle->mHyphens == NS_STYLE_HYPHENS_AUTO || (textStyle->mHyphens == NS_STYLE_HYPHENS_MANUAL && - (mTextRun->GetFlags() & gfxTextRunFactory::TEXT_ENABLE_HYPHEN_BREAKS) != 0)); + (textRun->GetFlags() & gfxTextRunFactory::TEXT_ENABLE_HYPHEN_BREAKS) != 0)); if (hyphenating) { gfxSkipCharsIterator tmp(iter); len = NS_MIN(GetContentOffset() + GetInFlowContentLength(), tmp.ConvertSkippedToOriginal(flowEndInTextRun)) - iter.GetOriginalOffset(); } - PropertyProvider provider(mTextRun, textStyle, frag, this, - iter, len, nsnull, 0); + PropertyProvider provider(textRun, textStyle, frag, this, + iter, len, nsnull, 0, nsTextFrame::eNotInflated); bool collapseWhitespace = !textStyle->WhiteSpaceIsSignificant(); bool preformatNewlines = textStyle->NewlineIsSignificant(); @@ -6402,9 +6560,9 @@ nsTextFrame::AddInlineMinWidthForFlow(nsRenderingContext *aRenderingContext, // XXXldb Shouldn't we be including the newline as part of the // segment that it ends rather than part of the segment that it // starts? - preformattedNewline = preformatNewlines && mTextRun->GetChar(i) == '\n'; - preformattedTab = preformatTabs && mTextRun->GetChar(i) == '\t'; - if (!mTextRun->CanBreakLineBefore(i) && + preformattedNewline = preformatNewlines && textRun->GetChar(i) == '\n'; + preformattedTab = preformatTabs && textRun->GetChar(i) == '\t'; + if (!textRun->CanBreakLineBefore(i) && !preformattedNewline && !preformattedTab && (!hyphBreakBefore || !hyphBreakBefore[i - start])) @@ -6416,7 +6574,7 @@ nsTextFrame::AddInlineMinWidthForFlow(nsRenderingContext *aRenderingContext, if (i > wordStart) { nscoord width = - NSToCoordCeilClamped(mTextRun->GetAdvanceWidth(wordStart, i - wordStart, &provider)); + NSToCoordCeilClamped(textRun->GetAdvanceWidth(wordStart, i - wordStart, &provider)); aData->currentLine = NSCoordSaturatingAdd(aData->currentLine, width); aData->atStartOfLine = false; @@ -6429,7 +6587,7 @@ nsTextFrame::AddInlineMinWidthForFlow(nsRenderingContext *aRenderingContext, } else { // Some non-whitespace so the old trailingWhitespace is no longer trailing aData->trailingWhitespace = - NSToCoordCeilClamped(mTextRun->GetAdvanceWidth(trimStart, i - trimStart, &provider)); + NSToCoordCeilClamped(textRun->GetAdvanceWidth(trimStart, i - trimStart, &provider)); } } else { aData->trailingWhitespace = 0; @@ -6442,12 +6600,12 @@ nsTextFrame::AddInlineMinWidthForFlow(nsRenderingContext *aRenderingContext, aData->currentLine += nscoord(spacing.mBefore); gfxFloat afterTab = AdvanceToNextTab(aData->currentLine, this, - mTextRun, &tabWidth); + textRun, &tabWidth); aData->currentLine = nscoord(afterTab + spacing.mAfter); wordStart = i + 1; } else if (i < flowEndInTextRun || - (i == mTextRun->GetLength() && - (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_HAS_TRAILING_BREAK))) { + (i == textRun->GetLength() && + (textRun->GetFlags() & nsTextFrameUtils::TEXT_HAS_TRAILING_BREAK))) { if (preformattedNewline) { aData->ForceBreak(aRenderingContext); } else if (i < flowEndInTextRun && hyphBreakBefore && @@ -6482,10 +6640,10 @@ nsTextFrame::AddInlineMinWidth(nsRenderingContext *aRenderingContext, // nsContinuingTextFrame does nothing for AddInlineMinWidth; all text frames // in the flow are handled right here. for (f = this; f; f = static_cast(f->GetNextContinuation())) { - // f->mTextRun could be null if we haven't set up textruns yet for f. - // Except in OOM situations, lastTextRun will only be null for the first - // text frame. - if (f == this || f->mTextRun != lastTextRun) { + // f->GetTextRun(nsTextFrame::eNotInflated) could be null if we + // haven't set up textruns yet for f. Except in OOM situations, + // lastTextRun will only be null for the first text frame. + if (f == this || f->GetTextRun(nsTextFrame::eNotInflated) != lastTextRun) { nsIFrame* lc; if (aData->lineContainer && aData->lineContainer != (lc = FindLineContainer(f))) { @@ -6497,7 +6655,7 @@ nsTextFrame::AddInlineMinWidth(nsRenderingContext *aRenderingContext, // This will process all the text frames that share the same textrun as f. f->AddInlineMinWidthForFlow(aRenderingContext, aData); - lastTextRun = f->mTextRun; + lastTextRun = f->GetTextRun(nsTextFrame::eNotInflated); } } } @@ -6511,8 +6669,10 @@ nsTextFrame::AddInlinePrefWidthForFlow(nsRenderingContext *aRenderingContext, PRUint32 flowEndInTextRun; gfxContext* ctx = aRenderingContext->ThebesContext(); gfxSkipCharsIterator iter = - EnsureTextRun(ctx, aData->lineContainer, aData->line, &flowEndInTextRun); - if (!mTextRun) + EnsureTextRun(nsTextFrame::eNotInflated, 1.0f, ctx, aData->lineContainer, + aData->line, &flowEndInTextRun); + gfxTextRun *textRun = GetTextRun(nsTextFrame::eNotInflated); + if (!textRun) return; // Pass null for the line container. This will disable tab spacing, but that's @@ -6520,8 +6680,9 @@ nsTextFrame::AddInlinePrefWidthForFlow(nsRenderingContext *aRenderingContext, const nsStyleText* textStyle = GetStyleText(); const nsTextFragment* frag = mContent->GetText(); - PropertyProvider provider(mTextRun, textStyle, frag, this, - iter, PR_INT32_MAX, nsnull, 0); + PropertyProvider provider(textRun, textStyle, frag, this, + iter, PR_INT32_MAX, nsnull, 0, + nsTextFrame::eNotInflated); bool collapseWhitespace = !textStyle->WhiteSpaceIsSignificant(); bool preformatNewlines = textStyle->NewlineIsSignificant(); @@ -6542,8 +6703,8 @@ nsTextFrame::AddInlinePrefWidthForFlow(nsRenderingContext *aRenderingContext, // segment that it ends rather than part of the segment that it // starts? NS_ASSERTION(preformatNewlines, "We can't be here unless newlines are hard breaks"); - preformattedNewline = preformatNewlines && mTextRun->GetChar(i) == '\n'; - preformattedTab = preformatTabs && mTextRun->GetChar(i) == '\t'; + preformattedNewline = preformatNewlines && textRun->GetChar(i) == '\n'; + preformattedTab = preformatTabs && textRun->GetChar(i) == '\t'; if (!preformattedNewline && !preformattedTab) { // we needn't break here (and it's not the end of the flow) continue; @@ -6552,7 +6713,7 @@ nsTextFrame::AddInlinePrefWidthForFlow(nsRenderingContext *aRenderingContext, if (i > lineStart) { nscoord width = - NSToCoordCeilClamped(mTextRun->GetAdvanceWidth(lineStart, i - lineStart, &provider)); + NSToCoordCeilClamped(textRun->GetAdvanceWidth(lineStart, i - lineStart, &provider)); aData->currentLine = NSCoordSaturatingAdd(aData->currentLine, width); if (collapseWhitespace) { @@ -6564,7 +6725,7 @@ nsTextFrame::AddInlinePrefWidthForFlow(nsRenderingContext *aRenderingContext, } else { // Some non-whitespace so the old trailingWhitespace is no longer trailing aData->trailingWhitespace = - NSToCoordCeilClamped(mTextRun->GetAdvanceWidth(trimStart, i - trimStart, &provider)); + NSToCoordCeilClamped(textRun->GetAdvanceWidth(trimStart, i - trimStart, &provider)); } } else { aData->trailingWhitespace = 0; @@ -6577,7 +6738,7 @@ nsTextFrame::AddInlinePrefWidthForFlow(nsRenderingContext *aRenderingContext, aData->currentLine += nscoord(spacing.mBefore); gfxFloat afterTab = AdvanceToNextTab(aData->currentLine, this, - mTextRun, &tabWidth); + textRun, &tabWidth); aData->currentLine = nscoord(afterTab + spacing.mAfter); lineStart = i + 1; } else if (preformattedNewline) { @@ -6606,10 +6767,10 @@ nsTextFrame::AddInlinePrefWidth(nsRenderingContext *aRenderingContext, // nsContinuingTextFrame does nothing for AddInlineMinWidth; all text frames // in the flow are handled right here. for (f = this; f; f = static_cast(f->GetNextContinuation())) { - // f->mTextRun could be null if we haven't set up textruns yet for f. - // Except in OOM situations, lastTextRun will only be null for the first - // text frame. - if (f == this || f->mTextRun != lastTextRun) { + // f->GetTextRun(nsTextFrame::eNotInflated) could be null if we + // haven't set up textruns yet for f. Except in OOM situations, + // lastTextRun will only be null for the first text frame. + if (f == this || f->GetTextRun(nsTextFrame::eNotInflated) != lastTextRun) { nsIFrame* lc; if (aData->lineContainer && aData->lineContainer != (lc = FindLineContainer(f))) { @@ -6621,7 +6782,7 @@ nsTextFrame::AddInlinePrefWidth(nsRenderingContext *aRenderingContext, // This will process all the text frames that share the same textrun as f. f->AddInlinePrefWidthForFlow(aRenderingContext, aData); - lastTextRun = f->mTextRun; + lastTextRun = f->GetTextRun(nsTextFrame::eNotInflated); } } } @@ -6656,11 +6817,13 @@ nsTextFrame::ComputeTightBounds(gfxContext* aContext) const return GetVisualOverflowRect(); } - gfxSkipCharsIterator iter = const_cast(this)->EnsureTextRun(); + gfxSkipCharsIterator iter = + const_cast(this)->EnsureTextRun(nsTextFrame::eInflated); if (!mTextRun) return nsRect(0, 0, 0, 0); - PropertyProvider provider(const_cast(this), iter); + PropertyProvider provider(const_cast(this), iter, + nsTextFrame::eInflated); // Trim trailing whitespace provider.InitializeForDisplay(true); @@ -6794,9 +6957,9 @@ nsTextFrame::SetLength(PRInt32 aLength, nsLineLayout* aLineLayout, } f->mContentOffset = end; - if (f->GetTextRun() != mTextRun) { - ClearTextRun(nsnull); - f->ClearTextRun(nsnull); + if (f->GetTextRun(nsTextFrame::eInflated) != mTextRun) { + ClearTextRuns(); + f->ClearTextRuns(); } return; } @@ -6811,9 +6974,9 @@ nsTextFrame::SetLength(PRInt32 aLength, nsLineLayout* aLineLayout, nsIFrame *framesToRemove = nsnull; while (f && f->mContentOffset < end) { f->mContentOffset = end; - if (f->GetTextRun() != mTextRun) { - ClearTextRun(nsnull); - f->ClearTextRun(nsnull); + if (f->GetTextRun(nsTextFrame::eInflated) != mTextRun) { + ClearTextRuns(); + f->ClearTextRuns(); } nsTextFrame* next = static_cast(f->GetNextInFlow()); // Note: the "f->GetNextSibling() == next" check below is to restrict @@ -7041,10 +7204,13 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, // floating first-letter boundaries are significant in textrun // construction, so clear the textrun out every time we hit a first-letter // and have changed our length (which controls the first-letter boundary) - ClearTextRun(nsnull); + ClearTextRuns(); // Find the length of the first-letter. We need a textrun for this. + // REVIEW: maybe-bogus inflation should be ok (fixed below) gfxSkipCharsIterator iter = - EnsureTextRun(ctx, lineContainer, aLineLayout.GetLine(), &flowEndInTextRun); + EnsureTextRun(nsTextFrame::eInflated, GetFontSizeInflation(), ctx, + lineContainer, aLineLayout.GetLine(), + &flowEndInTextRun); if (mTextRun) { PRInt32 firstLetterLength = length; @@ -7080,22 +7246,37 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, SetLength(offset + length - GetContentOffset(), &aLineLayout, ALLOW_FRAME_CREATION_AND_DESTRUCTION); // Ensure that the textrun will be rebuilt - ClearTextRun(nsnull); + ClearTextRuns(); } } } + float fontSizeInflation = nsLayoutUtils::FontSizeInflationInner(this, + nsLayoutUtils::InflationMinFontSizeFor( + *aLineLayout.GetLineContainerRS())); + + if (fontSizeInflation != GetFontSizeInflation()) { + // FIXME: Ideally, if we already have a text run, we'd move it to be + // the uninflated text run. + ClearTextRun(nsnull, nsTextFrame::eInflated); + } + gfxSkipCharsIterator iter = - EnsureTextRun(ctx, lineContainer, aLineLayout.GetLine(), &flowEndInTextRun); + EnsureTextRun(nsTextFrame::eInflated, fontSizeInflation, ctx, + lineContainer, aLineLayout.GetLine(), &flowEndInTextRun); + + NS_ABORT_IF_FALSE(GetFontSizeInflation() == fontSizeInflation, + "EnsureTextRun should have set font size inflation"); if (mTextRun && iter.GetOriginalEnd() < offset + length) { // The textrun does not map enough text for this frame. This can happen // when the textrun was ended in the middle of a text node because a // preformatted newline was encountered, and prev-in-flow frames have // consumed all the text of the textrun. We need a new textrun. - ClearTextRun(nsnull); - iter = EnsureTextRun(ctx, lineContainer, - aLineLayout.GetLine(), &flowEndInTextRun); + ClearTextRuns(); + iter = EnsureTextRun(nsTextFrame::eInflated, fontSizeInflation, ctx, + lineContainer, aLineLayout.GetLine(), + &flowEndInTextRun); } if (!mTextRun) { @@ -7118,7 +7299,7 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, lineContainer->GetUsedBorderAndPadding().left) : -1; PropertyProvider provider(mTextRun, textStyle, frag, this, iter, length, - lineContainer, xOffsetForTabs); + lineContainer, xOffsetForTabs, nsTextFrame::eInflated); PRUint32 transformedOffset = provider.GetStart().GetSkippedOffset(); @@ -7459,7 +7640,8 @@ nsTextFrame::TrimTrailingWhiteSpace(nsRenderingContext* aRC) return result; gfxContext* ctx = aRC->ThebesContext(); - gfxSkipCharsIterator start = EnsureTextRun(ctx); + gfxSkipCharsIterator start = + EnsureTextRun(nsTextFrame::eInflated, GetFontSizeInflation(), ctx); NS_ENSURE_TRUE(mTextRun, result); PRUint32 trimmedStart = start.GetSkippedOffset(); @@ -7481,7 +7663,7 @@ nsTextFrame::TrimTrailingWhiteSpace(nsRenderingContext* aRC) // We can't be dealing with tabs here ... they wouldn't be trimmed. So it's // OK to pass null for the line container. PropertyProvider provider(mTextRun, textStyle, frag, this, start, contentLength, - nsnull, 0); + nsnull, 0, nsTextFrame::eInflated); delta = mTextRun->GetAdvanceWidth(trimmedEnd, endOffset - trimmedEnd, &provider); // non-compressed whitespace being skipped at end of line -> justifiable // XXX should we actually *count* justifiable characters that should be @@ -7495,7 +7677,7 @@ nsTextFrame::TrimTrailingWhiteSpace(nsRenderingContext* aRC) (GetStateBits() & TEXT_JUSTIFICATION_ENABLED)) { // Check if any character in the last cluster is justifiable PropertyProvider provider(mTextRun, textStyle, frag, this, start, contentLength, - nsnull, 0); + nsnull, 0, nsTextFrame::eInflated); bool isCJK = IsChineseOrJapanese(this); gfxSkipCharsIterator justificationStart(start), justificationEnd(trimmedEndIter); provider.FindJustificationRange(&justificationStart, &justificationEnd); @@ -7550,11 +7732,11 @@ nsTextFrame::RecomputeOverflow(const nsHTMLReflowState& aBlockReflowState) nsRect bounds(nsPoint(0, 0), GetSize()); nsOverflowAreas result(bounds, bounds); - gfxSkipCharsIterator iter = EnsureTextRun(); + gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated); if (!mTextRun) return result; - PropertyProvider provider(this, iter); + PropertyProvider provider(this, iter, nsTextFrame::eInflated); provider.InitializeForDisplay(true); gfxTextRun::Metrics textMetrics = @@ -7615,7 +7797,8 @@ nsresult nsTextFrame::GetRenderedText(nsAString* aAppendToString, } // Ensure the text run and grab the gfxSkipCharsIterator for it - gfxSkipCharsIterator iter = textFrame->EnsureTextRun(); + gfxSkipCharsIterator iter = + textFrame->EnsureTextRun(nsTextFrame::eInflated); if (!textFrame->mTextRun) return NS_ERROR_FAILURE; @@ -7841,7 +8024,7 @@ nsTextFrame::AdjustOffsetsForBidi(PRInt32 aStart, PRInt32 aEnd) * This is called during bidi resolution from the block container, so we * shouldn't be holding a local reference to a textrun anywhere. */ - ClearTextRun(nsnull); + ClearTextRuns(); nsTextFrame* prev = static_cast(GetPrevContinuation()); if (prev) { @@ -7850,7 +8033,7 @@ nsTextFrame::AdjustOffsetsForBidi(PRInt32 aStart, PRInt32 aEnd) PRInt32 prevOffset = prev->GetContentOffset(); aStart = NS_MAX(aStart, prevOffset); aEnd = NS_MAX(aEnd, prevOffset); - prev->ClearTextRun(nsnull); + prev->ClearTextRuns(); } mContentOffset = aStart; @@ -7895,7 +8078,7 @@ nsTextFrame::GetBaseline() const bool nsTextFrame::HasAnyNoncollapsedCharacters() { - gfxSkipCharsIterator iter = EnsureTextRun(); + gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated); PRInt32 offset = GetContentOffset(), offsetEnd = GetContentEnd(); PRInt32 skippedOffset = iter.ConvertOriginalToSkipped(offset); From 9523a6cd1055f1d98625d2494bb6e2d6a010d352 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:01 +1300 Subject: [PATCH 14/34] Remove the unused context parameter to MeasureCharClippedText. (Bug 627842, patch 10) r=roc --- layout/generic/TextOverflow.cpp | 7 ++----- layout/generic/nsTextFrame.h | 6 ++---- layout/generic/nsTextFrameThebes.cpp | 14 ++++++-------- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/layout/generic/TextOverflow.cpp b/layout/generic/TextOverflow.cpp index 29ba6a226b9c..d509f3081483 100644 --- a/layout/generic/TextOverflow.cpp +++ b/layout/generic/TextOverflow.cpp @@ -105,11 +105,8 @@ IsFullyClipped(nsTextFrame* aFrame, nscoord aLeft, nscoord aRight, if (aLeft <= 0 && aRight <= 0) { return false; } - nsRefPtr rc = - aFrame->PresContext()->PresShell()->GetReferenceRenderingContext(); - return rc && - !aFrame->MeasureCharClippedText(rc->ThebesContext(), aLeft, aRight, - aSnappedLeft, aSnappedRight); + return !aFrame->MeasureCharClippedText(aLeft, aRight, + aSnappedLeft, aSnappedRight); } static bool diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h index 36463cdadfb3..daba355eda32 100644 --- a/layout/generic/nsTextFrame.h +++ b/layout/generic/nsTextFrame.h @@ -289,8 +289,7 @@ public: * the method returns false. * @return true if at least one whole grapheme cluster fit between the edges */ - bool MeasureCharClippedText(gfxContext* aCtx, - nscoord aLeftEdge, nscoord aRightEdge, + bool MeasureCharClippedText(nscoord aLeftEdge, nscoord aRightEdge, nscoord* aSnappedLeftEdge, nscoord* aSnappedRightEdge); /** @@ -299,8 +298,7 @@ public: * undefined when the method returns false. * @return true if at least one whole grapheme cluster fit between the edges */ - bool MeasureCharClippedText(gfxContext* aCtx, - PropertyProvider& aProvider, + bool MeasureCharClippedText(PropertyProvider& aProvider, nscoord aLeftEdge, nscoord aRightEdge, PRUint32* aStartOffset, PRUint32* aMaxLength, nscoord* aSnappedLeftEdge, diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 1800cc367a0f..df732b93e45b 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -5272,13 +5272,12 @@ ComputeTransformedLength(PropertyProvider& aProvider) } bool -nsTextFrame::MeasureCharClippedText(gfxContext* aCtx, - nscoord aLeftEdge, nscoord aRightEdge, +nsTextFrame::MeasureCharClippedText(nscoord aLeftEdge, nscoord aRightEdge, nscoord* aSnappedLeftEdge, nscoord* aSnappedRightEdge) { - // Don't pass in aRenderingContext here, because we need a *reference* - // context and aRenderingContext might have some transform in it + // We need a *reference* rendering context (not one that might have a + // transform), so we don't have a rendering context argument. // XXX get the block and line passed to us somehow! This is slow! gfxSkipCharsIterator iter = EnsureTextRun(nsTextFrame::eInflated); if (!mTextRun) @@ -5290,7 +5289,7 @@ nsTextFrame::MeasureCharClippedText(gfxContext* aCtx, PRUint32 startOffset = provider.GetStart().GetSkippedOffset(); PRUint32 maxLength = ComputeTransformedLength(provider); - return MeasureCharClippedText(aCtx, provider, aLeftEdge, aRightEdge, + return MeasureCharClippedText(provider, aLeftEdge, aRightEdge, &startOffset, &maxLength, aSnappedLeftEdge, aSnappedRightEdge); } @@ -5314,8 +5313,7 @@ static PRUint32 GetClusterLength(gfxTextRun* aTextRun, } bool -nsTextFrame::MeasureCharClippedText(gfxContext* aCtx, - PropertyProvider& aProvider, +nsTextFrame::MeasureCharClippedText(PropertyProvider& aProvider, nscoord aLeftEdge, nscoord aRightEdge, PRUint32* aStartOffset, PRUint32* aMaxLength, @@ -5401,7 +5399,7 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt, PRUint32 startOffset = provider.GetStart().GetSkippedOffset(); PRUint32 maxLength = ComputeTransformedLength(provider); nscoord snappedLeftEdge, snappedRightEdge; - if (!MeasureCharClippedText(ctx, provider, aItem.mLeftEdge, aItem.mRightEdge, + if (!MeasureCharClippedText(provider, aItem.mLeftEdge, aItem.mRightEdge, &startOffset, &maxLength, &snappedLeftEdge, &snappedRightEdge)) { return; } From 17facb7829c1ba8132c32d75e7173796d061a45b Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:01 +1300 Subject: [PATCH 15/34] Apply font size inflation to line heights. (Bug 627842, patch 11) r=roc Since font size inflation applies to the text after style data computation, we must separately apply this inflation to line heights. --- layout/forms/nsTextControlFrame.cpp | 53 +++++++++++++++++++++++----- layout/forms/nsTextControlFrame.h | 3 +- layout/generic/nsBlockFrame.cpp | 3 +- layout/generic/nsHTMLReflowState.cpp | 27 ++++++++++---- layout/generic/nsHTMLReflowState.h | 7 +++- layout/generic/nsLineLayout.cpp | 18 ++++++++-- layout/generic/nsLineLayout.h | 2 ++ layout/generic/nsTextFrameThebes.cpp | 3 +- layout/style/nsComputedDOMStyle.cpp | 4 ++- 9 files changed, 97 insertions(+), 23 deletions(-) diff --git a/layout/forms/nsTextControlFrame.cpp b/layout/forms/nsTextControlFrame.cpp index be6bdba9e2aa..a84f9adeaf2c 100644 --- a/layout/forms/nsTextControlFrame.cpp +++ b/layout/forms/nsTextControlFrame.cpp @@ -217,7 +217,8 @@ nsTextControlFrame::GetType() const nsresult nsTextControlFrame::CalcIntrinsicSize(nsRenderingContext* aRenderingContext, - nsSize& aIntrinsicSize) + nsSize& aIntrinsicSize, + float aFontSizeInflation) { // Get leading and the Average/MaxAdvance char width nscoord lineHeight = 0; @@ -226,12 +227,14 @@ nsTextControlFrame::CalcIntrinsicSize(nsRenderingContext* aRenderingContext, nsRefPtr fontMet; nsresult rv = - nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet)); + nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet), + aFontSizeInflation); NS_ENSURE_SUCCESS(rv, rv); aRenderingContext->SetFont(fontMet); lineHeight = - nsHTMLReflowState::CalcLineHeight(GetStyleContext(), NS_AUTOHEIGHT); + nsHTMLReflowState::CalcLineHeight(GetStyleContext(), NS_AUTOHEIGHT, + aFontSizeInflation); charWidth = fontMet->AveCharWidth(); charMaxAdvance = fontMet->MaxAdvance(); @@ -498,8 +501,16 @@ nsTextControlFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext, nsSize aMargin, nsSize aBorder, nsSize aPadding, bool aShrinkWrap) { + float inflation; + if (nsLayoutUtils::IsContainerForFontSizeInflation(this)) { + // FIXME: This won't turn out so well for the height; maybe disable + // inflation entirely in this case? + inflation = 1.0f; + } else { + inflation = nsLayoutUtils::FontSizeInflationFor(this, aCBSize.width); + } nsSize autoSize; - nsresult rv = CalcIntrinsicSize(aRenderingContext, autoSize); + nsresult rv = CalcIntrinsicSize(aRenderingContext, autoSize, inflation); if (NS_FAILED(rv)) { // What now? autoSize.SizeTo(0, 0); @@ -512,7 +523,8 @@ nsTextControlFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext, aCBSize, aAvailableWidth, aMargin, aBorder, aPadding, aShrinkWrap); - NS_ASSERTION(ancestorAutoSize.width == autoSize.width, + // Disabled when there's inflation; see comment in GetPrefSize. + NS_ASSERTION(inflation != 1.0f || ancestorAutoSize.width == autoSize.width, "Incorrect size computed by ComputeAutoSize?"); } #endif @@ -553,7 +565,11 @@ nsTextControlFrame::GetPrefSize(nsBoxLayoutState& aState) nsSize pref(0,0); - nsresult rv = CalcIntrinsicSize(aState.GetRenderingContext(), pref); + // FIXME: This inflation parameter isn't correct; we should fix it if + // we want font size inflation to work well in XUL. If we do, we can + // also re-enable the assertion in ComputeAutoSize when inflation is + // enabled. + nsresult rv = CalcIntrinsicSize(aState.GetRenderingContext(), pref, 1.0f); NS_ENSURE_SUCCESS(rv, pref); AddBorderAndPadding(pref); @@ -599,16 +615,37 @@ nsTextControlFrame::GetBoxAscent(nsBoxLayoutState& aState) // Return the baseline of the first (nominal) row, with centering for // single-line controls. + float inflation; + if (nsLayoutUtils::IsContainerForFontSizeInflation(this)) { + inflation = + nsLayoutUtils::FontSizeInflationFor(this, GetContentRect().width); + } else { + const nsHTMLReflowState *outerReflowState = aState.OuterReflowState(); + NS_ASSERTION(outerReflowState || !mParent || mParent->IsBoxFrame() || + !(mParent->GetStateBits() & NS_FRAME_IN_REFLOW), + "when a text control is reflowed by one of its ancestors " + "and its parent is non-XUL, we should have the outer " + "reflow state in the box layout state"); + if (outerReflowState && outerReflowState->frame == this) { + inflation = nsLayoutUtils::FontSizeInflationFor(*outerReflowState); + } else { + inflation = nsLayoutUtils::FontSizeInflationInner(this, + nsLayoutUtils::InflationMinFontSizeFor(mParent)); + } + } + // First calculate the ascent wrt the client rect nsRect clientRect; GetClientRect(clientRect); nscoord lineHeight = IsSingleLineTextControl() ? clientRect.height : - nsHTMLReflowState::CalcLineHeight(GetStyleContext(), NS_AUTOHEIGHT); + nsHTMLReflowState::CalcLineHeight(GetStyleContext(), NS_AUTOHEIGHT, + inflation); nsRefPtr fontMet; nsresult rv = - nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet)); + nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet), + inflation); NS_ENSURE_SUCCESS(rv, 0); nscoord ascent = nsLayoutUtils::GetCenteredFontBaseline(fontMet, lineHeight); diff --git a/layout/forms/nsTextControlFrame.h b/layout/forms/nsTextControlFrame.h index 6615d8573ce4..b2af727b57d0 100644 --- a/layout/forms/nsTextControlFrame.h +++ b/layout/forms/nsTextControlFrame.h @@ -392,7 +392,8 @@ protected: // etc. Just the size of our actual area for the text (and the scrollbars, // for diff --git a/layout/base/tests/font-inflation/textarea-1.html b/layout/base/tests/font-inflation/textarea-1.html new file mode 100644 index 000000000000..34e2446c4b0d --- /dev/null +++ b/layout/base/tests/font-inflation/textarea-1.html @@ -0,0 +1,11 @@ + + + +
diff --git a/layout/base/tests/font-inflation/textarea-2-ref.html b/layout/base/tests/font-inflation/textarea-2-ref.html new file mode 100644 index 000000000000..da650e128fe1 --- /dev/null +++ b/layout/base/tests/font-inflation/textarea-2-ref.html @@ -0,0 +1,11 @@ + + + +
diff --git a/layout/base/tests/font-inflation/textarea-2.html b/layout/base/tests/font-inflation/textarea-2.html new file mode 100644 index 000000000000..7405f70754b3 --- /dev/null +++ b/layout/base/tests/font-inflation/textarea-2.html @@ -0,0 +1,11 @@ + + + +
diff --git a/layout/base/tests/font-inflation/textarea-3-ref.html b/layout/base/tests/font-inflation/textarea-3-ref.html new file mode 100644 index 000000000000..4f9d6065bcff --- /dev/null +++ b/layout/base/tests/font-inflation/textarea-3-ref.html @@ -0,0 +1,11 @@ + + + +
diff --git a/layout/base/tests/font-inflation/textarea-3.html b/layout/base/tests/font-inflation/textarea-3.html new file mode 100644 index 000000000000..e4ed681f4af5 --- /dev/null +++ b/layout/base/tests/font-inflation/textarea-3.html @@ -0,0 +1,11 @@ + + + +
diff --git a/layout/base/tests/test_font_inflation_reftests.html b/layout/base/tests/test_font_inflation_reftests.html new file mode 100644 index 000000000000..81c29f252788 --- /dev/null +++ b/layout/base/tests/test_font_inflation_reftests.html @@ -0,0 +1,127 @@ + + + + + Font size inflation reftests + + + + + + +Mozilla Bug 627842 +
+
+
+ + diff --git a/testing/mochitest/tests/SimpleTest/WindowSnapshot.js b/testing/mochitest/tests/SimpleTest/WindowSnapshot.js index 91215f83cdd3..35034abc2527 100644 --- a/testing/mochitest/tests/SimpleTest/WindowSnapshot.js +++ b/testing/mochitest/tests/SimpleTest/WindowSnapshot.js @@ -45,3 +45,19 @@ function compareSnapshots(s1, s2, expected) { return [correct, s1Str, s2Str]; } + +function assertSnapshots(s1, s2, expected, s1name, s2name) { + var [correct, s1Str, s2Str] = compareSnapshots(s1, s2, expected); + var sym = expected ? "==" : "!="; + ok(correct, "reftest comparison: " + sym + " " + s1name + " " + s2name); + if (!correct) { + var report = "REFTEST TEST-UNEXPECTED-FAIL | " + s1name + " | image comparison (" + sym + ")\n"; + if (expected) { + report += "REFTEST IMAGE 1 (TEST): " + s1Str + "\n"; + report += "REFTEST IMAGE 2 (REFERENCE): " + s2Str + "\n"; + } else { + report += "REFTEST IMAGE: " + s1Str + "\n"; + } + dump(report); + } +} From a9396bac024223f68f931a1e2067929a8c89dc46 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:01 +1300 Subject: [PATCH 21/34] Run existing tests without font size inflation, even when it is enabled. (Bug 627842, patch 17) r=roc --- build/automation.py.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/automation.py.in b/build/automation.py.in index ad35c6892c6a..f5ec28b61b65 100644 --- a/build/automation.py.in +++ b/build/automation.py.in @@ -430,6 +430,9 @@ user_pref("app.update.enabled", false); user_pref("browser.panorama.experienced_first_run", true); // Assume experienced user_pref("dom.w3c_touch_events.enabled", true); user_pref("toolkit.telemetry.prompted", 2); +// Existing tests assume there is no font size inflation. +user_pref("font.size.inflation.emPerLine", 0); +user_pref("font.size.inflation.minTwips", 0); // Only load extensions from the application and user profile // AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION From 8b295cc6ce55f481079b0c0eb2cb5c8010380cae Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 8 Nov 2011 16:41:50 -0500 Subject: [PATCH 22/34] Bug 692185 - Flush PrintWriter prior to extracting printed string; r=blassey Not flushing the PrintWriter might cause data to get left in the PrintWriter's internal buffers, and not get written into the underlying StringWriter. This might explain why the stack trace does not get written out to the crash report. --- embedding/android/GeckoApp.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/embedding/android/GeckoApp.java b/embedding/android/GeckoApp.java index 3945e6ad28de..c6254c7c92e8 100644 --- a/embedding/android/GeckoApp.java +++ b/embedding/android/GeckoApp.java @@ -358,7 +358,9 @@ abstract public class GeckoApp } catch (Exception e) { Log.e(LOG_FILE_NAME, "top level exception", e); StringWriter sw = new StringWriter(); - e.printStackTrace(new PrintWriter(sw)); + PrintWriter pw = new PrintWriter(sw); + e.printStackTrace(pw); + pw.flush(); GeckoAppShell.reportJavaCrash(sw.toString()); } // resetting this is kinda pointless, but oh well From 8370e105a7f8387b9e0cad7ce44ad0e3dd7755ca Mon Sep 17 00:00:00 2001 From: William Lachance Date: Tue, 15 Nov 2011 04:33:21 +0000 Subject: [PATCH 23/34] Bug 679759 - Drop MINIDUMP_STACKWALK_CGI support, let harness download symbols as needed; r=ted --- build/automation.py.in | 66 +---------- build/automationutils.py | 183 +++++++++++++++++++++---------- build/poster.zip | Bin 14900 -> 0 bytes layout/tools/reftest/Makefile.in | 1 - testing/mochitest/Makefile.in | 1 - testing/xpcshell/Makefile.in | 1 - 6 files changed, 124 insertions(+), 128 deletions(-) delete mode 100644 build/poster.zip diff --git a/build/automation.py.in b/build/automation.py.in index f5ec28b61b65..42fd472c0810 100644 --- a/build/automation.py.in +++ b/build/automation.py.in @@ -52,7 +52,6 @@ import sys import threading import tempfile import sqlite3 -import zipfile SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0]))) sys.path.insert(0, SCRIPT_DIR) @@ -98,69 +97,6 @@ _log.setLevel(logging.INFO) _log.addHandler(handler) -class ZipFileReader(object): - """ - Class to read zip files in Python 2.5 and later. Limited to only what we - actually use. - """ - - def __init__(self, filename): - self._zipfile = zipfile.ZipFile(filename, "r") - - def __del__(self): - self._zipfile.close() - - def _getnormalizedpath(self, path): - """ - Gets a normalized path from 'path' (or the current working directory if - 'path' is None). Also asserts that the path exists. - """ - if path is None: - path = os.curdir - path = os.path.normpath(os.path.expanduser(path)) - assert os.path.isdir(path) - return path - - def _extractname(self, name, path): - """ - Extracts a file with the given name from the zip file to the given path. - Also creates any directories needed along the way. - """ - filename = os.path.normpath(os.path.join(path, name)) - if name.endswith("/"): - os.makedirs(filename) - else: - path = os.path.split(filename)[0] - if not os.path.isdir(path): - os.makedirs(path) - with open(filename, "wb") as dest: - dest.write(self._zipfile.read(name)) - - def namelist(self): - return self._zipfile.namelist() - - def read(self, name): - return self._zipfile.read(name) - - def extract(self, name, path = None): - if hasattr(self._zipfile, "extract"): - return self._zipfile.extract(name, path) - - # This will throw if name is not part of the zip file. - self._zipfile.getinfo(name) - - self._extractname(name, self._getnormalizedpath(path)) - - def extractall(self, path = None): - if hasattr(self._zipfile, "extractall"): - return self._zipfile.extractall(path) - - path = self._getnormalizedpath(path) - - for name in self._zipfile.namelist(): - self._extractname(name, path) - - ################# # PROFILE SETUP # ################# @@ -1056,7 +992,7 @@ user_pref("camino.use_system_proxy_settings", false); // Camino-only, harmless t os.makedirs(extensionsRootDir) if os.path.isfile(extensionSource): - reader = ZipFileReader(extensionSource) + reader = automationutils.ZipFileReader(extensionSource) for filename in reader.namelist(): # Sanity check the zip file. diff --git a/build/automationutils.py b/build/automationutils.py index 3f52516af8d3..7506e3e8fe09 100644 --- a/build/automationutils.py +++ b/build/automationutils.py @@ -36,11 +36,13 @@ # # ***** END LICENSE BLOCK ***** */ -import glob, logging, os, platform, shutil, subprocess, sys +from __future__ import with_statement +import glob, logging, os, platform, shutil, subprocess, sys, tempfile, urllib2, zipfile import re from urlparse import urlparse __all__ = [ + "ZipFileReader", "addCommonOptions", "checkForCrashes", "dumpLeakLog", @@ -70,6 +72,68 @@ DEBUGGER_INFO = { } } +class ZipFileReader(object): + """ + Class to read zip files in Python 2.5 and later. Limited to only what we + actually use. + """ + + def __init__(self, filename): + self._zipfile = zipfile.ZipFile(filename, "r") + + def __del__(self): + self._zipfile.close() + + def _getnormalizedpath(self, path): + """ + Gets a normalized path from 'path' (or the current working directory if + 'path' is None). Also asserts that the path exists. + """ + if path is None: + path = os.curdir + path = os.path.normpath(os.path.expanduser(path)) + assert os.path.isdir(path) + return path + + def _extractname(self, name, path): + """ + Extracts a file with the given name from the zip file to the given path. + Also creates any directories needed along the way. + """ + filename = os.path.normpath(os.path.join(path, name)) + if name.endswith("/"): + os.makedirs(filename) + else: + path = os.path.split(filename)[0] + if not os.path.isdir(path): + os.makedirs(path) + with open(filename, "wb") as dest: + dest.write(self._zipfile.read(name)) + + def namelist(self): + return self._zipfile.namelist() + + def read(self, name): + return self._zipfile.read(name) + + def extract(self, name, path = None): + if hasattr(self._zipfile, "extract"): + return self._zipfile.extract(name, path) + + # This will throw if name is not part of the zip file. + self._zipfile.getinfo(name) + + self._extractname(name, self._getnormalizedpath(path)) + + def extractall(self, path = None): + if hasattr(self._zipfile, "extractall"): + return self._zipfile.extractall(path) + + path = self._getnormalizedpath(path) + + for name in self._zipfile.namelist(): + self._extractname(name, path) + log = logging.getLogger() def isURL(thing): @@ -102,7 +166,6 @@ def addCommonOptions(parser, defaults={}): def checkForCrashes(dumpDir, symbolsPath, testName=None): stackwalkPath = os.environ.get('MINIDUMP_STACKWALK', None) - stackwalkCGI = os.environ.get('MINIDUMP_STACKWALK_CGI', None) # try to get the caller's filename if no test name is given if testName is None: try: @@ -110,70 +173,70 @@ def checkForCrashes(dumpDir, symbolsPath, testName=None): except: testName = "unknown" - foundCrash = False + # Check preconditions dumps = glob.glob(os.path.join(dumpDir, '*.dmp')) - for d in dumps: - log.info("PROCESS-CRASH | %s | application crashed (minidump found)", testName) - print "Crash dump filename: " + d - if symbolsPath and stackwalkPath and os.path.exists(stackwalkPath): - p = subprocess.Popen([stackwalkPath, d, symbolsPath], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - (out, err) = p.communicate() - if len(out) > 3: - # minidump_stackwalk is chatty, so ignore stderr when it succeeds. - print out - else: - print "stderr from minidump_stackwalk:" - print err - if p.returncode != 0: - print "minidump_stackwalk exited with return code %d" % p.returncode - elif stackwalkCGI and symbolsPath and isURL(symbolsPath): - f = None - try: - f = open(d, "rb") - sys.path.append(os.path.join(os.path.dirname(__file__), "poster.zip")) - from poster.encode import multipart_encode - from poster.streaminghttp import register_openers - import urllib2 - register_openers() - datagen, headers = multipart_encode({"minidump": f, - "symbols": symbolsPath}) - request = urllib2.Request(stackwalkCGI, datagen, headers) - result = urllib2.urlopen(request).read() - if len(result) > 3: - print result + if len(dumps) == 0: + return False + + foundCrash = False + removeSymbolsPath = False + + # If our symbols are at a remote URL, download them now + if isURL(symbolsPath): + print "Downloading symbols from: " + symbolsPath + removeSymbolsPath = True + # Get the symbols and write them to a temporary zipfile + data = urllib2.urlopen(symbolsPath) + symbolsFile = tempfile.TemporaryFile() + symbolsFile.write(data.read()) + # extract symbols to a temporary directory (which we'll delete after + # processing all crashes) + symbolsPath = tempfile.mkdtemp() + zfile = ZipFileReader(symbolsFile) + zfile.extractall(symbolsPath) + + try: + for d in dumps: + log.info("PROCESS-CRASH | %s | application crashed (minidump found)", testName) + print "Crash dump filename: " + d + if symbolsPath and stackwalkPath and os.path.exists(stackwalkPath): + # run minidump stackwalk + p = subprocess.Popen([stackwalkPath, d, symbolsPath], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + (out, err) = p.communicate() + if len(out) > 3: + # minidump_stackwalk is chatty, so ignore stderr when it succeeds. + print out else: - print "stackwalkCGI returned nothing." - finally: - if f: - f.close() - else: - if not symbolsPath: - print "No symbols path given, can't process dump." - if not stackwalkPath and not stackwalkCGI: - print "Neither MINIDUMP_STACKWALK nor MINIDUMP_STACKWALK_CGI is set, can't process dump." + print "stderr from minidump_stackwalk:" + print err + if p.returncode != 0: + print "minidump_stackwalk exited with return code %d" % p.returncode else: - if stackwalkPath and not os.path.exists(stackwalkPath): + if not symbolsPath: + print "No symbols path given, can't process dump." + if not stackwalkPath: + print "MINIDUMP_STACKWALK not set, can't process dump." + elif stackwalkPath and not os.path.exists(stackwalkPath): print "MINIDUMP_STACKWALK binary not found: %s" % stackwalkPath - elif stackwalkCGI and not isURL(stackwalkCGI): - print "MINIDUMP_STACKWALK_CGI is not a URL: %s" % stackwalkCGI - elif symbolsPath and not isURL(symbolsPath): - print "symbolsPath is not a URL: %s" % symbolsPath - dumpSavePath = os.environ.get('MINIDUMP_SAVE_PATH', None) - if dumpSavePath: - shutil.move(d, dumpSavePath) - print "Saved dump as %s" % os.path.join(dumpSavePath, - os.path.basename(d)) - else: - os.remove(d) - extra = os.path.splitext(d)[0] + ".extra" - if os.path.exists(extra): - os.remove(extra) - foundCrash = True + dumpSavePath = os.environ.get('MINIDUMP_SAVE_PATH', None) + if dumpSavePath: + shutil.move(d, dumpSavePath) + print "Saved dump as %s" % os.path.join(dumpSavePath, + os.path.basename(d)) + else: + os.remove(d) + extra = os.path.splitext(d)[0] + ".extra" + if os.path.exists(extra): + os.remove(extra) + foundCrash = True + finally: + if removeSymbolsPath: + shutil.rmtree(symbolsPath) return foundCrash - + def getFullPath(directory, path): "Get an absolute path relative to 'directory'." return os.path.normpath(os.path.join(directory, os.path.expanduser(path))) diff --git a/build/poster.zip b/build/poster.zip deleted file mode 100644 index 122b4acd4698a52d208293a904130c5310851ab9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14900 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 Date: Tue, 15 Nov 2011 04:59:03 +0000 Subject: [PATCH 24/34] Bug 334411: Introduce flashing invalidates areas when paint flashing is enabled. r=roc --- layout/base/FrameLayerBuilder.cpp | 25 +++++++++++++++++++++++++ layout/base/FrameLayerBuilder.h | 3 +++ 2 files changed, 28 insertions(+) diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 1a18cf5069cc..3b6634254e9a 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -49,6 +49,8 @@ #include "nsImageFrame.h" #include "nsRenderingContext.h" +#include "mozilla/Preferences.h" + #ifdef DEBUG #include #endif @@ -470,6 +472,27 @@ FrameLayerBuilder::DisplayItemDataEntry::HasNonEmptyContainerLayer() return false; } +void +FrameLayerBuilder::FlashPaint(gfxContext *aContext) +{ + static bool sPaintFlashingEnabled; + static bool sPaintFlashingPrefCached = false; + + if (!sPaintFlashingPrefCached) { + sPaintFlashingPrefCached = true; + mozilla::Preferences::AddBoolVarCache(&sPaintFlashingEnabled, + "nglayout.debug.paint_flashing"); + } + + if (sPaintFlashingEnabled) { + float r = float(rand()) / RAND_MAX; + float g = float(rand()) / RAND_MAX; + float b = float(rand()) / RAND_MAX; + aContext->SetColor(gfxRGBA(r, g, b, 0.2)); + aContext->Paint(); + } +} + /* static */ nsTArray* FrameLayerBuilder::GetDisplayItemDataArrayForFrame(nsIFrame* aFrame) { @@ -2127,6 +2150,8 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer, if (setClipRect) { aContext->Restore(); } + + FlashPaint(aContext); } bool diff --git a/layout/base/FrameLayerBuilder.h b/layout/base/FrameLayerBuilder.h index da2082a6f60e..99a2e6dd47fd 100644 --- a/layout/base/FrameLayerBuilder.h +++ b/layout/base/FrameLayerBuilder.h @@ -441,6 +441,9 @@ protected: // LayerManagerData needs to see DisplayItemDataEntry. friend class LayerManagerData; + // Flash the area within the context clip if paint flashing is enabled. + static void FlashPaint(gfxContext *aContext); + /* * Get the DisplayItemData array associated with this frame, or null if one * doesn't exist. From 2ba268a8ecb7396067cf97f12cfdde5dcef76a1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20=C3=81vila=20de=20Esp=C3=ADndola?= Date: Tue, 15 Nov 2011 01:10:51 -0500 Subject: [PATCH 25/34] Bug 702275 - check AddObserver return code in nsDOMStorage.cpp. r=honzab. --- dom/src/storage/nsDOMStorage.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/dom/src/storage/nsDOMStorage.cpp b/dom/src/storage/nsDOMStorage.cpp index 9de9633ec364..87feb60f253f 100644 --- a/dom/src/storage/nsDOMStorage.cpp +++ b/dom/src/storage/nsDOMStorage.cpp @@ -287,16 +287,27 @@ nsDOMStorageManager::Initialize() if (!os) return NS_OK; - os->AddObserver(gStorageManager, "cookie-changed", false); - os->AddObserver(gStorageManager, "offline-app-removed", false); - os->AddObserver(gStorageManager, NS_PRIVATE_BROWSING_SWITCH_TOPIC, false); - os->AddObserver(gStorageManager, "profile-after-change", false); - os->AddObserver(gStorageManager, "perm-changed", false); - os->AddObserver(gStorageManager, "browser:purge-domain-data", false); + nsresult rv; + rv = os->AddObserver(gStorageManager, "cookie-changed", false); + NS_ENSURE_SUCCESS(rv, rv); + rv = os->AddObserver(gStorageManager, "offline-app-removed", false); + NS_ENSURE_SUCCESS(rv, rv); + rv = os->AddObserver(gStorageManager, NS_PRIVATE_BROWSING_SWITCH_TOPIC, + false); + NS_ENSURE_SUCCESS(rv, rv); + rv = os->AddObserver(gStorageManager, "profile-after-change", false); + NS_ENSURE_SUCCESS(rv, rv); + rv = os->AddObserver(gStorageManager, "perm-changed", false); + NS_ENSURE_SUCCESS(rv, rv); + rv = os->AddObserver(gStorageManager, "browser:purge-domain-data", false); + NS_ENSURE_SUCCESS(rv, rv); // Used for temporary table flushing - os->AddObserver(gStorageManager, "profile-before-change", false); - os->AddObserver(gStorageManager, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); - os->AddObserver(gStorageManager, NS_DOMSTORAGE_FLUSH_TIMER_TOPIC, false); + rv = os->AddObserver(gStorageManager, "profile-before-change", false); + NS_ENSURE_SUCCESS(rv, rv); + rv = os->AddObserver(gStorageManager, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); + NS_ENSURE_SUCCESS(rv, rv); + rv = os->AddObserver(gStorageManager, NS_DOMSTORAGE_FLUSH_TIMER_TOPIC, false); + NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } From 47ec399c96049d0b5c55241da4a6664495d75ec3 Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Mon, 14 Nov 2011 22:12:31 -0800 Subject: [PATCH 26/34] Backout changesets c9abc8ef4626, d62512892555, 69f89ee5d08f, c511af7d8f58, 6a6a560a1492, ac0ec1183d19, 46669afabd15, 74f32abaa8c0, f197554cf989, 0a2405eb5b90, b48954598d7d, e0a82577259c, 0235d1541e58, 450f2557d3a2, e24d196602bf, 03c2ea0eeba3, 7aca4ef8e538, 11ec362e780b, 4b92a3b96446 (bug 627842) for Windows crashtest assertions and Android reftest failures --HG-- extra : rebase_source : fc8946055314369bfba5038ded32afcb00bf134d --- build/automation.py.in | 3 - content/base/src/nsRange.cpp | 6 +- content/events/src/nsEventStateManager.cpp | 3 +- dom/interfaces/css/nsIDOMCSS2Properties.idl | 5 +- layout/base/nsCaret.cpp | 3 +- layout/base/nsLayoutUtils.cpp | 354 +------------ layout/base/nsLayoutUtils.h | 61 +-- layout/base/nsStyleConsts.h | 4 - layout/base/tests/Makefile.in | 7 - .../tests/font-inflation/bullet-1-ref.html | 9 - .../base/tests/font-inflation/bullet-1.html | 9 - .../tests/font-inflation/bullet-2-ref.html | 9 - .../base/tests/font-inflation/bullet-2.html | 9 - .../font-inflation/css-transform-1-ref.html | 6 - .../tests/font-inflation/css-transform-1.html | 10 - .../font-inflation/css-transform-2-ref.html | 6 - .../tests/font-inflation/css-transform-2.html | 10 - .../font-inflation/decoration-1-ref.html | 8 - .../tests/font-inflation/decoration-1.html | 13 - .../font-inflation/input-text-1-ref.html | 11 - .../tests/font-inflation/input-text-1.html | 11 - .../font-inflation/input-text-2-ref.html | 11 - .../tests/font-inflation/input-text-2.html | 11 - .../font-inflation/input-text-3-ref.html | 11 - .../tests/font-inflation/input-text-3.html | 11 - .../base/tests/font-inflation/text-1-ref.html | 6 - layout/base/tests/font-inflation/text-1.html | 10 - .../base/tests/font-inflation/text-2-ref.html | 6 - layout/base/tests/font-inflation/text-2.html | 10 - .../base/tests/font-inflation/text-3-ref.html | 7 - layout/base/tests/font-inflation/text-3.html | 11 - .../base/tests/font-inflation/text-4-ref.html | 7 - layout/base/tests/font-inflation/text-4.html | 11 - .../tests/font-inflation/textarea-1-ref.html | 11 - .../base/tests/font-inflation/textarea-1.html | 11 - .../tests/font-inflation/textarea-2-ref.html | 11 - .../base/tests/font-inflation/textarea-2.html | 11 - .../tests/font-inflation/textarea-3-ref.html | 11 - .../base/tests/font-inflation/textarea-3.html | 11 - .../tests/test_font_inflation_reftests.html | 127 ----- layout/build/nsLayoutStatics.cpp | 1 - layout/forms/nsListControlFrame.cpp | 38 +- layout/forms/nsListControlFrame.h | 13 +- layout/forms/nsProgressFrame.cpp | 5 +- layout/forms/nsSelectsAreaFrame.cpp | 2 +- layout/forms/nsTextControlFrame.cpp | 53 +- layout/forms/nsTextControlFrame.h | 3 +- layout/generic/TextOverflow.cpp | 21 +- layout/generic/nsBRFrame.cpp | 24 +- layout/generic/nsBlockFrame.cpp | 9 +- layout/generic/nsBulletFrame.cpp | 60 +-- layout/generic/nsBulletFrame.h | 17 +- layout/generic/nsFrame.cpp | 27 +- layout/generic/nsGfxScrollFrame.cpp | 3 +- layout/generic/nsHTMLReflowState.cpp | 65 +-- layout/generic/nsHTMLReflowState.h | 7 +- layout/generic/nsIFrame.h | 13 +- layout/generic/nsImageFrame.cpp | 3 +- layout/generic/nsInlineFrame.cpp | 3 +- layout/generic/nsLineLayout.cpp | 20 +- layout/generic/nsLineLayout.h | 5 - layout/generic/nsTextFrame.h | 77 +-- layout/generic/nsTextFrameThebes.cpp | 470 ++++++------------ layout/style/nsCSSPropList.h | 9 - layout/style/nsComputedDOMStyle.cpp | 23 +- layout/style/nsComputedDOMStyle.h | 1 - layout/style/nsRuleNode.cpp | 9 - layout/style/nsStyleStruct.cpp | 3 - layout/style/nsStyleStruct.h | 1 - layout/style/test/property_database.js | 8 - layout/tables/nsTableRowGroupFrame.cpp | 18 +- layout/xul/base/src/nsBoxFrame.cpp | 2 +- layout/xul/base/src/nsBoxLayoutState.cpp | 3 - layout/xul/base/src/nsBoxLayoutState.h | 10 +- mobile/app/mobile.js | 2 - modules/libpref/src/init/all.js | 23 - .../tests/SimpleTest/WindowSnapshot.js | 16 - 77 files changed, 273 insertions(+), 1656 deletions(-) delete mode 100644 layout/base/tests/font-inflation/bullet-1-ref.html delete mode 100644 layout/base/tests/font-inflation/bullet-1.html delete mode 100644 layout/base/tests/font-inflation/bullet-2-ref.html delete mode 100644 layout/base/tests/font-inflation/bullet-2.html delete mode 100644 layout/base/tests/font-inflation/css-transform-1-ref.html delete mode 100644 layout/base/tests/font-inflation/css-transform-1.html delete mode 100644 layout/base/tests/font-inflation/css-transform-2-ref.html delete mode 100644 layout/base/tests/font-inflation/css-transform-2.html delete mode 100644 layout/base/tests/font-inflation/decoration-1-ref.html delete mode 100644 layout/base/tests/font-inflation/decoration-1.html delete mode 100644 layout/base/tests/font-inflation/input-text-1-ref.html delete mode 100644 layout/base/tests/font-inflation/input-text-1.html delete mode 100644 layout/base/tests/font-inflation/input-text-2-ref.html delete mode 100644 layout/base/tests/font-inflation/input-text-2.html delete mode 100644 layout/base/tests/font-inflation/input-text-3-ref.html delete mode 100644 layout/base/tests/font-inflation/input-text-3.html delete mode 100644 layout/base/tests/font-inflation/text-1-ref.html delete mode 100644 layout/base/tests/font-inflation/text-1.html delete mode 100644 layout/base/tests/font-inflation/text-2-ref.html delete mode 100644 layout/base/tests/font-inflation/text-2.html delete mode 100644 layout/base/tests/font-inflation/text-3-ref.html delete mode 100644 layout/base/tests/font-inflation/text-3.html delete mode 100644 layout/base/tests/font-inflation/text-4-ref.html delete mode 100644 layout/base/tests/font-inflation/text-4.html delete mode 100644 layout/base/tests/font-inflation/textarea-1-ref.html delete mode 100644 layout/base/tests/font-inflation/textarea-1.html delete mode 100644 layout/base/tests/font-inflation/textarea-2-ref.html delete mode 100644 layout/base/tests/font-inflation/textarea-2.html delete mode 100644 layout/base/tests/font-inflation/textarea-3-ref.html delete mode 100644 layout/base/tests/font-inflation/textarea-3.html delete mode 100644 layout/base/tests/test_font_inflation_reftests.html diff --git a/build/automation.py.in b/build/automation.py.in index 42fd472c0810..fdd8e8c896e8 100644 --- a/build/automation.py.in +++ b/build/automation.py.in @@ -366,9 +366,6 @@ user_pref("app.update.enabled", false); user_pref("browser.panorama.experienced_first_run", true); // Assume experienced user_pref("dom.w3c_touch_events.enabled", true); user_pref("toolkit.telemetry.prompted", 2); -// Existing tests assume there is no font size inflation. -user_pref("font.size.inflation.emPerLine", 0); -user_pref("font.size.inflation.minTwips", 0); // Only load extensions from the application and user profile // AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION diff --git a/content/base/src/nsRange.cpp b/content/base/src/nsRange.cpp index 49fb52ae3d2b..30d2e9245af4 100644 --- a/content/base/src/nsRange.cpp +++ b/content/base/src/nsRange.cpp @@ -2167,9 +2167,9 @@ static nsresult GetPartialTextRect(nsLayoutUtils::RectCallback* aCallback, continue; // overlapping with the offset we want - f->EnsureTextRun(nsTextFrame::eInflated); - NS_ENSURE_TRUE(f->GetTextRun(nsTextFrame::eInflated), NS_ERROR_OUT_OF_MEMORY); - bool rtl = f->GetTextRun(nsTextFrame::eInflated)->IsRightToLeft(); + f->EnsureTextRun(); + NS_ENSURE_TRUE(f->GetTextRun(), NS_ERROR_OUT_OF_MEMORY); + bool rtl = f->GetTextRun()->IsRightToLeft(); nsRect r(f->GetOffsetTo(relativeTo), f->GetSize()); if (fstart < aStartOffset) { // aStartOffset is within this frame diff --git a/content/events/src/nsEventStateManager.cpp b/content/events/src/nsEventStateManager.cpp index b27d1ea19c18..42147daba60b 100644 --- a/content/events/src/nsEventStateManager.cpp +++ b/content/events/src/nsEventStateManager.cpp @@ -2547,8 +2547,7 @@ GetScrollableLineHeight(nsIFrame* aTargetFrame) // Fall back to the font height of the target frame. nsRefPtr fm; - nsLayoutUtils::GetFontMetricsForFrame(aTargetFrame, getter_AddRefs(fm), - nsLayoutUtils::FontSizeInflationFor(aTargetFrame)); + nsLayoutUtils::GetFontMetricsForFrame(aTargetFrame, getter_AddRefs(fm)); NS_ASSERTION(fm, "FontMetrics is null!"); if (fm) return fm->MaxHeight(); diff --git a/dom/interfaces/css/nsIDOMCSS2Properties.idl b/dom/interfaces/css/nsIDOMCSS2Properties.idl index 2942e572dfe7..2a968befb870 100644 --- a/dom/interfaces/css/nsIDOMCSS2Properties.idl +++ b/dom/interfaces/css/nsIDOMCSS2Properties.idl @@ -51,7 +51,7 @@ * http://www.w3.org/TR/DOM-Level-2-Style */ -[builtinclass, scriptable, uuid(0a6fc4c6-a62a-4f52-9ab6-3d398b958843)] +[builtinclass, scriptable, uuid(519ae4fa-0fee-4aaa-bcb9-34b503236801)] interface nsIDOMCSS2Properties : nsISupports { attribute DOMString background; @@ -764,7 +764,4 @@ interface nsIDOMCSS2Properties : nsISupports attribute DOMString MozAnimation; // raises(DOMException) on setting - - attribute DOMString MozTextSizeAdjust; - // raises(DOMException) on setting }; diff --git a/layout/base/nsCaret.cpp b/layout/base/nsCaret.cpp index 0d7f799ba864..c64466982bca 100644 --- a/layout/base/nsCaret.cpp +++ b/layout/base/nsCaret.cpp @@ -350,8 +350,7 @@ nsCaret::GetGeometryForFrame(nsIFrame* aFrame, nscoord baseline = frame->GetCaretBaseline(); nscoord ascent = 0, descent = 0; nsRefPtr fm; - nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm), - nsLayoutUtils::FontSizeInflationFor(aFrame)); + nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm)); NS_ASSERTION(fm, "We should be able to get the font metrics"); if (fm) { ascent = fm->MaxAscent(); diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index a7b42cac3deb..546abc05996c 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -128,9 +128,6 @@ bool nsLayoutUtils::gPreventAssertInCompareTreePosition = false; typedef gfxPattern::GraphicsFilter GraphicsFilter; typedef FrameMetrics::ViewID ViewID; -static PRUint32 sFontSizeInflationEmPerLine; -static PRUint32 sFontSizeInflationMinTwips; - static ViewID sScrollIdCounter = FrameMetrics::START_SCROLL_ID; typedef nsDataHashtable ContentMap; @@ -1928,26 +1925,22 @@ nsLayoutUtils::GetTextShadowRectsUnion(const nsRect& aTextAndDecorationsRect, nsresult nsLayoutUtils::GetFontMetricsForFrame(const nsIFrame* aFrame, - nsFontMetrics** aFontMetrics, - float aInflation) + nsFontMetrics** aFontMetrics) { return nsLayoutUtils::GetFontMetricsForStyleContext(aFrame->GetStyleContext(), - aFontMetrics, - aInflation); + aFontMetrics); } nsresult nsLayoutUtils::GetFontMetricsForStyleContext(nsStyleContext* aStyleContext, - nsFontMetrics** aFontMetrics, - float aInflation) + nsFontMetrics** aFontMetrics) { // pass the user font set object into the device context to pass along to CreateFontGroup gfxUserFontSet* fs = aStyleContext->PresContext()->GetUserFontSet(); - nsFont font = aStyleContext->GetStyleFont()->mFont; - font.size = NSToCoordRound(font.size * aInflation); return aStyleContext->PresContext()->DeviceContext()->GetMetricsFor( - font, aStyleContext->GetStyleVisibility()->mLanguage, + aStyleContext->GetStyleFont()->mFont, + aStyleContext->GetStyleVisibility()->mLanguage, fs, *aFontMetrics); } @@ -4275,8 +4268,8 @@ nsLayoutUtils::GetFontFacesForText(nsIFrame* aFrame, } // overlapping with the offset we want - gfxSkipCharsIterator iter = curr->EnsureTextRun(nsTextFrame::eInflated); - gfxTextRun* textRun = curr->GetTextRun(nsTextFrame::eInflated); + gfxSkipCharsIterator iter = curr->EnsureTextRun(); + gfxTextRun* textRun = curr->GetTextRun(); NS_ENSURE_TRUE(textRun, NS_ERROR_OUT_OF_MEMORY); PRUint32 skipStart = iter.ConvertOriginalToSkipped(fstart); @@ -4299,15 +4292,12 @@ nsLayoutUtils::GetTextRunMemoryForFrames(nsIFrame* aFrame, PRUint64* aTotal) if (aFrame->GetType() == nsGkAtoms::textFrame) { nsTextFrame* textFrame = static_cast(aFrame); - for (PRUint32 i = 0; i < 2; ++i) { - gfxTextRun *run = textFrame->GetTextRun( - (i != 0) ? nsTextFrame::eInflated : nsTextFrame::eNotInflated); - if (run) { - if (aTotal) { - run->AccountForSize(aTotal); - } else { - run->ClearSizeAccounted(); - } + gfxTextRun *run = textFrame->GetTextRun(); + if (run) { + if (aTotal) { + run->AccountForSize(aTotal); + } else { + run->ClearSizeAccounted(); } } return NS_OK; @@ -4327,16 +4317,6 @@ nsLayoutUtils::GetTextRunMemoryForFrames(nsIFrame* aFrame, PRUint64* aTotal) return NS_OK; } -/* static */ -void -nsLayoutUtils::Initialize() -{ - mozilla::Preferences::AddUintVarCache(&sFontSizeInflationEmPerLine, - "font.size.inflation.emPerLine"); - mozilla::Preferences::AddUintVarCache(&sFontSizeInflationMinTwips, - "font.size.inflation.minTwips"); -} - /* static */ void nsLayoutUtils::Shutdown() @@ -4499,311 +4479,3 @@ nsReflowFrameRunnable::Run() } return NS_OK; } - -/** - * Compute the minimum font size inside of a container with the given - * width, such that **when the user zooms the container to fill the full - * width of the device**, the fonts satisfy our minima. - */ -static nscoord -MinimumFontSizeFor(nsPresContext* aPresContext, nscoord aContainerWidth) -{ - if (sFontSizeInflationEmPerLine == 0 && sFontSizeInflationMinTwips == 0) { - return 0; - } - nscoord byLine = 0, byInch = 0; - if (sFontSizeInflationEmPerLine != 0) { - byLine = aContainerWidth / sFontSizeInflationEmPerLine; - } - if (sFontSizeInflationMinTwips != 0) { - // REVIEW: Is this giving us app units and sizes *not* counting - // viewport scaling? - nsDeviceContext *dx = aPresContext->DeviceContext(); - nsRect clientRect; - dx->GetClientRect(clientRect); // FIXME: GetClientRect looks expensive - float deviceWidthInches = - float(clientRect.width) / float(dx->AppUnitsPerPhysicalInch()); - byInch = NSToCoordRound(aContainerWidth / - (deviceWidthInches * 1440 / - sFontSizeInflationMinTwips )); - } - return NS_MAX(byLine, byInch); -} - -/* static */ float -nsLayoutUtils::FontSizeInflationInner(const nsIFrame *aFrame, - nscoord aMinFontSize) -{ - // Note that line heights should be inflated by the same ratio as the - // font size of the same text; thus we operate only on the font size - // even when we're scaling a line height. - nscoord styleFontSize = aFrame->GetStyleFont()->mFont.size; - if (styleFontSize <= 0) { - // Never scale zero font size. - return 1.0; - } - - if (aMinFontSize <= 0) { - // No need to scale. - return 1.0; - } - - // Scale everything from 0-1.5 times min to instead fit in the range - // 1-1.5 times min, so that we still show some distinction rather than - // just enforcing a minimum. - // FIXME: Fiddle with this algorithm; maybe have prefs to control it? - float ratio = float(styleFontSize) / float(aMinFontSize); - if (ratio >= 1.5f) { - // If we're already at 1.5 or more times the minimum, don't scale. - return 1.0; - } - - // To scale 0-1.5 times min to instead be 1-1.5 times min, we want - // to the desired multiple of min to be 1 + (ratio/3) (where ratio - // is our input's multiple of min). The scaling needed to produce - // that is that divided by |ratio|, or: - return (1.0f / ratio) + (1.0f / 3.0f); -} - -/* static */ bool -nsLayoutUtils::IsContainerForFontSizeInflation(const nsIFrame *aFrame) -{ - /* - * Font size inflation is build around the idea that we're inflating - * the fonts for a pan-and-zoom UI so that when the user scales up a - * block or other container to fill the width of the device, the fonts - * will be readable. To do this, we need to pick what counts as a - * container. - * - * From a code perspective, the only hard requirement is that frames - * that are line participants - * (nsIFrame::IsFrameOfType(nsIFrame::eLineParticipant)) are never - * containers, since line layout assumes that the inflation is - * consistent within a line. - * - * This is not an imposition, since we obviously want a bunch of text - * (possibly with inline elements) flowing within a block to count the - * block (or higher) as its container. - * - * We also want form controls, including the text in the anonymous - * content inside of them, to match each other and the text next to - * them, so they and their anonymous content should also not be a - * container. - * - * There are contexts where it would be nice if some blocks didn't - * count as a container, so that, for example, an indented quotation - * didn't end up with a smaller font size. However, it's hard to - * distinguish these situations where we really do want the indented - * thing to count as a container, so we don't try, and blocks are - * always containers. - */ - bool isInline = aFrame->GetStyleDisplay()->mDisplay == - NS_STYLE_DISPLAY_INLINE || - aFrame->GetContent()->IsInNativeAnonymousSubtree(); - NS_ASSERTION(!aFrame->IsFrameOfType(nsIFrame::eLineParticipant) || isInline, - "line participants must not be containers"); - NS_ASSERTION(aFrame->GetType() != nsGkAtoms::bulletFrame || isInline, - "bullets should not be containers"); - return !isInline; -} - -static bool -ShouldInflateFontsForContainer(const nsIFrame *aFrame) -{ - // We only want to inflate fonts for text that is in a place - // with room to expand. The question is what the best heuristic for - // that is... - // For now, we're going to use NS_FRAME_IN_CONSTRAINED_HEIGHT, which - // indicates whether the frame is inside something with a constrained - // height (propagating down the tree), but the propagation stops when - // we hit overflow-y: scroll or auto. - return aFrame->GetStyleText()->mTextSizeAdjust != - NS_STYLE_TEXT_SIZE_ADJUST_NONE && - !(aFrame->GetStateBits() & NS_FRAME_IN_CONSTRAINED_HEIGHT); -} - -nscoord -nsLayoutUtils::InflationMinFontSizeFor(const nsHTMLReflowState &aReflowState) -{ -#ifdef DEBUG - { - const nsHTMLReflowState *rs = &aReflowState; - const nsIFrame *f = aReflowState.frame; - for (; rs; rs = rs->parentReflowState, f = f->GetParent()) { - NS_ABORT_IF_FALSE(rs->frame == f, - "reflow state parentage must match frame parentage"); - } - } -#endif - - if (!FontSizeInflationEnabled(aReflowState.frame->PresContext())) { - return 0; - } - - nsIFrame *reflowRoot = nsnull; - for (const nsHTMLReflowState *rs = &aReflowState; rs; - reflowRoot = rs->frame, rs = rs->parentReflowState) { - if (IsContainerForFontSizeInflation(rs->frame)) { - if (!ShouldInflateFontsForContainer(rs->frame)) { - return 0; - } - - NS_ABORT_IF_FALSE(rs->ComputedWidth() != NS_INTRINSICSIZE, - "must have a computed width"); - return MinimumFontSizeFor(aReflowState.frame->PresContext(), - rs->ComputedWidth()); - } - } - - // We've hit the end of the reflow state chain. There are two - // possibilities now: we're either at a reflow root or we're crossing - // into flexbox layout. (Note that sometimes we cross into and out of - // flexbox layout on the same frame, e.g., for nsTextControlFrame, - // which breaks the reflow state parentage chain.) - // This code depends on: - // * When we cross from HTML to XUL and then on the child jump back - // to HTML again, we link the reflow states correctly (see hack in - // nsFrame::BoxReflow setting reflowState.parentReflowState). - // * For any other cases, the XUL frame is a font size inflation - // container, so we won't cross back into HTML (see the conditions - // under which we test the assertion in - // InflationMinFontSizeFor(const nsIFrame *). - - return InflationMinFontSizeFor(reflowRoot->GetParent()); -} - -nscoord -nsLayoutUtils::InflationMinFontSizeFor(const nsIFrame *aFrame) -{ -#ifdef DEBUG - // Check that neither this frame nor any of its ancestors are - // currently being reflowed. - // It's ok for box frames (but not arbitrary ancestors of box frames) - // since they set their size before reflow. - if (!(aFrame->IsBoxFrame() && IsContainerForFontSizeInflation(aFrame))) { - for (const nsIFrame *f = aFrame; f; f = f->GetParent()) { - NS_ABORT_IF_FALSE(!(f->GetStateBits() & NS_FRAME_IN_REFLOW), - "must call nsHTMLReflowState& version during reflow"); - } - } - // It's ok if frames are dirty, or even if they've never been - // reflowed, since they will be eventually and then we'll get the - // right size. -#endif - - if (!FontSizeInflationEnabled(aFrame->PresContext())) { - return 0; - } - - for (const nsIFrame *f = aFrame; f; f = f->GetParent()) { - if (IsContainerForFontSizeInflation(f)) { - if (!ShouldInflateFontsForContainer(f)) { - return 0; - } - - return MinimumFontSizeFor(aFrame->PresContext(), - f->GetContentRect().width); - } - } - - NS_ABORT_IF_FALSE(false, "root should always be container"); - - return 0; -} - -/* static */ nscoord -nsLayoutUtils::InflationMinFontSizeFor(const nsIFrame *aFrame, - nscoord aInflationContainerWidth) -{ - if (!FontSizeInflationEnabled(aFrame->PresContext())) { - return 0; - } - - for (const nsIFrame *f = aFrame; f; f = f->GetParent()) { - if (IsContainerForFontSizeInflation(f)) { - if (!ShouldInflateFontsForContainer(f)) { - return 0; - } - - // The caller is (sketchily) asserting that it picked the right - // container when passing aInflationContainerWidth. We only do - // this for text inputs and a few other limited situations. - return MinimumFontSizeFor(aFrame->PresContext(), - aInflationContainerWidth); - } - } - - NS_ABORT_IF_FALSE(false, "root should always be container"); - - return 0; -} - -float -nsLayoutUtils::FontSizeInflationFor(const nsHTMLReflowState &aReflowState) -{ -#ifdef DEBUG - { - const nsHTMLReflowState *rs = &aReflowState; - const nsIFrame *f = aReflowState.frame; - for (; rs; rs = rs->parentReflowState, f = f->GetParent()) { - NS_ABORT_IF_FALSE(rs->frame == f, - "reflow state parentage must match frame parentage"); - } - } -#endif - - if (!FontSizeInflationEnabled(aReflowState.frame->PresContext())) { - return 1.0; - } - - return FontSizeInflationInner(aReflowState.frame, - InflationMinFontSizeFor(aReflowState)); -} - -float -nsLayoutUtils::FontSizeInflationFor(const nsIFrame *aFrame) -{ -#ifdef DEBUG - // Check that neither this frame nor any of its ancestors are - // currently being reflowed. - // It's ok for box frames (but not arbitrary ancestors of box frames) - // since they set their size before reflow. - if (!(aFrame->IsBoxFrame() && IsContainerForFontSizeInflation(aFrame))) { - for (const nsIFrame *f = aFrame; f; f = f->GetParent()) { - NS_ABORT_IF_FALSE(!(f->GetStateBits() & NS_FRAME_IN_REFLOW), - "must call nsHTMLReflowState& version during reflow"); - } - } - // It's ok if frames are dirty, or even if they've never been - // reflowed, since they will be eventually and then we'll get the - // right size. -#endif - - if (!FontSizeInflationEnabled(aFrame->PresContext())) { - return 1.0; - } - - return FontSizeInflationInner(aFrame, - InflationMinFontSizeFor(aFrame)); -} - -/* static */ float -nsLayoutUtils::FontSizeInflationFor(const nsIFrame *aFrame, - nscoord aInflationContainerWidth) -{ - if (!FontSizeInflationEnabled(aFrame->PresContext())) { - return 1.0; - } - - return FontSizeInflationInner(aFrame, - InflationMinFontSizeFor(aFrame, - aInflationContainerWidth)); -} - -/* static */ bool -nsLayoutUtils::FontSizeInflationEnabled(nsPresContext *aPresContext) -{ - return (sFontSizeInflationEmPerLine != 0 || - sFontSizeInflationMinTwips != 0) && - !aPresContext->IsChrome(); -} diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index ecd6d66528d4..623bacb78f67 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -742,23 +742,19 @@ public: * Get the font metrics corresponding to the frame's style data. * @param aFrame the frame * @param aFontMetrics the font metrics result - * @param aSizeInflation number to multiply font size by * @return success or failure code */ static nsresult GetFontMetricsForFrame(const nsIFrame* aFrame, - nsFontMetrics** aFontMetrics, - float aSizeInflation = 1.0f); + nsFontMetrics** aFontMetrics); /** * Get the font metrics corresponding to the given style data. * @param aStyleContext the style data * @param aFontMetrics the font metrics result - * @param aSizeInflation number to multiply font size by * @return success or failure code */ static nsresult GetFontMetricsForStyleContext(nsStyleContext* aStyleContext, - nsFontMetrics** aFontMetrics, - float aSizeInflation = 1.0f); + nsFontMetrics** aFontMetrics); /** * Find the immediate child of aParent whose frame subtree contains @@ -1456,59 +1452,6 @@ public: */ static bool Are3DTransformsEnabled(); - /** - * Return whether this is a frame whose width is used when computing - * the font size inflation of its descendants. - */ - static bool IsContainerForFontSizeInflation(const nsIFrame *aFrame); - - /** - * Return the font size inflation *ratio* for a given frame. This is - * the factor by which font sizes should be inflated; it is never - * smaller than 1. - * - * There are three variants: pass a reflow state if the frame or any - * of its ancestors are currently being reflowed and a frame - * otherwise, or, if you know the width of the inflation container (a - * somewhat sketchy assumption), its width. - */ - static float FontSizeInflationFor(const nsHTMLReflowState &aReflowState); - static float FontSizeInflationFor(const nsIFrame *aFrame); - static float FontSizeInflationFor(const nsIFrame *aFrame, - nscoord aInflationContainerWidth); - - /** - * Perform the first half of the computation of FontSizeInflationFor - * (see above). - * This includes determining whether inflation should be performed - * within this container and returning 0 if it should not be. - * - * The result is guaranteed not to vary between line participants - * (inlines, text frames) within a line. - * - * The result should not be used directly since font sizes slightly - * above the minimum should always be adjusted as done by - * FontSizeInflationInner. - */ - static nscoord InflationMinFontSizeFor(const nsHTMLReflowState - &aReflowState); - static nscoord InflationMinFontSizeFor(const nsIFrame *aFrame); - static nscoord InflationMinFontSizeFor(const nsIFrame *aFrame, - nscoord aInflationContainerWidth); - - /** - * Perform the second half of the computation done by - * FontSizeInflationFor (see above). - * - * aMinFontSize must be the result of one of the - * InflationMinFontSizeFor methods above. - */ - static float FontSizeInflationInner(const nsIFrame *aFrame, - nscoord aMinFontSize); - - static bool FontSizeInflationEnabled(nsPresContext *aPresContext); - - static void Initialize(); static void Shutdown(); /** diff --git a/layout/base/nsStyleConsts.h b/layout/base/nsStyleConsts.h index 7b0cec3c2199..68985b6471dd 100644 --- a/layout/base/nsStyleConsts.h +++ b/layout/base/nsStyleConsts.h @@ -713,10 +713,6 @@ static inline mozilla::css::Side operator++(mozilla::css::Side& side, int) { #define NS_STYLE_HYPHENS_MANUAL 1 #define NS_STYLE_HYPHENS_AUTO 2 -// See nsStyleText -#define NS_STYLE_TEXT_SIZE_ADJUST_NONE 0 -#define NS_STYLE_TEXT_SIZE_ADJUST_AUTO 1 - // See nsStyleText #define NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT 0 diff --git a/layout/base/tests/Makefile.in b/layout/base/tests/Makefile.in index 899c432b0b89..4b58fa5097ac 100644 --- a/layout/base/tests/Makefile.in +++ b/layout/base/tests/Makefile.in @@ -180,7 +180,6 @@ _TEST_FILES = \ test_bug603550.html \ test_bug629838.html \ test_bug646757.html \ - test_font_inflation_reftests.html \ $(NULL) # Tests for bugs 441782, 467672 and 570378 don't pass reliably on Windows, because of bug 469208 @@ -378,16 +377,10 @@ _BROWSER_FILES = \ browser_bug617076.js \ $(NULL) -_INFLATION_REFTEST_FILES = \ - $(shell find $(srcdir)/font-inflation/ -name '*.html' -o -name '*.xhtml') \ - $(NULL) - libs:: $(_TEST_FILES) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir) libs:: $(_BROWSER_FILES) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir) -libs:: $(_INFLATION_REFTEST_FILES) - $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)/font-inflation/ check:: @$(EXIT_ON_ERROR) \ diff --git a/layout/base/tests/font-inflation/bullet-1-ref.html b/layout/base/tests/font-inflation/bullet-1-ref.html deleted file mode 100644 index 6f87b9407558..000000000000 --- a/layout/base/tests/font-inflation/bullet-1-ref.html +++ /dev/null @@ -1,9 +0,0 @@ - - -
    -
  • item
  • -
diff --git a/layout/base/tests/font-inflation/bullet-1.html b/layout/base/tests/font-inflation/bullet-1.html deleted file mode 100644 index 6433753fd622..000000000000 --- a/layout/base/tests/font-inflation/bullet-1.html +++ /dev/null @@ -1,9 +0,0 @@ - - -
    -
  • item
  • -
diff --git a/layout/base/tests/font-inflation/bullet-2-ref.html b/layout/base/tests/font-inflation/bullet-2-ref.html deleted file mode 100644 index 5f84a9d64e8c..000000000000 --- a/layout/base/tests/font-inflation/bullet-2-ref.html +++ /dev/null @@ -1,9 +0,0 @@ - - -
    -
  1. item
  2. -
diff --git a/layout/base/tests/font-inflation/bullet-2.html b/layout/base/tests/font-inflation/bullet-2.html deleted file mode 100644 index 9e1ce9240038..000000000000 --- a/layout/base/tests/font-inflation/bullet-2.html +++ /dev/null @@ -1,9 +0,0 @@ - - -
    -
  1. item
  2. -
diff --git a/layout/base/tests/font-inflation/css-transform-1-ref.html b/layout/base/tests/font-inflation/css-transform-1-ref.html deleted file mode 100644 index 36ea266158ac..000000000000 --- a/layout/base/tests/font-inflation/css-transform-1-ref.html +++ /dev/null @@ -1,6 +0,0 @@ - - -
Hello world
diff --git a/layout/base/tests/font-inflation/css-transform-1.html b/layout/base/tests/font-inflation/css-transform-1.html deleted file mode 100644 index 7fc0e8fe5305..000000000000 --- a/layout/base/tests/font-inflation/css-transform-1.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -
Hello world
diff --git a/layout/base/tests/font-inflation/css-transform-2-ref.html b/layout/base/tests/font-inflation/css-transform-2-ref.html deleted file mode 100644 index b0916faad805..000000000000 --- a/layout/base/tests/font-inflation/css-transform-2-ref.html +++ /dev/null @@ -1,6 +0,0 @@ - - -

Hello world

diff --git a/layout/base/tests/font-inflation/css-transform-2.html b/layout/base/tests/font-inflation/css-transform-2.html deleted file mode 100644 index 856ee8e2c625..000000000000 --- a/layout/base/tests/font-inflation/css-transform-2.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -

Hello world

diff --git a/layout/base/tests/font-inflation/decoration-1-ref.html b/layout/base/tests/font-inflation/decoration-1-ref.html deleted file mode 100644 index ce2b0c0ef0b8..000000000000 --- a/layout/base/tests/font-inflation/decoration-1-ref.html +++ /dev/null @@ -1,8 +0,0 @@ - - -
Hello world
diff --git a/layout/base/tests/font-inflation/decoration-1.html b/layout/base/tests/font-inflation/decoration-1.html deleted file mode 100644 index 9392fafcd187..000000000000 --- a/layout/base/tests/font-inflation/decoration-1.html +++ /dev/null @@ -1,13 +0,0 @@ - - - -
Hello world
diff --git a/layout/base/tests/font-inflation/input-text-1-ref.html b/layout/base/tests/font-inflation/input-text-1-ref.html deleted file mode 100644 index 2514297cc930..000000000000 --- a/layout/base/tests/font-inflation/input-text-1-ref.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
diff --git a/layout/base/tests/font-inflation/input-text-1.html b/layout/base/tests/font-inflation/input-text-1.html deleted file mode 100644 index 48bf661cc79c..000000000000 --- a/layout/base/tests/font-inflation/input-text-1.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
diff --git a/layout/base/tests/font-inflation/input-text-2-ref.html b/layout/base/tests/font-inflation/input-text-2-ref.html deleted file mode 100644 index 7e52747742e5..000000000000 --- a/layout/base/tests/font-inflation/input-text-2-ref.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
diff --git a/layout/base/tests/font-inflation/input-text-2.html b/layout/base/tests/font-inflation/input-text-2.html deleted file mode 100644 index cda175fdeae2..000000000000 --- a/layout/base/tests/font-inflation/input-text-2.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
diff --git a/layout/base/tests/font-inflation/input-text-3-ref.html b/layout/base/tests/font-inflation/input-text-3-ref.html deleted file mode 100644 index 65173d430ba4..000000000000 --- a/layout/base/tests/font-inflation/input-text-3-ref.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
diff --git a/layout/base/tests/font-inflation/input-text-3.html b/layout/base/tests/font-inflation/input-text-3.html deleted file mode 100644 index a4cb881f1a81..000000000000 --- a/layout/base/tests/font-inflation/input-text-3.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
diff --git a/layout/base/tests/font-inflation/text-1-ref.html b/layout/base/tests/font-inflation/text-1-ref.html deleted file mode 100644 index cdf5d8544804..000000000000 --- a/layout/base/tests/font-inflation/text-1-ref.html +++ /dev/null @@ -1,6 +0,0 @@ - - -
Hello world
diff --git a/layout/base/tests/font-inflation/text-1.html b/layout/base/tests/font-inflation/text-1.html deleted file mode 100644 index 3bc6129d3641..000000000000 --- a/layout/base/tests/font-inflation/text-1.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -
Hello world
diff --git a/layout/base/tests/font-inflation/text-2-ref.html b/layout/base/tests/font-inflation/text-2-ref.html deleted file mode 100644 index ea117963c01e..000000000000 --- a/layout/base/tests/font-inflation/text-2-ref.html +++ /dev/null @@ -1,6 +0,0 @@ - - -
Hello world
diff --git a/layout/base/tests/font-inflation/text-2.html b/layout/base/tests/font-inflation/text-2.html deleted file mode 100644 index 848a40eb3a75..000000000000 --- a/layout/base/tests/font-inflation/text-2.html +++ /dev/null @@ -1,10 +0,0 @@ - - - -
Hello world
diff --git a/layout/base/tests/font-inflation/text-3-ref.html b/layout/base/tests/font-inflation/text-3-ref.html deleted file mode 100644 index c2565f0c97b7..000000000000 --- a/layout/base/tests/font-inflation/text-3-ref.html +++ /dev/null @@ -1,7 +0,0 @@ - - -
Hello world
diff --git a/layout/base/tests/font-inflation/text-3.html b/layout/base/tests/font-inflation/text-3.html deleted file mode 100644 index e410a10acea0..000000000000 --- a/layout/base/tests/font-inflation/text-3.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
Hello world
diff --git a/layout/base/tests/font-inflation/text-4-ref.html b/layout/base/tests/font-inflation/text-4-ref.html deleted file mode 100644 index b8930c11719e..000000000000 --- a/layout/base/tests/font-inflation/text-4-ref.html +++ /dev/null @@ -1,7 +0,0 @@ - - -
Hello world
diff --git a/layout/base/tests/font-inflation/text-4.html b/layout/base/tests/font-inflation/text-4.html deleted file mode 100644 index ba9ab9ef8055..000000000000 --- a/layout/base/tests/font-inflation/text-4.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
Hello world
diff --git a/layout/base/tests/font-inflation/textarea-1-ref.html b/layout/base/tests/font-inflation/textarea-1-ref.html deleted file mode 100644 index c393cb09c1ae..000000000000 --- a/layout/base/tests/font-inflation/textarea-1-ref.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
diff --git a/layout/base/tests/font-inflation/textarea-1.html b/layout/base/tests/font-inflation/textarea-1.html deleted file mode 100644 index 34e2446c4b0d..000000000000 --- a/layout/base/tests/font-inflation/textarea-1.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
diff --git a/layout/base/tests/font-inflation/textarea-2-ref.html b/layout/base/tests/font-inflation/textarea-2-ref.html deleted file mode 100644 index da650e128fe1..000000000000 --- a/layout/base/tests/font-inflation/textarea-2-ref.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
diff --git a/layout/base/tests/font-inflation/textarea-2.html b/layout/base/tests/font-inflation/textarea-2.html deleted file mode 100644 index 7405f70754b3..000000000000 --- a/layout/base/tests/font-inflation/textarea-2.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
diff --git a/layout/base/tests/font-inflation/textarea-3-ref.html b/layout/base/tests/font-inflation/textarea-3-ref.html deleted file mode 100644 index 4f9d6065bcff..000000000000 --- a/layout/base/tests/font-inflation/textarea-3-ref.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
diff --git a/layout/base/tests/font-inflation/textarea-3.html b/layout/base/tests/font-inflation/textarea-3.html deleted file mode 100644 index e4ed681f4af5..000000000000 --- a/layout/base/tests/font-inflation/textarea-3.html +++ /dev/null @@ -1,11 +0,0 @@ - - - -
diff --git a/layout/base/tests/test_font_inflation_reftests.html b/layout/base/tests/test_font_inflation_reftests.html deleted file mode 100644 index 81c29f252788..000000000000 --- a/layout/base/tests/test_font_inflation_reftests.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - Font size inflation reftests - - - - - - -Mozilla Bug 627842 -
-
-
- - diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index 3fa323e25ca0..645d48eee0da 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -258,7 +258,6 @@ nsLayoutStatics::Initialize() nsContentSink::InitializeStatics(); nsHtml5Module::InitializeStatics(); - nsLayoutUtils::Initialize(); nsIPresShell::InitializeStatics(); nsRefreshDriver::InitializeStatics(); diff --git a/layout/forms/nsListControlFrame.cpp b/layout/forms/nsListControlFrame.cpp index 2db13423c1f1..4341d91cc0d7 100644 --- a/layout/forms/nsListControlFrame.cpp +++ b/layout/forms/nsListControlFrame.cpp @@ -257,10 +257,9 @@ void nsListControlFrame::PaintFocus(nsRenderingContext& aRC, nsPoint aPt) // get it into our coordinates fRect.MoveBy(childframe->GetParent()->GetOffsetTo(this)); } else { - float inflation = nsLayoutUtils::FontSizeInflationFor(this); fRect.x = fRect.y = 0; fRect.width = GetScrollPortRect().width; - fRect.height = CalcFallbackRowHeight(inflation); + fRect.height = CalcFallbackRowHeight(); fRect.MoveBy(containerFrame->GetOffsetTo(this)); } fRect += aPt; @@ -284,7 +283,7 @@ void nsListControlFrame::PaintFocus(nsRenderingContext& aRC, nsPoint aPt) } void -nsListControlFrame::InvalidateFocus(const nsHTMLReflowState *aReflowState) +nsListControlFrame::InvalidateFocus() { if (mFocused != this) return; @@ -294,16 +293,8 @@ nsListControlFrame::InvalidateFocus(const nsHTMLReflowState *aReflowState) // Invalidating from the containerFrame because that's where our focus // is drawn. // The origin of the scrollport is the origin of containerFrame. - float inflation; - if (aReflowState) { - NS_ABORT_IF_FALSE(aReflowState->frame == this, "wrong reflow state"); - inflation = nsLayoutUtils::FontSizeInflationFor(*aReflowState); - } else { - inflation = nsLayoutUtils::FontSizeInflationFor(this); - } nsRect invalidateArea = containerFrame->GetVisualOverflowRect(); - nsRect emptyFallbackArea(0, 0, GetScrollPortRect().width, - CalcFallbackRowHeight(inflation)); + nsRect emptyFallbackArea(0, 0, GetScrollPortRect().width, CalcFallbackRowHeight()); invalidateArea.UnionRect(invalidateArea, emptyFallbackArea); containerFrame->Invalidate(invalidateArea); } @@ -374,11 +365,8 @@ GetNumberOfOptionsRecursive(nsIContent* aContent) // Main Reflow for ListBox/Dropdown //----------------------------------------------------------------- -// Note that it doesn't much matter *which* reflow state aReflowState -// is (as long as it's in the right block); we intentionally pass -// whatever reflow state is most convenient. nscoord -nsListControlFrame::CalcHeightOfARow(const nsHTMLReflowState& aReflowState) +nsListControlFrame::CalcHeightOfARow() { // Calculate the height of a single row in the listbox or dropdown list by // using the tallest thing in the subtree, since there may be option groups @@ -389,9 +377,7 @@ nsListControlFrame::CalcHeightOfARow(const nsHTMLReflowState& aReflowState) // Check to see if we have zero items (and optimize by checking // heightOfARow first) if (heightOfARow == 0 && GetNumberOfOptions() == 0) { - nscoord minFontSize = nsLayoutUtils::InflationMinFontSizeFor(aReflowState); - float inflation = nsLayoutUtils::FontSizeInflationInner(this, minFontSize); - heightOfARow = CalcFallbackRowHeight(inflation); + heightOfARow = CalcFallbackRowHeight(); } return heightOfARow; @@ -514,7 +500,7 @@ nsListControlFrame::Reflow(nsPresContext* aPresContext, // already set mNumDisplayRows in CalcIntrinsicHeight. Also note that we // can't use HeightOfARow() here because that just uses a cached value // that we didn't compute. - nscoord rowHeight = CalcHeightOfARow(aReflowState); + nscoord rowHeight = CalcHeightOfARow(); if (rowHeight == 0) { // Just pick something mNumDisplayRows = 1; @@ -1181,8 +1167,7 @@ nsListControlFrame::OnContentReset() } void -nsListControlFrame::ResetList(bool aAllowScrolling, - const nsHTMLReflowState *aReflowState) +nsListControlFrame::ResetList(bool aAllowScrolling) { // if all the frames aren't here // don't bother reseting @@ -1206,7 +1191,7 @@ nsListControlFrame::ResetList(bool aAllowScrolling, mStartSelectionIndex = kNothingSelected; mEndSelectionIndex = kNothingSelected; - InvalidateFocus(aReflowState); + InvalidateFocus(); // Combobox will redisplay itself with the OnOptionSelected event } @@ -1759,7 +1744,7 @@ nsListControlFrame::DidReflow(nsPresContext* aPresContext, // The idea is that we want scroll history restoration to trump ResetList // scrolling to the selected element, when the ResetList was probably only // caused by content loading normally. - ResetList(!DidHistoryRestore() || mPostChildrenLoadedReset, aReflowState); + ResetList(!DidHistoryRestore() || mPostChildrenLoadedReset); } mHasPendingInterruptAtStartOfReflow = false; @@ -1828,13 +1813,12 @@ nsListControlFrame::IsLeftButton(nsIDOMEvent* aMouseEvent) } nscoord -nsListControlFrame::CalcFallbackRowHeight(float aFontSizeInflation) +nsListControlFrame::CalcFallbackRowHeight() { nscoord rowHeight = 0; nsRefPtr fontMet; - nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet), - aFontSizeInflation); + nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet)); if (fontMet) { rowHeight = fontMet->MaxHeight(); } diff --git a/layout/forms/nsListControlFrame.h b/layout/forms/nsListControlFrame.h index 245eabfc3601..b86fd290e0cc 100644 --- a/layout/forms/nsListControlFrame.h +++ b/layout/forms/nsListControlFrame.h @@ -239,16 +239,14 @@ public: * that PaintFocus will or could have painted --- basically the whole * GetOptionsContainer, plus some extra stuff if there are no options. This * must be called every time mEndSelectionIndex changes. - * - * Pass non-null aReflowState if during reflow. */ - void InvalidateFocus(const nsHTMLReflowState* aReflowState = nsnull); + void InvalidateFocus(); /** * Function to calculate the height a row, for use with the "size" attribute. * Can't be const because GetNumberOfOptions() isn't const. */ - nscoord CalcHeightOfARow(const nsHTMLReflowState& aReflowState); + nscoord CalcHeightOfARow(); /** * Function to ask whether we're currently in what might be the @@ -334,11 +332,8 @@ protected: /** * Resets the select back to it's original default values; * those values as determined by the original HTML - * - * Pass non-null aReflowState if during reflow. */ - virtual void ResetList(bool aAllowScrolling, - const nsHTMLReflowState* aReflowState = nsnull); + virtual void ResetList(bool aAllowScrolling); nsListControlFrame(nsIPresShell* aShell, nsIDocument* aDocument, nsStyleContext* aContext); virtual ~nsListControlFrame(); @@ -378,7 +373,7 @@ protected: bool IsLeftButton(nsIDOMEvent* aMouseEvent); // guess at a row height based on our own style. - nscoord CalcFallbackRowHeight(float aFontSizeInflation); + nscoord CalcFallbackRowHeight(); // CalcIntrinsicHeight computes our intrinsic height (taking the "size" // attribute into account). This should only be called in non-dropdown mode. diff --git a/layout/forms/nsProgressFrame.cpp b/layout/forms/nsProgressFrame.cpp index fefa6095ca32..8a83b19446e0 100644 --- a/layout/forms/nsProgressFrame.cpp +++ b/layout/forms/nsProgressFrame.cpp @@ -262,12 +262,9 @@ nsProgressFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext, nsSize aMargin, nsSize aBorder, nsSize aPadding, bool aShrinkWrap) { - float inflation = - nsLayoutUtils::FontSizeInflationFor(this, aCBSize.width); nsRefPtr fontMet; NS_ENSURE_SUCCESS(nsLayoutUtils::GetFontMetricsForFrame(this, - getter_AddRefs(fontMet), - inflation), + getter_AddRefs(fontMet)), nsSize(0, 0)); nsSize autoSize; diff --git a/layout/forms/nsSelectsAreaFrame.cpp b/layout/forms/nsSelectsAreaFrame.cpp index 00a6f706a4bc..10506d92ce78 100644 --- a/layout/forms/nsSelectsAreaFrame.cpp +++ b/layout/forms/nsSelectsAreaFrame.cpp @@ -234,7 +234,7 @@ nsSelectsAreaFrame::Reflow(nsPresContext* aPresContext, // Check whether we need to suppress scrolbar updates. We want to do that if // we're in a possible first pass and our height of a row has changed. if (list->MightNeedSecondPass()) { - nscoord newHeightOfARow = list->CalcHeightOfARow(aReflowState); + nscoord newHeightOfARow = list->CalcHeightOfARow(); // We'll need a second pass if our height of a row changed. For // comboboxes, we'll also need it if our height changed. If we're going // to do a second pass, suppress scrollbar updates for this pass. diff --git a/layout/forms/nsTextControlFrame.cpp b/layout/forms/nsTextControlFrame.cpp index a84f9adeaf2c..be6bdba9e2aa 100644 --- a/layout/forms/nsTextControlFrame.cpp +++ b/layout/forms/nsTextControlFrame.cpp @@ -217,8 +217,7 @@ nsTextControlFrame::GetType() const nsresult nsTextControlFrame::CalcIntrinsicSize(nsRenderingContext* aRenderingContext, - nsSize& aIntrinsicSize, - float aFontSizeInflation) + nsSize& aIntrinsicSize) { // Get leading and the Average/MaxAdvance char width nscoord lineHeight = 0; @@ -227,14 +226,12 @@ nsTextControlFrame::CalcIntrinsicSize(nsRenderingContext* aRenderingContext, nsRefPtr fontMet; nsresult rv = - nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet), - aFontSizeInflation); + nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet)); NS_ENSURE_SUCCESS(rv, rv); aRenderingContext->SetFont(fontMet); lineHeight = - nsHTMLReflowState::CalcLineHeight(GetStyleContext(), NS_AUTOHEIGHT, - aFontSizeInflation); + nsHTMLReflowState::CalcLineHeight(GetStyleContext(), NS_AUTOHEIGHT); charWidth = fontMet->AveCharWidth(); charMaxAdvance = fontMet->MaxAdvance(); @@ -501,16 +498,8 @@ nsTextControlFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext, nsSize aMargin, nsSize aBorder, nsSize aPadding, bool aShrinkWrap) { - float inflation; - if (nsLayoutUtils::IsContainerForFontSizeInflation(this)) { - // FIXME: This won't turn out so well for the height; maybe disable - // inflation entirely in this case? - inflation = 1.0f; - } else { - inflation = nsLayoutUtils::FontSizeInflationFor(this, aCBSize.width); - } nsSize autoSize; - nsresult rv = CalcIntrinsicSize(aRenderingContext, autoSize, inflation); + nsresult rv = CalcIntrinsicSize(aRenderingContext, autoSize); if (NS_FAILED(rv)) { // What now? autoSize.SizeTo(0, 0); @@ -523,8 +512,7 @@ nsTextControlFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext, aCBSize, aAvailableWidth, aMargin, aBorder, aPadding, aShrinkWrap); - // Disabled when there's inflation; see comment in GetPrefSize. - NS_ASSERTION(inflation != 1.0f || ancestorAutoSize.width == autoSize.width, + NS_ASSERTION(ancestorAutoSize.width == autoSize.width, "Incorrect size computed by ComputeAutoSize?"); } #endif @@ -565,11 +553,7 @@ nsTextControlFrame::GetPrefSize(nsBoxLayoutState& aState) nsSize pref(0,0); - // FIXME: This inflation parameter isn't correct; we should fix it if - // we want font size inflation to work well in XUL. If we do, we can - // also re-enable the assertion in ComputeAutoSize when inflation is - // enabled. - nsresult rv = CalcIntrinsicSize(aState.GetRenderingContext(), pref, 1.0f); + nsresult rv = CalcIntrinsicSize(aState.GetRenderingContext(), pref); NS_ENSURE_SUCCESS(rv, pref); AddBorderAndPadding(pref); @@ -615,37 +599,16 @@ nsTextControlFrame::GetBoxAscent(nsBoxLayoutState& aState) // Return the baseline of the first (nominal) row, with centering for // single-line controls. - float inflation; - if (nsLayoutUtils::IsContainerForFontSizeInflation(this)) { - inflation = - nsLayoutUtils::FontSizeInflationFor(this, GetContentRect().width); - } else { - const nsHTMLReflowState *outerReflowState = aState.OuterReflowState(); - NS_ASSERTION(outerReflowState || !mParent || mParent->IsBoxFrame() || - !(mParent->GetStateBits() & NS_FRAME_IN_REFLOW), - "when a text control is reflowed by one of its ancestors " - "and its parent is non-XUL, we should have the outer " - "reflow state in the box layout state"); - if (outerReflowState && outerReflowState->frame == this) { - inflation = nsLayoutUtils::FontSizeInflationFor(*outerReflowState); - } else { - inflation = nsLayoutUtils::FontSizeInflationInner(this, - nsLayoutUtils::InflationMinFontSizeFor(mParent)); - } - } - // First calculate the ascent wrt the client rect nsRect clientRect; GetClientRect(clientRect); nscoord lineHeight = IsSingleLineTextControl() ? clientRect.height : - nsHTMLReflowState::CalcLineHeight(GetStyleContext(), NS_AUTOHEIGHT, - inflation); + nsHTMLReflowState::CalcLineHeight(GetStyleContext(), NS_AUTOHEIGHT); nsRefPtr fontMet; nsresult rv = - nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet), - inflation); + nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet)); NS_ENSURE_SUCCESS(rv, 0); nscoord ascent = nsLayoutUtils::GetCenteredFontBaseline(fontMet, lineHeight); diff --git a/layout/forms/nsTextControlFrame.h b/layout/forms/nsTextControlFrame.h index b2af727b57d0..6615d8573ce4 100644 --- a/layout/forms/nsTextControlFrame.h +++ b/layout/forms/nsTextControlFrame.h @@ -392,8 +392,7 @@ protected: // etc. Just the size of our actual area for the text (and the scrollbars, // for