michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsLayoutUtils_h__ michael@0: #define nsLayoutUtils_h__ michael@0: michael@0: #include "mozilla/MemoryReporting.h" michael@0: #include "nsChangeHint.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "nsFrameList.h" michael@0: #include "mozilla/layout/FrameChildList.h" michael@0: #include "nsThreadUtils.h" michael@0: #include "nsIPrincipal.h" michael@0: #include "GraphicsFilter.h" michael@0: #include "nsCSSPseudoElements.h" michael@0: #include "FrameMetrics.h" michael@0: #include "gfx3DMatrix.h" michael@0: #include "nsIWidget.h" michael@0: #include "nsCSSProperty.h" michael@0: #include "nsStyleCoord.h" michael@0: #include "nsStyleConsts.h" michael@0: #include "nsGkAtoms.h" michael@0: #include "nsRuleNode.h" michael@0: #include "imgIContainer.h" michael@0: #include "mozilla/gfx/2D.h" michael@0: #include "Units.h" michael@0: michael@0: #include michael@0: #include michael@0: michael@0: class nsIFormControlFrame; michael@0: class nsPresContext; michael@0: class nsIContent; michael@0: class nsIAtom; michael@0: class nsIScrollableFrame; michael@0: class nsIDOMEvent; michael@0: class nsRegion; michael@0: class nsDisplayListBuilder; michael@0: class nsDisplayItem; michael@0: class nsFontMetrics; michael@0: class nsFontFaceList; michael@0: class nsIImageLoadingContent; michael@0: class nsStyleContext; michael@0: class nsBlockFrame; michael@0: class gfxASurface; michael@0: class gfxDrawable; michael@0: class nsView; michael@0: class nsIFrame; michael@0: class nsStyleCoord; michael@0: class nsStyleCorners; michael@0: class gfxContext; michael@0: class nsPIDOMWindow; michael@0: class imgIRequest; michael@0: class nsIDocument; michael@0: class gfxPoint; michael@0: struct nsStyleFont; michael@0: struct nsStyleImageOrientation; michael@0: struct nsOverflowAreas; michael@0: michael@0: namespace mozilla { michael@0: class SVGImageContext; michael@0: struct IntrinsicSize; michael@0: struct ContainerLayerParameters; michael@0: namespace dom { michael@0: class DOMRectList; michael@0: class Element; michael@0: class HTMLImageElement; michael@0: class HTMLCanvasElement; michael@0: class HTMLVideoElement; michael@0: } // namespace dom michael@0: namespace layers { michael@0: class Layer; michael@0: } michael@0: } michael@0: michael@0: namespace mozilla { michael@0: michael@0: struct DisplayPortPropertyData { michael@0: DisplayPortPropertyData(const nsRect& aRect, uint32_t aPriority) michael@0: : mRect(aRect) michael@0: , mPriority(aPriority) michael@0: {} michael@0: nsRect mRect; michael@0: uint32_t mPriority; michael@0: }; michael@0: michael@0: struct DisplayPortMarginsPropertyData { michael@0: DisplayPortMarginsPropertyData(const LayerMargin& aMargins, michael@0: uint32_t aAlignmentX, uint32_t aAlignmentY, michael@0: uint32_t aPriority) michael@0: : mMargins(aMargins) michael@0: , mAlignmentX(aAlignmentX) michael@0: , mAlignmentY(aAlignmentY) michael@0: , mPriority(aPriority) michael@0: {} michael@0: LayerMargin mMargins; michael@0: uint32_t mAlignmentX; michael@0: uint32_t mAlignmentY; michael@0: uint32_t mPriority; michael@0: }; michael@0: michael@0: template michael@0: extern AnimationsOrTransitions* HasAnimationOrTransition(nsIContent* aContent, michael@0: nsIAtom* aAnimationProperty, michael@0: nsCSSProperty aProperty); michael@0: michael@0: } // namespace mozilla michael@0: michael@0: /** michael@0: * nsLayoutUtils is a namespace class used for various helper michael@0: * functions that are useful in multiple places in layout. The goal michael@0: * is not to define multiple copies of the same static helper. michael@0: */ michael@0: class nsLayoutUtils michael@0: { michael@0: typedef ::GraphicsFilter GraphicsFilter; michael@0: typedef mozilla::dom::DOMRectList DOMRectList; michael@0: typedef mozilla::layers::Layer Layer; michael@0: typedef mozilla::ContainerLayerParameters ContainerLayerParameters; michael@0: typedef mozilla::gfx::SourceSurface SourceSurface; michael@0: typedef mozilla::gfx::DrawTarget DrawTarget; michael@0: typedef mozilla::gfx::Rect Rect; michael@0: michael@0: public: michael@0: typedef mozilla::layers::FrameMetrics FrameMetrics; michael@0: typedef FrameMetrics::ViewID ViewID; michael@0: typedef mozilla::CSSPoint CSSPoint; michael@0: typedef mozilla::CSSSize CSSSize; michael@0: typedef mozilla::LayerMargin LayerMargin; michael@0: michael@0: /** michael@0: * Finds previously assigned ViewID for the given content element, if any. michael@0: * Returns whether a ViewID was previously assigned. michael@0: */ michael@0: static bool FindIDFor(const nsIContent* aContent, ViewID* aOutViewId); michael@0: michael@0: /** michael@0: * Finds previously assigned or generates a unique ViewID for the given michael@0: * content element. michael@0: */ michael@0: static ViewID FindOrCreateIDFor(nsIContent* aContent); michael@0: michael@0: /** michael@0: * Find content for given ID. michael@0: */ michael@0: static nsIContent* FindContentFor(ViewID aId); michael@0: michael@0: /** michael@0: * Find the scrollable frame for a given ID. michael@0: */ michael@0: static nsIScrollableFrame* FindScrollableFrameFor(ViewID aId); michael@0: michael@0: /** michael@0: * Get display port for the given element. michael@0: */ michael@0: static bool GetDisplayPort(nsIContent* aContent, nsRect *aResult = nullptr); michael@0: michael@0: MOZ_BEGIN_NESTED_ENUM_CLASS(RepaintMode, uint8_t) michael@0: Repaint, michael@0: DoNotRepaint michael@0: MOZ_END_NESTED_ENUM_CLASS(RepaintMode) michael@0: michael@0: /** michael@0: * Set the display port margins for a content element to be used with a michael@0: * display port base (see SetDisplayPortBase()). michael@0: * See also nsIDOMWindowUtils.setDisplayPortMargins. michael@0: * @param aContent the content element for which to set the margins michael@0: * @param aPresShell the pres shell for the document containing the element michael@0: * @param aMargins the margins to set michael@0: * @param aAlignmentX, alignmentY the amount of pixels to which to align the michael@0: * displayport built by combining the base michael@0: * rect with the margins, in either direction michael@0: * @param aPriority a priority value to determine which margins take effect michael@0: * when multiple callers specify margins michael@0: * @param aRepaintMode whether to schedule a paint after setting the margins michael@0: */ michael@0: static void SetDisplayPortMargins(nsIContent* aContent, michael@0: nsIPresShell* aPresShell, michael@0: const LayerMargin& aMargins, michael@0: uint32_t aAlignmentX, michael@0: uint32_t aAlignmentY, michael@0: uint32_t aPriority = 0, michael@0: RepaintMode aRepaintMode = RepaintMode::Repaint); michael@0: michael@0: /** michael@0: * Set the display port base rect for given element to be used with display michael@0: * port margins. michael@0: * SetDisplayPortBaseIfNotSet is like SetDisplayPortBase except it only sets michael@0: * the display port base to aBase if no display port base is currently set. michael@0: */ michael@0: static void SetDisplayPortBase(nsIContent* aContent, const nsRect& aBase); michael@0: static void SetDisplayPortBaseIfNotSet(nsIContent* aContent, const nsRect& aBase); michael@0: michael@0: /** michael@0: * Get the critical display port for the given element. michael@0: */ michael@0: static bool GetCriticalDisplayPort(nsIContent* aContent, nsRect* aResult = nullptr); michael@0: michael@0: /** michael@0: * Use heuristics to figure out the child list that michael@0: * aChildFrame is currently in. michael@0: */ michael@0: static mozilla::layout::FrameChildListID GetChildListNameFor(nsIFrame* aChildFrame); michael@0: michael@0: /** michael@0: * GetBeforeFrame returns the outermost :before frame of the given frame, if michael@0: * one exists. This is typically O(1). The frame passed in must be michael@0: * the first-in-flow. michael@0: * michael@0: * @param aFrame the frame whose :before is wanted michael@0: * @return the :before frame or nullptr if there isn't one michael@0: */ michael@0: static nsIFrame* GetBeforeFrame(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * GetAfterFrame returns the outermost :after frame of the given frame, if one michael@0: * exists. This will walk the in-flow chain to the last-in-flow if michael@0: * needed. This function is typically O(N) in the number of child michael@0: * frames, following in-flows, etc. michael@0: * michael@0: * @param aFrame the frame whose :after is wanted michael@0: * @return the :after frame or nullptr if there isn't one michael@0: */ michael@0: static nsIFrame* GetAfterFrame(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Given a frame, search up the frame tree until we find an michael@0: * ancestor that (or the frame itself) is of type aFrameType, if any. michael@0: * michael@0: * @param aFrame the frame to start at michael@0: * @param aFrameType the frame type to look for michael@0: * @return a frame of the given type or nullptr if no michael@0: * such ancestor exists michael@0: */ michael@0: static nsIFrame* GetClosestFrameOfType(nsIFrame* aFrame, nsIAtom* aFrameType); michael@0: michael@0: /** michael@0: * Given a frame, search up the frame tree until we find an michael@0: * ancestor that (or the frame itself) is a "Page" frame, if any. michael@0: * michael@0: * @param aFrame the frame to start at michael@0: * @return a frame of type nsGkAtoms::pageFrame or nullptr if no michael@0: * such ancestor exists michael@0: */ michael@0: static nsIFrame* GetPageFrame(nsIFrame* aFrame) michael@0: { michael@0: return GetClosestFrameOfType(aFrame, nsGkAtoms::pageFrame); michael@0: } michael@0: michael@0: /** michael@0: * Given a frame which is the primary frame for an element, michael@0: * return the frame that has the non-psuedoelement style context for michael@0: * the content. michael@0: * This is aPrimaryFrame itself except for tableOuter frames. michael@0: */ michael@0: static nsIFrame* GetStyleFrame(nsIFrame* aPrimaryFrame); michael@0: michael@0: /** michael@0: * Given a content node, michael@0: * return the frame that has the non-psuedoelement style context for michael@0: * the content. May return null. michael@0: * This is aContent->GetPrimaryFrame() except for tableOuter frames. michael@0: */ michael@0: static nsIFrame* GetStyleFrame(const nsIContent* aContent); michael@0: michael@0: /** michael@0: * IsGeneratedContentFor returns true if aFrame is the outermost michael@0: * frame for generated content of type aPseudoElement for aContent. michael@0: * aFrame *might not* have the aPseudoElement pseudo-style! For example michael@0: * it might be a table outer frame and the inner table frame might michael@0: * have the pseudo-style. michael@0: * michael@0: * @param aContent the content node we're looking at. If this is michael@0: * null, then we just assume that aFrame has the right content michael@0: * pointer. michael@0: * @param aFrame the frame we're looking at michael@0: * @param aPseudoElement the pseudo type we're interested in michael@0: * @return whether aFrame is the generated aPseudoElement frame for aContent michael@0: */ michael@0: static bool IsGeneratedContentFor(nsIContent* aContent, nsIFrame* aFrame, michael@0: nsIAtom* aPseudoElement); michael@0: michael@0: #ifdef DEBUG michael@0: // TODO: remove, see bug 598468. michael@0: static bool gPreventAssertInCompareTreePosition; michael@0: #endif // DEBUG michael@0: michael@0: /** michael@0: * CompareTreePosition determines whether aContent1 comes before or michael@0: * after aContent2 in a preorder traversal of the content tree. michael@0: * michael@0: * @param aCommonAncestor either null, or a common ancestor of michael@0: * aContent1 and aContent2. Actually this is michael@0: * only a hint; if it's not an ancestor of michael@0: * aContent1 or aContent2, this function will michael@0: * still work, but it will be slower than michael@0: * normal. michael@0: * @return < 0 if aContent1 is before aContent2 michael@0: * > 0 if aContent1 is after aContent2, michael@0: * 0 otherwise (meaning they're the same, or they're in michael@0: * different documents) michael@0: */ michael@0: static int32_t CompareTreePosition(nsIContent* aContent1, michael@0: nsIContent* aContent2, michael@0: const nsIContent* aCommonAncestor = nullptr) michael@0: { michael@0: return DoCompareTreePosition(aContent1, aContent2, -1, 1, aCommonAncestor); michael@0: } michael@0: michael@0: /* michael@0: * More generic version of |CompareTreePosition|. |aIf1Ancestor| michael@0: * gives the value to return when 1 is an ancestor of 2, and likewise michael@0: * for |aIf2Ancestor|. Passing (-1, 1) gives preorder traversal michael@0: * order, and (1, -1) gives postorder traversal order. michael@0: */ michael@0: static int32_t DoCompareTreePosition(nsIContent* aContent1, michael@0: nsIContent* aContent2, michael@0: int32_t aIf1Ancestor, michael@0: int32_t aIf2Ancestor, michael@0: const nsIContent* aCommonAncestor = nullptr); michael@0: michael@0: /** michael@0: * CompareTreePosition determines whether aFrame1 comes before or michael@0: * after aFrame2 in a preorder traversal of the frame tree, where out michael@0: * of flow frames are treated as children of their placeholders. This is michael@0: * basically the same ordering as DoCompareTreePosition(nsIContent*) except michael@0: * that it handles anonymous content properly and there are subtleties with michael@0: * continuations. michael@0: * michael@0: * @param aCommonAncestor either null, or a common ancestor of michael@0: * aContent1 and aContent2. Actually this is michael@0: * only a hint; if it's not an ancestor of michael@0: * aContent1 or aContent2, this function will michael@0: * still work, but it will be slower than michael@0: * normal. michael@0: * @return < 0 if aContent1 is before aContent2 michael@0: * > 0 if aContent1 is after aContent2, michael@0: * 0 otherwise (meaning they're the same, or they're in michael@0: * different frame trees) michael@0: */ michael@0: static int32_t CompareTreePosition(nsIFrame* aFrame1, michael@0: nsIFrame* aFrame2, michael@0: nsIFrame* aCommonAncestor = nullptr) michael@0: { michael@0: return DoCompareTreePosition(aFrame1, aFrame2, -1, 1, aCommonAncestor); michael@0: } michael@0: michael@0: static int32_t CompareTreePosition(nsIFrame* aFrame1, michael@0: nsIFrame* aFrame2, michael@0: nsTArray& aFrame2Ancestors, michael@0: nsIFrame* aCommonAncestor = nullptr) michael@0: { michael@0: return DoCompareTreePosition(aFrame1, aFrame2, aFrame2Ancestors, michael@0: -1, 1, aCommonAncestor); michael@0: } michael@0: michael@0: /* michael@0: * More generic version of |CompareTreePosition|. |aIf1Ancestor| michael@0: * gives the value to return when 1 is an ancestor of 2, and likewise michael@0: * for |aIf2Ancestor|. Passing (-1, 1) gives preorder traversal michael@0: * order, and (1, -1) gives postorder traversal order. michael@0: */ michael@0: static int32_t DoCompareTreePosition(nsIFrame* aFrame1, michael@0: nsIFrame* aFrame2, michael@0: int32_t aIf1Ancestor, michael@0: int32_t aIf2Ancestor, michael@0: nsIFrame* aCommonAncestor = nullptr); michael@0: michael@0: static nsIFrame* FillAncestors(nsIFrame* aFrame, michael@0: nsIFrame* aStopAtAncestor, michael@0: nsTArray* aAncestors); michael@0: michael@0: static int32_t DoCompareTreePosition(nsIFrame* aFrame1, michael@0: nsIFrame* aFrame2, michael@0: nsTArray& aFrame2Ancestors, michael@0: int32_t aIf1Ancestor, michael@0: int32_t aIf2Ancestor, michael@0: nsIFrame* aCommonAncestor); michael@0: michael@0: /** michael@0: * LastContinuationWithChild gets the last continuation in aFrame's chain michael@0: * that has a child, or the first continuation if the frame has no children. michael@0: */ michael@0: static nsIFrame* LastContinuationWithChild(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * GetLastSibling simply finds the last sibling of aFrame, or returns nullptr if michael@0: * aFrame is null. michael@0: */ michael@0: static nsIFrame* GetLastSibling(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * FindSiblingViewFor locates the child of aParentView that aFrame's michael@0: * view should be inserted 'above' (i.e., before in sibling view michael@0: * order). This is the first child view of aParentView whose michael@0: * corresponding content is before aFrame's content (view siblings michael@0: * are in reverse content order). michael@0: */ michael@0: static nsView* FindSiblingViewFor(nsView* aParentView, nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Get the parent of aFrame. If aFrame is the root frame for a document, michael@0: * and the document has a parent document in the same view hierarchy, then michael@0: * we try to return the subdocumentframe in the parent document. michael@0: * @param aExtraOffset [in/out] if non-null, then as we cross documents michael@0: * an extra offset may be required and it will be added to aCrossDocOffset. michael@0: * Be careful dealing with this extra offset as it is in app units of the michael@0: * parent document, which may have a different app units per dev pixel ratio michael@0: * than the child document. michael@0: */ michael@0: static nsIFrame* GetCrossDocParentFrame(const nsIFrame* aFrame, michael@0: nsPoint* aCrossDocOffset = nullptr); michael@0: michael@0: /** michael@0: * IsProperAncestorFrame checks whether aAncestorFrame is an ancestor michael@0: * of aFrame and not equal to aFrame. michael@0: * @param aCommonAncestor nullptr, or a common ancestor of aFrame and michael@0: * aAncestorFrame. If non-null, this can bound the search and speed up michael@0: * the function michael@0: */ michael@0: static bool IsProperAncestorFrame(nsIFrame* aAncestorFrame, nsIFrame* aFrame, michael@0: nsIFrame* aCommonAncestor = nullptr); michael@0: michael@0: /** michael@0: * Like IsProperAncestorFrame, but looks across document boundaries. michael@0: * michael@0: * Just like IsAncestorFrameCrossDoc, except that it returns false when michael@0: * aFrame == aAncestorFrame. michael@0: */ michael@0: static bool IsProperAncestorFrameCrossDoc(nsIFrame* aAncestorFrame, nsIFrame* aFrame, michael@0: nsIFrame* aCommonAncestor = nullptr); michael@0: michael@0: /** michael@0: * IsAncestorFrameCrossDoc checks whether aAncestorFrame is an ancestor michael@0: * of aFrame or equal to aFrame, looking across document boundaries. michael@0: * @param aCommonAncestor nullptr, or a common ancestor of aFrame and michael@0: * aAncestorFrame. If non-null, this can bound the search and speed up michael@0: * the function. michael@0: * michael@0: * Just like IsProperAncestorFrameCrossDoc, except that it returns true when michael@0: * aFrame == aAncestorFrame. michael@0: */ michael@0: static bool IsAncestorFrameCrossDoc(const nsIFrame* aAncestorFrame, const nsIFrame* aFrame, michael@0: const nsIFrame* aCommonAncestor = nullptr); michael@0: michael@0: /** michael@0: * Sets the fixed-pos metadata properties on aLayer. michael@0: * aAnchorRect is the basic anchor rectangle. If aFixedPosFrame is not a viewport michael@0: * frame, then we pick a corner of aAnchorRect to as the anchor point for the michael@0: * fixed-pos layer (i.e. the point to remain stable during zooming), based michael@0: * on which of the fixed-pos frame's CSS absolute positioning offset michael@0: * properties (top, left, right, bottom) are auto. aAnchorRect is in the michael@0: * coordinate space of aLayer's container layer (i.e. relative to the reference michael@0: * frame of the display item which is building aLayer's container layer). michael@0: */ michael@0: static void SetFixedPositionLayerData(Layer* aLayer, const nsIFrame* aViewportFrame, michael@0: const nsRect& aAnchorRect, michael@0: const nsIFrame* aFixedPosFrame, michael@0: nsPresContext* aPresContext, michael@0: const ContainerLayerParameters& aContainerParameters); michael@0: michael@0: /** michael@0: * Return true if aPresContext's viewport has a displayport. michael@0: * Fills in aDisplayPort with the displayport rectangle if non-null. michael@0: */ michael@0: static bool ViewportHasDisplayPort(nsPresContext* aPresContext, michael@0: nsRect* aDisplayPort = nullptr); michael@0: michael@0: /** michael@0: * Return true if aFrame is a fixed-pos frame and is a child of a viewport michael@0: * which has a displayport. These frames get special treatment from the compositor. michael@0: * aDisplayPort, if non-null, is set to the display port rectangle (relative to michael@0: * the viewport). michael@0: */ michael@0: static bool IsFixedPosFrameInDisplayPort(const nsIFrame* aFrame, michael@0: nsRect* aDisplayPort = nullptr); michael@0: michael@0: /** michael@0: * Finds the nearest ancestor frame to aItem that is considered to have (or michael@0: * will have) "animated geometry". For example the scrolled frames of michael@0: * scrollframes which are actively being scrolled fall into this category. michael@0: * Frames with certain CSS properties that are being animated (e.g. michael@0: * 'left'/'top' etc) are also placed in this category. michael@0: * Frames with different active geometry roots are in different ThebesLayers, michael@0: * so that we can animate the geometry root by changing its transform (either michael@0: * on the main thread or in the compositor). michael@0: * The animated geometry root is required to be a descendant (or equal to) michael@0: * aItem's ReferenceFrame(), which means that we will fall back to michael@0: * returning aItem->ReferenceFrame() when we can't find another animated michael@0: * geometry root. michael@0: */ michael@0: static nsIFrame* GetAnimatedGeometryRootFor(nsDisplayItem* aItem, michael@0: nsDisplayListBuilder* aBuilder); michael@0: michael@0: /** michael@0: * GetScrollableFrameFor returns the scrollable frame for a scrolled frame michael@0: */ michael@0: static nsIScrollableFrame* GetScrollableFrameFor(const nsIFrame *aScrolledFrame); michael@0: michael@0: /** michael@0: * GetNearestScrollableFrameForDirection locates the first ancestor of michael@0: * aFrame (or aFrame itself) that is scrollable with overflow:scroll or michael@0: * overflow:auto in the given direction and where either the scrollbar for michael@0: * that direction is visible or the frame can be scrolled by some michael@0: * positive amount in that direction. michael@0: * The search extends across document boundaries. michael@0: * michael@0: * @param aFrame the frame to start with michael@0: * @param aDirection Whether it's for horizontal or vertical scrolling. michael@0: * @return the nearest scrollable frame or nullptr if not found michael@0: */ michael@0: enum Direction { eHorizontal, eVertical }; michael@0: static nsIScrollableFrame* GetNearestScrollableFrameForDirection(nsIFrame* aFrame, michael@0: Direction aDirection); michael@0: michael@0: enum { michael@0: SCROLLABLE_SAME_DOC = 0x01, michael@0: SCROLLABLE_INCLUDE_HIDDEN = 0x02 michael@0: }; michael@0: /** michael@0: * GetNearestScrollableFrame locates the first ancestor of aFrame michael@0: * (or aFrame itself) that is scrollable with overflow:scroll or michael@0: * overflow:auto in some direction. michael@0: * michael@0: * @param aFrame the frame to start with michael@0: * @param aFlags if SCROLLABLE_SAME_DOC is set, do not search across michael@0: * document boundaries. If SCROLLABLE_INCLUDE_HIDDEN is set, include michael@0: * frames scrollable with overflow:hidden. michael@0: * @return the nearest scrollable frame or nullptr if not found michael@0: */ michael@0: static nsIScrollableFrame* GetNearestScrollableFrame(nsIFrame* aFrame, michael@0: uint32_t aFlags = 0); michael@0: michael@0: /** michael@0: * GetScrolledRect returns the range of allowable scroll offsets michael@0: * for aScrolledFrame, assuming the scrollable overflow area is michael@0: * aScrolledFrameOverflowArea and the scrollport size is aScrollPortSize. michael@0: * aDirection is either NS_STYLE_DIRECTION_LTR or NS_STYLE_DIRECTION_RTL. michael@0: */ michael@0: static nsRect GetScrolledRect(nsIFrame* aScrolledFrame, michael@0: const nsRect& aScrolledFrameOverflowArea, michael@0: const nsSize& aScrollPortSize, michael@0: uint8_t aDirection); michael@0: michael@0: /** michael@0: * HasPseudoStyle returns true if aContent (whose primary style michael@0: * context is aStyleContext) has the aPseudoElement pseudo-style michael@0: * attached to it; returns false otherwise. michael@0: * michael@0: * @param aContent the content node we're looking at michael@0: * @param aStyleContext aContent's style context michael@0: * @param aPseudoElement the id of the pseudo style we care about michael@0: * @param aPresContext the presentation context michael@0: * @return whether aContent has aPseudoElement style attached to it michael@0: */ michael@0: static bool HasPseudoStyle(nsIContent* aContent, michael@0: nsStyleContext* aStyleContext, michael@0: nsCSSPseudoElements::Type aPseudoElement, michael@0: nsPresContext* aPresContext); michael@0: michael@0: /** michael@0: * If this frame is a placeholder for a float, then return the float, michael@0: * otherwise return nullptr. aPlaceholder must be a placeholder frame. michael@0: */ michael@0: static nsIFrame* GetFloatFromPlaceholder(nsIFrame* aPlaceholder); michael@0: michael@0: // Combine aNewBreakType with aOrigBreakType, but limit the break types michael@0: // to NS_STYLE_CLEAR_LEFT, RIGHT, LEFT_AND_RIGHT. michael@0: static uint8_t CombineBreakType(uint8_t aOrigBreakType, uint8_t aNewBreakType); michael@0: michael@0: /** michael@0: * Get the coordinates of a given DOM mouse event, relative to a given michael@0: * frame. Works only for DOM events generated by WidgetGUIEvents. michael@0: * @param aDOMEvent the event michael@0: * @param aFrame the frame to make coordinates relative to michael@0: * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if michael@0: * for some reason the coordinates for the mouse are not known (e.g., michael@0: * the event is not a GUI event). michael@0: */ michael@0: static nsPoint GetDOMEventCoordinatesRelativeTo(nsIDOMEvent* aDOMEvent, michael@0: nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Get the coordinates of a given native mouse event, relative to a given michael@0: * frame. michael@0: * @param aEvent the event michael@0: * @param aFrame the frame to make coordinates relative to michael@0: * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if michael@0: * for some reason the coordinates for the mouse are not known (e.g., michael@0: * the event is not a GUI event). michael@0: */ michael@0: static nsPoint GetEventCoordinatesRelativeTo( michael@0: const mozilla::WidgetEvent* aEvent, michael@0: nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Get the coordinates of a given point relative to an event and a michael@0: * given frame. michael@0: * @param aEvent the event michael@0: * @param aPoint the point to get the coordinates relative to michael@0: * @param aFrame the frame to make coordinates relative to michael@0: * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if michael@0: * for some reason the coordinates for the mouse are not known (e.g., michael@0: * the event is not a GUI event). michael@0: */ michael@0: static nsPoint GetEventCoordinatesRelativeTo( michael@0: const mozilla::WidgetEvent* aEvent, michael@0: const nsIntPoint aPoint, michael@0: nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Get the coordinates of a given point relative to a widget and a michael@0: * given frame. michael@0: * @param aWidget the event src widget michael@0: * @param aPoint the point to get the coordinates relative to michael@0: * @param aFrame the frame to make coordinates relative to michael@0: * @return the point, or (NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE) if michael@0: * for some reason the coordinates for the mouse are not known (e.g., michael@0: * the event is not a GUI event). michael@0: */ michael@0: static nsPoint GetEventCoordinatesRelativeTo(nsIWidget* aWidget, michael@0: const nsIntPoint aPoint, michael@0: nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Get the popup frame of a given native mouse event. michael@0: * @param aPresContext only check popups within aPresContext or a descendant michael@0: * @param aEvent the event. michael@0: * @return Null, if there is no popup frame at the point, otherwise, michael@0: * returns top-most popup frame at the point. michael@0: */ michael@0: static nsIFrame* GetPopupFrameForEventCoordinates( michael@0: nsPresContext* aPresContext, michael@0: const mozilla::WidgetEvent* aEvent); michael@0: michael@0: /** michael@0: * Translate from widget coordinates to the view's coordinates michael@0: * @param aPresContext the PresContext for the view michael@0: * @param aWidget the widget michael@0: * @param aPt the point relative to the widget michael@0: * @param aView view to which returned coordinates are relative michael@0: * @return the point in the view's coordinates michael@0: */ michael@0: static nsPoint TranslateWidgetToView(nsPresContext* aPresContext, michael@0: nsIWidget* aWidget, nsIntPoint aPt, michael@0: nsView* aView); michael@0: michael@0: /** michael@0: * Given a matrix and a point, let T be the transformation matrix translating points michael@0: * in the coordinate space with origin aOrigin to the coordinate space used by the michael@0: * matrix. If M is the stored matrix, this function returns (T-1)MT, the matrix michael@0: * that's equivalent to aMatrix but in the coordinate space that treats aOrigin michael@0: * as the origin. michael@0: * michael@0: * @param aOrigin The origin to translate to. michael@0: * @param aMatrix The matrix to change the basis of. michael@0: * @return A matrix equivalent to aMatrix, but operating in the coordinate system with michael@0: * origin aOrigin. michael@0: */ michael@0: static gfx3DMatrix ChangeMatrixBasis(const gfxPoint3D &aOrigin, const gfx3DMatrix &aMatrix); michael@0: michael@0: /** michael@0: * Find IDs corresponding to a scrollable content element in the child process. michael@0: * In correspondence with the shadow layer tree, you can use this to perform a michael@0: * hit test that corresponds to a specific shadow layer that you can then perform michael@0: * transformations on to do parent-side scrolling. michael@0: * michael@0: * @param aFrame The root frame of a stack context michael@0: * @param aTarget The rect to hit test relative to the frame origin michael@0: * @param aOutIDs All found IDs are added here michael@0: * @param aIgnoreRootScrollFrame a boolean to control if the display list michael@0: * builder should ignore the root scroll frame michael@0: */ michael@0: static nsresult GetRemoteContentIds(nsIFrame* aFrame, michael@0: const nsRect& aTarget, michael@0: nsTArray &aOutIDs, michael@0: bool aIgnoreRootScrollFrame); michael@0: michael@0: enum FrameForPointFlags { michael@0: /** michael@0: * When set, paint suppression is ignored, so we'll return non-root page michael@0: * elements even if paint suppression is stopping them from painting. michael@0: */ michael@0: IGNORE_PAINT_SUPPRESSION = 0x01, michael@0: /** michael@0: * When set, clipping due to the root scroll frame (and any other viewport- michael@0: * related clipping) is ignored. michael@0: */ michael@0: IGNORE_ROOT_SCROLL_FRAME = 0x02, michael@0: /** michael@0: * When set, return only content in the same document as aFrame. michael@0: */ michael@0: IGNORE_CROSS_DOC = 0x04 michael@0: }; michael@0: michael@0: /** michael@0: * Given aFrame, the root frame of a stacking context, find its descendant michael@0: * frame under the point aPt that receives a mouse event at that location, michael@0: * or nullptr if there is no such frame. michael@0: * @param aPt the point, relative to the frame origin michael@0: * @param aFlags some combination of FrameForPointFlags michael@0: */ michael@0: static nsIFrame* GetFrameForPoint(nsIFrame* aFrame, nsPoint aPt, michael@0: uint32_t aFlags = 0); michael@0: michael@0: /** michael@0: * Given aFrame, the root frame of a stacking context, find all descendant michael@0: * frames under the area of a rectangle that receives a mouse event, michael@0: * or nullptr if there is no such frame. michael@0: * @param aRect the rect, relative to the frame origin michael@0: * @param aOutFrames an array to add all the frames found michael@0: * @param aFlags some combination of FrameForPointFlags michael@0: */ michael@0: static nsresult GetFramesForArea(nsIFrame* aFrame, const nsRect& aRect, michael@0: nsTArray &aOutFrames, michael@0: uint32_t aFlags = 0); michael@0: michael@0: /** michael@0: * Transform aRect relative to aFrame up to the coordinate system of michael@0: * aAncestor. Computes the bounding-box of the true quadrilateral. michael@0: * Pass non-null aPreservesAxisAlignedRectangles and it will be set to true if michael@0: * we only need to use a 2d transform that PreservesAxisAlignedRectangles(). michael@0: */ michael@0: static nsRect TransformFrameRectToAncestor(nsIFrame* aFrame, michael@0: const nsRect& aRect, michael@0: const nsIFrame* aAncestor, michael@0: bool* aPreservesAxisAlignedRectangles = nullptr); michael@0: michael@0: michael@0: /** michael@0: * Gets the transform for aFrame relative to aAncestor. Pass null for aAncestor michael@0: * to go up to the root frame. michael@0: */ michael@0: static gfx3DMatrix GetTransformToAncestor(nsIFrame *aFrame, const nsIFrame *aAncestor); michael@0: michael@0: /** michael@0: * Transforms a list of CSSPoints from aFromFrame to aToFrame, taking into michael@0: * account all relevant transformations on the frames up to (but excluding) michael@0: * their nearest common ancestor. michael@0: * If we encounter a transform that we need to invert but which is michael@0: * non-invertible, we return NONINVERTIBLE_TRANSFORM. If the frames have michael@0: * no common ancestor, we return NO_COMMON_ANCESTOR. michael@0: * If this returns TRANSFORM_SUCCEEDED, the points in aPoints are transformed michael@0: * in-place, otherwise they are untouched. michael@0: */ michael@0: enum TransformResult { michael@0: TRANSFORM_SUCCEEDED, michael@0: NO_COMMON_ANCESTOR, michael@0: NONINVERTIBLE_TRANSFORM michael@0: }; michael@0: static TransformResult TransformPoints(nsIFrame* aFromFrame, nsIFrame* aToFrame, michael@0: uint32_t aPointCount, CSSPoint* aPoints); michael@0: michael@0: /** michael@0: * Return true if a "layer transform" could be computed for aFrame, michael@0: * and optionally return the computed transform. The returned michael@0: * transform is what would be set on the layer currently if a layers michael@0: * transaction were opened at the time this helper is called. michael@0: */ michael@0: static bool GetLayerTransformForFrame(nsIFrame* aFrame, michael@0: gfx3DMatrix* aTransform); michael@0: michael@0: /** michael@0: * Given a point in the global coordinate space, returns that point expressed michael@0: * in the coordinate system of aFrame. This effectively inverts all transforms michael@0: * between this point and the root frame. michael@0: * michael@0: * @param aFrame The frame that acts as the coordinate space container. michael@0: * @param aPoint The point, in the global space, to get in the frame-local space. michael@0: * @return aPoint, expressed in aFrame's canonical coordinate space. michael@0: */ michael@0: static nsPoint TransformRootPointToFrame(nsIFrame* aFrame, michael@0: const nsPoint &aPoint) michael@0: { michael@0: return TransformAncestorPointToFrame(aFrame, aPoint, nullptr); michael@0: } michael@0: michael@0: /** michael@0: * Transform aPoint relative to aAncestor down to the coordinate system of michael@0: * aFrame. michael@0: */ michael@0: static nsPoint TransformAncestorPointToFrame(nsIFrame* aFrame, michael@0: const nsPoint& aPoint, michael@0: nsIFrame* aAncestor); michael@0: michael@0: /** michael@0: * Helper function that, given a rectangle and a matrix, returns the smallest michael@0: * rectangle containing the image of the source rectangle. michael@0: * michael@0: * @param aBounds The rectangle to transform. michael@0: * @param aMatrix The matrix to transform it with. michael@0: * @param aFactor The number of app units per graphics unit. michael@0: * @return The smallest rect that contains the image of aBounds. michael@0: */ michael@0: static nsRect MatrixTransformRect(const nsRect &aBounds, michael@0: const gfx3DMatrix &aMatrix, float aFactor); michael@0: michael@0: /** michael@0: * Helper function that, given a rectangle and a matrix, returns the smallest michael@0: * rectangle containing the image of the source rectangle rounded out to the nearest michael@0: * pixel value. michael@0: * michael@0: * @param aBounds The rectangle to transform. michael@0: * @param aMatrix The matrix to transform it with. michael@0: * @param aFactor The number of app units per graphics unit. michael@0: * @return The smallest rect that contains the image of aBounds. michael@0: */ michael@0: static nsRect MatrixTransformRectOut(const nsRect &aBounds, michael@0: const gfx3DMatrix &aMatrix, float aFactor); michael@0: /** michael@0: * Helper function that, given a point and a matrix, returns the image michael@0: * of that point under the matrix transform. michael@0: * michael@0: * @param aPoint The point to transform. michael@0: * @param aMatrix The matrix to transform it with. michael@0: * @param aFactor The number of app units per graphics unit. michael@0: * @return The image of the point under the transform. michael@0: */ michael@0: static nsPoint MatrixTransformPoint(const nsPoint &aPoint, michael@0: const gfx3DMatrix &aMatrix, float aFactor); michael@0: michael@0: /** michael@0: * Given a graphics rectangle in graphics space, return a rectangle in michael@0: * app space that contains the graphics rectangle, rounding out as necessary. michael@0: * michael@0: * @param aRect The graphics rect to round outward. michael@0: * @param aFactor The number of app units per graphics unit. michael@0: * @return The smallest rectangle in app space that contains aRect. michael@0: */ michael@0: static nsRect RoundGfxRectToAppRect(const Rect &aRect, float aFactor); michael@0: michael@0: /** michael@0: * Given a graphics rectangle in graphics space, return a rectangle in michael@0: * app space that contains the graphics rectangle, rounding out as necessary. michael@0: * michael@0: * @param aRect The graphics rect to round outward. michael@0: * @param aFactor The number of app units per graphics unit. michael@0: * @return The smallest rectangle in app space that contains aRect. michael@0: */ michael@0: static nsRect RoundGfxRectToAppRect(const gfxRect &aRect, float aFactor); michael@0: michael@0: /** michael@0: * Returns a subrectangle of aContainedRect that is entirely inside the rounded michael@0: * rect. Complex cases are handled conservatively by returning a smaller michael@0: * rect than necessary. michael@0: */ michael@0: static nsRegion RoundedRectIntersectRect(const nsRect& aRoundedRect, michael@0: const nscoord aRadii[8], michael@0: const nsRect& aContainedRect); michael@0: michael@0: /** michael@0: * Return whether any part of aTestRect is inside of the rounded michael@0: * rectangle formed by aBounds and aRadii (which are indexed by the michael@0: * NS_CORNER_* constants in nsStyleConsts.h). This is precise. michael@0: */ michael@0: static bool RoundedRectIntersectsRect(const nsRect& aRoundedRect, michael@0: const nscoord aRadii[8], michael@0: const nsRect& aTestRect); michael@0: michael@0: enum { michael@0: PAINT_IN_TRANSFORM = 0x01, michael@0: PAINT_SYNC_DECODE_IMAGES = 0x02, michael@0: PAINT_WIDGET_LAYERS = 0x04, michael@0: PAINT_IGNORE_SUPPRESSION = 0x08, michael@0: PAINT_DOCUMENT_RELATIVE = 0x10, michael@0: PAINT_HIDE_CARET = 0x20, michael@0: PAINT_ALL_CONTINUATIONS = 0x40, michael@0: PAINT_TO_WINDOW = 0x80, michael@0: PAINT_EXISTING_TRANSACTION = 0x100, michael@0: PAINT_NO_COMPOSITE = 0x200, michael@0: PAINT_COMPRESSED = 0x400 michael@0: }; michael@0: michael@0: /** michael@0: * Given aFrame, the root frame of a stacking context, paint it and its michael@0: * descendants to aRenderingContext. michael@0: * @param aRenderingContext a rendering context translated so that (0,0) michael@0: * is the origin of aFrame; for best results, (0,0) should transform michael@0: * to pixel-aligned coordinates. This can be null, in which case michael@0: * aFrame must be a "display root" (root frame for a root document, michael@0: * or the root of a popup) with an associated widget and we draw using michael@0: * the layer manager for the frame's widget. michael@0: * @param aDirtyRegion the region that must be painted, in the coordinates michael@0: * of aFrame michael@0: * @param aBackstop paint the dirty area with this color before drawing michael@0: * the actual content; pass NS_RGBA(0,0,0,0) to draw no background michael@0: * @param aFlags if PAINT_IN_TRANSFORM is set, then we assume michael@0: * this is inside a transform or SVG foreignObject. If michael@0: * PAINT_SYNC_DECODE_IMAGES is set, we force synchronous decode on all michael@0: * images. If PAINT_WIDGET_LAYERS is set, aFrame must be a display root, michael@0: * and we will use the frame's widget's layer manager to paint michael@0: * even if aRenderingContext is non-null. This is useful if you want michael@0: * to force rendering to use the widget's layer manager for testing michael@0: * or speed. PAINT_WIDGET_LAYERS must be set if aRenderingContext is null. michael@0: * If PAINT_DOCUMENT_RELATIVE is used, the visible region is interpreted michael@0: * as being relative to the document. (Normally it's relative to the CSS michael@0: * viewport.) PAINT_TO_WINDOW sets painting to window to true on the display michael@0: * list builder even if we can't tell that we are painting to the window. michael@0: * If PAINT_EXISTING_TRANSACTION is set, then BeginTransaction() has already michael@0: * been called on aFrame's widget's layer manager and should not be michael@0: * called again. michael@0: * If PAINT_COMPRESSED is set, the FrameLayerBuilder should be set to compressed mode michael@0: * to avoid short cut optimizations. michael@0: * michael@0: * So there are three possible behaviours: michael@0: * 1) PAINT_WIDGET_LAYERS is set and aRenderingContext is null; we paint michael@0: * by calling BeginTransaction on the widget's layer manager michael@0: * 2) PAINT_WIDGET_LAYERS is set and aRenderingContext is non-null; we michael@0: * paint by calling BeginTransactionWithTarget on the widget's layer michael@0: * maanger michael@0: * 3) PAINT_WIDGET_LAYERS is not set and aRenderingContext is non-null; michael@0: * we paint by construct a BasicLayerManager and calling michael@0: * BeginTransactionWithTarget on it. This is desirable if we're doing michael@0: * something like drawWindow in a mode where what gets rendered doesn't michael@0: * necessarily correspond to what's visible in the window; we don't michael@0: * want to mess up the widget's layer tree. michael@0: */ michael@0: static nsresult PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFrame, michael@0: const nsRegion& aDirtyRegion, nscolor aBackstop, michael@0: uint32_t aFlags = 0); michael@0: michael@0: /** michael@0: * Uses a binary search for find where the cursor falls in the line of text michael@0: * It also keeps track of the part of the string that has already been measured michael@0: * so it doesn't have to keep measuring the same text over and over michael@0: * michael@0: * @param "aBaseWidth" contains the width in twips of the portion michael@0: * of the text that has already been measured, and aBaseInx contains michael@0: * the index of the text that has already been measured. michael@0: * michael@0: * @param aTextWidth returns the (in twips) the length of the text that falls michael@0: * before the cursor aIndex contains the index of the text where the cursor falls michael@0: */ michael@0: static bool michael@0: BinarySearchForPosition(nsRenderingContext* acx, michael@0: const char16_t* aText, michael@0: int32_t aBaseWidth, michael@0: int32_t aBaseInx, michael@0: int32_t aStartInx, michael@0: int32_t aEndInx, michael@0: int32_t aCursorPos, michael@0: int32_t& aIndex, michael@0: int32_t& aTextWidth); michael@0: michael@0: class BoxCallback { michael@0: public: michael@0: virtual void AddBox(nsIFrame* aFrame) = 0; michael@0: }; michael@0: /** michael@0: * Collect all CSS boxes associated with aFrame and its michael@0: * continuations, "drilling down" through outer table frames and michael@0: * some anonymous blocks since they're not real CSS boxes. michael@0: * If aFrame is null, no boxes are returned. michael@0: * SVG frames return a single box, themselves. michael@0: */ michael@0: static void GetAllInFlowBoxes(nsIFrame* aFrame, BoxCallback* aCallback); michael@0: michael@0: /** michael@0: * Find the first frame descendant of aFrame (including aFrame) which is michael@0: * not an anonymous frame that getBoxQuads/getClientRects should ignore. michael@0: */ michael@0: static nsIFrame* GetFirstNonAnonymousFrame(nsIFrame* aFrame); michael@0: michael@0: class RectCallback { michael@0: public: michael@0: virtual void AddRect(const nsRect& aRect) = 0; michael@0: }; michael@0: michael@0: struct RectAccumulator : public RectCallback { michael@0: nsRect mResultRect; michael@0: nsRect mFirstRect; michael@0: bool mSeenFirstRect; michael@0: michael@0: RectAccumulator(); michael@0: michael@0: virtual void AddRect(const nsRect& aRect); michael@0: }; michael@0: michael@0: struct RectListBuilder : public RectCallback { michael@0: DOMRectList* mRectList; michael@0: michael@0: RectListBuilder(DOMRectList* aList); michael@0: virtual void AddRect(const nsRect& aRect); michael@0: }; michael@0: michael@0: static nsIFrame* GetContainingBlockForClientRect(nsIFrame* aFrame); michael@0: michael@0: enum { michael@0: RECTS_ACCOUNT_FOR_TRANSFORMS = 0x01, michael@0: // Two bits for specifying which box type to use. michael@0: // With neither bit set (default), use the border box. michael@0: RECTS_USE_CONTENT_BOX = 0x02, michael@0: RECTS_USE_PADDING_BOX = 0x04, michael@0: RECTS_USE_MARGIN_BOX = 0x06, // both bits set michael@0: RECTS_WHICH_BOX_MASK = 0x06 // bitmask for these two bits michael@0: }; michael@0: /** michael@0: * Collect all CSS boxes (content, padding, border, or margin) associated michael@0: * with aFrame and its continuations, "drilling down" through outer table michael@0: * frames and some anonymous blocks since they're not real CSS boxes. michael@0: * The boxes are positioned relative to aRelativeTo (taking scrolling michael@0: * into account) and passed to the callback in frame-tree order. michael@0: * If aFrame is null, no boxes are returned. michael@0: * For SVG frames, returns one rectangle, the bounding box. michael@0: * If aFlags includes RECTS_ACCOUNT_FOR_TRANSFORMS, then when converting michael@0: * the boxes into aRelativeTo coordinates, transforms (including CSS michael@0: * and SVG transforms) are taken into account. michael@0: * If aFlags includes one of RECTS_USE_CONTENT_BOX, RECTS_USE_PADDING_BOX, michael@0: * or RECTS_USE_MARGIN_BOX, the corresponding type of box is used. michael@0: * Otherwise (by default), the border box is used. michael@0: */ michael@0: static void GetAllInFlowRects(nsIFrame* aFrame, nsIFrame* aRelativeTo, michael@0: RectCallback* aCallback, uint32_t aFlags = 0); michael@0: michael@0: /** michael@0: * Computes the union of all rects returned by GetAllInFlowRects. If michael@0: * the union is empty, returns the first rect. michael@0: * If aFlags includes RECTS_ACCOUNT_FOR_TRANSFORMS, then when converting michael@0: * the boxes into aRelativeTo coordinates, transforms (including CSS michael@0: * and SVG transforms) are taken into account. michael@0: * If aFlags includes one of RECTS_USE_CONTENT_BOX, RECTS_USE_PADDING_BOX, michael@0: * or RECTS_USE_MARGIN_BOX, the corresponding type of box is used. michael@0: * Otherwise (by default), the border box is used. michael@0: */ michael@0: static nsRect GetAllInFlowRectsUnion(nsIFrame* aFrame, nsIFrame* aRelativeTo, michael@0: uint32_t aFlags = 0); michael@0: michael@0: enum { michael@0: EXCLUDE_BLUR_SHADOWS = 0x01 michael@0: }; michael@0: /** michael@0: * Takes a text-shadow array from the style properties of a given nsIFrame and michael@0: * computes the union of those shadows along with the given initial rect. michael@0: * If there are no shadows, the initial rect is returned. michael@0: */ michael@0: static nsRect GetTextShadowRectsUnion(const nsRect& aTextAndDecorationsRect, michael@0: nsIFrame* aFrame, michael@0: uint32_t aFlags = 0); michael@0: michael@0: /** michael@0: * Get the font metrics corresponding to the frame's style data. michael@0: * @param aFrame the frame michael@0: * @param aFontMetrics the font metrics result michael@0: * @param aSizeInflation number to multiply font size by michael@0: * @return success or failure code michael@0: */ michael@0: static nsresult GetFontMetricsForFrame(const nsIFrame* aFrame, michael@0: nsFontMetrics** aFontMetrics, michael@0: float aSizeInflation = 1.0f); michael@0: michael@0: /** michael@0: * Get the font metrics corresponding to the given style data. michael@0: * @param aStyleContext the style data michael@0: * @param aFontMetrics the font metrics result michael@0: * @param aSizeInflation number to multiply font size by michael@0: * @return success or failure code michael@0: */ michael@0: static nsresult GetFontMetricsForStyleContext(nsStyleContext* aStyleContext, michael@0: nsFontMetrics** aFontMetrics, michael@0: float aSizeInflation = 1.0f); michael@0: michael@0: /** michael@0: * Find the immediate child of aParent whose frame subtree contains michael@0: * aDescendantFrame. Returns null if aDescendantFrame is not a descendant michael@0: * of aParent. michael@0: */ michael@0: static nsIFrame* FindChildContainingDescendant(nsIFrame* aParent, nsIFrame* aDescendantFrame); michael@0: michael@0: /** michael@0: * Find the nearest ancestor that's a block michael@0: */ michael@0: static nsBlockFrame* FindNearestBlockAncestor(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Find the nearest ancestor that's not for generated content. Will return michael@0: * aFrame if aFrame is not for generated content. michael@0: */ michael@0: static nsIFrame* GetNonGeneratedAncestor(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Cast aFrame to an nsBlockFrame* or return null if it's not michael@0: * an nsBlockFrame. michael@0: */ michael@0: static nsBlockFrame* GetAsBlock(nsIFrame* aFrame); michael@0: michael@0: /* michael@0: * Whether the frame is an nsBlockFrame which is not a wrapper block. michael@0: */ michael@0: static bool IsNonWrapperBlock(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * If aFrame is an out of flow frame, return its placeholder, otherwise michael@0: * return its parent. michael@0: */ michael@0: static nsIFrame* GetParentOrPlaceholderFor(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * If aFrame is an out of flow frame, return its placeholder, otherwise michael@0: * return its (possibly cross-doc) parent. michael@0: */ michael@0: static nsIFrame* GetParentOrPlaceholderForCrossDoc(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Get a frame's next-in-flow, or, if it doesn't have one, its michael@0: * block-in-inline-split sibling. michael@0: */ michael@0: static nsIFrame* michael@0: GetNextContinuationOrIBSplitSibling(nsIFrame *aFrame); michael@0: michael@0: /** michael@0: * Get the first frame in the continuation-plus-ib-split-sibling chain michael@0: * containing aFrame. michael@0: */ michael@0: static nsIFrame* michael@0: FirstContinuationOrIBSplitSibling(nsIFrame *aFrame); michael@0: michael@0: /** michael@0: * Is FirstContinuationOrIBSplitSibling(aFrame) going to return michael@0: * aFrame? michael@0: */ michael@0: static bool michael@0: IsFirstContinuationOrIBSplitSibling(nsIFrame *aFrame); michael@0: michael@0: /** michael@0: * Check whether aFrame is a part of the scrollbar or scrollcorner of michael@0: * the root content. michael@0: * @param aFrame the checking frame michael@0: * @return if TRUE, the frame is a part of the scrollbar or scrollcorner of michael@0: * the root content. michael@0: */ michael@0: static bool IsViewportScrollbarFrame(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Get the contribution of aFrame to its containing block's intrinsic michael@0: * width. This considers the child's intrinsic width, its 'width', michael@0: * 'min-width', and 'max-width' properties, and its padding, border, michael@0: * and margin. michael@0: */ michael@0: enum IntrinsicWidthType { MIN_WIDTH, PREF_WIDTH }; michael@0: enum { michael@0: IGNORE_PADDING = 0x01 michael@0: }; michael@0: static nscoord IntrinsicForContainer(nsRenderingContext* aRenderingContext, michael@0: nsIFrame* aFrame, michael@0: IntrinsicWidthType aType, michael@0: uint32_t aFlags = 0); michael@0: michael@0: /* michael@0: * Convert nsStyleCoord to nscoord when percentages depend on the michael@0: * containing block size. michael@0: * @param aPercentBasis The width or height of the containing block michael@0: * (whichever the client wants to use for resolving percentages). michael@0: */ michael@0: static nscoord ComputeCBDependentValue(nscoord aPercentBasis, michael@0: const nsStyleCoord& aCoord); michael@0: michael@0: /* michael@0: * Convert nsStyleCoord to nscoord when percentages depend on the michael@0: * containing block width, and enumerated values are for width, michael@0: * min-width, or max-width. Returns the content-box width value based michael@0: * on aContentEdgeToBoxSizing and aBoxSizingToMarginEdge (which are michael@0: * also used for the enumerated values for width. This function does michael@0: * not handle 'auto'. It ensures that the result is nonnegative. michael@0: * michael@0: * @param aRenderingContext Rendering context for font measurement/metrics. michael@0: * @param aFrame Frame whose (min-/max-/)width is being computed michael@0: * @param aContainingBlockWidth Width of aFrame's containing block. michael@0: * @param aContentEdgeToBoxSizing The sum of any left/right padding and michael@0: * border that goes inside the rect chosen by box-sizing. michael@0: * @param aBoxSizingToMarginEdge The sum of any left/right padding, border, michael@0: * and margin that goes outside the rect chosen by box-sizing. michael@0: * @param aCoord The width value to compute. michael@0: */ michael@0: static nscoord ComputeWidthValue( michael@0: nsRenderingContext* aRenderingContext, michael@0: nsIFrame* aFrame, michael@0: nscoord aContainingBlockWidth, michael@0: nscoord aContentEdgeToBoxSizing, michael@0: nscoord aBoxSizingToMarginEdge, michael@0: const nsStyleCoord& aCoord); michael@0: michael@0: /* michael@0: * Convert nsStyleCoord to nscoord when percentages depend on the michael@0: * containing block height. michael@0: */ michael@0: static nscoord ComputeHeightDependentValue( michael@0: nscoord aContainingBlockHeight, michael@0: const nsStyleCoord& aCoord); michael@0: michael@0: /* michael@0: * Likewise, but for 'height', 'min-height', or 'max-height'. michael@0: */ michael@0: static nscoord ComputeHeightValue(nscoord aContainingBlockHeight, michael@0: nscoord aContentEdgeToBoxSizingBoxEdge, michael@0: const nsStyleCoord& aCoord) michael@0: { michael@0: MOZ_ASSERT(aContainingBlockHeight != nscoord_MAX || !aCoord.HasPercent(), michael@0: "caller must deal with %% of unconstrained height"); michael@0: MOZ_ASSERT(aCoord.IsCoordPercentCalcUnit()); michael@0: michael@0: nscoord result = michael@0: nsRuleNode::ComputeCoordPercentCalc(aCoord, aContainingBlockHeight); michael@0: // Clamp calc(), and the subtraction for box-sizing. michael@0: return std::max(0, result - aContentEdgeToBoxSizingBoxEdge); michael@0: } michael@0: michael@0: static bool IsAutoHeight(const nsStyleCoord &aCoord, nscoord aCBHeight) michael@0: { michael@0: nsStyleUnit unit = aCoord.GetUnit(); michael@0: return unit == eStyleUnit_Auto || // only for 'height' michael@0: unit == eStyleUnit_None || // only for 'max-height' michael@0: (aCBHeight == nscoord_MAX && aCoord.HasPercent()); michael@0: } michael@0: michael@0: static bool IsPaddingZero(const nsStyleCoord &aCoord) michael@0: { michael@0: return (aCoord.GetUnit() == eStyleUnit_Coord && michael@0: aCoord.GetCoordValue() == 0) || michael@0: (aCoord.GetUnit() == eStyleUnit_Percent && michael@0: aCoord.GetPercentValue() == 0.0f) || michael@0: (aCoord.IsCalcUnit() && michael@0: // clamp negative calc() to 0 michael@0: nsRuleNode::ComputeCoordPercentCalc(aCoord, nscoord_MAX) <= 0 && michael@0: nsRuleNode::ComputeCoordPercentCalc(aCoord, 0) <= 0); michael@0: } michael@0: michael@0: static bool IsMarginZero(const nsStyleCoord &aCoord) michael@0: { michael@0: return (aCoord.GetUnit() == eStyleUnit_Coord && michael@0: aCoord.GetCoordValue() == 0) || michael@0: (aCoord.GetUnit() == eStyleUnit_Percent && michael@0: aCoord.GetPercentValue() == 0.0f) || michael@0: (aCoord.IsCalcUnit() && michael@0: nsRuleNode::ComputeCoordPercentCalc(aCoord, nscoord_MAX) == 0 && michael@0: nsRuleNode::ComputeCoordPercentCalc(aCoord, 0) == 0); michael@0: } michael@0: michael@0: static void MarkDescendantsDirty(nsIFrame *aSubtreeRoot); michael@0: michael@0: /* michael@0: * Calculate the used values for 'width' and 'height' for a replaced element. michael@0: * michael@0: * http://www.w3.org/TR/CSS21/visudet.html#min-max-widths michael@0: */ michael@0: static nsSize ComputeSizeWithIntrinsicDimensions( michael@0: nsRenderingContext* aRenderingContext, nsIFrame* aFrame, michael@0: const mozilla::IntrinsicSize& aIntrinsicSize, michael@0: nsSize aIntrinsicRatio, nsSize aCBSize, michael@0: nsSize aMargin, nsSize aBorder, nsSize aPadding); michael@0: michael@0: /* michael@0: * Calculate the used values for 'width' and 'height' when width michael@0: * and height are 'auto'. The tentWidth and tentHeight arguments should be michael@0: * the result of applying the rules for computing intrinsic sizes and ratios. michael@0: * as specified by CSS 2.1 sections 10.3.2 and 10.6.2 michael@0: */ michael@0: static nsSize ComputeAutoSizeWithIntrinsicDimensions(nscoord minWidth, nscoord minHeight, michael@0: nscoord maxWidth, nscoord maxHeight, michael@0: nscoord tentWidth, nscoord tentHeight); michael@0: michael@0: // Implement nsIFrame::GetPrefWidth in terms of nsIFrame::AddInlinePrefWidth michael@0: static nscoord PrefWidthFromInline(nsIFrame* aFrame, michael@0: nsRenderingContext* aRenderingContext); michael@0: michael@0: // Implement nsIFrame::GetMinWidth in terms of nsIFrame::AddInlineMinWidth michael@0: static nscoord MinWidthFromInline(nsIFrame* aFrame, michael@0: nsRenderingContext* aRenderingContext); michael@0: michael@0: // Get a suitable foreground color for painting aProperty for aFrame. michael@0: static nscolor GetColor(nsIFrame* aFrame, nsCSSProperty aProperty); michael@0: michael@0: // Get the native text color if appropriate. If false is returned, callers michael@0: // should fallback to the CSS color. michael@0: static bool GetNativeTextColor(nsIFrame* aFrame, nscolor& aColor); michael@0: michael@0: // Get a baseline y position in app units that is snapped to device pixels. michael@0: static gfxFloat GetSnappedBaselineY(nsIFrame* aFrame, gfxContext* aContext, michael@0: nscoord aY, nscoord aAscent); michael@0: michael@0: static void DrawString(const nsIFrame* aFrame, michael@0: nsRenderingContext* aContext, michael@0: const char16_t* aString, michael@0: int32_t aLength, michael@0: nsPoint aPoint, michael@0: nsStyleContext* aStyleContext = nullptr); michael@0: michael@0: static nscoord GetStringWidth(const nsIFrame* aFrame, michael@0: nsRenderingContext* aContext, michael@0: const char16_t* aString, michael@0: int32_t aLength); michael@0: michael@0: /** michael@0: * Helper function for drawing text-shadow. The callback's job michael@0: * is to draw whatever needs to be blurred onto the given context. michael@0: */ michael@0: typedef void (* TextShadowCallback)(nsRenderingContext* aCtx, michael@0: nsPoint aShadowOffset, michael@0: const nscolor& aShadowColor, michael@0: void* aData); michael@0: michael@0: static void PaintTextShadow(const nsIFrame* aFrame, michael@0: nsRenderingContext* aContext, michael@0: const nsRect& aTextRect, michael@0: const nsRect& aDirtyRect, michael@0: const nscolor& aForegroundColor, michael@0: TextShadowCallback aCallback, michael@0: void* aCallbackData); michael@0: michael@0: /** michael@0: * Gets the baseline to vertically center text from a font within a michael@0: * line of specified height. michael@0: * michael@0: * Returns the baseline position relative to the top of the line. michael@0: */ michael@0: static nscoord GetCenteredFontBaseline(nsFontMetrics* aFontMetrics, michael@0: nscoord aLineHeight); michael@0: michael@0: /** michael@0: * Derive a baseline of |aFrame| (measured from its top border edge) michael@0: * from its first in-flow line box (not descending into anything with michael@0: * 'overflow' not 'visible', potentially including aFrame itself). michael@0: * michael@0: * Returns true if a baseline was found (and fills in aResult). michael@0: * Otherwise returns false. michael@0: */ michael@0: static bool GetFirstLineBaseline(const nsIFrame* aFrame, nscoord* aResult); michael@0: michael@0: /** michael@0: * Just like GetFirstLineBaseline, except also returns the top and michael@0: * bottom of the line with the baseline. michael@0: * michael@0: * Returns true if a line was found (and fills in aResult). michael@0: * Otherwise returns false. michael@0: */ michael@0: struct LinePosition { michael@0: nscoord mTop, mBaseline, mBottom; michael@0: michael@0: LinePosition operator+(nscoord aOffset) const { michael@0: LinePosition result; michael@0: result.mTop = mTop + aOffset; michael@0: result.mBaseline = mBaseline + aOffset; michael@0: result.mBottom = mBottom + aOffset; michael@0: return result; michael@0: } michael@0: }; michael@0: static bool GetFirstLinePosition(const nsIFrame* aFrame, michael@0: LinePosition* aResult); michael@0: michael@0: michael@0: /** michael@0: * Derive a baseline of |aFrame| (measured from its top border edge) michael@0: * from its last in-flow line box (not descending into anything with michael@0: * 'overflow' not 'visible', potentially including aFrame itself). michael@0: * michael@0: * Returns true if a baseline was found (and fills in aResult). michael@0: * Otherwise returns false. michael@0: */ michael@0: static bool GetLastLineBaseline(const nsIFrame* aFrame, nscoord* aResult); michael@0: michael@0: /** michael@0: * Returns a y coordinate relative to this frame's origin that represents michael@0: * the logical bottom of the frame or its visible content, whichever is lower. michael@0: * Relative positioning is ignored and margins and glyph bounds are not michael@0: * considered. michael@0: * This value will be >= mRect.height() and <= overflowRect.YMost() unless michael@0: * relative positioning is applied. michael@0: */ michael@0: static nscoord CalculateContentBottom(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Gets the closest frame (the frame passed in or one of its parents) that michael@0: * qualifies as a "layer"; used in DOM0 methods that depends upon that michael@0: * definition. This is the nearest frame that is either positioned or scrolled michael@0: * (the child of a scroll frame). michael@0: */ michael@0: static nsIFrame* GetClosestLayer(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Gets the graphics filter for the frame michael@0: */ michael@0: static GraphicsFilter GetGraphicsFilterForFrame(nsIFrame* aFrame); michael@0: michael@0: /* N.B. The only difference between variants of the Draw*Image michael@0: * functions below is the type of the aImage argument. michael@0: */ michael@0: michael@0: /** michael@0: * Draw a background image. The image's dimensions are as specified in aDest; michael@0: * the image itself is not consulted to determine a size. michael@0: * See https://wiki.mozilla.org/Gecko:Image_Snapping_and_Rendering michael@0: * @param aRenderingContext Where to draw the image, set up with an michael@0: * appropriate scale and transform for drawing in michael@0: * app units. michael@0: * @param aImage The image. michael@0: * @param aImageSize The unscaled size of the image being drawn. michael@0: * (This might be the image's size if no scaling michael@0: * occurs, or it might be the image's size if michael@0: * the image is a vector image being rendered at michael@0: * that size.) michael@0: * @param aDest The position and scaled area where one copy of michael@0: * the image should be drawn. michael@0: * @param aFill The area to be filled with copies of the michael@0: * image. michael@0: * @param aAnchor A point in aFill which we will ensure is michael@0: * pixel-aligned in the output. michael@0: * @param aDirty Pixels outside this area may be skipped. michael@0: * @param aImageFlags Image flags of the imgIContainer::FLAG_* variety michael@0: */ michael@0: static nsresult DrawBackgroundImage(nsRenderingContext* aRenderingContext, michael@0: imgIContainer* aImage, michael@0: const nsIntSize& aImageSize, michael@0: GraphicsFilter aGraphicsFilter, michael@0: const nsRect& aDest, michael@0: const nsRect& aFill, michael@0: const nsPoint& aAnchor, michael@0: const nsRect& aDirty, michael@0: uint32_t aImageFlags); michael@0: michael@0: /** michael@0: * Draw an image. michael@0: * See https://wiki.mozilla.org/Gecko:Image_Snapping_and_Rendering michael@0: * @param aRenderingContext Where to draw the image, set up with an michael@0: * appropriate scale and transform for drawing in michael@0: * app units. michael@0: * @param aImage The image. michael@0: * @param aDest Where one copy of the image should mapped to. michael@0: * @param aFill The area to be filled with copies of the michael@0: * image. michael@0: * @param aAnchor A point in aFill which we will ensure is michael@0: * pixel-aligned in the output. michael@0: * @param aDirty Pixels outside this area may be skipped. michael@0: * @param aImageFlags Image flags of the imgIContainer::FLAG_* variety michael@0: */ michael@0: static nsresult DrawImage(nsRenderingContext* aRenderingContext, michael@0: imgIContainer* aImage, michael@0: GraphicsFilter aGraphicsFilter, michael@0: const nsRect& aDest, michael@0: const nsRect& aFill, michael@0: const nsPoint& aAnchor, michael@0: const nsRect& aDirty, michael@0: uint32_t aImageFlags); michael@0: michael@0: /** michael@0: * Convert an nsRect to a gfxRect. michael@0: */ michael@0: static gfxRect RectToGfxRect(const nsRect& aRect, michael@0: int32_t aAppUnitsPerDevPixel); michael@0: michael@0: /** michael@0: * Draw a drawable using the pixel snapping algorithm. michael@0: * See https://wiki.mozilla.org/Gecko:Image_Snapping_and_Rendering michael@0: * @param aRenderingContext Where to draw the image, set up with an michael@0: * appropriate scale and transform for drawing in michael@0: * app units. michael@0: * @param aDrawable The drawable we want to draw. michael@0: * @param aFilter The graphics filter we should draw with. michael@0: * @param aDest Where one copy of the image should mapped to. michael@0: * @param aFill The area to be filled with copies of the michael@0: * image. michael@0: * @param aAnchor A point in aFill which we will ensure is michael@0: * pixel-aligned in the output. michael@0: * @param aDirty Pixels outside this area may be skipped. michael@0: */ michael@0: static void DrawPixelSnapped(nsRenderingContext* aRenderingContext, michael@0: gfxDrawable* aDrawable, michael@0: GraphicsFilter aFilter, michael@0: const nsRect& aDest, michael@0: const nsRect& aFill, michael@0: const nsPoint& aAnchor, michael@0: const nsRect& aDirty); michael@0: michael@0: /** michael@0: * Draw a whole image without scaling or tiling. michael@0: * michael@0: * @param aRenderingContext Where to draw the image, set up with an michael@0: * appropriate scale and transform for drawing in michael@0: * app units. michael@0: * @param aImage The image. michael@0: * @param aDest The top-left where the image should be drawn michael@0: * @param aDirty If non-null, then pixels outside this area may michael@0: * be skipped. michael@0: * @param aImageFlags Image flags of the imgIContainer::FLAG_* variety michael@0: * @param aSourceArea If non-null, this area is extracted from michael@0: * the image and drawn at aDest. It's michael@0: * in appunits. For best results it should michael@0: * be aligned with image pixels. michael@0: */ michael@0: static nsresult DrawSingleUnscaledImage(nsRenderingContext* aRenderingContext, michael@0: imgIContainer* aImage, michael@0: GraphicsFilter aGraphicsFilter, michael@0: const nsPoint& aDest, michael@0: const nsRect* aDirty, michael@0: uint32_t aImageFlags, michael@0: const nsRect* aSourceArea = nullptr); michael@0: michael@0: /** michael@0: * Draw a whole image without tiling. michael@0: * michael@0: * @param aRenderingContext Where to draw the image, set up with an michael@0: * appropriate scale and transform for drawing in michael@0: * app units. michael@0: * @param aImage The image. michael@0: * @param aDest The area that the image should fill michael@0: * @param aDirty Pixels outside this area may be skipped. michael@0: * @param aSVGContext If non-null, SVG-related rendering context michael@0: * such as overridden attributes on the image michael@0: * document's root node. Ignored for michael@0: * raster images. michael@0: * @param aImageFlags Image flags of the imgIContainer::FLAG_* michael@0: * variety. michael@0: * @param aSourceArea If non-null, this area is extracted from michael@0: * the image and drawn in aDest. It's michael@0: * in appunits. For best results it should michael@0: * be aligned with image pixels. michael@0: */ michael@0: static nsresult DrawSingleImage(nsRenderingContext* aRenderingContext, michael@0: imgIContainer* aImage, michael@0: GraphicsFilter aGraphicsFilter, michael@0: const nsRect& aDest, michael@0: const nsRect& aDirty, michael@0: const mozilla::SVGImageContext* aSVGContext, michael@0: uint32_t aImageFlags, michael@0: const nsRect* aSourceArea = nullptr); michael@0: michael@0: /** michael@0: * Given an imgIContainer, this method attempts to obtain an intrinsic michael@0: * px-valued height & width for it. If the imgIContainer has a non-pixel michael@0: * value for either height or width, this method tries to generate a pixel michael@0: * value for that dimension using the intrinsic ratio (if available). The michael@0: * intrinsic ratio will be assigned to aIntrinsicRatio; if there's no michael@0: * intrinsic ratio then (0, 0) will be assigned. michael@0: * michael@0: * This method will always set aGotWidth and aGotHeight to indicate whether michael@0: * we were able to successfully obtain (or compute) a value for each michael@0: * dimension. michael@0: * michael@0: * NOTE: This method is similar to ComputeSizeWithIntrinsicDimensions. The michael@0: * difference is that this one is simpler and is suited to places where we michael@0: * have less information about the frame tree. michael@0: */ michael@0: static void ComputeSizeForDrawing(imgIContainer* aImage, michael@0: nsIntSize& aImageSize, michael@0: nsSize& aIntrinsicRatio, michael@0: bool& aGotWidth, michael@0: bool& aGotHeight); michael@0: michael@0: /** michael@0: * Given a source area of an image (in appunits) and a destination area michael@0: * that we want to map that source area too, computes the area that michael@0: * would be covered by the whole image. This is useful for passing to michael@0: * the aDest parameter of DrawImage, when we want to draw a subimage michael@0: * of an overall image. michael@0: */ michael@0: static nsRect GetWholeImageDestination(const nsIntSize& aWholeImageSize, michael@0: const nsRect& aImageSourceArea, michael@0: const nsRect& aDestArea); michael@0: michael@0: /** michael@0: * Given an image container and an orientation, returns an image container michael@0: * that contains the same image, reoriented appropriately. May return the michael@0: * original image container if no changes are needed. michael@0: * michael@0: * @param aContainer The image container to apply the orientation to. michael@0: * @param aOrientation The desired orientation. michael@0: */ michael@0: static already_AddRefed michael@0: OrientImage(imgIContainer* aContainer, michael@0: const nsStyleImageOrientation& aOrientation); michael@0: michael@0: /** michael@0: * Determine if any corner radius is of nonzero size michael@0: * @param aCorners the |nsStyleCorners| object to check michael@0: * @return true unless all the coordinates are 0%, 0 or null. michael@0: * michael@0: * A corner radius with one dimension zero and one nonzero is michael@0: * treated as a nonzero-radius corner, even though it will end up michael@0: * being rendered like a zero-radius corner. This is because such michael@0: * corners are not expected to appear outside of test cases, and it's michael@0: * simpler to implement the test this way. michael@0: */ michael@0: static bool HasNonZeroCorner(const nsStyleCorners& aCorners); michael@0: michael@0: /** michael@0: * Determine if there is any corner radius on corners adjacent to the michael@0: * given side. michael@0: */ michael@0: static bool HasNonZeroCornerOnSide(const nsStyleCorners& aCorners, michael@0: mozilla::css::Side aSide); michael@0: michael@0: /** michael@0: * Determine if a widget is likely to require transparency or translucency. michael@0: * @param aBackgroundFrame The frame that the background is set on. For michael@0: * s, this will be the canvas frame. michael@0: * @param aCSSRootFrame The frame that holds CSS properties affecting michael@0: * the widget's transparency. For menupopups, michael@0: * aBackgroundFrame and aCSSRootFrame will be the michael@0: * same. michael@0: * @return a value suitable for passing to SetWindowTranslucency michael@0: */ michael@0: static nsTransparencyMode GetFrameTransparency(nsIFrame* aBackgroundFrame, michael@0: nsIFrame* aCSSRootFrame); michael@0: michael@0: /** michael@0: * A frame is a popup if it has its own floating window. Menus, panels michael@0: * and combobox dropdowns are popups. michael@0: */ michael@0: static bool IsPopup(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Find the nearest "display root". This is the nearest enclosing michael@0: * popup frame or the root prescontext's root frame. michael@0: */ michael@0: static nsIFrame* GetDisplayRootFrame(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Get the reference frame that would be used when constructing a michael@0: * display item for this frame. (Note, however, that michael@0: * nsDisplayTransform use the reference frame appropriate for their michael@0: * GetTransformRootFrame(), rather than using their own frame as a michael@0: * reference frame.) michael@0: * michael@0: * This duplicates some of the logic of GetDisplayRootFrame above and michael@0: * of nsDisplayListBuilder::FindReferenceFrameFor. michael@0: * michael@0: * If you have an nsDisplayListBuilder, you should get the reference michael@0: * frame from it instead of calling this. michael@0: */ michael@0: static nsIFrame* GetReferenceFrame(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Get the parent of this frame, except if that parent is part of a michael@0: * preserve-3d hierarchy, get the parent of the root of the michael@0: * preserve-3d hierarchy. michael@0: * michael@0: * (This is used as the starting point for reference frame computation michael@0: * for nsDisplayTransform display items.) michael@0: */ michael@0: static nsIFrame* GetTransformRootFrame(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Get textrun construction flags determined by a given style; in particular michael@0: * some combination of: michael@0: * -- TEXT_DISABLE_OPTIONAL_LIGATURES if letter-spacing is in use michael@0: * -- TEXT_OPTIMIZE_SPEED if the text-rendering CSS property and font size michael@0: * and prefs indicate we should be optimizing for speed over quality michael@0: */ michael@0: static uint32_t GetTextRunFlagsForStyle(nsStyleContext* aStyleContext, michael@0: const nsStyleFont* aStyleFont, michael@0: const nsStyleText* aStyleText, michael@0: nscoord aLetterSpacing); michael@0: michael@0: /** michael@0: * Takes two rectangles whose origins must be the same, and computes michael@0: * the difference between their union and their intersection as two michael@0: * rectangles. (This difference is a superset of the difference michael@0: * between the two rectangles.) michael@0: */ michael@0: static void GetRectDifferenceStrips(const nsRect& aR1, const nsRect& aR2, michael@0: nsRect* aHStrip, nsRect* aVStrip); michael@0: michael@0: /** michael@0: * Get a device context that can be used to get up-to-date device michael@0: * dimensions for the given window. For some reason, this is more michael@0: * complicated than it ought to be in multi-monitor situations. michael@0: */ michael@0: static nsDeviceContext* michael@0: GetDeviceContextForScreenInfo(nsPIDOMWindow* aWindow); michael@0: michael@0: /** michael@0: * Some frames with 'position: fixed' (nsStylePosition::mDisplay == michael@0: * NS_STYLE_POSITION_FIXED) are not really fixed positioned, since michael@0: * they're inside an element with -moz-transform. This function says michael@0: * whether such an element is a real fixed-pos element. michael@0: */ michael@0: static bool IsReallyFixedPos(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Obtain a gfxASurface from the given DOM element, if possible. michael@0: * This obtains the most natural surface from the element; that michael@0: * is, the one that can be obtained with the fewest conversions. michael@0: * michael@0: * The flags below can modify the behaviour of this function. The michael@0: * result is returned as a SurfaceFromElementResult struct, also michael@0: * defined below. michael@0: * michael@0: * Currently, this will do: michael@0: * - HTML Canvas elements: will return the underlying canvas surface michael@0: * - HTML Video elements: will return the current video frame michael@0: * - Image elements: will return the image michael@0: * michael@0: * The above results are modified by the below flags (copying, michael@0: * forcing image surface, etc.). michael@0: */ michael@0: michael@0: enum { michael@0: /* When creating a new surface, create an image surface */ michael@0: SFE_WANT_IMAGE_SURFACE = 1 << 0, michael@0: /* Whether to extract the first frame (as opposed to the michael@0: current frame) in the case that the element is an image. */ michael@0: SFE_WANT_FIRST_FRAME = 1 << 1, michael@0: /* Whether we should skip colorspace/gamma conversion */ michael@0: SFE_NO_COLORSPACE_CONVERSION = 1 << 2, michael@0: /* Specifies that the caller wants unpremultiplied pixel data. michael@0: If this is can be done efficiently, the result will be a michael@0: DataSourceSurface and mIsPremultiplied with be set to false. */ michael@0: SFE_PREFER_NO_PREMULTIPLY_ALPHA = 1 << 3, michael@0: /* Whether we should skip getting a surface for vector images and michael@0: return a DirectDrawInfo containing an imgIContainer instead. */ michael@0: SFE_NO_RASTERIZING_VECTORS = 1 << 4 michael@0: }; michael@0: michael@0: struct DirectDrawInfo { michael@0: /* imgIContainer to directly draw to a context */ michael@0: nsCOMPtr mImgContainer; michael@0: /* which frame to draw */ michael@0: uint32_t mWhichFrame; michael@0: /* imgIContainer flags to use when drawing */ michael@0: uint32_t mDrawingFlags; michael@0: }; michael@0: michael@0: struct SurfaceFromElementResult { michael@0: SurfaceFromElementResult(); michael@0: michael@0: /* mSurface will contain the resulting surface, or will be nullptr on error */ michael@0: nsRefPtr mSurface; michael@0: mozilla::RefPtr mSourceSurface; michael@0: /* Contains info for drawing when there is no mSourceSurface. */ michael@0: DirectDrawInfo mDrawInfo; michael@0: michael@0: /* The size of the surface */ michael@0: gfxIntSize mSize; michael@0: /* The principal associated with the element whose surface was returned. michael@0: If there is a surface, this will never be null. */ michael@0: nsCOMPtr mPrincipal; michael@0: /* The image request, if the element is an nsIImageLoadingContent */ michael@0: nsCOMPtr mImageRequest; michael@0: /* Whether the element was "write only", that is, the bits should not be exposed to content */ michael@0: bool mIsWriteOnly; michael@0: /* Whether the element was still loading. Some consumers need to handle michael@0: this case specially. */ michael@0: bool mIsStillLoading; michael@0: /* Whether the element used CORS when loading. */ michael@0: bool mCORSUsed; michael@0: /* Whether the returned image contains premultiplied pixel data */ michael@0: bool mIsPremultiplied; michael@0: }; michael@0: michael@0: static SurfaceFromElementResult SurfaceFromElement(mozilla::dom::Element *aElement, michael@0: uint32_t aSurfaceFlags = 0, michael@0: DrawTarget *aTarget = nullptr); michael@0: static SurfaceFromElementResult SurfaceFromElement(nsIImageLoadingContent *aElement, michael@0: uint32_t aSurfaceFlags = 0, michael@0: DrawTarget *aTarget = nullptr); michael@0: // Need an HTMLImageElement overload, because otherwise the michael@0: // nsIImageLoadingContent and mozilla::dom::Element overloads are ambiguous michael@0: // for HTMLImageElement. michael@0: static SurfaceFromElementResult SurfaceFromElement(mozilla::dom::HTMLImageElement *aElement, michael@0: uint32_t aSurfaceFlags = 0, michael@0: DrawTarget *aTarget = nullptr); michael@0: static SurfaceFromElementResult SurfaceFromElement(mozilla::dom::HTMLCanvasElement *aElement, michael@0: uint32_t aSurfaceFlags = 0, michael@0: DrawTarget *aTarget = nullptr); michael@0: static SurfaceFromElementResult SurfaceFromElement(mozilla::dom::HTMLVideoElement *aElement, michael@0: uint32_t aSurfaceFlags = 0, michael@0: DrawTarget *aTarget = nullptr); michael@0: michael@0: /** michael@0: * When the document is editable by contenteditable attribute of its root michael@0: * content or body content. michael@0: * michael@0: * Be aware, this returns nullptr if it's in designMode. michael@0: * michael@0: * For example: michael@0: * michael@0: * michael@0: * returns the . michael@0: * michael@0: * michael@0: * michael@0: * With these cases, this returns the . michael@0: * NOTE: The latter case isn't created normally, however, it can be michael@0: * created by script with XHTML. michael@0: * michael@0: *

michael@0: * returns nullptr because isn't editable. michael@0: */ michael@0: static nsIContent* michael@0: GetEditableRootContentByContentEditable(nsIDocument* aDocument); michael@0: michael@0: /** michael@0: * Returns true if the passed in prescontext needs the dark grey background michael@0: * that goes behind the page of a print preview presentation. michael@0: */ michael@0: static bool NeedsPrintPreviewBackground(nsPresContext* aPresContext); michael@0: michael@0: /** michael@0: * Adds all font faces used in the frame tree starting from aFrame michael@0: * to the list aFontFaceList. michael@0: */ michael@0: static nsresult GetFontFacesForFrames(nsIFrame* aFrame, michael@0: nsFontFaceList* aFontFaceList); michael@0: michael@0: /** michael@0: * Adds all font faces used within the specified range of text in aFrame, michael@0: * and optionally its continuations, to the list in aFontFaceList. michael@0: * Pass 0 and INT32_MAX for aStartOffset and aEndOffset to specify the michael@0: * entire text is to be considered. michael@0: */ michael@0: static nsresult GetFontFacesForText(nsIFrame* aFrame, michael@0: int32_t aStartOffset, michael@0: int32_t aEndOffset, michael@0: bool aFollowContinuations, michael@0: nsFontFaceList* aFontFaceList); michael@0: michael@0: /** michael@0: * Walks the frame tree starting at aFrame looking for textRuns. michael@0: * If |clear| is true, just clears the TEXT_RUN_MEMORY_ACCOUNTED flag michael@0: * on each textRun found (and |aMallocSizeOf| is not used). michael@0: * If |clear| is false, adds the storage used for each textRun to the michael@0: * total, and sets the TEXT_RUN_MEMORY_ACCOUNTED flag to avoid double- michael@0: * accounting. (Runs with this flag already set will be skipped.) michael@0: * Expected usage pattern is therefore to call twice: michael@0: * (void)SizeOfTextRunsForFrames(rootFrame, nullptr, true); michael@0: * total = SizeOfTextRunsForFrames(rootFrame, mallocSizeOf, false); michael@0: */ michael@0: static size_t SizeOfTextRunsForFrames(nsIFrame* aFrame, michael@0: mozilla::MallocSizeOf aMallocSizeOf, michael@0: bool clear); michael@0: michael@0: /** michael@0: * Returns true if the content node has animations or transitions that can be michael@0: * performed on the compositor. michael@0: */ michael@0: static bool HasAnimationsForCompositor(nsIContent* aContent, michael@0: nsCSSProperty aProperty); michael@0: michael@0: /** michael@0: * Returns true if the content node has animations or transitions for the michael@0: * property. michael@0: */ michael@0: static bool HasAnimations(nsIContent* aContent, nsCSSProperty aProperty); michael@0: michael@0: /** michael@0: * Checks if off-main-thread animations are enabled. michael@0: */ michael@0: static bool AreAsyncAnimationsEnabled(); michael@0: michael@0: /** michael@0: * Checks if we should warn about animations that can't be async michael@0: */ michael@0: static bool IsAnimationLoggingEnabled(); michael@0: michael@0: /** michael@0: * Find a suitable scale for an element (aContent) over the course of any michael@0: * animations and transitions on the element. michael@0: * It will check the maximum and minimum scale during the animations and michael@0: * transitions and return a suitable value for performance and quality. michael@0: * Will return scale(1,1) if there is no animated scaling. michael@0: * Always return positive value. michael@0: */ michael@0: static gfxSize ComputeSuitableScaleForAnimation(nsIContent* aContent); michael@0: michael@0: /** michael@0: * Checks if we should forcibly use nearest pixel filtering for the michael@0: * background. michael@0: */ michael@0: static bool UseBackgroundNearestFiltering(); michael@0: michael@0: /** michael@0: * Checks whether we want to use the GPU to scale images when michael@0: * possible. michael@0: */ michael@0: static bool GPUImageScalingEnabled(); michael@0: michael@0: /** michael@0: * Checks whether we want to layerize animated images whenever possible. michael@0: */ michael@0: static bool AnimatedImageLayersEnabled(); michael@0: michael@0: /** michael@0: * Checks if we should enable parsing for CSS Filters. michael@0: */ michael@0: static bool CSSFiltersEnabled(); michael@0: michael@0: /** michael@0: * Checks whether support for the CSS-wide "unset" value is enabled. michael@0: */ michael@0: static bool UnsetValueEnabled(); michael@0: michael@0: /** michael@0: * Checks whether support for the CSS text-align (and -moz-text-align-last) michael@0: * 'true' value is enabled. michael@0: */ michael@0: static bool IsTextAlignTrueValueEnabled(); michael@0: michael@0: /** michael@0: * Checks if CSS variables are currently enabled. michael@0: */ michael@0: static bool CSSVariablesEnabled() michael@0: { michael@0: return sCSSVariablesEnabled; michael@0: } michael@0: michael@0: static bool InterruptibleReflowEnabled() michael@0: { michael@0: return sInterruptibleReflowEnabled; michael@0: } michael@0: michael@0: /** michael@0: * Unions the overflow areas of the children of aFrame with aOverflowAreas. michael@0: * aSkipChildLists specifies any child lists that should be skipped. michael@0: * kSelectPopupList and kPopupList are always skipped. michael@0: */ michael@0: static void UnionChildOverflow(nsIFrame* aFrame, michael@0: nsOverflowAreas& aOverflowAreas, michael@0: mozilla::layout::FrameChildListIDs aSkipChildLists = michael@0: mozilla::layout::FrameChildListIDs()); michael@0: michael@0: /** michael@0: * Return the font size inflation *ratio* for a given frame. This is michael@0: * the factor by which font sizes should be inflated; it is never michael@0: * smaller than 1. michael@0: */ michael@0: static float FontSizeInflationFor(const nsIFrame *aFrame); michael@0: michael@0: /** michael@0: * Perform the first half of the computation of FontSizeInflationFor michael@0: * (see above). michael@0: * This includes determining whether inflation should be performed michael@0: * within this container and returning 0 if it should not be. michael@0: * michael@0: * The result is guaranteed not to vary between line participants michael@0: * (inlines, text frames) within a line. michael@0: * michael@0: * The result should not be used directly since font sizes slightly michael@0: * above the minimum should always be adjusted as done by michael@0: * FontSizeInflationInner. michael@0: */ michael@0: static nscoord InflationMinFontSizeFor(const nsIFrame *aFrame); michael@0: michael@0: /** michael@0: * Perform the second half of the computation done by michael@0: * FontSizeInflationFor (see above). michael@0: * michael@0: * aMinFontSize must be the result of one of the michael@0: * InflationMinFontSizeFor methods above. michael@0: */ michael@0: static float FontSizeInflationInner(const nsIFrame *aFrame, michael@0: nscoord aMinFontSize); michael@0: michael@0: static bool FontSizeInflationEnabled(nsPresContext *aPresContext); michael@0: michael@0: /** michael@0: * See comment above "font.size.inflation.maxRatio" in michael@0: * modules/libpref/src/init/all.js . michael@0: */ michael@0: static uint32_t FontSizeInflationMaxRatio() { michael@0: return sFontSizeInflationMaxRatio; michael@0: } michael@0: michael@0: /** michael@0: * See comment above "font.size.inflation.emPerLine" in michael@0: * modules/libpref/src/init/all.js . michael@0: */ michael@0: static uint32_t FontSizeInflationEmPerLine() { michael@0: return sFontSizeInflationEmPerLine; michael@0: } michael@0: michael@0: /** michael@0: * See comment above "font.size.inflation.minTwips" in michael@0: * modules/libpref/src/init/all.js . michael@0: */ michael@0: static uint32_t FontSizeInflationMinTwips() { michael@0: return sFontSizeInflationMinTwips; michael@0: } michael@0: michael@0: /** michael@0: * See comment above "font.size.inflation.lineThreshold" in michael@0: * modules/libpref/src/init/all.js . michael@0: */ michael@0: static uint32_t FontSizeInflationLineThreshold() { michael@0: return sFontSizeInflationLineThreshold; michael@0: } michael@0: michael@0: static bool FontSizeInflationForceEnabled() { michael@0: return sFontSizeInflationForceEnabled; michael@0: } michael@0: michael@0: static bool FontSizeInflationDisabledInMasterProcess() { michael@0: return sFontSizeInflationDisabledInMasterProcess; michael@0: } michael@0: michael@0: /** michael@0: * See comment above "font.size.inflation.mappingIntercept" in michael@0: * modules/libpref/src/init/all.js . michael@0: */ michael@0: static int32_t FontSizeInflationMappingIntercept() { michael@0: return sFontSizeInflationMappingIntercept; michael@0: } michael@0: michael@0: /** michael@0: * Returns true if the nglayout.debug.invalidation pref is set to true. michael@0: * Note that sInvalidationDebuggingIsEnabled is declared outside this function to michael@0: * allow it to be accessed an manipulated from breakpoint conditions. michael@0: */ michael@0: static bool InvalidationDebuggingIsEnabled() { michael@0: return sInvalidationDebuggingIsEnabled || getenv("MOZ_DUMP_INVALIDATION") != 0; michael@0: } michael@0: michael@0: static void Initialize(); michael@0: static void Shutdown(); michael@0: michael@0: /** michael@0: * Register an imgIRequest object with a refresh driver. michael@0: * michael@0: * @param aPresContext The nsPresContext whose refresh driver we want to michael@0: * register with. michael@0: * @param aRequest A pointer to the imgIRequest object which the client wants michael@0: * to register with the refresh driver. michael@0: * @param aRequestRegistered A pointer to a boolean value which indicates michael@0: * whether the given image request is registered. If michael@0: * *aRequestRegistered is true, then this request will not be michael@0: * registered again. If the request is registered by this function, michael@0: * then *aRequestRegistered will be set to true upon the completion of michael@0: * this function. michael@0: * michael@0: */ michael@0: static void RegisterImageRequest(nsPresContext* aPresContext, michael@0: imgIRequest* aRequest, michael@0: bool* aRequestRegistered); michael@0: michael@0: /** michael@0: * Register an imgIRequest object with a refresh driver, but only if the michael@0: * request is for an image that is animated. michael@0: * michael@0: * @param aPresContext The nsPresContext whose refresh driver we want to michael@0: * register with. michael@0: * @param aRequest A pointer to the imgIRequest object which the client wants michael@0: * to register with the refresh driver. michael@0: * @param aRequestRegistered A pointer to a boolean value which indicates michael@0: * whether the given image request is registered. If michael@0: * *aRequestRegistered is true, then this request will not be michael@0: * registered again. If the request is registered by this function, michael@0: * then *aRequestRegistered will be set to true upon the completion of michael@0: * this function. michael@0: * michael@0: */ michael@0: static void RegisterImageRequestIfAnimated(nsPresContext* aPresContext, michael@0: imgIRequest* aRequest, michael@0: bool* aRequestRegistered); michael@0: michael@0: /** michael@0: * Deregister an imgIRequest object from a refresh driver. michael@0: * michael@0: * @param aPresContext The nsPresContext whose refresh driver we want to michael@0: * deregister from. michael@0: * @param aRequest A pointer to the imgIRequest object with which the client michael@0: * previously registered and now wants to deregister from the refresh michael@0: * driver. michael@0: * @param aRequestRegistered A pointer to a boolean value which indicates michael@0: * whether the given image request is registered. If michael@0: * *aRequestRegistered is false, then this request will not be michael@0: * deregistered. If the request is deregistered by this function, michael@0: * then *aRequestRegistered will be set to false upon the completion of michael@0: * this function. michael@0: */ michael@0: static void DeregisterImageRequest(nsPresContext* aPresContext, michael@0: imgIRequest* aRequest, michael@0: bool* aRequestRegistered); michael@0: michael@0: /** michael@0: * Shim to nsCSSFrameConstructor::PostRestyleEvent. Exists so that we michael@0: * can avoid including nsCSSFrameConstructor.h and all its dependencies michael@0: * in content files. michael@0: */ michael@0: static void PostRestyleEvent(mozilla::dom::Element* aElement, michael@0: nsRestyleHint aRestyleHint, michael@0: nsChangeHint aMinChangeHint); michael@0: michael@0: /** michael@0: * Updates a pair of x and y distances if a given point is closer to a given michael@0: * rectangle than the original distance values. If aPoint is closer to michael@0: * aRect than aClosestXDistance and aClosestYDistance indicate, then those michael@0: * two variables are updated with the distance between aPoint and aRect, michael@0: * and true is returned. If aPoint is not closer, then aClosestXDistance michael@0: * and aClosestYDistance are left unchanged, and false is returned. michael@0: * michael@0: * Distances are measured in the two dimensions separately; a closer x michael@0: * distance beats a closer y distance. michael@0: */ michael@0: template michael@0: static bool PointIsCloserToRect(PointType aPoint, const RectType& aRect, michael@0: CoordType& aClosestXDistance, michael@0: CoordType& aClosestYDistance); michael@0: /** michael@0: * Computes the box shadow rect for the frame, or returns an empty rect if michael@0: * there are no shadows. michael@0: * michael@0: * @param aFrame Frame to compute shadows for. michael@0: * @param aFrameSize Size of aFrame (in case it hasn't been set yet). michael@0: */ michael@0: static nsRect GetBoxShadowRectForFrame(nsIFrame* aFrame, const nsSize& aFrameSize); michael@0: michael@0: #ifdef DEBUG michael@0: /** michael@0: * Assert that there are no duplicate continuations of the same frame michael@0: * within aFrameList. Optimize the tests by assuming that all frames michael@0: * in aFrameList have parent aContainer. michael@0: */ michael@0: static void michael@0: AssertNoDuplicateContinuations(nsIFrame* aContainer, michael@0: const nsFrameList& aFrameList); michael@0: michael@0: /** michael@0: * Assert that the frame tree rooted at |aSubtreeRoot| is empty, i.e., michael@0: * that it contains no first-in-flows. michael@0: */ michael@0: static void michael@0: AssertTreeOnlyEmptyNextInFlows(nsIFrame *aSubtreeRoot); michael@0: #endif michael@0: michael@0: /** michael@0: * Determine if aImageFrame (which is an nsImageFrame, nsImageControlFrame, or michael@0: * nsSVGImageFrame) is visible or close to being visible via scrolling and michael@0: * update the presshell with this knowledge. michael@0: */ michael@0: static void michael@0: UpdateImageVisibilityForFrame(nsIFrame* aImageFrame); michael@0: michael@0: /** michael@0: * Calculate the compostion size for a frame. See FrameMetrics.h for michael@0: * defintion of composition size (or bounds). michael@0: */ michael@0: static nsSize michael@0: CalculateCompositionSizeForFrame(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Calculate the composition size for the root scroll frame of the root michael@0: * content document. michael@0: * @param aFrame A frame in the root content document (or a descendant of it). michael@0: * @param aIsRootContentDocRootScrollFrame Whether aFrame is already the root michael@0: * scroll frame of the root content document. In this case we just michael@0: * use aFrame's own composition size. michael@0: * @param aMetrics A partially populated FrameMetrics for aFrame. Must have at michael@0: * least mCompositionBounds, mCumulativeResolution, and michael@0: * mDevPixelsPerCSSPixel set. michael@0: */ michael@0: static CSSSize michael@0: CalculateRootCompositionSize(nsIFrame* aFrame, michael@0: bool aIsRootContentDocRootScrollFrame, michael@0: const FrameMetrics& aMetrics); michael@0: michael@0: /** michael@0: * Calculate the scrollable rect for a frame. See FrameMetrics.h for michael@0: * defintion of scrollable rect. aScrollableFrame is the scroll frame to calculate michael@0: * the scrollable rect for. If it's null then we calculate the scrollable rect michael@0: * as the rect of the root frame. michael@0: */ michael@0: static nsRect michael@0: CalculateScrollableRectForFrame(nsIScrollableFrame* aScrollableFrame, nsIFrame* aRootFrame); michael@0: michael@0: /** michael@0: * Calculate the expanded scrollable rect for a frame. See FrameMetrics.h for michael@0: * defintion of expanded scrollable rect. michael@0: */ michael@0: static nsRect michael@0: CalculateExpandedScrollableRect(nsIFrame* aFrame); michael@0: michael@0: /** michael@0: * Return whether we want to use APZ for subframes in this process. michael@0: * Currently we don't support APZ for the parent process on B2G. michael@0: */ michael@0: static bool WantSubAPZC(); michael@0: michael@0: /** michael@0: * Get the display port for |aScrollFrame|'s content. If |aScrollFrame| michael@0: * WantsAsyncScroll() and we don't have a scrollable displayport yet (as michael@0: * tracked by |aBuilder|), calculate and set a display port. Returns true if michael@0: * there is (now) a displayport, and if so the displayport is returned in michael@0: * |aOutDisplayport|. michael@0: * michael@0: * Note that a displayport can either be stored as a rect, or as a base michael@0: * rect + margins. If it is stored as a base rect + margins, the base rect michael@0: * is updated to |aDisplayPortBase|, and the rect assembled from the michael@0: * base rect and margins is returned. If this function creates a displayport, michael@0: * it computes margins and stores |aDisplayPortBase| as the base rect. michael@0: * michael@0: * This is intended to be called during display list building. michael@0: */ michael@0: static bool GetOrMaybeCreateDisplayPort(nsDisplayListBuilder& aBuilder, michael@0: nsIFrame* aScrollFrame, michael@0: nsRect aDisplayPortBase, michael@0: nsRect* aOutDisplayport); michael@0: michael@0: private: michael@0: static uint32_t sFontSizeInflationEmPerLine; michael@0: static uint32_t sFontSizeInflationMinTwips; michael@0: static uint32_t sFontSizeInflationLineThreshold; michael@0: static int32_t sFontSizeInflationMappingIntercept; michael@0: static uint32_t sFontSizeInflationMaxRatio; michael@0: static bool sFontSizeInflationForceEnabled; michael@0: static bool sFontSizeInflationDisabledInMasterProcess; michael@0: static bool sInvalidationDebuggingIsEnabled; michael@0: static bool sCSSVariablesEnabled; michael@0: static bool sInterruptibleReflowEnabled; michael@0: }; michael@0: michael@0: MOZ_FINISH_NESTED_ENUM_CLASS(nsLayoutUtils::RepaintMode) michael@0: michael@0: template michael@0: /* static */ bool michael@0: nsLayoutUtils::PointIsCloserToRect(PointType aPoint, const RectType& aRect, michael@0: CoordType& aClosestXDistance, michael@0: CoordType& aClosestYDistance) michael@0: { michael@0: CoordType fromLeft = aPoint.x - aRect.x; michael@0: CoordType fromRight = aPoint.x - aRect.XMost(); michael@0: michael@0: CoordType xDistance; michael@0: if (fromLeft >= 0 && fromRight <= 0) { michael@0: xDistance = 0; michael@0: } else { michael@0: xDistance = std::min(abs(fromLeft), abs(fromRight)); michael@0: } michael@0: michael@0: if (xDistance <= aClosestXDistance) { michael@0: if (xDistance < aClosestXDistance) { michael@0: aClosestYDistance = std::numeric_limits::max(); michael@0: } michael@0: michael@0: CoordType fromTop = aPoint.y - aRect.y; michael@0: CoordType fromBottom = aPoint.y - aRect.YMost(); michael@0: michael@0: CoordType yDistance; michael@0: if (fromTop >= 0 && fromBottom <= 0) { michael@0: yDistance = 0; michael@0: } else { michael@0: yDistance = std::min(abs(fromTop), abs(fromBottom)); michael@0: } michael@0: michael@0: if (yDistance < aClosestYDistance) { michael@0: aClosestXDistance = xDistance; michael@0: aClosestYDistance = yDistance; michael@0: return true; michael@0: } michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: michael@0: namespace mozilla { michael@0: namespace layout { michael@0: michael@0: /** michael@0: * An RAII class which will, for the duration of its lifetime, michael@0: * **if** the frame given is a container for font size inflation, michael@0: * set the current inflation container on the pres context to null michael@0: * (and then, in its destructor, restore the old value). michael@0: */ michael@0: class AutoMaybeDisableFontInflation { michael@0: public: michael@0: AutoMaybeDisableFontInflation(nsIFrame *aFrame); michael@0: michael@0: ~AutoMaybeDisableFontInflation(); michael@0: private: michael@0: nsPresContext *mPresContext; michael@0: bool mOldValue; michael@0: }; michael@0: michael@0: } michael@0: } michael@0: michael@0: class nsSetAttrRunnable : public nsRunnable michael@0: { michael@0: public: michael@0: nsSetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName, michael@0: const nsAString& aValue); michael@0: nsSetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName, michael@0: int32_t aValue); michael@0: michael@0: NS_DECL_NSIRUNNABLE michael@0: michael@0: nsCOMPtr mContent; michael@0: nsCOMPtr mAttrName; michael@0: nsAutoString mValue; michael@0: }; michael@0: michael@0: class nsUnsetAttrRunnable : public nsRunnable michael@0: { michael@0: public: michael@0: nsUnsetAttrRunnable(nsIContent* aContent, nsIAtom* aAttrName); michael@0: michael@0: NS_DECL_NSIRUNNABLE michael@0: michael@0: nsCOMPtr mContent; michael@0: nsCOMPtr mAttrName; michael@0: }; michael@0: michael@0: #endif // nsLayoutUtils_h__