From b64f6c4e3d101e59b7619bca7774241a71b1e93e Mon Sep 17 00:00:00 2001 From: Scott Johnson Date: Tue, 15 Nov 2011 10:59:19 +1300 Subject: [PATCH 01/40] 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 7fe9538eeb1..00000000000 --- 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 73e635e6d8b..8e3c73aac7d 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 4a0bfea577d..69127614a90 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 eb16264847e..3155f5d9224 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 c32501b38cf..e0beba4d915 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 ec9daedef4996c9bad69e7f2eb8e7fa26229248f Mon Sep 17 00:00:00 2001 From: Scott Johnson Date: Tue, 15 Nov 2011 15:45:43 +1300 Subject: [PATCH 02/40] 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 8c730cf238c..3b656ce3aa2 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 8ee0331573da1c5039dbe769fc1b8bebadb299ba Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:00 +1300 Subject: [PATCH 03/40] 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 2a968befb87..2942e572dfe 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 68985b6471d..7b0cec3c219 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 a075798442f..69268eee5a4 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 5363e010fbe..a0eebfff543 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 37e95178631..d1a432136bd 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 27336bf8ea5..2e7a332edad 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 988070a0bd2..559b45d60ca 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 332b089d570..d8114caec12 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 1e20b45c21b..7d7f231f566 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 9c01fd07df7b69d120a198a501349eb37c8da536 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:00 +1300 Subject: [PATCH 04/40] 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 58d22c684a3..a1d5b79a7c4 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 470b21aab8d..a57fa31fc7a 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 5270d5913fa1d5c64116c1e78f21beea26d69be8 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:00 +1300 Subject: [PATCH 05/40] 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 dec6ab3fc65..34460fe9ecc 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 f775d061f84..254aec7c00e 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 8e8b19397d3..f72a11375c1 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 3bec5e05930..452e30f2a39 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 0771ac796f2b2a9189c3d07ff82a7b452c598d9f Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:00 +1300 Subject: [PATCH 06/40] 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 a57fa31fc7a..eeca38cd295 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 7a61a331c0e29a48eeec3b7dfdc9a673ae2a59ae Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:00 +1300 Subject: [PATCH 07/40] 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 4f50057e5ae..c6c64f49bc2 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 443c311ad2016d7dbc0d053c124f3ca0a9e262fd Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:00 +1300 Subject: [PATCH 08/40] 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 546abc05996..795dc1f5539 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 623bacb78f6..ae925a6e8df 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 645d48eee0d..3fa323e25ca 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 b49fd031cf3..5271c1534bb 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 22d65a43ad8..89030231cc1 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 9bbf22c233f305679f0d8939aff32ceb0ce5ab4b Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:00 +1300 Subject: [PATCH 09/40] 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 34460fe9ecc..85fa63a9c66 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 a1d5b79a7c4..63bc722097c 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 1922ba1843493b95cb8925ddeacafb243e36af12 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:00 +1300 Subject: [PATCH 10/40] 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 795dc1f5539..e39dd12af70 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 ae925a6e8df..ecd6d66528d 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 182cc9987979f7318e97939527f9561c8cd80499 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:01 +1300 Subject: [PATCH 11/40] 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 f7868013594..9c6970e781e 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 fb0468e983931b46fc2f35fb38ae44d7580a8e6a Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:01 +1300 Subject: [PATCH 12/40] 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 33bcafda658..83bd073fccb 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 91eb19a61e3..9a42d97d893 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 d522ffcc8ae..ad18f1ccb3c 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 9c6970e781e..566713f5c16 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 9bdb215c120bdef114ef5ec3f6cf264745af4507 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:01 +1300 Subject: [PATCH 13/40] 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 30d2e9245af..49fb52ae3d2 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 e39dd12af70..17ca9bc52c5 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 ad18f1ccb3c..36463cdadfb 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 566713f5c16..1800cc367a0 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 58c07a0fce054d0b2044d0d3dc086157368bddca Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:01 +1300 Subject: [PATCH 14/40] 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 29ba6a226b9..d509f308148 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 36463cdadfb..daba355eda3 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 1800cc367a0..df732b93e45 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 2a79ab57263586453c8e3c7709c0322b7dcef58b Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:01 +1300 Subject: [PATCH 15/40] 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 be6bdba9e2a..a84f9adeaf2 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 6615d8573ce..b2af727b57d 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 00000000000..34e2446c4b0 --- /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 00000000000..da650e128fe --- /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 00000000000..7405f70754b --- /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 00000000000..4f9d6065bcf --- /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 00000000000..e4ed681f4af --- /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 00000000000..81c29f25278 --- /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 91215f83cdd..35034abc252 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 73020220e20898f6a3186d59ad3788eece49bf2a Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Tue, 15 Nov 2011 17:02:01 +1300 Subject: [PATCH 21/40] 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 ad35c6892c6..f5ec28b61b6 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 fa1f82307ef83fccdb93b1007091c19f7934c0b8 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 8 Nov 2011 16:41:50 -0500 Subject: [PATCH 22/40] 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 3945e6ad28d..c6254c7c92e 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 22f06b93fda0cfdcf1caaf0450af59a0642f9ed2 Mon Sep 17 00:00:00 2001 From: Jonathan Griffin Date: Tue, 8 Nov 2011 13:45:42 -0800 Subject: [PATCH 23/40] Bug 697824 - buildUrl isn't a member of self, a=testonly, DONTBUILD --- testing/tps/tps/testrunner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/tps/tps/testrunner.py b/testing/tps/tps/testrunner.py index bf107b83d6d..aaf3a134363 100644 --- a/testing/tps/tps/testrunner.py +++ b/testing/tps/tps/testrunner.py @@ -440,7 +440,7 @@ class TPSTestRunner(object): self.numpassed, self.numfailed, self.config['account']['serverURL'], - self.buildUrl) + buildUrl) subj = "TPS Report: " if self.numfailed == 0 and self.numpassed > 0: From 4d3ebede9adeb437918e62c17f88bb5817ed9107 Mon Sep 17 00:00:00 2001 From: Gregory Szorc Date: Thu, 10 Nov 2011 15:33:56 -0800 Subject: [PATCH 24/40] Bug 604565 - Enable previously-disabled xpcshell tests on OS X; a=philikon It has been a while since these disabled tests have been tested in the build environment. We're enabling them to see if they have magically fixed themselves. If so, great. If not, this commit should be reverted before merging into m-c. --- services/sync/tests/unit/xpcshell.ini | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/services/sync/tests/unit/xpcshell.ini b/services/sync/tests/unit/xpcshell.ini index 30a5cd83751..f8cc583e624 100644 --- a/services/sync/tests/unit/xpcshell.ini +++ b/services/sync/tests/unit/xpcshell.ini @@ -30,9 +30,8 @@ tail = # Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini) skip-if = os == "android" [test_errorhandler_sync_checkServerError.js] -# Bug 604565: this test intermittently hangs on OS X debug builds. # Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini) -skip-if = (os == "mac" && debug) || os == "android" +skip-if = os == "android" [test_forms_store.js] [test_forms_tracker.js] [test_history_engine.js] @@ -80,13 +79,11 @@ skip-if = os == "win" || os == "android" [test_service_sync_401.js] [test_service_sync_locked.js] [test_service_sync_remoteSetup.js] -# Bug 604565: this test intermittently hangs on OS X debug builds. # Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini) -skip-if = (os == "mac" && debug) || os == "android" +skip-if = os == "android" [test_service_sync_updateEnabledEngines.js] -# Bug 604565: this test intermittently hangs on OS X debug builds. # Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini) -skip-if = (os == "mac" && debug) || os == "android" +skip-if = os == "android" [test_service_verifyLogin.js] [test_service_wipeClient.js] [test_service_wipeServer.js] @@ -94,9 +91,8 @@ skip-if = (os == "mac" && debug) || os == "android" [test_status_checkSetup.js] [test_syncengine.js] [test_syncengine_sync.js] -# Bug 604565: this test intermittently hangs on OS X debug builds. # Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini) -skip-if = (os == "mac" && debug) || os == "android" +skip-if = os == "android" [test_syncscheduler.js] [test_syncstoragerequest.js] [test_tab_engine.js] From 3875e105d48bf93dfab373829457eb4e8f5fd6f7 Mon Sep 17 00:00:00 2001 From: Jonathan Griffin Date: Fri, 11 Nov 2011 11:16:11 -0800 Subject: [PATCH 25/40] Bug 697874 - disable perma-orange TPS test, r=rnewman, DONTBUILD --- services/sync/tests/tps/all_tests.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/services/sync/tests/tps/all_tests.json b/services/sync/tests/tps/all_tests.json index 9e0178bed88..43f4bedea21 100644 --- a/services/sync/tests/tps/all_tests.json +++ b/services/sync/tests/tps/all_tests.json @@ -21,8 +21,7 @@ "test_privbrw_tabs.js", "test_bookmarks_in_same_named_folder.js", "test_client_wipe.js", - "test_special_tabs.js", - "test_mozmill_sanity.js" + "test_special_tabs.js" ] } From f9de13262d6056d6ecd851f3c79ae421cabfb3ff Mon Sep 17 00:00:00 2001 From: William Lachance Date: Tue, 15 Nov 2011 04:33:21 +0000 Subject: [PATCH 26/40] 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 f5ec28b61b6..42fd472c081 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 3f52516af8d..7506e3e8fe0 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 27/40] 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 1a18cf5069c..3b6634254e9 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 da2082a6f60..99a2e6dd47f 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 7d165ccb6eb09954f060bdb36efbac3f386ab258 Mon Sep 17 00:00:00 2001 From: Jonathan Griffin Date: Mon, 14 Nov 2011 21:02:02 -0800 Subject: [PATCH 28/40] Bug 686019 - Add support for testing addon sync in TPS. r=mconnor --- services/sync/tests/tps/test_addon_sanity.js | 50 ++++ services/sync/tests/tps/unsigned-1.0.xml | 27 ++ services/sync/tests/tps/unsigned-1.0.xpi | Bin 0 -> 452 bytes .../tps/extensions/tps/modules/addons.jsm | 252 ++++++++++++++++++ .../sync/tps/extensions/tps/modules/tps.jsm | 80 ++++-- testing/tps/tps/__init__.py | 1 + testing/tps/tps/mozhttpd.py | 111 ++++++++ testing/tps/tps/testrunner.py | 7 +- 8 files changed, 500 insertions(+), 28 deletions(-) create mode 100644 services/sync/tests/tps/test_addon_sanity.js create mode 100644 services/sync/tests/tps/unsigned-1.0.xml create mode 100644 services/sync/tests/tps/unsigned-1.0.xpi create mode 100644 services/sync/tps/extensions/tps/modules/addons.jsm create mode 100644 testing/tps/tps/mozhttpd.py diff --git a/services/sync/tests/tps/test_addon_sanity.js b/services/sync/tests/tps/test_addon_sanity.js new file mode 100644 index 00000000000..78d56f4908d --- /dev/null +++ b/services/sync/tests/tps/test_addon_sanity.js @@ -0,0 +1,50 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* + * The list of phases mapped to their corresponding profiles. The object + * here must be in strict JSON format, as it will get parsed by the Python + * testrunner (no single quotes, extra comma's, etc). + */ + +var phases = { "phase1": "profile1", + "phase2": "profile1", + "phase3": "profile1", + "phase4": "profile1", + "phase5": "profile1" }; + +/* + * Test phases + */ + +Phase('phase1', [ + [Addons.install, ['unsigned-1.0.xml']], + [Addons.verify, ['unsigned-xpi@tests.mozilla.org'], STATE_DISABLED], + [Sync, SYNC_WIPE_SERVER], +]); + +Phase('phase2', [ + [Sync], + [Addons.verify, ['unsigned-xpi@tests.mozilla.org'], STATE_ENABLED], + [Addons.setState, ['unsigned-xpi@tests.mozilla.org'], STATE_DISABLED], + [Sync], +]); + +Phase('phase3', [ + [Sync], + [Addons.verify, ['unsigned-xpi@tests.mozilla.org'], STATE_DISABLED], + [Addons.setState, ['unsigned-xpi@tests.mozilla.org'], STATE_ENABLED], + [Sync], +]); + +Phase('phase4', [ + [Sync], + [Addons.verify, ['unsigned-xpi@tests.mozilla.org'], STATE_ENABLED], + [Addons.uninstall, ['unsigned-xpi@tests.mozilla.org']], + [Sync], +]); + +Phase('phase5', [ + [Sync], + [Addons.verifyNot, ['unsigned-xpi@tests.mozilla.org']], +]); diff --git a/services/sync/tests/tps/unsigned-1.0.xml b/services/sync/tests/tps/unsigned-1.0.xml new file mode 100644 index 00000000000..e311f47ddcc --- /dev/null +++ b/services/sync/tests/tps/unsigned-1.0.xml @@ -0,0 +1,27 @@ + + + + Unsigned Test XPI + Extension + unsigned-xpi@tests.mozilla.org + unsigned-xpi + 1.0 + + + Firefox + 1 + 3.6 + * + {ec8030f7-c20a-464f-9b0e-13a3a9e97384} + + ALL + + http://127.0.0.1:4567/unsigned-1.0.xpi + + 2009-09-14T04:47:42Z + + + 2011-09-05T20:42:09Z + + + \ No newline at end of file diff --git a/services/sync/tests/tps/unsigned-1.0.xpi b/services/sync/tests/tps/unsigned-1.0.xpi new file mode 100644 index 0000000000000000000000000000000000000000..51b00475a9641ea9d608874a3ab7679da3a4374b GIT binary patch literal 452 zcmWIWW@Zs#U}E54_?u^9#dA2DRf~~4Pa^m=!CAB@`#_JRJCLMTP zI9DyV<<;!;^s=<;=fu~BJ&BG`=N0*wGwVpVQP-#IS7-g;+M)E%WsUK%S<7acl?Nw( z&oP^SK626~lcn2k1%78f5zUn++E7tLzE!`U8JT5_uOTuP|ifs?i!UE8+CEYjcYy?ajS z8plGZ?O!gpMb-1SG`8M($7*+F>!j#D=h``2kGE-L^!%E%W6!hu!CPCtPtFy8#3UhH zdHeBp*^fM58gJ}(X{=0b>ML;8jErXXkXxv9p6O?ovig*H-&tb1i#~sHx%bD*`FKOi zcd5uS!$os`<_Ejg2Y53wi8JF0X + * + * 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 ***** */ + +var EXPORTED_SYMBOLS = ["Addon", "STATE_ENABLED", "STATE_DISABLED"]; + +const CC = Components.classes; +const CI = Components.interfaces; +const CU = Components.utils; + +CU.import("resource://gre/modules/AddonManager.jsm"); +CU.import("resource://gre/modules/AddonRepository.jsm"); +CU.import("resource://gre/modules/Services.jsm"); +CU.import("resource://services-sync/async.js"); +CU.import("resource://services-sync/util.js"); +CU.import("resource://tps/logger.jsm"); +var XPIProvider = CU.import("resource://gre/modules/XPIProvider.jsm") + .XPIProvider; + +const ADDONSGETURL = 'http://127.0.0.1:4567/'; +const STATE_ENABLED = 1; +const STATE_DISABLED = 2; + +function GetFileAsText(file) +{ + let channel = Services.io.newChannel(file, null, null); + let inputStream = channel.open(); + if (channel instanceof CI.nsIHttpChannel && + channel.responseStatus != 200) { + return ""; + } + + let streamBuf = ""; + let sis = CC["@mozilla.org/scriptableinputstream;1"] + .createInstance(CI.nsIScriptableInputStream); + sis.init(inputStream); + + let available; + while ((available = sis.available()) != 0) { + streamBuf += sis.read(available); + } + + inputStream.close(); + return streamBuf; +} + +function Addon(TPS, id) { + this.TPS = TPS; + this.id = id; +} + +Addon.prototype = { + _addons_requiring_restart: [], + _addons_pending_install: [], + + Delete: function() { + // find our addon locally + let cb = Async.makeSyncCallback(); + XPIProvider.getAddonsByTypes(null, cb); + let results = Async.waitForSyncCallback(cb); + var addon; + var id = this.id; + results.forEach(function(result) { + if (result.id == id) { + addon = result; + } + }); + Logger.AssertTrue(!!addon, 'could not find addon ' + this.id + ' to uninstall'); + addon.uninstall(); + }, + + Find: function(state) { + let cb = Async.makeSyncCallback(); + let addon_found = false; + var that = this; + + var log_addon = function(addon) { + that.addon = addon; + Logger.logInfo('addon ' + addon.id + ' found, isActive: ' + addon.isActive); + if (state == STATE_ENABLED || state == STATE_DISABLED) { + Logger.AssertEqual(addon.isActive, + state == STATE_ENABLED ? true : false, + "addon " + that.id + " has an incorrect enabled state"); + } + }; + + // first look in the list of all addons + XPIProvider.getAddonsByTypes(null, cb); + let addonlist = Async.waitForSyncCallback(cb); + addonlist.forEach(function(addon) { + if (addon.id == that.id) { + addon_found = true; + log_addon.call(that, addon); + } + }); + + if (!addon_found) { + // then look in the list of recent installs + cb = Async.makeSyncCallback(); + XPIProvider.getInstallsByTypes(null, cb); + addonlist = Async.waitForSyncCallback(cb); + for (var i in addonlist) { + if (addonlist[i].addon && addonlist[i].addon.id == that.id && + addonlist[i].state == AddonManager.STATE_INSTALLED) { + addon_found = true; + log_addon.call(that, addonlist[i].addon); + } + } + } + + return addon_found; + }, + + Install: function() { + // For Install, the id parameter initially passed is really the filename + // for the addon's install .xml; we'll read the actual id from the .xml. + let url = this.id; + + // set the url used by getAddonsByIDs + var prefs = CC["@mozilla.org/preferences-service;1"] + .getService(CI.nsIPrefBranch); + prefs.setCharPref('extensions.getAddons.get.url', ADDONSGETURL + url); + + // read the XML and find the addon id + xml = GetFileAsText(ADDONSGETURL + url); + Logger.AssertTrue(xml.indexOf("") > -1, 'guid not found in ' + url); + this.id = xml.substring(xml.indexOf("") + 6, xml.indexOf(" -1, + "onInstallEnded received for unexpected addon " + addon.addon.id); + this._addons_pending_install.splice( + this._addons_pending_install.indexOf(addon.addon.id), + 1); + } + catch(e) { + // We can't throw during a callback, as it will just get eaten by + // the callback's caller. + Utils.nextTick(function() { + this.DumpError(e); + }, this); + return; + } + this.TPS.FinishAsyncOperation(); + }, + + onInstallFailed: function(addon) { + Logger.logInfo('--------- event observed: addon onInstallFailed'); + Utils.nextTick(function() { + this.DumpError('Installation failed for addon ' + + (addon.addon && addon.addon.id ? addon.addon.id : 'unknown')); + }, this); + }, + + onDownloadFailed: function(addon) { + Logger.logInfo('--------- event observed: addon onDownloadFailed'); + Utils.nextTick(function() { + this.DumpError('Download failed for addon ' + + (addon.addon && addon.addon.id ? addon.addon.id : 'unknown')); + }, this); + }, + +}; diff --git a/services/sync/tps/extensions/tps/modules/tps.jsm b/services/sync/tps/extensions/tps/modules/tps.jsm index d9c20014a4e..3824405b7a0 100644 --- a/services/sync/tps/extensions/tps/modules/tps.jsm +++ b/services/sync/tps/extensions/tps/modules/tps.jsm @@ -48,9 +48,11 @@ const CU = Components.utils; CU.import("resource://services-sync/service.js"); CU.import("resource://services-sync/constants.js"); +CU.import("resource://services-sync/async.js"); CU.import("resource://services-sync/util.js"); CU.import("resource://gre/modules/XPCOMUtils.jsm"); CU.import("resource://gre/modules/Services.jsm"); +CU.import("resource://tps/addons.jsm"); CU.import("resource://tps/bookmarks.jsm"); CU.import("resource://tps/logger.jsm"); CU.import("resource://tps/passwords.jsm"); @@ -61,6 +63,8 @@ CU.import("resource://tps/tabs.jsm"); var hh = CC["@mozilla.org/network/protocol;1?name=http"] .getService(CI.nsIHttpProtocolHandler); +var prefs = CC["@mozilla.org/preferences-service;1"] + .getService(CI.nsIPrefBranch); var mozmillInit = {}; CU.import('resource://mozmill/modules/init.js', mozmillInit); @@ -73,37 +77,16 @@ const ACTION_SYNC = "sync"; const ACTION_DELETE = "delete"; const ACTION_PRIVATE_BROWSING = "private-browsing"; const ACTION_WIPE_SERVER = "wipe-server"; +const ACTION_SETSTATE = "set-state"; const ACTIONS = [ACTION_ADD, ACTION_VERIFY, ACTION_VERIFY_NOT, ACTION_MODIFY, ACTION_SYNC, ACTION_DELETE, - ACTION_PRIVATE_BROWSING, ACTION_WIPE_SERVER]; + ACTION_PRIVATE_BROWSING, ACTION_WIPE_SERVER, + ACTION_SETSTATE]; const SYNC_WIPE_SERVER = "wipe-server"; const SYNC_RESET_CLIENT = "reset-client"; const SYNC_WIPE_CLIENT = "wipe-client"; -function GetFileAsText(file) -{ - let channel = Services.io.newChannel(file, null, null); - let inputStream = channel.open(); - if (channel instanceof CI.nsIHttpChannel && - channel.responseStatus != 200) { - return ""; - } - - let streamBuf = ""; - let sis = CC["@mozilla.org/scriptableinputstream;1"] - .createInstance(CI.nsIScriptableInputStream); - sis.init(inputStream); - - let available; - while ((available = sis.available()) != 0) { - streamBuf += sis.read(available); - } - - inputStream.close(); - return streamBuf; -} - var TPS = { _waitingForSync: false, @@ -351,6 +334,33 @@ var TPS = } }, + HandleAddons: function (addons, action, state) { + for (var i in addons) { + Logger.logInfo("executing action " + action.toUpperCase() + + " on addon " + JSON.stringify(addons[i])); + var addon = new Addon(this, addons[i]); + switch(action) { + case ACTION_ADD: + addon.Install(); + break; + case ACTION_DELETE: + addon.Delete(); + break; + case ACTION_VERIFY: + Logger.AssertTrue(addon.Find(state), 'addon ' + addon.id + ' not found'); + break; + case ACTION_VERIFY_NOT: + Logger.AssertTrue(!addon.Find(state), 'addon ' + addon.id + " is present, but it shouldn't be"); + break; + case ACTION_SETSTATE: + Logger.AssertTrue(addon.SetState(state), 'addon ' + addon.id + ' not found'); + break; + } + } + Logger.logPass("executing action " + action.toUpperCase() + + " on addons"); + }, + HandleBookmarks: function (bookmarks, action) { try { let items = []; @@ -460,7 +470,7 @@ var TPS = let phase = this._phaselist["phase" + this._currentPhase]; let action = phase[this._currentAction]; Logger.logInfo("starting action: " + JSON.stringify(action)); - action[0].call(this, action[1]); + action[0].apply(this, action.slice(1)); // if we're in an async operation, don't continue on to the next action if (this._operations_pending) @@ -517,8 +527,6 @@ var TPS = // Store account details as prefs so they're accessible to the mozmill // framework. - let prefs = CC["@mozilla.org/preferences-service;1"] - .getService(CI.nsIPrefBranch); prefs.setCharPref('tps.account.username', this.config.account.username); prefs.setCharPref('tps.account.password', this.config.account.password); prefs.setCharPref('tps.account.passphrase', this.config.account.passphrase); @@ -634,6 +642,24 @@ var TPS = }, }; +var Addons = { + install: function Addons__install(addons) { + TPS.HandleAddons(addons, ACTION_ADD); + }, + setState: function Addons__setState(addons, state) { + TPS.HandleAddons(addons, ACTION_SETSTATE, state); + }, + uninstall: function Addons__uninstall(addons) { + TPS.HandleAddons(addons, ACTION_DELETE); + }, + verify: function Addons__verify(addons, state) { + TPS.HandleAddons(addons, ACTION_VERIFY, state); + }, + verifyNot: function Addons__verifyNot(addons) { + TPS.HandleAddons(addons, ACTION_VERIFY_NOT); + }, +}; + var Bookmarks = { add: function Bookmarks__add(bookmarks) { TPS.HandleBookmarks(bookmarks, ACTION_ADD); diff --git a/testing/tps/tps/__init__.py b/testing/tps/tps/__init__.py index 6d710ca4ce5..a9ad3167302 100644 --- a/testing/tps/tps/__init__.py +++ b/testing/tps/tps/__init__.py @@ -38,4 +38,5 @@ from firefoxrunner import TPSFirefoxRunner from pulse import TPSPulseMonitor from testrunner import TPSTestRunner +from mozhttpd import MozHttpd diff --git a/testing/tps/tps/mozhttpd.py b/testing/tps/tps/mozhttpd.py new file mode 100644 index 00000000000..daccf8ff41a --- /dev/null +++ b/testing/tps/tps/mozhttpd.py @@ -0,0 +1,111 @@ +#!/usr/bin/python +# +# ***** 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 +# the Mozilla Foundation. +# Portions created by the Initial Developer are Copyright (C) 2011 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Joel Maher +# +# 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 ***** + +import BaseHTTPServer +import SimpleHTTPServer +import threading +import sys +import os +import urllib +import re +from urlparse import urlparse +from SocketServer import ThreadingMixIn + +DOCROOT = '.' + +class EasyServer(ThreadingMixIn, BaseHTTPServer.HTTPServer): + allow_reuse_address = True + +class MozRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): + def translate_path(self, path): + # It appears that the default path is '/' and os.path.join makes the '/' + o = urlparse(path) + return "%s%s" % ('' if sys.platform == 'win32' else '/', '/'.join([i.strip('/') for i in (DOCROOT, o.path)])) + + # I found on my local network that calls to this were timing out + # I believe all of these calls are from log_message + def address_string(self): + return "a.b.c.d" + + # This produces a LOT of noise + def log_message(self, format, *args): + pass + +class MozHttpd(object): + def __init__(self, host="127.0.0.1", port=8888, docroot='.'): + global DOCROOT + self.host = host + self.port = int(port) + DOCROOT = docroot + + def start(self): + self.httpd = EasyServer((self.host, self.port), MozRequestHandler) + self.server = threading.Thread(target=self.httpd.serve_forever) + self.server.setDaemon(True) # don't hang on exit + self.server.start() + #self.testServer() + + #TODO: figure this out + def testServer(self): + fileList = os.listdir(DOCROOT) + filehandle = urllib.urlopen('http://%s:%s' % (self.host, self.port)) + data = filehandle.readlines(); + filehandle.close() + + for line in data: + found = False + # '@' denotes a symlink and we need to ignore it. + webline = re.sub('\<[a-zA-Z0-9\-\_\.\=\"\'\/\\\%\!\@\#\$\^\&\*\(\) ]*\>', '', line.strip('\n')).strip('/').strip().strip('@') + if webline != "": + if webline == "Directory listing for": + found = True + else: + for fileName in fileList: + if fileName == webline: + found = True + + if (found == False): + print "NOT FOUND: " + webline.strip() + + def stop(self): + if self.httpd: + self.httpd.shutdown() + + __del__ = stop + diff --git a/testing/tps/tps/testrunner.py b/testing/tps/tps/testrunner.py index aaf3a134363..4ecf5287677 100644 --- a/testing/tps/tps/testrunner.py +++ b/testing/tps/tps/testrunner.py @@ -53,7 +53,7 @@ from mozprofile import Profile from tps.firefoxrunner import TPSFirefoxRunner from tps.phase import TPSTestPhase - +from tps.mozhttpd import MozHttpd class TempFile(object): """Class for temporary files that delete themselves when garbage-collected. @@ -397,6 +397,9 @@ class TPSTestRunner(object): testlist = [os.path.basename(self.testfile)] testdir = os.path.dirname(self.testfile) + self.mozhttpd = MozHttpd(port=4567, docroot=testdir) + self.mozhttpd.start() + # run each test, and save the results for test in testlist: result = self.run_single_test(testdir, test) @@ -415,6 +418,8 @@ class TPSTestRunner(object): else: self.numfailed += 1 + self.mozhttpd.stop() + # generate the postdata we'll use to post the results to the db self.postdata = { 'tests': self.results, 'os':os_string, From 0ea79713a1d4259b56cc0f83ef1346ab416ec717 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 29/40] 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 9de9633ec36..87feb60f253 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 90c29a7b88f7f9892809a9cec3e4093b8ca89c65 Mon Sep 17 00:00:00 2001 From: Phil Ringnalda Date: Mon, 14 Nov 2011 22:12:31 -0800 Subject: [PATCH 30/40] 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 42fd472c081..fdd8e8c896e 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 49fb52ae3d2..30d2e9245af 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 b27d1ea19c1..42147daba60 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 2942e572dfe..2a968befb87 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 0d7f799ba86..c64466982bc 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 a7b42cac3de..546abc05996 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 ecd6d66528d..623bacb78f6 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 7b0cec3c219..68985b6471d 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 899c432b0b8..4b58fa5097a 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 6f87b940755..00000000000 --- 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 6433753fd62..00000000000 --- 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 5f84a9d64e8..00000000000 --- 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 9e1ce924003..00000000000 --- 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 36ea266158a..00000000000 --- 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 7fc0e8fe530..00000000000 --- 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 b0916faad80..00000000000 --- 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 856ee8e2c62..00000000000 --- 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 ce2b0c0ef0b..00000000000 --- 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 9392fafcd18..00000000000 --- 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 2514297cc93..00000000000 --- 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 48bf661cc79..00000000000 --- 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 7e52747742e..00000000000 --- 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 cda175fdeae..00000000000 --- 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 65173d430ba..00000000000 --- 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 a4cb881f1a8..00000000000 --- 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 cdf5d854480..00000000000 --- 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 3bc6129d364..00000000000 --- 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 ea117963c01..00000000000 --- 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 848a40eb3a7..00000000000 --- 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 c2565f0c97b..00000000000 --- 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 e410a10acea..00000000000 --- 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 b8930c11719..00000000000 --- 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 ba9ab9ef805..00000000000 --- 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 c393cb09c1a..00000000000 --- 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 34e2446c4b0..00000000000 --- 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 da650e128fe..00000000000 --- 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 7405f70754b..00000000000 --- 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 4f9d6065bcf..00000000000 --- 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 e4ed681f4af..00000000000 --- 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 81c29f25278..00000000000 --- 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 3fa323e25ca..645d48eee0d 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 2db13423c1f..4341d91cc0d 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 245eabfc360..b86fd290e0c 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 fefa6095ca3..8a83b19446e 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 00a6f706a4b..10506d92ce7 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 a84f9adeaf2..be6bdba9e2a 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 b2af727b57d..6615d8573ce 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