LCOV - code coverage report
Current view: directory - layout/base - nsDisplayList.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1381 0 0.0 %
Date: 2012-06-02 Functions: 181 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2                 :  * vim: set ts=2 sw=2 et tw=78:
       3                 :  * ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Novell code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is Novell Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2006
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *     robert@ocallahan.org
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      27                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK *****
      38                 :  */
      39                 : 
      40                 : /*
      41                 :  * structures that represent things to be painted (ordered in z-order),
      42                 :  * used during painting and hit testing
      43                 :  */
      44                 : 
      45                 : #include "nsDisplayList.h"
      46                 : 
      47                 : #include "nsCSSRendering.h"
      48                 : #include "nsRenderingContext.h"
      49                 : #include "nsISelectionController.h"
      50                 : #include "nsIPresShell.h"
      51                 : #include "nsRegion.h"
      52                 : #include "nsFrameManager.h"
      53                 : #include "gfxContext.h"
      54                 : #include "nsStyleStructInlines.h"
      55                 : #include "nsStyleTransformMatrix.h"
      56                 : #include "gfxMatrix.h"
      57                 : #include "nsSVGIntegrationUtils.h"
      58                 : #include "nsLayoutUtils.h"
      59                 : #include "nsIScrollableFrame.h"
      60                 : #include "nsThemeConstants.h"
      61                 : 
      62                 : #include "imgIContainer.h"
      63                 : #include "nsIInterfaceRequestorUtils.h"
      64                 : #include "BasicLayers.h"
      65                 : #include "nsBoxFrame.h"
      66                 : #include "nsViewportFrame.h"
      67                 : #include "nsSVGEffects.h"
      68                 : #include "nsSVGClipPathFrame.h"
      69                 : 
      70                 : using namespace mozilla;
      71                 : using namespace mozilla::layers;
      72                 : typedef FrameMetrics::ViewID ViewID;
      73                 : 
      74               0 : nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
      75                 :     Mode aMode, bool aBuildCaret)
      76                 :     : mReferenceFrame(aReferenceFrame),
      77                 :       mIgnoreScrollFrame(nsnull),
      78                 :       mCurrentTableItem(nsnull),
      79                 :       mFinalTransparentRegion(nsnull),
      80                 :       mMode(aMode),
      81                 :       mBuildCaret(aBuildCaret),
      82                 :       mIgnoreSuppression(false),
      83                 :       mHadToIgnoreSuppression(false),
      84                 :       mIsAtRootOfPseudoStackingContext(false),
      85                 :       mIncludeAllOutOfFlows(false),
      86                 :       mSelectedFramesOnly(false),
      87                 :       mAccurateVisibleRegions(false),
      88                 :       mInTransform(false),
      89                 :       mSyncDecodeImages(false),
      90                 :       mIsPaintingToWindow(false),
      91                 :       mSnappingEnabled(mMode != EVENT_DELIVERY),
      92                 :       mHasDisplayPort(false),
      93               0 :       mHasFixedItems(false)
      94                 : {
      95               0 :   MOZ_COUNT_CTOR(nsDisplayListBuilder);
      96                 :   PL_InitArenaPool(&mPool, "displayListArena", 1024,
      97               0 :                    NS_MAX(NS_ALIGNMENT_OF(void*),NS_ALIGNMENT_OF(double))-1);
      98                 : 
      99               0 :   nsPresContext* pc = aReferenceFrame->PresContext();
     100               0 :   nsIPresShell *shell = pc->PresShell();
     101               0 :   if (pc->IsRenderingOnlySelection()) {
     102               0 :     nsCOMPtr<nsISelectionController> selcon(do_QueryInterface(shell));
     103               0 :     if (selcon) {
     104               0 :       selcon->GetSelection(nsISelectionController::SELECTION_NORMAL,
     105               0 :                            getter_AddRefs(mBoundingSelection));
     106                 :     }
     107                 :   }
     108                 : 
     109               0 :   if(mReferenceFrame->GetType() == nsGkAtoms::viewportFrame) {
     110               0 :     ViewportFrame* viewportFrame = static_cast<ViewportFrame*>(mReferenceFrame);
     111               0 :     if (!viewportFrame->GetChildList(nsIFrame::kFixedList).IsEmpty()) {
     112               0 :       mHasFixedItems = true;
     113                 :     }
     114                 :   }
     115                 : 
     116               0 :   LayerBuilder()->Init(this);
     117                 : 
     118                 :   PR_STATIC_ASSERT(nsDisplayItem::TYPE_MAX < (1 << nsDisplayItem::TYPE_BITS));
     119               0 : }
     120                 : 
     121               0 : static void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) {
     122               0 :   nsFrameManager* frameManager = aFrame->PresContext()->PresShell()->FrameManager();
     123                 : 
     124               0 :   for (nsIFrame* f = aFrame; f;
     125                 :        f = nsLayoutUtils::GetParentOrPlaceholderFor(frameManager, f)) {
     126               0 :     if (f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)
     127               0 :       return;
     128               0 :     f->AddStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO);
     129               0 :     if (f == aStopAtFrame) {
     130                 :       // we've reached a frame that we know will be painted, so we can stop.
     131               0 :       break;
     132                 :     }
     133                 :   }
     134                 : }
     135                 : 
     136               0 : static bool IsFixedFrame(nsIFrame* aFrame)
     137                 : {
     138               0 :   return aFrame && aFrame->GetParent() && !aFrame->GetParent()->GetParent();
     139                 : }
     140                 : 
     141               0 : static bool IsFixedItem(nsDisplayItem *aItem, nsDisplayListBuilder* aBuilder)
     142                 : {
     143                 :   nsIFrame* activeScrolledRoot =
     144               0 :     nsLayoutUtils::GetActiveScrolledRootFor(aItem, aBuilder);
     145                 :   return activeScrolledRoot &&
     146                 :          !nsLayoutUtils::ScrolledByViewportScrolling(activeScrolledRoot,
     147               0 :                                                      aBuilder);
     148                 : }
     149                 : 
     150               0 : static bool ForceVisiblityForFixedItem(nsDisplayListBuilder* aBuilder,
     151                 :                                        nsDisplayItem* aItem)
     152                 : {
     153               0 :   return aBuilder->GetDisplayPort() && aBuilder->GetHasFixedItems() &&
     154               0 :          IsFixedItem(aItem, aBuilder);
     155                 : }
     156                 : 
     157               0 : void nsDisplayListBuilder::SetDisplayPort(const nsRect& aDisplayPort)
     158                 : {
     159               0 :     static bool fixedPositionLayersEnabled = getenv("MOZ_ENABLE_FIXED_POSITION_LAYERS") != 0;
     160               0 :     if (fixedPositionLayersEnabled) {
     161               0 :       mHasDisplayPort = true;
     162               0 :       mDisplayPort = aDisplayPort;
     163                 :     }
     164               0 : }
     165                 : 
     166               0 : void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
     167                 :                                                         nsIFrame* aFrame,
     168                 :                                                         const nsRect& aDirtyRect)
     169                 : {
     170               0 :   nsRect dirty = aDirtyRect - aFrame->GetOffsetTo(aDirtyFrame);
     171               0 :   nsRect overflowRect = aFrame->GetVisualOverflowRect();
     172                 : 
     173               0 :   if (mHasDisplayPort && IsFixedFrame(aFrame)) {
     174               0 :     dirty = overflowRect;
     175                 :   }
     176                 : 
     177               0 :   if (!dirty.IntersectRect(dirty, overflowRect))
     178                 :     return;
     179                 :   aFrame->Properties().Set(nsDisplayListBuilder::OutOfFlowDirtyRectProperty(),
     180               0 :                            new nsRect(dirty));
     181                 : 
     182               0 :   MarkFrameForDisplay(aFrame, aDirtyFrame);
     183                 : }
     184                 : 
     185               0 : static void UnmarkFrameForDisplay(nsIFrame* aFrame) {
     186               0 :   nsPresContext* presContext = aFrame->PresContext();
     187                 :   presContext->PropertyTable()->
     188               0 :     Delete(aFrame, nsDisplayListBuilder::OutOfFlowDirtyRectProperty());
     189                 : 
     190               0 :   nsFrameManager* frameManager = presContext->PresShell()->FrameManager();
     191                 : 
     192               0 :   for (nsIFrame* f = aFrame; f;
     193                 :        f = nsLayoutUtils::GetParentOrPlaceholderFor(frameManager, f)) {
     194               0 :     if (!(f->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO))
     195               0 :       return;
     196               0 :     f->RemoveStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO);
     197                 :   }
     198                 : }
     199                 : 
     200               0 : static void RecordFrameMetrics(nsIFrame* aForFrame,
     201                 :                                nsIFrame* aScrollFrame,
     202                 :                                ContainerLayer* aRoot,
     203                 :                                const nsRect& aVisibleRect,
     204                 :                                const nsRect& aViewport,
     205                 :                                nsRect* aDisplayPort,
     206                 :                                ViewID aScrollId,
     207                 :                                const nsDisplayItem::ContainerParameters& aContainerParameters) {
     208               0 :   nsPresContext* presContext = aForFrame->PresContext();
     209               0 :   PRInt32 auPerDevPixel = presContext->AppUnitsPerDevPixel();
     210                 : 
     211                 :   nsIntRect visible = aVisibleRect.ScaleToNearestPixels(
     212               0 :     aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
     213               0 :   aRoot->SetVisibleRegion(nsIntRegion(visible));
     214                 : 
     215               0 :   FrameMetrics metrics;
     216                 : 
     217                 :   metrics.mViewport = aViewport.ScaleToNearestPixels(
     218               0 :     aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
     219                 : 
     220               0 :   if (aDisplayPort) {
     221                 :     metrics.mDisplayPort = aDisplayPort->ScaleToNearestPixels(
     222               0 :       aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
     223                 :   }
     224                 : 
     225               0 :   nsIScrollableFrame* scrollableFrame = nsnull;
     226               0 :   if (aScrollFrame)
     227               0 :     scrollableFrame = aScrollFrame->GetScrollTargetFrame();
     228                 : 
     229               0 :   if (scrollableFrame) {
     230                 :     nsSize contentSize =
     231               0 :       scrollableFrame->GetScrollRange().Size() +
     232               0 :       scrollableFrame->GetScrollPortRect().Size();
     233                 :     metrics.mContentSize = contentSize.ScaleToNearestPixels(
     234               0 :       aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
     235               0 :     metrics.mViewportScrollOffset = scrollableFrame->GetScrollPosition().ScaleToNearestPixels(
     236               0 :       aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
     237                 :   }
     238                 :   else {
     239               0 :     nsSize contentSize = aForFrame->GetSize();
     240                 :     metrics.mContentSize = contentSize.ScaleToNearestPixels(
     241               0 :       aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
     242                 :   }
     243                 : 
     244               0 :   metrics.mScrollId = aScrollId;
     245               0 :   aRoot->SetFrameMetrics(metrics);
     246               0 : }
     247                 : 
     248               0 : nsDisplayListBuilder::~nsDisplayListBuilder() {
     249               0 :   NS_ASSERTION(mFramesMarkedForDisplay.Length() == 0,
     250                 :                "All frames should have been unmarked");
     251               0 :   NS_ASSERTION(mPresShellStates.Length() == 0,
     252                 :                "All presshells should have been exited");
     253               0 :   NS_ASSERTION(!mCurrentTableItem, "No table item should be active");
     254                 : 
     255               0 :   PL_FreeArenaPool(&mPool);
     256               0 :   PL_FinishArenaPool(&mPool);
     257               0 :   MOZ_COUNT_DTOR(nsDisplayListBuilder);
     258               0 : }
     259                 : 
     260                 : PRUint32
     261               0 : nsDisplayListBuilder::GetBackgroundPaintFlags() {
     262               0 :   PRUint32 flags = 0;
     263               0 :   if (mSyncDecodeImages) {
     264               0 :     flags |= nsCSSRendering::PAINTBG_SYNC_DECODE_IMAGES;
     265                 :   }
     266               0 :   if (mIsPaintingToWindow) {
     267               0 :     flags |= nsCSSRendering::PAINTBG_TO_WINDOW;
     268                 :   }
     269               0 :   return flags;
     270                 : }
     271                 : 
     272               0 : static PRUint64 RegionArea(const nsRegion& aRegion)
     273                 : {
     274               0 :   PRUint64 area = 0;
     275               0 :   nsRegionRectIterator iter(aRegion);
     276                 :   const nsRect* r;
     277               0 :   while ((r = iter.Next()) != nsnull) {
     278               0 :     area += PRUint64(r->width)*r->height;
     279                 :   }
     280               0 :   return area;
     281                 : }
     282                 : 
     283                 : void
     284               0 : nsDisplayListBuilder::SubtractFromVisibleRegion(nsRegion* aVisibleRegion,
     285                 :                                                 const nsRegion& aRegion)
     286                 : {
     287               0 :   if (aRegion.IsEmpty())
     288               0 :     return;
     289                 : 
     290               0 :   nsRegion tmp;
     291               0 :   tmp.Sub(*aVisibleRegion, aRegion);
     292                 :   // Don't let *aVisibleRegion get too complex, but don't let it fluff out
     293                 :   // to its bounds either, which can be very bad (see bug 516740).
     294                 :   // Do let aVisibleRegion get more complex if by doing so we reduce its
     295                 :   // area by at least half.
     296               0 :   if (GetAccurateVisibleRegions() || tmp.GetNumRects() <= 15 ||
     297               0 :       RegionArea(tmp) <= RegionArea(*aVisibleRegion)/2) {
     298               0 :     *aVisibleRegion = tmp;
     299                 :   }
     300                 : }
     301                 : 
     302                 : nsCaret *
     303               0 : nsDisplayListBuilder::GetCaret() {
     304               0 :   nsRefPtr<nsCaret> caret = CurrentPresShellState()->mPresShell->GetCaret();
     305               0 :   return caret;
     306                 : }
     307                 : 
     308                 : void
     309               0 : nsDisplayListBuilder::EnterPresShell(nsIFrame* aReferenceFrame,
     310                 :                                      const nsRect& aDirtyRect) {
     311               0 :   PresShellState* state = mPresShellStates.AppendElement();
     312               0 :   if (!state)
     313               0 :     return;
     314               0 :   state->mPresShell = aReferenceFrame->PresContext()->PresShell();
     315               0 :   state->mCaretFrame = nsnull;
     316               0 :   state->mFirstFrameMarkedForDisplay = mFramesMarkedForDisplay.Length();
     317                 : 
     318               0 :   state->mPresShell->UpdateCanvasBackground();
     319                 : 
     320               0 :   if (mIsPaintingToWindow) {
     321               0 :     mReferenceFrame->AddPaintedPresShell(state->mPresShell);
     322                 :     
     323               0 :     state->mPresShell->IncrementPaintCount();
     324                 :   }
     325                 : 
     326               0 :   bool buildCaret = mBuildCaret;
     327               0 :   if (mIgnoreSuppression || !state->mPresShell->IsPaintingSuppressed()) {
     328               0 :     if (state->mPresShell->IsPaintingSuppressed()) {
     329               0 :       mHadToIgnoreSuppression = true;
     330                 :     }
     331               0 :     state->mIsBackgroundOnly = false;
     332                 :   } else {
     333               0 :     state->mIsBackgroundOnly = true;
     334               0 :     buildCaret = false;
     335                 :   }
     336                 : 
     337               0 :   if (!buildCaret)
     338               0 :     return;
     339                 : 
     340               0 :   nsRefPtr<nsCaret> caret = state->mPresShell->GetCaret();
     341               0 :   state->mCaretFrame = caret->GetCaretFrame();
     342                 : 
     343               0 :   if (state->mCaretFrame) {
     344                 :     // Check if the dirty rect intersects with the caret's dirty rect.
     345                 :     nsRect caretRect =
     346               0 :       caret->GetCaretRect() + state->mCaretFrame->GetOffsetTo(aReferenceFrame);
     347               0 :     if (caretRect.Intersects(aDirtyRect)) {
     348                 :       // Okay, our rects intersect, let's mark the frame and all of its ancestors.
     349               0 :       mFramesMarkedForDisplay.AppendElement(state->mCaretFrame);
     350               0 :       MarkFrameForDisplay(state->mCaretFrame, nsnull);
     351                 :     }
     352                 :   }
     353                 : }
     354                 : 
     355                 : void
     356               0 : nsDisplayListBuilder::LeavePresShell(nsIFrame* aReferenceFrame,
     357                 :                                      const nsRect& aDirtyRect) {
     358               0 :   if (CurrentPresShellState()->mPresShell != aReferenceFrame->PresContext()->PresShell()) {
     359                 :     // Must have not allocated a state for this presshell, presumably due
     360                 :     // to OOM.
     361               0 :     return;
     362                 :   }
     363                 : 
     364                 :   // Unmark and pop off the frames marked for display in this pres shell.
     365               0 :   PRUint32 firstFrameForShell = CurrentPresShellState()->mFirstFrameMarkedForDisplay;
     366               0 :   for (PRUint32 i = firstFrameForShell;
     367               0 :        i < mFramesMarkedForDisplay.Length(); ++i) {
     368               0 :     UnmarkFrameForDisplay(mFramesMarkedForDisplay[i]);
     369                 :   }
     370               0 :   mFramesMarkedForDisplay.SetLength(firstFrameForShell);
     371               0 :   mPresShellStates.SetLength(mPresShellStates.Length() - 1);
     372                 : }
     373                 : 
     374                 : void
     375               0 : nsDisplayListBuilder::MarkFramesForDisplayList(nsIFrame* aDirtyFrame,
     376                 :                                                const nsFrameList& aFrames,
     377                 :                                                const nsRect& aDirtyRect) {
     378               0 :   for (nsFrameList::Enumerator e(aFrames); !e.AtEnd(); e.Next()) {
     379               0 :     mFramesMarkedForDisplay.AppendElement(e.get());
     380               0 :     MarkOutOfFlowFrameForDisplay(aDirtyFrame, e.get(), aDirtyRect);
     381                 :   }
     382               0 : }
     383                 : 
     384                 : void*
     385               0 : nsDisplayListBuilder::Allocate(size_t aSize) {
     386                 :   void *tmp;
     387               0 :   PL_ARENA_ALLOCATE(tmp, &mPool, aSize);
     388               0 :   return tmp;
     389                 : }
     390                 : 
     391               0 : void nsDisplayListSet::MoveTo(const nsDisplayListSet& aDestination) const
     392                 : {
     393               0 :   aDestination.BorderBackground()->AppendToTop(BorderBackground());
     394               0 :   aDestination.BlockBorderBackgrounds()->AppendToTop(BlockBorderBackgrounds());
     395               0 :   aDestination.Floats()->AppendToTop(Floats());
     396               0 :   aDestination.Content()->AppendToTop(Content());
     397               0 :   aDestination.PositionedDescendants()->AppendToTop(PositionedDescendants());
     398               0 :   aDestination.Outlines()->AppendToTop(Outlines());
     399               0 : }
     400                 : 
     401                 : void
     402               0 : nsDisplayList::FlattenTo(nsTArray<nsDisplayItem*>* aElements) {
     403                 :   nsDisplayItem* item;
     404               0 :   while ((item = RemoveBottom()) != nsnull) {
     405               0 :     if (item->GetType() == nsDisplayItem::TYPE_WRAP_LIST) {
     406               0 :       item->GetList()->FlattenTo(aElements);
     407               0 :       item->~nsDisplayItem();
     408                 :     } else {
     409               0 :       aElements->AppendElement(item);
     410                 :     }
     411                 :   }
     412               0 : }
     413                 : 
     414                 : nsRect
     415               0 : nsDisplayList::GetBounds(nsDisplayListBuilder* aBuilder) const {
     416               0 :   nsRect bounds;
     417               0 :   for (nsDisplayItem* i = GetBottom(); i != nsnull; i = i->GetAbove()) {
     418               0 :     bounds.UnionRect(bounds, i->GetBounds(aBuilder));
     419                 :   }
     420                 :   return bounds;
     421                 : }
     422                 : 
     423                 : bool
     424               0 : nsDisplayList::ComputeVisibilityForRoot(nsDisplayListBuilder* aBuilder,
     425                 :                                         nsRegion* aVisibleRegion) {
     426               0 :   nsRegion r;
     427               0 :   r.And(*aVisibleRegion, GetBounds(aBuilder));
     428               0 :   return ComputeVisibilityForSublist(aBuilder, aVisibleRegion, r.GetBounds(), r.GetBounds());
     429                 : }
     430                 : 
     431                 : static nsRegion
     432               0 : TreatAsOpaque(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder,
     433                 :               bool* aTransparentBackground)
     434                 : {
     435               0 :   nsRegion opaque = aItem->GetOpaqueRegion(aBuilder, aTransparentBackground);
     436               0 :   if (aBuilder->IsForPluginGeometry()) {
     437                 :     // Treat all chrome items as opaque, unless their frames are opacity:0.
     438                 :     // Since opacity:0 frames generate an nsDisplayOpacity, that item will
     439                 :     // not be treated as opaque here, so opacity:0 chrome content will be
     440                 :     // effectively ignored, as it should be.
     441               0 :     nsIFrame* f = aItem->GetUnderlyingFrame();
     442               0 :     if (f && f->PresContext()->IsChrome() && f->GetStyleDisplay()->mOpacity != 0.0) {
     443               0 :       opaque = aItem->GetBounds(aBuilder);
     444                 :     }
     445                 :   }
     446                 :   return opaque;
     447                 : }
     448                 : 
     449                 : static nsRect
     450               0 : GetDisplayPortBounds(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem)
     451                 : {
     452                 :   // GetDisplayPortBounds() rectangle is used in order to restrict fixed aItem's
     453                 :   // visible bounds. nsDisplayTransform bounds already take item's
     454                 :   // transform into account, so there is no need to apply it here one more time.
     455                 :   // Start TransformRectToBoundsInAncestor() calculations from aItem's frame
     456                 :   // parent in this case.
     457               0 :   nsIFrame* frame = aItem->GetUnderlyingFrame();
     458               0 :   if (aItem->GetType() == nsDisplayItem::TYPE_TRANSFORM) {
     459               0 :     frame = nsLayoutUtils::GetCrossDocParentFrame(frame);
     460                 :   }
     461                 : 
     462               0 :   const nsRect* displayport = aBuilder->GetDisplayPort();
     463                 :   nsRect result = nsLayoutUtils::TransformAncestorRectToFrame(
     464                 :                     frame,
     465               0 :                     nsRect(0, 0, displayport->width, displayport->height),
     466               0 :                     aBuilder->ReferenceFrame());
     467               0 :   result.MoveBy(aBuilder->ToReferenceFrame(frame));
     468                 :   return result;
     469                 : }
     470                 : 
     471                 : bool
     472               0 : nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
     473                 :                                            nsRegion* aVisibleRegion,
     474                 :                                            const nsRect& aListVisibleBounds,
     475                 :                                            const nsRect& aAllowVisibleRegionExpansion) {
     476                 : #ifdef DEBUG
     477               0 :   nsRegion r;
     478               0 :   r.And(*aVisibleRegion, GetBounds(aBuilder));
     479               0 :   NS_ASSERTION(r.GetBounds().IsEqualInterior(aListVisibleBounds),
     480                 :                "bad aListVisibleBounds");
     481                 : #endif
     482               0 :   mVisibleRect = aListVisibleBounds;
     483               0 :   bool anyVisible = false;
     484                 : 
     485               0 :   nsAutoTArray<nsDisplayItem*, 512> elements;
     486               0 :   FlattenTo(&elements);
     487                 : 
     488               0 :   bool forceTransparentSurface = false;
     489                 : 
     490               0 :   for (PRInt32 i = elements.Length() - 1; i >= 0; --i) {
     491               0 :     nsDisplayItem* item = elements[i];
     492               0 :     nsDisplayItem* belowItem = i < 1 ? nsnull : elements[i - 1];
     493                 : 
     494               0 :     if (belowItem && item->TryMerge(aBuilder, belowItem)) {
     495               0 :       belowItem->~nsDisplayItem();
     496               0 :       elements.ReplaceElementsAt(i - 1, 1, item);
     497               0 :       continue;
     498                 :     }
     499                 : 
     500               0 :     nsDisplayList* list = item->GetList();
     501               0 :     if (list && item->ShouldFlattenAway(aBuilder)) {
     502                 :       // The elements on the list >= i no longer serve any use.
     503               0 :       elements.SetLength(i);
     504               0 :       list->FlattenTo(&elements);
     505               0 :       i = elements.Length();
     506               0 :       item->~nsDisplayItem();
     507               0 :       continue;
     508                 :     }
     509                 : 
     510               0 :     nsRect bounds = item->GetBounds(aBuilder);
     511                 : 
     512               0 :     nsRegion itemVisible;
     513               0 :     if (ForceVisiblityForFixedItem(aBuilder, item)) {
     514               0 :       itemVisible.And(GetDisplayPortBounds(aBuilder, item), bounds);
     515                 :     } else {
     516               0 :       itemVisible.And(*aVisibleRegion, bounds);
     517                 :     }
     518               0 :     item->mVisibleRect = itemVisible.GetBounds();
     519                 : 
     520               0 :     if (item->ComputeVisibility(aBuilder, aVisibleRegion, aAllowVisibleRegionExpansion)) {
     521               0 :       anyVisible = true;
     522               0 :       bool transparentBackground = false;
     523               0 :       nsRegion opaque = TreatAsOpaque(item, aBuilder, &transparentBackground);
     524                 :       // Subtract opaque item from the visible region
     525               0 :       aBuilder->SubtractFromVisibleRegion(aVisibleRegion, opaque);
     526               0 :       forceTransparentSurface = forceTransparentSurface || transparentBackground;
     527                 :     }
     528               0 :     AppendToBottom(item);
     529                 :   }
     530                 : 
     531               0 :   mIsOpaque = !aVisibleRegion->Intersects(mVisibleRect);
     532               0 :   mForceTransparentSurface = forceTransparentSurface;
     533                 : #ifdef DEBUG
     534               0 :   mDidComputeVisibility = true;
     535                 : #endif
     536               0 :   return anyVisible;
     537                 : }
     538                 : 
     539               0 : void nsDisplayList::PaintRoot(nsDisplayListBuilder* aBuilder,
     540                 :                               nsRenderingContext* aCtx,
     541                 :                               PRUint32 aFlags) const {
     542               0 :   PaintForFrame(aBuilder, aCtx, aBuilder->ReferenceFrame(), aFlags);
     543               0 : }
     544                 : 
     545                 : /**
     546                 :  * We paint by executing a layer manager transaction, constructing a
     547                 :  * single layer representing the display list, and then making it the
     548                 :  * root of the layer manager, drawing into the ThebesLayers.
     549                 :  */
     550               0 : void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
     551                 :                                   nsRenderingContext* aCtx,
     552                 :                                   nsIFrame* aForFrame,
     553                 :                                   PRUint32 aFlags) const {
     554               0 :   NS_ASSERTION(mDidComputeVisibility,
     555                 :                "Must call ComputeVisibility before calling Paint");
     556                 : 
     557               0 :   nsRefPtr<LayerManager> layerManager;
     558               0 :   bool allowRetaining = false;
     559               0 :   bool doBeginTransaction = true;
     560               0 :   if (aFlags & PAINT_USE_WIDGET_LAYERS) {
     561               0 :     nsIFrame* referenceFrame = aBuilder->ReferenceFrame();
     562               0 :     NS_ASSERTION(referenceFrame == nsLayoutUtils::GetDisplayRootFrame(referenceFrame),
     563                 :                  "Reference frame must be a display root for us to use the layer manager");
     564               0 :     nsIWidget* window = referenceFrame->GetNearestWidget();
     565               0 :     if (window) {
     566               0 :       layerManager = window->GetLayerManager(&allowRetaining);
     567               0 :       if (layerManager) {
     568               0 :         doBeginTransaction = !(aFlags & PAINT_EXISTING_TRANSACTION);
     569                 :       }
     570                 :     }
     571                 :   }
     572               0 :   if (!layerManager) {
     573               0 :     if (!aCtx) {
     574               0 :       NS_WARNING("Nowhere to paint into");
     575                 :       return;
     576                 :     }
     577               0 :     layerManager = new BasicLayerManager();
     578                 :   }
     579                 : 
     580               0 :   if (aFlags & PAINT_FLUSH_LAYERS) {
     581               0 :     FrameLayerBuilder::InvalidateAllLayers(layerManager);
     582                 :   }
     583                 : 
     584               0 :   if (doBeginTransaction) {
     585               0 :     if (aCtx) {
     586               0 :       layerManager->BeginTransactionWithTarget(aCtx->ThebesContext());
     587                 :     } else {
     588               0 :       layerManager->BeginTransaction();
     589                 :     }
     590                 :   }
     591               0 :   if (allowRetaining) {
     592               0 :     aBuilder->LayerBuilder()->DidBeginRetainedLayerTransaction(layerManager);
     593                 :   }
     594                 : 
     595               0 :   nsPresContext* presContext = aForFrame->PresContext();
     596               0 :   nsIPresShell* presShell = presContext->GetPresShell();
     597                 : 
     598                 :   nsDisplayItem::ContainerParameters containerParameters
     599               0 :     (presShell->GetXResolution(), presShell->GetYResolution());
     600                 :   nsRefPtr<ContainerLayer> root = aBuilder->LayerBuilder()->
     601                 :     BuildContainerLayerFor(aBuilder, layerManager, aForFrame, nsnull, *this,
     602               0 :                            containerParameters, nsnull);
     603               0 :   if (!root)
     604                 :     return;
     605                 :   // Root is being scaled up by the X/Y resolution. Scale it back down.
     606               0 :   gfx3DMatrix rootTransform = root->GetTransform()*
     607                 :     gfx3DMatrix::ScalingMatrix(1.0f/containerParameters.mXScale,
     608               0 :                                1.0f/containerParameters.mYScale, 1.0f);
     609               0 :   root->SetTransform(rootTransform);
     610                 : 
     611               0 :   ViewID id = presContext->IsRootContentDocument() ? FrameMetrics::ROOT_SCROLL_ID
     612               0 :                                                    : FrameMetrics::NULL_SCROLL_ID;
     613                 : 
     614               0 :   nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
     615               0 :   nsRect displayport;
     616               0 :   bool usingDisplayport = false;
     617               0 :   if (rootScrollFrame) {
     618               0 :     nsIContent* content = rootScrollFrame->GetContent();
     619               0 :     if (content) {
     620               0 :       usingDisplayport = nsLayoutUtils::GetDisplayPort(content, &displayport);
     621                 :     }
     622                 :   }
     623                 :   RecordFrameMetrics(aForFrame, rootScrollFrame,
     624                 :                      root, mVisibleRect, mVisibleRect,
     625                 :                      (usingDisplayport ? &displayport : nsnull), id,
     626               0 :                      containerParameters);
     627               0 :   if (usingDisplayport &&
     628               0 :       !(root->GetContentFlags() & Layer::CONTENT_OPAQUE)) {
     629                 :     // See bug 693938, attachment 567017
     630               0 :     NS_WARNING("We don't support transparent content with displayports, force it to be opqaue");
     631               0 :     root->SetContentFlags(Layer::CONTENT_OPAQUE);
     632                 :   }
     633                 : 
     634               0 :   layerManager->SetRoot(root);
     635               0 :   aBuilder->LayerBuilder()->WillEndTransaction(layerManager);
     636               0 :   layerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer,
     637               0 :                                aBuilder);
     638               0 :   aBuilder->LayerBuilder()->DidEndTransaction(layerManager);
     639                 : 
     640               0 :   if (aFlags & PAINT_FLUSH_LAYERS) {
     641               0 :     FrameLayerBuilder::InvalidateAllLayers(layerManager);
     642                 :   }
     643                 : 
     644               0 :   nsCSSRendering::DidPaint();
     645                 : }
     646                 : 
     647               0 : PRUint32 nsDisplayList::Count() const {
     648               0 :   PRUint32 count = 0;
     649               0 :   for (nsDisplayItem* i = GetBottom(); i; i = i->GetAbove()) {
     650               0 :     ++count;
     651                 :   }
     652               0 :   return count;
     653                 : }
     654                 : 
     655               0 : nsDisplayItem* nsDisplayList::RemoveBottom() {
     656               0 :   nsDisplayItem* item = mSentinel.mAbove;
     657               0 :   if (!item)
     658               0 :     return nsnull;
     659               0 :   mSentinel.mAbove = item->mAbove;
     660               0 :   if (item == mTop) {
     661                 :     // must have been the only item
     662               0 :     mTop = &mSentinel;
     663                 :   }
     664               0 :   item->mAbove = nsnull;
     665               0 :   return item;
     666                 : }
     667                 : 
     668               0 : void nsDisplayList::DeleteAll() {
     669                 :   nsDisplayItem* item;
     670               0 :   while ((item = RemoveBottom()) != nsnull) {
     671               0 :     item->~nsDisplayItem();
     672                 :   }
     673               0 : }
     674                 : 
     675                 : static bool
     676               0 : GetMouseThrough(const nsIFrame* aFrame)
     677                 : {
     678               0 :   if (!aFrame->IsBoxFrame())
     679               0 :     return false;
     680                 : 
     681               0 :   const nsIFrame* frame = aFrame;
     682               0 :   while (frame) {
     683               0 :     if (frame->GetStateBits() & NS_FRAME_MOUSE_THROUGH_ALWAYS) {
     684               0 :       return true;
     685               0 :     } else if (frame->GetStateBits() & NS_FRAME_MOUSE_THROUGH_NEVER) {
     686               0 :       return false;
     687                 :     }
     688               0 :     frame = frame->GetParentBox();
     689                 :   }
     690               0 :   return false;
     691                 : }
     692                 : 
     693                 : // A list of frames, and their z depth. Used for sorting
     694                 : // the results of hit testing.
     695                 : struct FramesWithDepth
     696               0 : {
     697               0 :   FramesWithDepth(float aDepth) :
     698               0 :     mDepth(aDepth)
     699               0 :   {}
     700                 : 
     701               0 :   bool operator<(const FramesWithDepth& aOther) const {
     702               0 :     if (mDepth != aOther.mDepth) {
     703                 :       // We want to sort so that the shallowest item (highest depth value) is first
     704               0 :       return mDepth > aOther.mDepth;
     705                 :     }
     706               0 :     return this < &aOther;
     707                 :   }
     708               0 :   bool operator==(const FramesWithDepth& aOther) const {
     709               0 :     return this == &aOther;
     710                 :   }
     711                 : 
     712                 :   float mDepth;
     713                 :   nsTArray<nsIFrame*> mFrames;
     714                 : };
     715                 : 
     716                 : // Sort the frames by depth and then moves all the contained frames to the destination
     717               0 : void FlushFramesArray(nsTArray<FramesWithDepth>& aSource, nsTArray<nsIFrame*>* aDest)
     718                 : {
     719               0 :   if (aSource.IsEmpty()) {
     720               0 :     return;
     721                 :   }
     722               0 :   aSource.Sort();
     723               0 :   PRUint32 length = aSource.Length();
     724               0 :   for (PRUint32 i = 0; i < length; i++) {
     725               0 :     aDest->MoveElementsFrom(aSource[i].mFrames);
     726                 :   }
     727               0 :   aSource.Clear();
     728                 : }
     729                 : 
     730               0 : void nsDisplayList::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
     731                 :                             nsDisplayItem::HitTestState* aState,
     732                 :                             nsTArray<nsIFrame*> *aOutFrames) const {
     733               0 :   PRInt32 itemBufferStart = aState->mItemBuffer.Length();
     734                 :   nsDisplayItem* item;
     735               0 :   for (item = GetBottom(); item; item = item->GetAbove()) {
     736               0 :     aState->mItemBuffer.AppendElement(item);
     737                 :   }
     738               0 :   nsAutoTArray<FramesWithDepth, 16> temp;
     739               0 :   for (PRInt32 i = aState->mItemBuffer.Length() - 1; i >= itemBufferStart; --i) {
     740                 :     // Pop element off the end of the buffer. We want to shorten the buffer
     741                 :     // so that recursive calls to HitTest have more buffer space.
     742               0 :     item = aState->mItemBuffer[i];
     743               0 :     aState->mItemBuffer.SetLength(i);
     744                 : 
     745               0 :     if (aRect.Intersects(item->GetBounds(aBuilder))) {
     746               0 :       nsAutoTArray<nsIFrame*, 16> outFrames;
     747               0 :       item->HitTest(aBuilder, aRect, aState, &outFrames);
     748                 :       
     749                 :       // For 3d transforms with preserve-3d we add hit frames into the temp list 
     750                 :       // so we can sort them later, otherwise we add them directly to the output list.
     751               0 :       nsTArray<nsIFrame*> *writeFrames = aOutFrames;
     752               0 :       if (item->GetType() == nsDisplayItem::TYPE_TRANSFORM &&
     753               0 :           item->GetUnderlyingFrame()->Preserves3D()) {
     754               0 :         if (outFrames.Length()) {
     755               0 :           nsDisplayTransform *transform = static_cast<nsDisplayTransform*>(item);
     756               0 :           nsPoint point = aRect.TopLeft();
     757                 :           // A 1x1 rect means a point, otherwise use the center of the rect
     758               0 :           if (aRect.width != 1 || aRect.height != 1) {
     759               0 :             point = aRect.Center();
     760                 :           }
     761               0 :           temp.AppendElement(FramesWithDepth(transform->GetHitDepthAtPoint(point)));
     762               0 :           writeFrames = &temp[temp.Length() - 1].mFrames;
     763                 :         }
     764                 :       } else {
     765                 :         // We may have just finished a run of consecutive preserve-3d transforms, 
     766                 :         // so flush these into the destination array before processing our frame list.
     767               0 :         FlushFramesArray(temp, aOutFrames);
     768                 :       }
     769                 : 
     770               0 :       for (PRUint32 j = 0; j < outFrames.Length(); j++) {
     771               0 :         nsIFrame *f = outFrames.ElementAt(j);
     772                 :         // Handle the XUL 'mousethrough' feature and 'pointer-events'.
     773               0 :         if (!GetMouseThrough(f) &&
     774               0 :             f->GetStyleVisibility()->mPointerEvents != NS_STYLE_POINTER_EVENTS_NONE) {
     775               0 :           writeFrames->AppendElement(f);
     776                 :         }
     777                 :       }
     778                 :     }
     779                 :   }
     780                 :   // Clear any remaining preserve-3d transforms.
     781               0 :   FlushFramesArray(temp, aOutFrames);
     782               0 :   NS_ASSERTION(aState->mItemBuffer.Length() == PRUint32(itemBufferStart),
     783                 :                "How did we forget to pop some elements?");
     784               0 : }
     785                 : 
     786               0 : static void Sort(nsDisplayList* aList, PRInt32 aCount, nsDisplayList::SortLEQ aCmp,
     787                 :                  void* aClosure) {
     788               0 :   if (aCount < 2)
     789               0 :     return;
     790                 : 
     791               0 :   nsDisplayList list1;
     792               0 :   nsDisplayList list2;
     793                 :   int i;
     794               0 :   PRInt32 half = aCount/2;
     795               0 :   bool sorted = true;
     796               0 :   nsDisplayItem* prev = nsnull;
     797               0 :   for (i = 0; i < aCount; ++i) {
     798               0 :     nsDisplayItem* item = aList->RemoveBottom();
     799               0 :     (i < half ? &list1 : &list2)->AppendToTop(item);
     800               0 :     if (sorted && prev && !aCmp(prev, item, aClosure)) {
     801               0 :       sorted = false;
     802                 :     }
     803               0 :     prev = item;
     804                 :   }
     805               0 :   if (sorted) {
     806               0 :     aList->AppendToTop(&list1);
     807               0 :     aList->AppendToTop(&list2);
     808                 :     return;
     809                 :   }
     810                 :   
     811               0 :   Sort(&list1, half, aCmp, aClosure);
     812               0 :   Sort(&list2, aCount - half, aCmp, aClosure);
     813                 : 
     814               0 :   for (i = 0; i < aCount; ++i) {
     815               0 :     if (list1.GetBottom() &&
     816               0 :         (!list2.GetBottom() ||
     817               0 :          aCmp(list1.GetBottom(), list2.GetBottom(), aClosure))) {
     818               0 :       aList->AppendToTop(list1.RemoveBottom());
     819                 :     } else {
     820               0 :       aList->AppendToTop(list2.RemoveBottom());
     821                 :     }
     822                 :   }
     823                 : }
     824                 : 
     825               0 : static bool IsContentLEQ(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
     826                 :                            void* aClosure) {
     827                 :   // These GetUnderlyingFrame calls return non-null because we're only used
     828                 :   // in sorting
     829                 :   return nsLayoutUtils::CompareTreePosition(
     830                 :       aItem1->GetUnderlyingFrame()->GetContent(),
     831                 :       aItem2->GetUnderlyingFrame()->GetContent(),
     832               0 :       static_cast<nsIContent*>(aClosure)) <= 0;
     833                 : }
     834                 : 
     835               0 : static bool IsZOrderLEQ(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
     836                 :                           void* aClosure) {
     837                 :   // These GetUnderlyingFrame calls return non-null because we're only used
     838                 :   // in sorting.  Note that we can't just take the difference of the two
     839                 :   // z-indices here, because that might overflow a 32-bit int.
     840               0 :   PRInt32 index1 = nsLayoutUtils::GetZIndex(aItem1->GetUnderlyingFrame());
     841               0 :   PRInt32 index2 = nsLayoutUtils::GetZIndex(aItem2->GetUnderlyingFrame());
     842               0 :   if (index1 == index2)
     843               0 :     return IsContentLEQ(aItem1, aItem2, aClosure);
     844               0 :   return index1 < index2;
     845                 : }
     846                 : 
     847               0 : void nsDisplayList::ExplodeAnonymousChildLists(nsDisplayListBuilder* aBuilder) {
     848                 :   // See if there's anything to do
     849               0 :   bool anyAnonymousItems = false;
     850                 :   nsDisplayItem* i;
     851               0 :   for (i = GetBottom(); i != nsnull; i = i->GetAbove()) {
     852               0 :     if (!i->GetUnderlyingFrame()) {
     853               0 :       anyAnonymousItems = true;
     854               0 :       break;
     855                 :     }
     856                 :   }
     857               0 :   if (!anyAnonymousItems)
     858               0 :     return;
     859                 : 
     860               0 :   nsDisplayList tmp;
     861               0 :   while ((i = RemoveBottom()) != nsnull) {
     862               0 :     if (i->GetUnderlyingFrame()) {
     863               0 :       tmp.AppendToTop(i);
     864                 :     } else {
     865               0 :       nsDisplayList* list = i->GetList();
     866               0 :       NS_ASSERTION(list, "leaf items can't be anonymous");
     867               0 :       list->ExplodeAnonymousChildLists(aBuilder);
     868                 :       nsDisplayItem* j;
     869               0 :       while ((j = list->RemoveBottom()) != nsnull) {
     870                 :         tmp.AppendToTop(static_cast<nsDisplayWrapList*>(i)->
     871               0 :             WrapWithClone(aBuilder, j));
     872                 :       }
     873               0 :       i->~nsDisplayItem();
     874                 :     }
     875                 :   }
     876                 :   
     877               0 :   AppendToTop(&tmp);
     878                 : }
     879                 : 
     880               0 : void nsDisplayList::SortByZOrder(nsDisplayListBuilder* aBuilder,
     881                 :                                  nsIContent* aCommonAncestor) {
     882               0 :   Sort(aBuilder, IsZOrderLEQ, aCommonAncestor);
     883               0 : }
     884                 : 
     885               0 : void nsDisplayList::SortByContentOrder(nsDisplayListBuilder* aBuilder,
     886                 :                                        nsIContent* aCommonAncestor) {
     887               0 :   Sort(aBuilder, IsContentLEQ, aCommonAncestor);
     888               0 : }
     889                 : 
     890               0 : void nsDisplayList::Sort(nsDisplayListBuilder* aBuilder,
     891                 :                          SortLEQ aCmp, void* aClosure) {
     892               0 :   ExplodeAnonymousChildLists(aBuilder);
     893               0 :   ::Sort(this, Count(), aCmp, aClosure);
     894               0 : }
     895                 : 
     896               0 : bool nsDisplayItem::RecomputeVisibility(nsDisplayListBuilder* aBuilder,
     897                 :                                           nsRegion* aVisibleRegion) {
     898               0 :   nsRect bounds = GetBounds(aBuilder);
     899                 : 
     900               0 :   nsRegion itemVisible;
     901               0 :   if (ForceVisiblityForFixedItem(aBuilder, this)) {
     902               0 :     itemVisible.And(GetDisplayPortBounds(aBuilder, this), bounds);
     903                 :   } else {
     904               0 :     itemVisible.And(*aVisibleRegion, bounds);
     905                 :   }
     906               0 :   mVisibleRect = itemVisible.GetBounds();
     907                 : 
     908                 :   // When we recompute visibility within layers we don't need to
     909                 :   // expand the visible region for content behind plugins (the plugin
     910                 :   // is not in the layer).
     911               0 :   if (!ComputeVisibility(aBuilder, aVisibleRegion, nsRect()))
     912               0 :     return false;
     913                 : 
     914                 :   bool forceTransparentBackground;
     915               0 :   nsRegion opaque = TreatAsOpaque(this, aBuilder, &forceTransparentBackground);
     916               0 :   aBuilder->SubtractFromVisibleRegion(aVisibleRegion, opaque);
     917               0 :   return true;
     918                 : }
     919                 : 
     920                 : // Note that even if the rectangle we draw and snap is smaller than aRect,
     921                 : // it's OK to call this to get a bounding rect for what we'll draw, because
     922                 : // snapping a rectangle which is contained in R always gives you a
     923                 : // rectangle which is contained in the snapped R.
     924                 : static nsRect
     925               0 : SnapBounds(bool aSnappingEnabled, nsPresContext* aPresContext,
     926                 :            const nsRect& aRect) {
     927               0 :   nsRect r = aRect;
     928               0 :   if (aSnappingEnabled) {
     929               0 :     nscoord appUnitsPerDevPixel = aPresContext->AppUnitsPerDevPixel();
     930               0 :     r = r.ToNearestPixels(appUnitsPerDevPixel).ToAppUnits(appUnitsPerDevPixel);
     931                 :   }
     932                 :   return r;
     933                 : }
     934                 : 
     935                 : nsRect
     936               0 : nsDisplaySolidColor::GetBounds(nsDisplayListBuilder* aBuilder)
     937                 : {
     938               0 :   nsPresContext* presContext = mFrame->PresContext();
     939               0 :   return SnapBounds(mSnappingEnabled, presContext, mBounds);
     940                 : }
     941                 : 
     942                 : void
     943               0 : nsDisplaySolidColor::Paint(nsDisplayListBuilder* aBuilder,
     944                 :                            nsRenderingContext* aCtx)
     945                 : {
     946               0 :   aCtx->SetColor(mColor);
     947               0 :   aCtx->FillRect(mVisibleRect);
     948               0 : }
     949                 : 
     950                 : static void
     951               0 : RegisterThemeGeometry(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
     952                 : {
     953               0 :   nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(aFrame);
     954                 : 
     955               0 :   for (nsIFrame* f = aFrame; f; f = f->GetParent()) {
     956                 :     // Bail out if we're in a transformed subtree
     957               0 :     if (f->IsTransformed())
     958               0 :       return;
     959                 :     // Bail out if we're not in the displayRoot's document
     960               0 :     if (!f->GetParent() && f != displayRoot)
     961               0 :       return;
     962                 :   }
     963                 : 
     964               0 :   nsRect borderBox(aFrame->GetOffsetTo(displayRoot), aFrame->GetSize());
     965               0 :   aBuilder->RegisterThemeGeometry(aFrame->GetStyleDisplay()->mAppearance,
     966               0 :       borderBox.ToNearestPixels(aFrame->PresContext()->AppUnitsPerDevPixel()));
     967                 : }
     968                 : 
     969               0 : nsDisplayBackground::nsDisplayBackground(nsDisplayListBuilder* aBuilder,
     970                 :                                          nsIFrame* aFrame)
     971                 :   : nsDisplayItem(aBuilder, aFrame),
     972               0 :     mSnappingEnabled(aBuilder->IsSnappingEnabled() && !aBuilder->IsInTransform())
     973                 : {
     974               0 :   MOZ_COUNT_CTOR(nsDisplayBackground);
     975               0 :   const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
     976               0 :   mIsThemed = mFrame->IsThemed(disp, &mThemeTransparency);
     977                 : 
     978               0 :   if (mIsThemed) {
     979                 :     // Perform necessary RegisterThemeGeometry
     980               0 :     if (disp->mAppearance == NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR ||
     981                 :         disp->mAppearance == NS_THEME_TOOLBAR) {
     982               0 :       RegisterThemeGeometry(aBuilder, aFrame);
     983                 :     }
     984                 :   } else {
     985                 :     // Set HasFixedItems if we construct a background-attachment:fixed item
     986               0 :     nsPresContext* presContext = mFrame->PresContext();
     987                 :     nsStyleContext* bgSC;
     988               0 :     bool hasBG = nsCSSRendering::FindBackground(presContext, mFrame, &bgSC);
     989               0 :     if (hasBG && bgSC->GetStyleBackground()->HasFixedBackground()) {
     990               0 :       aBuilder->SetHasFixedItems();
     991                 :     }
     992                 :   }
     993               0 : }
     994                 : 
     995                 : // Helper for RoundedRectIntersectsRect.
     996                 : static bool
     997               0 : CheckCorner(nscoord aXOffset, nscoord aYOffset,
     998                 :             nscoord aXRadius, nscoord aYRadius)
     999                 : {
    1000               0 :   NS_ABORT_IF_FALSE(aXOffset > 0 && aYOffset > 0,
    1001                 :                     "must not pass nonpositives to CheckCorner");
    1002               0 :   NS_ABORT_IF_FALSE(aXRadius >= 0 && aYRadius >= 0,
    1003                 :                     "must not pass negatives to CheckCorner");
    1004                 : 
    1005                 :   // Avoid floating point math unless we're either (1) within the
    1006                 :   // quarter-ellipse area at the rounded corner or (2) outside the
    1007                 :   // rounding.
    1008               0 :   if (aXOffset >= aXRadius || aYOffset >= aYRadius)
    1009               0 :     return true;
    1010                 : 
    1011                 :   // Convert coordinates to a unit circle with (0,0) as the center of
    1012                 :   // curvature, and see if we're inside the circle or outside.
    1013               0 :   float scaledX = float(aXRadius - aXOffset) / float(aXRadius);
    1014               0 :   float scaledY = float(aYRadius - aYOffset) / float(aYRadius);
    1015               0 :   return scaledX * scaledX + scaledY * scaledY < 1.0f;
    1016                 : }
    1017                 : 
    1018                 : 
    1019                 : /**
    1020                 :  * Return whether any part of aTestRect is inside of the rounded
    1021                 :  * rectangle formed by aBounds and aRadii (which are indexed by the
    1022                 :  * NS_CORNER_* constants in nsStyleConsts.h).
    1023                 :  *
    1024                 :  * See also RoundedRectContainsRect.
    1025                 :  */
    1026                 : static bool
    1027               0 : RoundedRectIntersectsRect(const nsRect& aRoundedRect, nscoord aRadii[8],
    1028                 :                           const nsRect& aTestRect)
    1029                 : {
    1030               0 :   NS_ABORT_IF_FALSE(aTestRect.Intersects(aRoundedRect),
    1031                 :                     "we should already have tested basic rect intersection");
    1032                 : 
    1033                 :   // distances from this edge of aRoundedRect to opposite edge of aTestRect,
    1034                 :   // which we know are positive due to the Intersects check above.
    1035               0 :   nsMargin insets;
    1036               0 :   insets.top = aTestRect.YMost() - aRoundedRect.y;
    1037               0 :   insets.right = aRoundedRect.XMost() - aTestRect.x;
    1038               0 :   insets.bottom = aRoundedRect.YMost() - aTestRect.y;
    1039               0 :   insets.left = aTestRect.XMost() - aRoundedRect.x;
    1040                 : 
    1041                 :   // Check whether the bottom-right corner of aTestRect is inside the
    1042                 :   // top left corner of aBounds when rounded by aRadii, etc.  If any
    1043                 :   // corner is not, then fail; otherwise succeed.
    1044                 :   return CheckCorner(insets.left, insets.top,
    1045                 :                      aRadii[NS_CORNER_TOP_LEFT_X],
    1046               0 :                      aRadii[NS_CORNER_TOP_LEFT_Y]) &&
    1047                 :          CheckCorner(insets.right, insets.top,
    1048               0 :                      aRadii[NS_CORNER_TOP_RIGHT_X],
    1049               0 :                      aRadii[NS_CORNER_TOP_RIGHT_Y]) &&
    1050                 :          CheckCorner(insets.right, insets.bottom,
    1051               0 :                      aRadii[NS_CORNER_BOTTOM_RIGHT_X],
    1052               0 :                      aRadii[NS_CORNER_BOTTOM_RIGHT_Y]) &&
    1053                 :          CheckCorner(insets.left, insets.bottom,
    1054               0 :                      aRadii[NS_CORNER_BOTTOM_LEFT_X],
    1055               0 :                      aRadii[NS_CORNER_BOTTOM_LEFT_Y]);
    1056                 : }
    1057                 : 
    1058                 : // Check that the rounded border of aFrame, added to aToReferenceFrame,
    1059                 : // intersects aRect.  Assumes that the unrounded border has already
    1060                 : // been checked for intersection.
    1061                 : static bool
    1062               0 : RoundedBorderIntersectsRect(nsIFrame* aFrame,
    1063                 :                             const nsPoint& aFrameToReferenceFrame,
    1064                 :                             const nsRect& aTestRect)
    1065                 : {
    1066               0 :   if (!nsRect(aFrameToReferenceFrame, aFrame->GetSize()).Intersects(aTestRect))
    1067               0 :     return false;
    1068                 : 
    1069                 :   nscoord radii[8];
    1070               0 :   return !aFrame->GetBorderRadii(radii) ||
    1071                 :          RoundedRectIntersectsRect(nsRect(aFrameToReferenceFrame,
    1072               0 :                                           aFrame->GetSize()),
    1073               0 :                                    radii, aTestRect);
    1074                 : }
    1075                 : 
    1076                 : // Returns TRUE if aContainedRect is guaranteed to be contained in
    1077                 : // the rounded rect defined by aRoundedRect and aRadii. Complex cases are
    1078                 : // handled conservatively by returning FALSE in some situations where
    1079                 : // a more thorough analysis could return TRUE.
    1080                 : //
    1081                 : // See also RoundedRectIntersectsRect.
    1082               0 : static bool RoundedRectContainsRect(const nsRect& aRoundedRect,
    1083                 :                                       const nscoord aRadii[8],
    1084                 :                                       const nsRect& aContainedRect) {
    1085               0 :   nsRegion rgn = nsLayoutUtils::RoundedRectIntersectRect(aRoundedRect, aRadii, aContainedRect);
    1086               0 :   return rgn.Contains(aContainedRect);
    1087                 : }
    1088                 : 
    1089                 : void
    1090               0 : nsDisplayBackground::HitTest(nsDisplayListBuilder* aBuilder,
    1091                 :                              const nsRect& aRect,
    1092                 :                              HitTestState* aState,
    1093                 :                              nsTArray<nsIFrame*> *aOutFrames)
    1094                 : {
    1095               0 :   if (mIsThemed) {
    1096                 :     // For theme backgrounds, assume that any point in our border rect is a hit.
    1097               0 :     if (!nsRect(ToReferenceFrame(), mFrame->GetSize()).Intersects(aRect))
    1098               0 :       return;
    1099                 :   } else {
    1100               0 :     if (!RoundedBorderIntersectsRect(mFrame, ToReferenceFrame(), aRect)) {
    1101                 :       // aRect doesn't intersect our border-radius curve.
    1102               0 :       return;
    1103                 :     }
    1104                 :   }
    1105                 : 
    1106               0 :   aOutFrames->AppendElement(mFrame);
    1107                 : }
    1108                 : 
    1109                 : bool
    1110               0 : nsDisplayBackground::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    1111                 :                                        nsRegion* aVisibleRegion,
    1112                 :                                        const nsRect& aAllowVisibleRegionExpansion)
    1113                 : {
    1114               0 :   if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
    1115               0 :                                         aAllowVisibleRegionExpansion)) {
    1116               0 :     return false;
    1117                 :   }
    1118                 : 
    1119                 :   // Return false if the background was propagated away from this
    1120                 :   // frame. We don't want this display item to show up and confuse
    1121                 :   // anything.
    1122                 :   nsStyleContext* bgSC;
    1123                 :   return mIsThemed ||
    1124               0 :     nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bgSC);
    1125                 : }
    1126                 : 
    1127                 : nsRegion
    1128               0 : nsDisplayBackground::GetInsideClipRegion(nsPresContext* aPresContext,
    1129                 :                                          PRUint8 aClip, const nsRect& aRect)
    1130                 : {
    1131               0 :   nsRegion result;
    1132               0 :   if (aRect.IsEmpty())
    1133               0 :     return result;
    1134                 : 
    1135                 :   nscoord radii[8];
    1136               0 :   nsRect clipRect;
    1137                 :   bool haveRadii;
    1138               0 :   switch (aClip) {
    1139                 :   case NS_STYLE_BG_CLIP_BORDER:
    1140               0 :     haveRadii = mFrame->GetBorderRadii(radii);
    1141               0 :     clipRect = nsRect(ToReferenceFrame(), mFrame->GetSize());
    1142               0 :     break;
    1143                 :   case NS_STYLE_BG_CLIP_PADDING:
    1144               0 :     haveRadii = mFrame->GetPaddingBoxBorderRadii(radii);
    1145               0 :     clipRect = mFrame->GetPaddingRect() - mFrame->GetPosition() + ToReferenceFrame();
    1146               0 :     break;
    1147                 :   case NS_STYLE_BG_CLIP_CONTENT:
    1148               0 :     haveRadii = mFrame->GetContentBoxBorderRadii(radii);
    1149               0 :     clipRect = mFrame->GetContentRect() - mFrame->GetPosition() + ToReferenceFrame();
    1150               0 :     break;
    1151                 :   default:
    1152               0 :     NS_NOTREACHED("Unknown clip type");
    1153                 :     return result;
    1154                 :   }
    1155                 : 
    1156               0 :   nsRect inputRect = SnapBounds(mSnappingEnabled, aPresContext, aRect);
    1157               0 :   clipRect = SnapBounds(mSnappingEnabled, aPresContext, clipRect);
    1158                 : 
    1159               0 :   if (haveRadii) {
    1160               0 :     result = nsLayoutUtils::RoundedRectIntersectRect(clipRect, radii, inputRect);
    1161                 :   } else {
    1162               0 :     nsRect r;
    1163               0 :     r.IntersectRect(clipRect, inputRect);
    1164               0 :     result = r;
    1165                 :   }
    1166                 :   return result;
    1167                 : }
    1168                 : 
    1169                 : nsRegion
    1170               0 : nsDisplayBackground::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
    1171                 :                                      bool* aForceTransparentSurface) {
    1172               0 :   nsRegion result;
    1173               0 :   if (aForceTransparentSurface) {
    1174               0 :     *aForceTransparentSurface = false;
    1175                 :   }
    1176                 :   // theme background overrides any other background
    1177               0 :   if (mIsThemed) {
    1178               0 :     if (aForceTransparentSurface) {
    1179               0 :       const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
    1180                 :       *aForceTransparentSurface = disp->mAppearance == NS_THEME_WIN_BORDERLESS_GLASS ||
    1181               0 :                                   disp->mAppearance == NS_THEME_WIN_GLASS;
    1182                 :     }
    1183               0 :     if (mThemeTransparency == nsITheme::eOpaque) {
    1184               0 :       result = GetBounds(aBuilder);
    1185                 :     }
    1186               0 :     return result;
    1187                 :   }
    1188                 : 
    1189                 :   nsStyleContext* bgSC;
    1190               0 :   nsPresContext* presContext = mFrame->PresContext();
    1191               0 :   if (!nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bgSC))
    1192               0 :     return result;
    1193               0 :   const nsStyleBackground* bg = bgSC->GetStyleBackground();
    1194               0 :   const nsStyleBackground::Layer& bottomLayer = bg->BottomLayer();
    1195                 : 
    1196               0 :   nsRect borderBox = nsRect(ToReferenceFrame(), mFrame->GetSize());
    1197               0 :   if (NS_GET_A(bg->mBackgroundColor) == 255 &&
    1198               0 :       !nsCSSRendering::IsCanvasFrame(mFrame)) {
    1199               0 :     result = GetInsideClipRegion(presContext, bottomLayer.mClip, borderBox);
    1200                 :   }
    1201                 : 
    1202                 :   // For policies other than EACH_BOX, don't try to optimize here, since
    1203                 :   // this could easily lead to O(N^2) behavior inside InlineBackgroundData,
    1204                 :   // which expects frames to be sent to it in content order, not reverse
    1205                 :   // content order which we'll produce here.
    1206                 :   // Of course, if there's only one frame in the flow, it doesn't matter.
    1207               0 :   if (bg->mBackgroundInlinePolicy == NS_STYLE_BG_INLINE_POLICY_EACH_BOX ||
    1208               0 :       (!mFrame->GetPrevContinuation() && !mFrame->GetNextContinuation())) {
    1209               0 :     NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
    1210               0 :       const nsStyleBackground::Layer& layer = bg->mLayers[i];
    1211               0 :       if (layer.mImage.IsOpaque()) {
    1212                 :         nsRect r = nsCSSRendering::GetBackgroundLayerRect(presContext, mFrame,
    1213               0 :             borderBox, *bg, layer);
    1214               0 :         result.Or(result, GetInsideClipRegion(presContext, layer.mClip, r));
    1215                 :       }
    1216                 :     }
    1217                 :   }
    1218                 : 
    1219                 :   return result;
    1220                 : }
    1221                 : 
    1222                 : bool
    1223               0 : nsDisplayBackground::IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) {
    1224                 :   // theme background overrides any other background
    1225               0 :   if (mIsThemed) {
    1226               0 :     const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
    1227               0 :     if (disp->mAppearance == NS_THEME_WIN_BORDERLESS_GLASS ||
    1228                 :         disp->mAppearance == NS_THEME_WIN_GLASS) {
    1229               0 :       *aColor = NS_RGBA(0,0,0,0);
    1230               0 :       return true;
    1231                 :     }
    1232               0 :     return false;
    1233                 :   }
    1234                 : 
    1235                 :   nsStyleContext *bgSC;
    1236                 :   bool hasBG =
    1237               0 :     nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bgSC);
    1238               0 :   if (!hasBG) {
    1239               0 :     *aColor = NS_RGBA(0,0,0,0);
    1240               0 :     return true;
    1241                 :   }
    1242               0 :   const nsStyleBackground* bg = bgSC->GetStyleBackground();
    1243               0 :   if (bg->BottomLayer().mImage.IsEmpty() &&
    1244                 :       bg->mImageCount == 1 &&
    1245               0 :       !nsLayoutUtils::HasNonZeroCorner(mFrame->GetStyleBorder()->mBorderRadius) &&
    1246               0 :       bg->BottomLayer().mClip == NS_STYLE_BG_CLIP_BORDER) {
    1247                 :     // Canvas frames don't actually render their background color, since that
    1248                 :     // gets propagated to the solid color of the viewport
    1249                 :     // (see nsCSSRendering::PaintBackgroundWithSC)
    1250               0 :     *aColor = nsCSSRendering::IsCanvasFrame(mFrame) ? NS_RGBA(0,0,0,0)
    1251               0 :         : bg->mBackgroundColor;
    1252               0 :     return true;
    1253                 :   }
    1254               0 :   return false;
    1255                 : }
    1256                 : 
    1257                 : bool
    1258               0 : nsDisplayBackground::IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
    1259                 :                                                     nsIFrame* aFrame)
    1260                 : {
    1261                 :   // theme background overrides any other background and is never fixed
    1262               0 :   if (mIsThemed)
    1263               0 :     return false;
    1264                 : 
    1265               0 :   nsPresContext* presContext = mFrame->PresContext();
    1266                 :   nsStyleContext *bgSC;
    1267                 :   bool hasBG =
    1268               0 :     nsCSSRendering::FindBackground(presContext, mFrame, &bgSC);
    1269               0 :   if (!hasBG)
    1270               0 :     return false;
    1271               0 :   const nsStyleBackground* bg = bgSC->GetStyleBackground();
    1272               0 :   if (!bg->HasFixedBackground())
    1273               0 :     return false;
    1274                 : 
    1275                 :   // If aFrame is mFrame or an ancestor in this document, and aFrame is
    1276                 :   // not the viewport frame, then moving aFrame will move mFrame
    1277                 :   // relative to the viewport, so our fixed-pos background will change.
    1278               0 :   return aFrame->GetParent() &&
    1279                 :     (aFrame == mFrame ||
    1280               0 :      nsLayoutUtils::IsProperAncestorFrame(aFrame, mFrame));
    1281                 : }
    1282                 : 
    1283                 : bool
    1284               0 : nsDisplayBackground::ShouldFixToViewport(nsDisplayListBuilder* aBuilder)
    1285                 : {
    1286               0 :   if (mIsThemed)
    1287               0 :     return false;
    1288                 : 
    1289               0 :   nsPresContext* presContext = mFrame->PresContext();
    1290                 :   nsStyleContext* bgSC;
    1291                 :   bool hasBG =
    1292               0 :     nsCSSRendering::FindBackground(presContext, mFrame, &bgSC);
    1293               0 :   if (!hasBG)
    1294               0 :     return false;
    1295                 : 
    1296               0 :   const nsStyleBackground* bg = bgSC->GetStyleBackground();
    1297               0 :   if (!bg->HasFixedBackground())
    1298               0 :     return false;
    1299                 : 
    1300               0 :   NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
    1301               0 :     const nsStyleBackground::Layer& layer = bg->mLayers[i];
    1302               0 :     if (layer.mAttachment != NS_STYLE_BG_ATTACHMENT_FIXED &&
    1303               0 :         !layer.mImage.IsEmpty()) {
    1304               0 :       return false;
    1305                 :     }
    1306               0 :     if (layer.mClip != NS_STYLE_BG_CLIP_BORDER)
    1307               0 :       return false;
    1308                 :   }
    1309                 : 
    1310               0 :   if (nsLayoutUtils::HasNonZeroCorner(mFrame->GetStyleBorder()->mBorderRadius))
    1311               0 :     return false;
    1312                 : 
    1313               0 :   nsRect bounds = GetBounds(aBuilder);
    1314               0 :   nsIFrame* rootScrollFrame = presContext->PresShell()->GetRootScrollFrame();
    1315               0 :   if (!rootScrollFrame)
    1316               0 :     return false;
    1317               0 :   nsIScrollableFrame* scrollable = do_QueryFrame(rootScrollFrame);
    1318               0 :   nsRect scrollport = scrollable->GetScrollPortRect() +
    1319               0 :     aBuilder->ToReferenceFrame(rootScrollFrame);
    1320               0 :   return bounds.Contains(scrollport);
    1321                 : }
    1322                 : 
    1323                 : void
    1324               0 : nsDisplayBackground::Paint(nsDisplayListBuilder* aBuilder,
    1325                 :                            nsRenderingContext* aCtx) {
    1326               0 :   nsPoint offset = ToReferenceFrame();
    1327               0 :   PRUint32 flags = aBuilder->GetBackgroundPaintFlags();
    1328               0 :   nsDisplayItem* nextItem = GetAbove();
    1329               0 :   if (nextItem && nextItem->GetUnderlyingFrame() == mFrame &&
    1330               0 :       nextItem->GetType() == TYPE_BORDER) {
    1331               0 :     flags |= nsCSSRendering::PAINTBG_WILL_PAINT_BORDER;
    1332                 :   }
    1333                 :   nsCSSRendering::PaintBackground(mFrame->PresContext(), *aCtx, mFrame,
    1334                 :                                   mVisibleRect,
    1335               0 :                                   nsRect(offset, mFrame->GetSize()),
    1336               0 :                                   flags);
    1337               0 : }
    1338                 : 
    1339                 : nsRect
    1340               0 : nsDisplayBackground::GetBounds(nsDisplayListBuilder* aBuilder) {
    1341               0 :   nsRect r(nsPoint(0,0), mFrame->GetSize());
    1342               0 :   nsPresContext* presContext = mFrame->PresContext();
    1343                 : 
    1344               0 :   if (mIsThemed) {
    1345               0 :     presContext->GetTheme()->
    1346                 :         GetWidgetOverflow(presContext->DeviceContext(), mFrame,
    1347               0 :                           mFrame->GetStyleDisplay()->mAppearance, &r);
    1348                 :   }
    1349                 : 
    1350               0 :   return SnapBounds(mSnappingEnabled, presContext, r + ToReferenceFrame());
    1351                 : }
    1352                 : 
    1353                 : nsRect
    1354               0 : nsDisplayOutline::GetBounds(nsDisplayListBuilder* aBuilder) {
    1355               0 :   return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
    1356                 : }
    1357                 : 
    1358                 : void
    1359               0 : nsDisplayOutline::Paint(nsDisplayListBuilder* aBuilder,
    1360                 :                         nsRenderingContext* aCtx) {
    1361                 :   // TODO join outlines together
    1362               0 :   nsPoint offset = ToReferenceFrame();
    1363                 :   nsCSSRendering::PaintOutline(mFrame->PresContext(), *aCtx, mFrame,
    1364                 :                                mVisibleRect,
    1365               0 :                                nsRect(offset, mFrame->GetSize()),
    1366               0 :                                mFrame->GetStyleContext());
    1367               0 : }
    1368                 : 
    1369                 : bool
    1370               0 : nsDisplayOutline::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    1371                 :                                     nsRegion* aVisibleRegion,
    1372                 :                                     const nsRect& aAllowVisibleRegionExpansion) {
    1373               0 :   if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
    1374               0 :                                         aAllowVisibleRegionExpansion)) {
    1375               0 :     return false;
    1376                 :   }
    1377                 : 
    1378               0 :   const nsStyleOutline* outline = mFrame->GetStyleOutline();
    1379               0 :   nsRect borderBox(ToReferenceFrame(), mFrame->GetSize());
    1380               0 :   if (borderBox.Contains(aVisibleRegion->GetBounds()) &&
    1381               0 :       !nsLayoutUtils::HasNonZeroCorner(outline->mOutlineRadius)) {
    1382               0 :     if (outline->mOutlineOffset >= 0) {
    1383                 :       // the visible region is entirely inside the border-rect, and the outline
    1384                 :       // isn't rendered inside the border-rect, so the outline is not visible
    1385               0 :       return false;
    1386                 :     }
    1387                 :   }
    1388                 : 
    1389               0 :   return true;
    1390                 : }
    1391                 : 
    1392                 : void
    1393               0 : nsDisplayEventReceiver::HitTest(nsDisplayListBuilder* aBuilder,
    1394                 :                                 const nsRect& aRect,
    1395                 :                                 HitTestState* aState,
    1396                 :                                 nsTArray<nsIFrame*> *aOutFrames)
    1397                 : {
    1398               0 :   if (!RoundedBorderIntersectsRect(mFrame, ToReferenceFrame(), aRect)) {
    1399                 :     // aRect doesn't intersect our border-radius curve.
    1400               0 :     return;
    1401                 :   }
    1402                 : 
    1403               0 :   aOutFrames->AppendElement(mFrame);
    1404                 : }
    1405                 : 
    1406                 : void
    1407               0 : nsDisplayCaret::Paint(nsDisplayListBuilder* aBuilder,
    1408                 :                       nsRenderingContext* aCtx) {
    1409                 :   // Note: Because we exist, we know that the caret is visible, so we don't
    1410                 :   // need to check for the caret's visibility.
    1411               0 :   mCaret->PaintCaret(aBuilder, aCtx, mFrame, ToReferenceFrame());
    1412               0 : }
    1413                 : 
    1414                 : bool
    1415               0 : nsDisplayBorder::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    1416                 :                                    nsRegion* aVisibleRegion,
    1417                 :                                    const nsRect& aAllowVisibleRegionExpansion) {
    1418               0 :   if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
    1419               0 :                                         aAllowVisibleRegionExpansion)) {
    1420               0 :     return false;
    1421                 :   }
    1422                 : 
    1423               0 :   nsRect paddingRect = mFrame->GetPaddingRect() - mFrame->GetPosition() +
    1424               0 :     ToReferenceFrame();
    1425                 :   const nsStyleBorder *styleBorder;
    1426               0 :   if (paddingRect.Contains(aVisibleRegion->GetBounds()) &&
    1427               0 :       !(styleBorder = mFrame->GetStyleBorder())->IsBorderImageLoaded() &&
    1428               0 :       !nsLayoutUtils::HasNonZeroCorner(styleBorder->mBorderRadius)) {
    1429                 :     // the visible region is entirely inside the content rect, and no part
    1430                 :     // of the border is rendered inside the content rect, so we are not
    1431                 :     // visible
    1432                 :     // Skip this if there's a border-image (which draws a background
    1433                 :     // too) or if there is a border-radius (which makes the border draw
    1434                 :     // further in).
    1435               0 :     return false;
    1436                 :   }
    1437                 : 
    1438               0 :   return true;
    1439                 : }
    1440                 : 
    1441                 : void
    1442               0 : nsDisplayBorder::Paint(nsDisplayListBuilder* aBuilder,
    1443                 :                        nsRenderingContext* aCtx) {
    1444               0 :   nsPoint offset = ToReferenceFrame();
    1445                 :   nsCSSRendering::PaintBorder(mFrame->PresContext(), *aCtx, mFrame,
    1446                 :                               mVisibleRect,
    1447               0 :                               nsRect(offset, mFrame->GetSize()),
    1448                 :                               mFrame->GetStyleContext(),
    1449               0 :                               mFrame->GetSkipSides());
    1450               0 : }
    1451                 : 
    1452                 : nsRect
    1453               0 : nsDisplayBorder::GetBounds(nsDisplayListBuilder* aBuilder)
    1454                 : {
    1455                 :   return SnapBounds(mSnappingEnabled, mFrame->PresContext(),
    1456               0 :                     nsRect(ToReferenceFrame(), mFrame->GetSize()));
    1457                 : }
    1458                 : 
    1459                 : // Given a region, compute a conservative approximation to it as a list
    1460                 : // of rectangles that aren't vertically adjacent (i.e., vertically
    1461                 : // adjacent or overlapping rectangles are combined).
    1462                 : // Right now this is only approximate, some vertically overlapping rectangles
    1463                 : // aren't guaranteed to be combined.
    1464                 : static void
    1465               0 : ComputeDisjointRectangles(const nsRegion& aRegion,
    1466                 :                           nsTArray<nsRect>* aRects) {
    1467               0 :   nscoord accumulationMargin = nsPresContext::CSSPixelsToAppUnits(25);
    1468               0 :   nsRect accumulated;
    1469               0 :   nsRegionRectIterator iter(aRegion);
    1470               0 :   while (true) {
    1471               0 :     const nsRect* r = iter.Next();
    1472               0 :     if (r && !accumulated.IsEmpty() &&
    1473               0 :         accumulated.YMost() >= r->y - accumulationMargin) {
    1474               0 :       accumulated.UnionRect(accumulated, *r);
    1475               0 :       continue;
    1476                 :     }
    1477                 : 
    1478               0 :     if (!accumulated.IsEmpty()) {
    1479               0 :       aRects->AppendElement(accumulated);
    1480               0 :       accumulated.SetEmpty();
    1481                 :     }
    1482                 : 
    1483               0 :     if (!r)
    1484                 :       break;
    1485                 : 
    1486               0 :     accumulated = *r;
    1487                 :   }
    1488               0 : }
    1489                 : 
    1490                 : void
    1491               0 : nsDisplayBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
    1492                 :                                nsRenderingContext* aCtx) {
    1493               0 :   nsPoint offset = ToReferenceFrame();
    1494               0 :   nsRect borderRect = nsRect(offset, mFrame->GetSize());
    1495               0 :   nsPresContext* presContext = mFrame->PresContext();
    1496               0 :   nsAutoTArray<nsRect,10> rects;
    1497               0 :   ComputeDisjointRectangles(mVisibleRegion, &rects);
    1498                 : 
    1499               0 :   for (PRUint32 i = 0; i < rects.Length(); ++i) {
    1500               0 :     aCtx->PushState();
    1501               0 :     aCtx->IntersectClip(rects[i]);
    1502                 :     nsCSSRendering::PaintBoxShadowOuter(presContext, *aCtx, mFrame,
    1503               0 :                                         borderRect, rects[i]);
    1504               0 :     aCtx->PopState();
    1505                 :   }
    1506               0 : }
    1507                 : 
    1508                 : nsRect
    1509               0 : nsDisplayBoxShadowOuter::GetBounds(nsDisplayListBuilder* aBuilder) {
    1510               0 :   return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
    1511                 : }
    1512                 : 
    1513                 : bool
    1514               0 : nsDisplayBoxShadowOuter::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    1515                 :                                            nsRegion* aVisibleRegion,
    1516                 :                                            const nsRect& aAllowVisibleRegionExpansion) {
    1517               0 :   if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
    1518               0 :                                         aAllowVisibleRegionExpansion)) {
    1519               0 :     return false;
    1520                 :   }
    1521                 : 
    1522                 :   // Store the actual visible region
    1523               0 :   mVisibleRegion.And(*aVisibleRegion, mVisibleRect);
    1524                 : 
    1525               0 :   nsPoint origin = ToReferenceFrame();
    1526               0 :   nsRect visibleBounds = aVisibleRegion->GetBounds();
    1527               0 :   nsRect frameRect(origin, mFrame->GetSize());
    1528               0 :   if (!frameRect.Contains(visibleBounds))
    1529               0 :     return true;
    1530                 : 
    1531                 :   // the visible region is entirely inside the border-rect, and box shadows
    1532                 :   // never render within the border-rect (unless there's a border radius).
    1533                 :   nscoord twipsRadii[8];
    1534               0 :   bool hasBorderRadii = mFrame->GetBorderRadii(twipsRadii);
    1535               0 :   if (!hasBorderRadii)
    1536               0 :     return false;
    1537                 : 
    1538               0 :   return !RoundedRectContainsRect(frameRect, twipsRadii, visibleBounds);
    1539                 : }
    1540                 : 
    1541                 : void
    1542               0 : nsDisplayBoxShadowInner::Paint(nsDisplayListBuilder* aBuilder,
    1543                 :                                nsRenderingContext* aCtx) {
    1544               0 :   nsPoint offset = ToReferenceFrame();
    1545               0 :   nsRect borderRect = nsRect(offset, mFrame->GetSize());
    1546               0 :   nsPresContext* presContext = mFrame->PresContext();
    1547               0 :   nsAutoTArray<nsRect,10> rects;
    1548               0 :   ComputeDisjointRectangles(mVisibleRegion, &rects);
    1549                 : 
    1550               0 :   for (PRUint32 i = 0; i < rects.Length(); ++i) {
    1551               0 :     aCtx->PushState();
    1552               0 :     aCtx->IntersectClip(rects[i]);
    1553                 :     nsCSSRendering::PaintBoxShadowInner(presContext, *aCtx, mFrame,
    1554               0 :                                         borderRect, rects[i]);
    1555               0 :     aCtx->PopState();
    1556                 :   }
    1557               0 : }
    1558                 : 
    1559                 : bool
    1560               0 : nsDisplayBoxShadowInner::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    1561                 :                                            nsRegion* aVisibleRegion,
    1562                 :                                            const nsRect& aAllowVisibleRegionExpansion) {
    1563               0 :   if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion,
    1564               0 :                                         aAllowVisibleRegionExpansion)) {
    1565               0 :     return false;
    1566                 :   }
    1567                 : 
    1568                 :   // Store the actual visible region
    1569               0 :   mVisibleRegion.And(*aVisibleRegion, mVisibleRect);
    1570               0 :   return true;
    1571                 : }
    1572                 : 
    1573               0 : nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
    1574                 :                                      nsIFrame* aFrame, nsDisplayList* aList)
    1575               0 :   : nsDisplayItem(aBuilder, aFrame) {
    1576               0 :   mList.AppendToTop(aList);
    1577               0 : }
    1578                 : 
    1579               0 : nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
    1580                 :                                      nsIFrame* aFrame, nsDisplayItem* aItem)
    1581               0 :   : nsDisplayItem(aBuilder, aFrame) {
    1582               0 :   mList.AppendToTop(aItem);
    1583               0 : }
    1584                 : 
    1585               0 : nsDisplayWrapList::nsDisplayWrapList(nsDisplayListBuilder* aBuilder,
    1586                 :                                      nsIFrame* aFrame)
    1587               0 :   : nsDisplayItem(aBuilder, aFrame) {
    1588               0 : }
    1589                 : 
    1590               0 : nsDisplayWrapList::~nsDisplayWrapList() {
    1591               0 :   mList.DeleteAll();
    1592               0 : }
    1593                 : 
    1594                 : void
    1595               0 : nsDisplayWrapList::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
    1596                 :                            HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {
    1597               0 :   mList.HitTest(aBuilder, aRect, aState, aOutFrames);
    1598               0 : }
    1599                 : 
    1600                 : nsRect
    1601               0 : nsDisplayWrapList::GetBounds(nsDisplayListBuilder* aBuilder) {
    1602               0 :   return mList.GetBounds(aBuilder);
    1603                 : }
    1604                 : 
    1605                 : bool
    1606               0 : nsDisplayWrapList::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    1607                 :                                      nsRegion* aVisibleRegion,
    1608                 :                                      const nsRect& aAllowVisibleRegionExpansion) {
    1609                 :   return mList.ComputeVisibilityForSublist(aBuilder, aVisibleRegion,
    1610                 :                                            mVisibleRect,
    1611               0 :                                            aAllowVisibleRegionExpansion);
    1612                 : }
    1613                 : 
    1614                 : nsRegion
    1615               0 : nsDisplayWrapList::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
    1616                 :                                    bool* aForceTransparentSurface) {
    1617               0 :   if (aForceTransparentSurface) {
    1618               0 :     *aForceTransparentSurface = false;
    1619                 :   }
    1620               0 :   nsRegion result;
    1621               0 :   if (mList.IsOpaque()) {
    1622               0 :     result = GetBounds(aBuilder);
    1623                 :   }
    1624                 :   return result;
    1625                 : }
    1626                 : 
    1627               0 : bool nsDisplayWrapList::IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) {
    1628                 :   // We could try to do something but let's conservatively just return false.
    1629               0 :   return false;
    1630                 : }
    1631                 : 
    1632               0 : bool nsDisplayWrapList::IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
    1633                 :                                                          nsIFrame* aFrame) {
    1634               0 :   NS_WARNING("nsDisplayWrapList::IsVaryingRelativeToMovingFrame called unexpectedly");
    1635                 :   // We could try to do something but let's conservatively just return true.
    1636               0 :   return true;
    1637                 : }
    1638                 : 
    1639               0 : void nsDisplayWrapList::Paint(nsDisplayListBuilder* aBuilder,
    1640                 :                               nsRenderingContext* aCtx) {
    1641               0 :   NS_ERROR("nsDisplayWrapList should have been flattened away for painting");
    1642               0 : }
    1643                 : 
    1644               0 : bool nsDisplayWrapList::ChildrenCanBeInactive(nsDisplayListBuilder* aBuilder,
    1645                 :                                                 LayerManager* aManager,
    1646                 :                                                 const nsDisplayList& aList,
    1647                 :                                                 nsIFrame* aActiveScrolledRoot) {
    1648               0 :   for (nsDisplayItem* i = aList.GetBottom(); i; i = i->GetAbove()) {
    1649               0 :     nsIFrame* f = i->GetUnderlyingFrame();
    1650               0 :     if (f) {
    1651                 :       nsIFrame* activeScrolledRoot =
    1652               0 :         nsLayoutUtils::GetActiveScrolledRootFor(f, nsnull);
    1653               0 :       if (activeScrolledRoot != aActiveScrolledRoot)
    1654               0 :         return false;
    1655                 :     }
    1656                 : 
    1657               0 :     LayerState state = i->GetLayerState(aBuilder, aManager);
    1658               0 :     if (state == LAYER_ACTIVE)
    1659               0 :       return false;
    1660               0 :     if (state == LAYER_NONE) {
    1661               0 :       nsDisplayList* list = i->GetList();
    1662               0 :       if (list && !ChildrenCanBeInactive(aBuilder, aManager, *list, aActiveScrolledRoot))
    1663               0 :         return false;
    1664                 :     }
    1665                 :   }
    1666               0 :   return true;
    1667                 : }
    1668                 : 
    1669               0 : nsRect nsDisplayWrapList::GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder)
    1670                 : {
    1671               0 :   nsRect bounds;
    1672               0 :   for (nsDisplayItem* i = mList.GetBottom(); i; i = i->GetAbove()) {
    1673               0 :     bounds.UnionRect(bounds, i->GetComponentAlphaBounds(aBuilder));
    1674                 :   }
    1675                 :   return bounds;
    1676                 : }
    1677                 : 
    1678                 : static nsresult
    1679               0 : WrapDisplayList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
    1680                 :                 nsDisplayList* aList, nsDisplayWrapper* aWrapper) {
    1681               0 :   if (!aList->GetTop())
    1682               0 :     return NS_OK;
    1683               0 :   nsDisplayItem* item = aWrapper->WrapList(aBuilder, aFrame, aList);
    1684               0 :   if (!item)
    1685               0 :     return NS_ERROR_OUT_OF_MEMORY;
    1686                 :   // aList was emptied
    1687               0 :   aList->AppendToTop(item);
    1688               0 :   return NS_OK;
    1689                 : }
    1690                 : 
    1691                 : static nsresult
    1692               0 : WrapEachDisplayItem(nsDisplayListBuilder* aBuilder,
    1693                 :                     nsDisplayList* aList, nsDisplayWrapper* aWrapper) {
    1694               0 :   nsDisplayList newList;
    1695                 :   nsDisplayItem* item;
    1696               0 :   while ((item = aList->RemoveBottom())) {
    1697               0 :     item = aWrapper->WrapItem(aBuilder, item);
    1698               0 :     if (!item)
    1699               0 :       return NS_ERROR_OUT_OF_MEMORY;
    1700               0 :     newList.AppendToTop(item);
    1701                 :   }
    1702                 :   // aList was emptied
    1703               0 :   aList->AppendToTop(&newList);
    1704               0 :   return NS_OK;
    1705                 : }
    1706                 : 
    1707               0 : nsresult nsDisplayWrapper::WrapLists(nsDisplayListBuilder* aBuilder,
    1708                 :     nsIFrame* aFrame, const nsDisplayListSet& aIn, const nsDisplayListSet& aOut)
    1709                 : {
    1710               0 :   nsresult rv = WrapListsInPlace(aBuilder, aFrame, aIn);
    1711               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1712                 : 
    1713               0 :   if (&aOut == &aIn)
    1714               0 :     return NS_OK;
    1715               0 :   aOut.BorderBackground()->AppendToTop(aIn.BorderBackground());
    1716               0 :   aOut.BlockBorderBackgrounds()->AppendToTop(aIn.BlockBorderBackgrounds());
    1717               0 :   aOut.Floats()->AppendToTop(aIn.Floats());
    1718               0 :   aOut.Content()->AppendToTop(aIn.Content());
    1719               0 :   aOut.PositionedDescendants()->AppendToTop(aIn.PositionedDescendants());
    1720               0 :   aOut.Outlines()->AppendToTop(aIn.Outlines());
    1721               0 :   return NS_OK;
    1722                 : }
    1723                 : 
    1724               0 : nsresult nsDisplayWrapper::WrapListsInPlace(nsDisplayListBuilder* aBuilder,
    1725                 :     nsIFrame* aFrame, const nsDisplayListSet& aLists)
    1726                 : {
    1727                 :   nsresult rv;
    1728               0 :   if (WrapBorderBackground()) {
    1729                 :     // Our border-backgrounds are in-flow
    1730               0 :     rv = WrapDisplayList(aBuilder, aFrame, aLists.BorderBackground(), this);
    1731               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1732                 :   }
    1733                 :   // Our block border-backgrounds are in-flow
    1734               0 :   rv = WrapDisplayList(aBuilder, aFrame, aLists.BlockBorderBackgrounds(), this);
    1735               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1736                 :   // The floats are not in flow
    1737               0 :   rv = WrapEachDisplayItem(aBuilder, aLists.Floats(), this);
    1738               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1739                 :   // Our child content is in flow
    1740               0 :   rv = WrapDisplayList(aBuilder, aFrame, aLists.Content(), this);
    1741               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1742                 :   // The positioned descendants may not be in-flow
    1743               0 :   rv = WrapEachDisplayItem(aBuilder, aLists.PositionedDescendants(), this);
    1744               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1745                 :   // The outlines may not be in-flow
    1746               0 :   return WrapEachDisplayItem(aBuilder, aLists.Outlines(), this);
    1747                 : }
    1748                 : 
    1749               0 : nsDisplayOpacity::nsDisplayOpacity(nsDisplayListBuilder* aBuilder,
    1750                 :                                    nsIFrame* aFrame, nsDisplayList* aList)
    1751               0 :     : nsDisplayWrapList(aBuilder, aFrame, aList) {
    1752               0 :   MOZ_COUNT_CTOR(nsDisplayOpacity);
    1753               0 : }
    1754                 : 
    1755                 : #ifdef NS_BUILD_REFCNT_LOGGING
    1756               0 : nsDisplayOpacity::~nsDisplayOpacity() {
    1757               0 :   MOZ_COUNT_DTOR(nsDisplayOpacity);
    1758               0 : }
    1759                 : #endif
    1760                 : 
    1761               0 : nsRegion nsDisplayOpacity::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
    1762                 :                                            bool* aForceTransparentSurface) {
    1763               0 :   if (aForceTransparentSurface) {
    1764               0 :     *aForceTransparentSurface = false;
    1765                 :   }
    1766                 :   // We are never opaque, if our opacity was < 1 then we wouldn't have
    1767                 :   // been created.
    1768               0 :   return nsRegion();
    1769                 : }
    1770                 : 
    1771                 : // nsDisplayOpacity uses layers for rendering
    1772                 : already_AddRefed<Layer>
    1773               0 : nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder,
    1774                 :                              LayerManager* aManager,
    1775                 :                              const ContainerParameters& aContainerParameters) {
    1776                 :   nsRefPtr<Layer> layer = aBuilder->LayerBuilder()->
    1777                 :     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
    1778               0 :                            aContainerParameters, nsnull);
    1779               0 :   if (!layer)
    1780               0 :     return nsnull;
    1781                 : 
    1782               0 :   layer->SetOpacity(mFrame->GetStyleDisplay()->mOpacity);
    1783               0 :   return layer.forget();
    1784                 : }
    1785                 : 
    1786                 : /**
    1787                 :  * This doesn't take into account layer scaling --- the layer may be
    1788                 :  * rendered at a higher (or lower) resolution, affecting the retained layer
    1789                 :  * size --- but this should be good enough.
    1790                 :  */
    1791                 : static bool
    1792               0 : IsItemTooSmallForActiveLayer(nsDisplayItem* aItem)
    1793                 : {
    1794               0 :   nsIntRect visibleDevPixels = aItem->GetVisibleRect().ToOutsidePixels(
    1795               0 :           aItem->GetUnderlyingFrame()->PresContext()->AppUnitsPerDevPixel());
    1796                 :   static const int MIN_ACTIVE_LAYER_SIZE_DEV_PIXELS = 16;
    1797                 :   return visibleDevPixels.Size() <
    1798               0 :     nsIntSize(MIN_ACTIVE_LAYER_SIZE_DEV_PIXELS, MIN_ACTIVE_LAYER_SIZE_DEV_PIXELS);
    1799                 : }
    1800                 : 
    1801                 : nsDisplayItem::LayerState
    1802               0 : nsDisplayOpacity::GetLayerState(nsDisplayListBuilder* aBuilder,
    1803                 :                                 LayerManager* aManager) {
    1804               0 :   if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateOpacityLayer) &&
    1805               0 :       !IsItemTooSmallForActiveLayer(this))
    1806               0 :     return LAYER_ACTIVE;
    1807                 :   nsIFrame* activeScrolledRoot =
    1808               0 :     nsLayoutUtils::GetActiveScrolledRootFor(mFrame, nsnull);
    1809               0 :   return !ChildrenCanBeInactive(aBuilder, aManager, mList, activeScrolledRoot)
    1810               0 :       ? LAYER_ACTIVE : LAYER_INACTIVE;
    1811                 : }
    1812                 : 
    1813                 : bool
    1814               0 : nsDisplayOpacity::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    1815                 :                                     nsRegion* aVisibleRegion,
    1816                 :                                     const nsRect& aAllowVisibleRegionExpansion) {
    1817                 :   // Our children are translucent so we should not allow them to subtract
    1818                 :   // area from aVisibleRegion. We do need to find out what is visible under
    1819                 :   // our children in the temporary compositing buffer, because if our children
    1820                 :   // paint our entire bounds opaquely then we don't need an alpha channel in
    1821                 :   // the temporary compositing buffer.
    1822               0 :   nsRect bounds = GetBounds(aBuilder);
    1823               0 :   nsRegion visibleUnderChildren;
    1824               0 :   visibleUnderChildren.And(*aVisibleRegion, bounds);
    1825               0 :   nsRect allowExpansion;
    1826               0 :   allowExpansion.IntersectRect(bounds, aAllowVisibleRegionExpansion);
    1827                 :   return
    1828                 :     nsDisplayWrapList::ComputeVisibility(aBuilder, &visibleUnderChildren,
    1829               0 :                                          allowExpansion);
    1830                 : }
    1831                 : 
    1832               0 : bool nsDisplayOpacity::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
    1833               0 :   if (aItem->GetType() != TYPE_OPACITY)
    1834               0 :     return false;
    1835                 :   // items for the same content element should be merged into a single
    1836                 :   // compositing group
    1837                 :   // aItem->GetUnderlyingFrame() returns non-null because it's nsDisplayOpacity
    1838               0 :   if (aItem->GetUnderlyingFrame()->GetContent() != mFrame->GetContent())
    1839               0 :     return false;
    1840               0 :   mList.AppendToBottom(&static_cast<nsDisplayOpacity*>(aItem)->mList);
    1841               0 :   return true;
    1842                 : }
    1843                 : 
    1844               0 : nsDisplayOwnLayer::nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder,
    1845                 :                                      nsIFrame* aFrame, nsDisplayList* aList)
    1846               0 :     : nsDisplayWrapList(aBuilder, aFrame, aList) {
    1847               0 :   MOZ_COUNT_CTOR(nsDisplayOwnLayer);
    1848               0 : }
    1849                 : 
    1850                 : #ifdef NS_BUILD_REFCNT_LOGGING
    1851               0 : nsDisplayOwnLayer::~nsDisplayOwnLayer() {
    1852               0 :   MOZ_COUNT_DTOR(nsDisplayOwnLayer);
    1853               0 : }
    1854                 : #endif
    1855                 : 
    1856                 : // nsDisplayOpacity uses layers for rendering
    1857                 : already_AddRefed<Layer>
    1858               0 : nsDisplayOwnLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
    1859                 :                               LayerManager* aManager,
    1860                 :                               const ContainerParameters& aContainerParameters) {
    1861                 :   nsRefPtr<Layer> layer = aBuilder->LayerBuilder()->
    1862                 :     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
    1863               0 :                            aContainerParameters, nsnull);
    1864               0 :   return layer.forget();
    1865                 : }
    1866                 : 
    1867               0 : nsDisplayScrollLayer::nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
    1868                 :                                            nsDisplayList* aList,
    1869                 :                                            nsIFrame* aForFrame,
    1870                 :                                            nsIFrame* aScrolledFrame,
    1871                 :                                            nsIFrame* aScrollFrame)
    1872                 :   : nsDisplayWrapList(aBuilder, aForFrame, aList)
    1873                 :   , mScrollFrame(aScrollFrame)
    1874               0 :   , mScrolledFrame(aScrolledFrame)
    1875                 : {
    1876                 : #ifdef NS_BUILD_REFCNT_LOGGING
    1877               0 :   MOZ_COUNT_CTOR(nsDisplayScrollLayer);
    1878                 : #endif
    1879                 : 
    1880               0 :   NS_ASSERTION(mScrolledFrame && mScrolledFrame->GetContent(),
    1881                 :                "Need a child frame with content");
    1882               0 : }
    1883                 : 
    1884               0 : nsDisplayScrollLayer::nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
    1885                 :                                            nsDisplayItem* aItem,
    1886                 :                                            nsIFrame* aForFrame,
    1887                 :                                            nsIFrame* aScrolledFrame,
    1888                 :                                            nsIFrame* aScrollFrame)
    1889                 :   : nsDisplayWrapList(aBuilder, aForFrame, aItem)
    1890                 :   , mScrollFrame(aScrollFrame)
    1891               0 :   , mScrolledFrame(aScrolledFrame)
    1892                 : {
    1893                 : #ifdef NS_BUILD_REFCNT_LOGGING
    1894               0 :   MOZ_COUNT_CTOR(nsDisplayScrollLayer);
    1895                 : #endif
    1896                 : 
    1897               0 :   NS_ASSERTION(mScrolledFrame && mScrolledFrame->GetContent(),
    1898                 :                "Need a child frame with content");
    1899               0 : }
    1900                 : 
    1901               0 : nsDisplayScrollLayer::nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
    1902                 :                                            nsIFrame* aForFrame,
    1903                 :                                            nsIFrame* aScrolledFrame,
    1904                 :                                            nsIFrame* aScrollFrame)
    1905                 :   : nsDisplayWrapList(aBuilder, aForFrame)
    1906                 :   , mScrollFrame(aScrollFrame)
    1907               0 :   , mScrolledFrame(aScrolledFrame)
    1908                 : {
    1909                 : #ifdef NS_BUILD_REFCNT_LOGGING
    1910               0 :   MOZ_COUNT_CTOR(nsDisplayScrollLayer);
    1911                 : #endif
    1912                 : 
    1913               0 :   NS_ASSERTION(mScrolledFrame && mScrolledFrame->GetContent(),
    1914                 :                "Need a child frame with content");
    1915               0 : }
    1916                 : 
    1917                 : #ifdef NS_BUILD_REFCNT_LOGGING
    1918               0 : nsDisplayScrollLayer::~nsDisplayScrollLayer()
    1919                 : {
    1920               0 :   MOZ_COUNT_DTOR(nsDisplayScrollLayer);
    1921               0 : }
    1922                 : #endif
    1923                 : 
    1924                 : already_AddRefed<Layer>
    1925               0 : nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
    1926                 :                                  LayerManager* aManager,
    1927                 :                                  const ContainerParameters& aContainerParameters) {
    1928                 :   nsRefPtr<ContainerLayer> layer = aBuilder->LayerBuilder()->
    1929                 :     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, mList,
    1930               0 :                            aContainerParameters, nsnull);
    1931                 : 
    1932                 :   // Get the already set unique ID for scrolling this content remotely.
    1933                 :   // Or, if not set, generate a new ID.
    1934               0 :   nsIContent* content = mScrolledFrame->GetContent();
    1935               0 :   ViewID scrollId = nsLayoutUtils::FindIDFor(content);
    1936                 : 
    1937               0 :   nsRect viewport = mScrollFrame->GetRect() -
    1938               0 :                     mScrollFrame->GetPosition() +
    1939               0 :                     aBuilder->ToReferenceFrame(mScrollFrame);
    1940                 : 
    1941               0 :   bool usingDisplayport = false;
    1942               0 :   nsRect displayport;
    1943               0 :   if (content) {
    1944               0 :     usingDisplayport = nsLayoutUtils::GetDisplayPort(content, &displayport);
    1945                 :   }
    1946                 :   RecordFrameMetrics(mScrolledFrame, mScrollFrame, layer, mVisibleRect, viewport,
    1947                 :                      (usingDisplayport ? &displayport : nsnull), scrollId,
    1948               0 :                      aContainerParameters);
    1949                 : 
    1950               0 :   return layer.forget();
    1951                 : }
    1952                 : 
    1953                 : bool
    1954               0 : nsDisplayScrollLayer::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    1955                 :                                         nsRegion* aVisibleRegion,
    1956                 :                                         const nsRect& aAllowVisibleRegionExpansion)
    1957                 : {
    1958               0 :   nsRect displayport;
    1959               0 :   if (nsLayoutUtils::GetDisplayPort(mScrolledFrame->GetContent(), &displayport)) {
    1960                 :     // The visible region for the children may be much bigger than the hole we
    1961                 :     // are viewing the children from, so that the compositor process has enough
    1962                 :     // content to asynchronously pan while content is being refreshed.
    1963                 : 
    1964               0 :     nsRegion childVisibleRegion = displayport + aBuilder->ToReferenceFrame(mScrollFrame);
    1965                 : 
    1966               0 :     nsRect boundedRect;
    1967               0 :     boundedRect.IntersectRect(childVisibleRegion.GetBounds(), mList.GetBounds(aBuilder));
    1968               0 :     nsRect allowExpansion;
    1969               0 :     allowExpansion.IntersectRect(allowExpansion, boundedRect);
    1970                 :     bool visible = mList.ComputeVisibilityForSublist(
    1971               0 :       aBuilder, &childVisibleRegion, boundedRect, allowExpansion);
    1972               0 :     mVisibleRect = boundedRect;
    1973                 : 
    1974               0 :     return visible;
    1975                 : 
    1976                 :   } else {
    1977                 :     return nsDisplayWrapList::ComputeVisibility(aBuilder, aVisibleRegion,
    1978               0 :                                                 aAllowVisibleRegionExpansion);
    1979                 :   }
    1980                 : }
    1981                 : 
    1982                 : LayerState
    1983               0 : nsDisplayScrollLayer::GetLayerState(nsDisplayListBuilder* aBuilder,
    1984                 :                                     LayerManager* aManager)
    1985                 : {
    1986                 :   // Force this as a layer so we can scroll asynchronously.
    1987                 :   // This causes incorrect rendering for rounded clips!
    1988               0 :   return LAYER_ACTIVE_FORCE;
    1989                 : }
    1990                 : 
    1991                 : bool
    1992               0 : nsDisplayScrollLayer::TryMerge(nsDisplayListBuilder* aBuilder,
    1993                 :                                nsDisplayItem* aItem)
    1994                 : {
    1995               0 :   if (aItem->GetType() != TYPE_SCROLL_LAYER) {
    1996               0 :     return false;
    1997                 :   }
    1998                 : 
    1999               0 :   nsDisplayScrollLayer* other = static_cast<nsDisplayScrollLayer*>(aItem);
    2000               0 :   if (other->mScrolledFrame != this->mScrolledFrame) {
    2001               0 :     return false;
    2002                 :   }
    2003                 : 
    2004               0 :   FrameProperties props = mScrolledFrame->Properties();
    2005                 :   props.Set(nsIFrame::ScrollLayerCount(),
    2006               0 :     reinterpret_cast<void*>(GetScrollLayerCount() - 1));
    2007                 : 
    2008               0 :   mList.AppendToBottom(&other->mList);
    2009                 :   // XXX - This ensures that the frame associated with a scroll layer after
    2010                 :   // merging is the first, rather than the last. This tends to change less,
    2011                 :   // ensuring we're more likely to retain the associated gfx layer.
    2012                 :   // See Bug 729534 and Bug 731641.
    2013               0 :   mFrame = other->mFrame;
    2014               0 :   return true;
    2015                 : }
    2016                 : 
    2017                 : bool
    2018               0 : nsDisplayScrollLayer::ShouldFlattenAway(nsDisplayListBuilder* aBuilder)
    2019                 : {
    2020               0 :   return GetScrollLayerCount() > 1;
    2021                 : }
    2022                 : 
    2023                 : PRWord
    2024               0 : nsDisplayScrollLayer::GetScrollLayerCount()
    2025                 : {
    2026               0 :   FrameProperties props = mScrolledFrame->Properties();
    2027                 : #ifdef DEBUG
    2028               0 :   bool hasCount = false;
    2029                 :   PRWord result = reinterpret_cast<PRWord>(
    2030               0 :     props.Get(nsIFrame::ScrollLayerCount(), &hasCount));
    2031                 :   // If this aborts, then the property was either not added before scroll
    2032                 :   // layers were created or the property was deleted to early. If the latter,
    2033                 :   // make sure that nsDisplayScrollInfoLayer is on the bottom of the list so
    2034                 :   // that it is processed last.
    2035               0 :   NS_ABORT_IF_FALSE(hasCount, "nsDisplayScrollLayer should always be defined");
    2036               0 :   return result;
    2037                 : #else
    2038                 :   return reinterpret_cast<PRWord>(props.Get(nsIFrame::ScrollLayerCount()));
    2039                 : #endif
    2040                 : }
    2041                 : 
    2042                 : PRWord
    2043               0 : nsDisplayScrollLayer::RemoveScrollLayerCount()
    2044                 : {
    2045               0 :   PRWord result = GetScrollLayerCount();
    2046               0 :   FrameProperties props = mScrolledFrame->Properties();
    2047               0 :   props.Remove(nsIFrame::ScrollLayerCount());
    2048               0 :   return result;
    2049                 : }
    2050                 : 
    2051                 : 
    2052               0 : nsDisplayScrollInfoLayer::nsDisplayScrollInfoLayer(
    2053                 :   nsDisplayListBuilder* aBuilder,
    2054                 :   nsIFrame* aScrolledFrame,
    2055                 :   nsIFrame* aScrollFrame)
    2056               0 :   : nsDisplayScrollLayer(aBuilder, aScrolledFrame, aScrolledFrame, aScrollFrame)
    2057                 : {
    2058                 : #ifdef NS_BUILD_REFCNT_LOGGING
    2059               0 :   MOZ_COUNT_CTOR(nsDisplayScrollInfoLayer);
    2060                 : #endif
    2061               0 : }
    2062                 : 
    2063                 : #ifdef NS_BUILD_REFCNT_LOGGING
    2064               0 : nsDisplayScrollInfoLayer::~nsDisplayScrollInfoLayer()
    2065                 : {
    2066               0 :   MOZ_COUNT_DTOR(nsDisplayScrollInfoLayer);
    2067               0 : }
    2068                 : #endif
    2069                 : 
    2070                 : LayerState
    2071               0 : nsDisplayScrollInfoLayer::GetLayerState(nsDisplayListBuilder* aBuilder,
    2072                 :                                         LayerManager* aManager)
    2073                 : {
    2074               0 :   return LAYER_ACTIVE_EMPTY;
    2075                 : }
    2076                 : 
    2077                 : bool
    2078               0 : nsDisplayScrollInfoLayer::TryMerge(nsDisplayListBuilder* aBuilder,
    2079                 :                                    nsDisplayItem* aItem)
    2080                 : {
    2081               0 :   return false;
    2082                 : }
    2083                 : 
    2084                 : bool
    2085               0 : nsDisplayScrollInfoLayer::ShouldFlattenAway(nsDisplayListBuilder* aBuilder)
    2086                 : {
    2087                 :   // Layer metadata for a particular scroll frame needs to be unique. Only
    2088                 :   // one nsDisplayScrollLayer (with rendered content) or one
    2089                 :   // nsDisplayScrollInfoLayer (with only the metadata) should survive the
    2090                 :   // visibility computation. 
    2091               0 :   return RemoveScrollLayerCount() == 1;
    2092                 : }
    2093                 : 
    2094               0 : nsDisplayClip::nsDisplayClip(nsDisplayListBuilder* aBuilder,
    2095                 :                              nsIFrame* aFrame, nsDisplayItem* aItem,
    2096                 :                              const nsRect& aRect)
    2097               0 :    : nsDisplayWrapList(aBuilder, aFrame, aItem) {
    2098               0 :   MOZ_COUNT_CTOR(nsDisplayClip);
    2099               0 :   mClip = SnapBounds(aBuilder->IsSnappingEnabled() && !aBuilder->IsInTransform(),
    2100               0 :                      aBuilder->CurrentPresContext(), aRect);
    2101               0 : }
    2102                 : 
    2103               0 : nsDisplayClip::nsDisplayClip(nsDisplayListBuilder* aBuilder,
    2104                 :                              nsIFrame* aFrame, nsDisplayList* aList,
    2105                 :                              const nsRect& aRect)
    2106               0 :    : nsDisplayWrapList(aBuilder, aFrame, aList) {
    2107               0 :   MOZ_COUNT_CTOR(nsDisplayClip);
    2108               0 :   mClip = SnapBounds(aBuilder->IsSnappingEnabled() && !aBuilder->IsInTransform(),
    2109               0 :                      aBuilder->CurrentPresContext(), aRect);
    2110               0 : }
    2111                 : 
    2112               0 : nsRect nsDisplayClip::GetBounds(nsDisplayListBuilder* aBuilder) {
    2113               0 :   nsRect r = nsDisplayWrapList::GetBounds(aBuilder);
    2114               0 :   r.IntersectRect(mClip, r);
    2115                 :   return r;
    2116                 : }
    2117                 : 
    2118                 : #ifdef NS_BUILD_REFCNT_LOGGING
    2119               0 : nsDisplayClip::~nsDisplayClip() {
    2120               0 :   MOZ_COUNT_DTOR(nsDisplayClip);
    2121               0 : }
    2122                 : #endif
    2123                 : 
    2124               0 : void nsDisplayClip::Paint(nsDisplayListBuilder* aBuilder,
    2125                 :                           nsRenderingContext* aCtx) {
    2126               0 :   NS_ERROR("nsDisplayClip should have been flattened away for painting");
    2127               0 : }
    2128                 : 
    2129               0 : bool nsDisplayClip::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    2130                 :                                         nsRegion* aVisibleRegion,
    2131                 :                                         const nsRect& aAllowVisibleRegionExpansion) {
    2132               0 :   nsRegion clipped;
    2133               0 :   clipped.And(*aVisibleRegion, mClip);
    2134                 : 
    2135               0 :   nsRegion finalClipped(clipped);
    2136               0 :   nsRect allowExpansion;
    2137               0 :   allowExpansion.IntersectRect(mClip, aAllowVisibleRegionExpansion);
    2138                 :   bool anyVisible =
    2139                 :     nsDisplayWrapList::ComputeVisibility(aBuilder, &finalClipped,
    2140               0 :                                          allowExpansion);
    2141                 : 
    2142               0 :   nsRegion removed;
    2143               0 :   removed.Sub(clipped, finalClipped);
    2144               0 :   aBuilder->SubtractFromVisibleRegion(aVisibleRegion, removed);
    2145                 : 
    2146               0 :   return anyVisible;
    2147                 : }
    2148                 : 
    2149               0 : bool nsDisplayClip::TryMerge(nsDisplayListBuilder* aBuilder,
    2150                 :                                nsDisplayItem* aItem) {
    2151               0 :   if (aItem->GetType() != TYPE_CLIP)
    2152               0 :     return false;
    2153               0 :   nsDisplayClip* other = static_cast<nsDisplayClip*>(aItem);
    2154               0 :   if (!other->mClip.IsEqualInterior(mClip))
    2155               0 :     return false;
    2156               0 :   mList.AppendToBottom(&other->mList);
    2157               0 :   return true;
    2158                 : }
    2159                 : 
    2160               0 : nsDisplayWrapList* nsDisplayClip::WrapWithClone(nsDisplayListBuilder* aBuilder,
    2161                 :                                                 nsDisplayItem* aItem) {
    2162                 :   return new (aBuilder)
    2163               0 :     nsDisplayClip(aBuilder, aItem->GetUnderlyingFrame(), aItem, mClip);
    2164                 : }
    2165                 : 
    2166               0 : nsDisplayClipRoundedRect::nsDisplayClipRoundedRect(
    2167                 :                              nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
    2168                 :                              nsDisplayItem* aItem,
    2169                 :                              const nsRect& aRect, nscoord aRadii[8])
    2170               0 :     : nsDisplayClip(aBuilder, aFrame, aItem, aRect)
    2171                 : {
    2172               0 :   MOZ_COUNT_CTOR(nsDisplayClipRoundedRect);
    2173               0 :   memcpy(mRadii, aRadii, sizeof(mRadii));
    2174               0 : }
    2175                 : 
    2176               0 : nsDisplayClipRoundedRect::nsDisplayClipRoundedRect(
    2177                 :                              nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
    2178                 :                              nsDisplayList* aList,
    2179                 :                              const nsRect& aRect, nscoord aRadii[8])
    2180               0 :     : nsDisplayClip(aBuilder, aFrame, aList, aRect)
    2181                 : {
    2182               0 :   MOZ_COUNT_CTOR(nsDisplayClipRoundedRect);
    2183               0 :   memcpy(mRadii, aRadii, sizeof(mRadii));
    2184               0 : }
    2185                 : 
    2186                 : #ifdef NS_BUILD_REFCNT_LOGGING
    2187               0 : nsDisplayClipRoundedRect::~nsDisplayClipRoundedRect()
    2188                 : {
    2189               0 :   MOZ_COUNT_DTOR(nsDisplayClipRoundedRect);
    2190               0 : }
    2191                 : #endif
    2192                 : 
    2193                 : nsRegion
    2194               0 : nsDisplayClipRoundedRect::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
    2195                 :                                           bool* aForceTransparentSurface)
    2196                 : {
    2197               0 :   if (aForceTransparentSurface) {
    2198               0 :     *aForceTransparentSurface = false;
    2199                 :   }
    2200               0 :   return nsRegion();
    2201                 : }
    2202                 : 
    2203                 : void
    2204               0 : nsDisplayClipRoundedRect::HitTest(nsDisplayListBuilder* aBuilder,
    2205                 :                                   const nsRect& aRect, HitTestState* aState,
    2206                 :                                   nsTArray<nsIFrame*> *aOutFrames)
    2207                 : {
    2208               0 :   if (!RoundedRectIntersectsRect(mClip, mRadii, aRect)) {
    2209                 :     // aRect doesn't intersect our border-radius curve.
    2210                 : 
    2211                 :     // FIXME: This isn't quite sufficient for aRect having nontrivial
    2212                 :     // size (which is the unusual case here), since it's possible that
    2213                 :     // the part of aRect that intersects the the rounded rect isn't the
    2214                 :     // part that intersects the items in mList.
    2215               0 :     return;
    2216                 :   }
    2217                 : 
    2218               0 :   mList.HitTest(aBuilder, aRect, aState, aOutFrames);
    2219                 : }
    2220                 : 
    2221                 : nsDisplayWrapList*
    2222               0 : nsDisplayClipRoundedRect::WrapWithClone(nsDisplayListBuilder* aBuilder,
    2223                 :                                         nsDisplayItem* aItem) {
    2224                 :   return new (aBuilder)
    2225                 :     nsDisplayClipRoundedRect(aBuilder, aItem->GetUnderlyingFrame(), aItem,
    2226               0 :                              mClip, mRadii);
    2227                 : }
    2228                 : 
    2229               0 : bool nsDisplayClipRoundedRect::ComputeVisibility(
    2230                 :                                     nsDisplayListBuilder* aBuilder,
    2231                 :                                     nsRegion* aVisibleRegion,
    2232                 :                                     const nsRect& aAllowVisibleRegionExpansion)
    2233                 : {
    2234               0 :   nsRegion clipped;
    2235               0 :   clipped.And(*aVisibleRegion, mClip);
    2236                 : 
    2237               0 :   return nsDisplayWrapList::ComputeVisibility(aBuilder, &clipped, nsRect());
    2238                 :   // FIXME: Remove a *conservative* opaque region from aVisibleRegion
    2239                 :   // (like in nsDisplayClip::ComputeVisibility).
    2240                 : }
    2241                 : 
    2242               0 : bool nsDisplayClipRoundedRect::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem)
    2243                 : {
    2244               0 :   if (aItem->GetType() != TYPE_CLIP_ROUNDED_RECT)
    2245               0 :     return false;
    2246                 :   nsDisplayClipRoundedRect* other =
    2247               0 :     static_cast<nsDisplayClipRoundedRect*>(aItem);
    2248               0 :   if (!mClip.IsEqualInterior(other->mClip) ||
    2249               0 :       memcmp(mRadii, other->mRadii, sizeof(mRadii)) != 0)
    2250               0 :     return false;
    2251               0 :   mList.AppendToBottom(&other->mList);
    2252               0 :   return true;
    2253                 : }
    2254                 : 
    2255               0 : nsDisplayZoom::nsDisplayZoom(nsDisplayListBuilder* aBuilder,
    2256                 :                              nsIFrame* aFrame, nsDisplayList* aList,
    2257                 :                              PRInt32 aAPD, PRInt32 aParentAPD)
    2258                 :     : nsDisplayOwnLayer(aBuilder, aFrame, aList), mAPD(aAPD),
    2259               0 :       mParentAPD(aParentAPD) {
    2260               0 :   MOZ_COUNT_CTOR(nsDisplayZoom);
    2261               0 : }
    2262                 : 
    2263                 : #ifdef NS_BUILD_REFCNT_LOGGING
    2264               0 : nsDisplayZoom::~nsDisplayZoom() {
    2265               0 :   MOZ_COUNT_DTOR(nsDisplayZoom);
    2266               0 : }
    2267                 : #endif
    2268                 : 
    2269               0 : nsRect nsDisplayZoom::GetBounds(nsDisplayListBuilder* aBuilder)
    2270                 : {
    2271               0 :   nsRect bounds = nsDisplayWrapList::GetBounds(aBuilder);
    2272               0 :   return bounds.ConvertAppUnitsRoundOut(mAPD, mParentAPD);
    2273                 : }
    2274                 : 
    2275               0 : void nsDisplayZoom::HitTest(nsDisplayListBuilder *aBuilder,
    2276                 :                             const nsRect& aRect,
    2277                 :                             HitTestState *aState,
    2278                 :                             nsTArray<nsIFrame*> *aOutFrames)
    2279                 : {
    2280               0 :   nsRect rect;
    2281                 :   // A 1x1 rect indicates we are just hit testing a point, so pass down a 1x1
    2282                 :   // rect as well instead of possibly rounding the width or height to zero.
    2283               0 :   if (aRect.width == 1 && aRect.height == 1) {
    2284               0 :     rect.MoveTo(aRect.TopLeft().ConvertAppUnits(mParentAPD, mAPD));
    2285               0 :     rect.width = rect.height = 1;
    2286                 :   } else {
    2287               0 :     rect = aRect.ConvertAppUnitsRoundOut(mParentAPD, mAPD);
    2288                 :   }
    2289               0 :   mList.HitTest(aBuilder, rect, aState, aOutFrames);
    2290               0 : }
    2291                 : 
    2292               0 : void nsDisplayZoom::Paint(nsDisplayListBuilder* aBuilder,
    2293                 :                           nsRenderingContext* aCtx)
    2294                 : {
    2295               0 :   mList.PaintForFrame(aBuilder, aCtx, mFrame, nsDisplayList::PAINT_DEFAULT);
    2296               0 : }
    2297                 : 
    2298               0 : bool nsDisplayZoom::ComputeVisibility(nsDisplayListBuilder *aBuilder,
    2299                 :                                         nsRegion *aVisibleRegion,
    2300                 :                                         const nsRect& aAllowVisibleRegionExpansion)
    2301                 : {
    2302                 :   // Convert the passed in visible region to our appunits.
    2303                 :   nsRegion visibleRegion =
    2304               0 :     aVisibleRegion->ConvertAppUnitsRoundOut(mParentAPD, mAPD);
    2305               0 :   nsRegion originalVisibleRegion = visibleRegion;
    2306                 : 
    2307                 :   nsRect transformedVisibleRect =
    2308               0 :     mVisibleRect.ConvertAppUnitsRoundOut(mParentAPD, mAPD);
    2309                 :   nsRect allowExpansion =
    2310               0 :     aAllowVisibleRegionExpansion.ConvertAppUnitsRoundIn(mParentAPD, mAPD);
    2311                 :   bool retval =
    2312                 :     mList.ComputeVisibilityForSublist(aBuilder, &visibleRegion,
    2313                 :                                       transformedVisibleRect,
    2314               0 :                                       allowExpansion);
    2315                 : 
    2316               0 :   nsRegion removed;
    2317                 :   // removed = originalVisibleRegion - visibleRegion
    2318               0 :   removed.Sub(originalVisibleRegion, visibleRegion);
    2319                 :   // Convert removed region to parent appunits.
    2320               0 :   removed = removed.ConvertAppUnitsRoundIn(mAPD, mParentAPD);
    2321                 :   // aVisibleRegion = aVisibleRegion - removed (modulo any simplifications
    2322                 :   // SubtractFromVisibleRegion does)
    2323               0 :   aBuilder->SubtractFromVisibleRegion(aVisibleRegion, removed);
    2324                 : 
    2325               0 :   return retval;
    2326                 : }
    2327                 : 
    2328                 : ///////////////////////////////////////////////////
    2329                 : // nsDisplayTransform Implementation
    2330                 : //
    2331                 : 
    2332                 : // Write #define UNIFIED_CONTINUATIONS here to have the transform property try
    2333                 : // to transform content with continuations as one unified block instead of
    2334                 : // several smaller ones.  This is currently disabled because it doesn't work
    2335                 : // correctly, since when the frames are initially being reflowed, their
    2336                 : // continuations all compute their bounding rects independently of each other
    2337                 : // and consequently get the wrong value.  Write #define DEBUG_HIT here to have
    2338                 : // the nsDisplayTransform class dump out a bunch of information about hit
    2339                 : // detection.
    2340                 : #undef  UNIFIED_CONTINUATIONS
    2341                 : #undef  DEBUG_HIT
    2342                 : 
    2343                 : /* Returns the bounds of a frame as defined for transforms.  If
    2344                 :  * UNIFIED_CONTINUATIONS is not defined, this is simply the frame's bounding
    2345                 :  * rectangle, translated to the origin. Otherwise, returns the smallest
    2346                 :  * rectangle containing a frame and all of its continuations.  For example, if
    2347                 :  * there is a <span> element with several continuations split over several
    2348                 :  * lines, this function will return the rectangle containing all of those
    2349                 :  * continuations.  This rectangle is relative to the origin of the frame's local
    2350                 :  * coordinate space.
    2351                 :  */
    2352                 : #ifndef UNIFIED_CONTINUATIONS
    2353                 : 
    2354                 : nsRect
    2355               0 : nsDisplayTransform::GetFrameBoundsForTransform(const nsIFrame* aFrame)
    2356                 : {
    2357               0 :   NS_PRECONDITION(aFrame, "Can't get the bounds of a nonexistent frame!");
    2358               0 :   return nsRect(nsPoint(0, 0), aFrame->GetSize());
    2359                 : }
    2360                 : 
    2361                 : #else
    2362                 : 
    2363                 : nsRect
    2364                 : nsDisplayTransform::GetFrameBoundsForTransform(const nsIFrame* aFrame)
    2365                 : {
    2366                 :   NS_PRECONDITION(aFrame, "Can't get the bounds of a nonexistent frame!");
    2367                 : 
    2368                 :   nsRect result;
    2369                 :   
    2370                 :   /* Iterate through the continuation list, unioning together all the
    2371                 :    * bounding rects.
    2372                 :    */
    2373                 :   for (const nsIFrame *currFrame = aFrame->GetFirstContinuation();
    2374                 :        currFrame != nsnull;
    2375                 :        currFrame = currFrame->GetNextContinuation())
    2376                 :     {
    2377                 :       /* Get the frame rect in local coordinates, then translate back to the
    2378                 :        * original coordinates.
    2379                 :        */
    2380                 :       result.UnionRect(result, nsRect(currFrame->GetOffsetTo(aFrame),
    2381                 :                                       currFrame->GetSize()));
    2382                 :     }
    2383                 : 
    2384                 :   return result;
    2385                 : }
    2386                 : 
    2387                 : #endif
    2388                 : 
    2389                 : /* Returns the delta specified by the -moz-transform-origin property.
    2390                 :  * This is a positive delta, meaning that it indicates the direction to move
    2391                 :  * to get from (0, 0) of the frame to the transform origin.
    2392                 :  */
    2393                 : static
    2394               0 : gfxPoint3D GetDeltaToMozTransformOrigin(const nsIFrame* aFrame,
    2395                 :                                         float aAppUnitsPerPixel,
    2396                 :                                         const nsRect* aBoundsOverride)
    2397                 : {
    2398               0 :   NS_PRECONDITION(aFrame, "Can't get delta for a null frame!");
    2399               0 :   NS_PRECONDITION(aFrame->GetStyleDisplay()->HasTransform(),
    2400                 :                   "Can't get a delta for an untransformed frame!");
    2401                 : 
    2402                 :   /* For both of the coordinates, if the value of -moz-transform is a
    2403                 :    * percentage, it's relative to the size of the frame.  Otherwise, if it's
    2404                 :    * a distance, it's already computed for us!
    2405                 :    */
    2406               0 :   const nsStyleDisplay* display = aFrame->GetStyleDisplay();
    2407                 :   nsRect boundingRect = (aBoundsOverride ? *aBoundsOverride :
    2408               0 :                          nsDisplayTransform::GetFrameBoundsForTransform(aFrame));
    2409                 : 
    2410                 :   /* Allows us to access named variables by index. */
    2411               0 :   gfxPoint3D result;
    2412               0 :   gfxFloat* coords[3] = {&result.x, &result.y, &result.z};
    2413                 :   const nscoord* dimensions[2] =
    2414               0 :     {&boundingRect.width, &boundingRect.height};
    2415                 : 
    2416               0 :   for (PRUint8 index = 0; index < 2; ++index) {
    2417                 :     /* If the -moz-transform-origin specifies a percentage, take the percentage
    2418                 :      * of the size of the box.
    2419                 :      */
    2420               0 :     const nsStyleCoord &coord = display->mTransformOrigin[index];
    2421               0 :     if (coord.GetUnit() == eStyleUnit_Calc) {
    2422               0 :       const nsStyleCoord::Calc *calc = coord.GetCalcValue();
    2423               0 :       *coords[index] =
    2424               0 :         NSAppUnitsToFloatPixels(*dimensions[index], aAppUnitsPerPixel) *
    2425                 :           calc->mPercent +
    2426               0 :         NSAppUnitsToFloatPixels(calc->mLength, aAppUnitsPerPixel);
    2427               0 :     } else if (coord.GetUnit() == eStyleUnit_Percent) {
    2428               0 :       *coords[index] =
    2429               0 :         NSAppUnitsToFloatPixels(*dimensions[index], aAppUnitsPerPixel) *
    2430               0 :         coord.GetPercentValue();
    2431                 :     } else {
    2432               0 :       NS_ABORT_IF_FALSE(coord.GetUnit() == eStyleUnit_Coord, "unexpected unit");
    2433               0 :       *coords[index] =
    2434               0 :         NSAppUnitsToFloatPixels(coord.GetCoordValue(), aAppUnitsPerPixel);
    2435                 :     }
    2436                 :   }
    2437                 : 
    2438               0 :   *coords[2] = NSAppUnitsToFloatPixels(display->mTransformOrigin[2].GetCoordValue(),
    2439               0 :                                        aAppUnitsPerPixel);
    2440                 :   /* Adjust based on the origin of the rectangle. */
    2441               0 :   result.x += NSAppUnitsToFloatPixels(boundingRect.x, aAppUnitsPerPixel);
    2442               0 :   result.y += NSAppUnitsToFloatPixels(boundingRect.y, aAppUnitsPerPixel);
    2443                 : 
    2444                 :   return result;
    2445                 : }
    2446                 : 
    2447                 : /* Returns the delta specified by the -moz-perspective-origin property.
    2448                 :  * This is a positive delta, meaning that it indicates the direction to move
    2449                 :  * to get from (0, 0) of the frame to the perspective origin.
    2450                 :  */
    2451                 : static
    2452               0 : gfxPoint3D GetDeltaToMozPerspectiveOrigin(const nsIFrame* aFrame,
    2453                 :                                           float aAppUnitsPerPixel)
    2454                 : {
    2455               0 :   NS_PRECONDITION(aFrame, "Can't get delta for a null frame!");
    2456               0 :   NS_PRECONDITION(aFrame->GetStyleDisplay()->HasTransform(),
    2457                 :                   "Can't get a delta for an untransformed frame!");
    2458               0 :   NS_PRECONDITION(aFrame->GetParentStyleContextFrame(), 
    2459                 :                   "Can't get delta without a style parent!");
    2460                 : 
    2461                 :   /* For both of the coordinates, if the value of -moz-perspective-origin is a
    2462                 :    * percentage, it's relative to the size of the frame.  Otherwise, if it's
    2463                 :    * a distance, it's already computed for us!
    2464                 :    */
    2465                 : 
    2466                 :   //TODO: Should this be using our bounds or the parent's bounds?
    2467                 :   // How do we handle aBoundsOverride in the latter case?
    2468               0 :   nsIFrame* parent = aFrame->GetParentStyleContextFrame();
    2469               0 :   const nsStyleDisplay* display = aFrame->GetParent()->GetStyleDisplay();
    2470               0 :   nsRect boundingRect = nsDisplayTransform::GetFrameBoundsForTransform(parent);
    2471                 : 
    2472                 :   /* Allows us to access named variables by index. */
    2473               0 :   gfxPoint3D result;
    2474               0 :   result.z = 0.0f;
    2475               0 :   gfxFloat* coords[2] = {&result.x, &result.y};
    2476                 :   const nscoord* dimensions[2] =
    2477               0 :     {&boundingRect.width, &boundingRect.height};
    2478                 : 
    2479               0 :   for (PRUint8 index = 0; index < 2; ++index) {
    2480                 :     /* If the -moz-transform-origin specifies a percentage, take the percentage
    2481                 :      * of the size of the box.
    2482                 :      */
    2483               0 :     const nsStyleCoord &coord = display->mPerspectiveOrigin[index];
    2484               0 :     if (coord.GetUnit() == eStyleUnit_Calc) {
    2485               0 :       const nsStyleCoord::Calc *calc = coord.GetCalcValue();
    2486               0 :       *coords[index] =
    2487               0 :         NSAppUnitsToFloatPixels(*dimensions[index], aAppUnitsPerPixel) *
    2488                 :           calc->mPercent +
    2489               0 :         NSAppUnitsToFloatPixels(calc->mLength, aAppUnitsPerPixel);
    2490               0 :     } else if (coord.GetUnit() == eStyleUnit_Percent) {
    2491               0 :       *coords[index] =
    2492               0 :         NSAppUnitsToFloatPixels(*dimensions[index], aAppUnitsPerPixel) *
    2493               0 :         coord.GetPercentValue();
    2494                 :     } else {
    2495               0 :       NS_ABORT_IF_FALSE(coord.GetUnit() == eStyleUnit_Coord, "unexpected unit");
    2496               0 :       *coords[index] =
    2497               0 :         NSAppUnitsToFloatPixels(coord.GetCoordValue(), aAppUnitsPerPixel);
    2498                 :     }
    2499                 :   }
    2500                 : 
    2501               0 :   nsPoint parentOffset = aFrame->GetOffsetTo(parent);
    2502                 :   gfxPoint3D gfxOffset(
    2503               0 :                NSAppUnitsToFloatPixels(parentOffset.x, aAppUnitsPerPixel),
    2504               0 :                NSAppUnitsToFloatPixels(parentOffset.y, aAppUnitsPerPixel),
    2505               0 :                0.0f);
    2506                 : 
    2507               0 :   return result - gfxOffset;
    2508                 : }
    2509                 : 
    2510                 : /* Wraps up the -moz-transform matrix in a change-of-basis matrix pair that
    2511                 :  * translates from local coordinate space to transform coordinate space, then
    2512                 :  * hands it back.
    2513                 :  */
    2514                 : gfx3DMatrix
    2515               0 : nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
    2516                 :                                                 const nsPoint &aOrigin,
    2517                 :                                                 float aAppUnitsPerPixel,
    2518                 :                                                 const nsRect* aBoundsOverride,
    2519                 :                                                 nsIFrame** aOutAncestor)
    2520                 : {
    2521               0 :   NS_PRECONDITION(aFrame, "Cannot get transform matrix for a null frame!");
    2522                 : 
    2523               0 :   if (aOutAncestor) {
    2524               0 :       *aOutAncestor = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
    2525                 :   }
    2526                 : 
    2527                 :   /* Account for the -moz-transform-origin property by translating the
    2528                 :    * coordinate space to the new origin.
    2529                 :    */
    2530                 :   gfxPoint3D toMozOrigin =
    2531               0 :     GetDeltaToMozTransformOrigin(aFrame, aAppUnitsPerPixel, aBoundsOverride);
    2532                 :   gfxPoint3D newOrigin =
    2533               0 :     gfxPoint3D(NSAppUnitsToFloatPixels(aOrigin.x, aAppUnitsPerPixel),
    2534               0 :                NSAppUnitsToFloatPixels(aOrigin.y, aAppUnitsPerPixel),
    2535               0 :                0.0f);
    2536                 : 
    2537                 :   /* Get the underlying transform matrix.  This requires us to get the
    2538                 :    * bounds of the frame.
    2539                 :    */
    2540               0 :   const nsStyleDisplay* disp = aFrame->GetStyleDisplay();
    2541                 :   nsRect bounds = (aBoundsOverride ? *aBoundsOverride :
    2542               0 :                    nsDisplayTransform::GetFrameBoundsForTransform(aFrame));
    2543                 : 
    2544                 :   /* Get the matrix, then change its basis to factor in the origin. */
    2545                 :   bool dummy;
    2546               0 :   gfx3DMatrix result;
    2547                 :   /* Transformed frames always have a transform, or are preserving 3d (and might still have perspective!) */
    2548               0 :   if (disp->mSpecifiedTransform) {
    2549                 :     result = nsStyleTransformMatrix::ReadTransforms(disp->mSpecifiedTransform,
    2550                 :                                                     aFrame->GetStyleContext(),
    2551                 :                                                     aFrame->PresContext(),
    2552               0 :                                                     dummy, bounds, aAppUnitsPerPixel);
    2553                 :   } else {
    2554               0 :      NS_ASSERTION(aFrame->GetStyleDisplay()->mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
    2555                 :                   aFrame->GetStyleDisplay()->mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN,
    2556                 :                   "If we don't have a transform, then we must have another reason to have an nsDisplayTransform created");
    2557                 :   }
    2558                 : 
    2559               0 :   const nsStyleDisplay* parentDisp = nsnull;
    2560               0 :   nsStyleContext* parentStyleContext = aFrame->GetStyleContext()->GetParent();
    2561               0 :   if (parentStyleContext) {
    2562               0 :     parentDisp = parentStyleContext->GetStyleDisplay();
    2563                 :   }
    2564               0 :   if (nsLayoutUtils::Are3DTransformsEnabled() &&
    2565               0 :       parentDisp && parentDisp->mChildPerspective.GetUnit() == eStyleUnit_Coord &&
    2566               0 :       parentDisp->mChildPerspective.GetCoordValue() > 0.0) {
    2567               0 :     gfx3DMatrix perspective;
    2568                 :     perspective._34 =
    2569                 :       -1.0 / NSAppUnitsToFloatPixels(parentDisp->mChildPerspective.GetCoordValue(),
    2570               0 :                                      aAppUnitsPerPixel);
    2571                 :     /* At the point when perspective is applied, we have been translated to the transform origin.
    2572                 :      * The translation to the perspective origin is the difference between these values.
    2573                 :      */
    2574               0 :     gfxPoint3D toPerspectiveOrigin = GetDeltaToMozPerspectiveOrigin(aFrame, aAppUnitsPerPixel);
    2575               0 :     result = result * nsLayoutUtils::ChangeMatrixBasis(toPerspectiveOrigin - toMozOrigin, perspective);
    2576                 :   }
    2577                 : 
    2578               0 :   if (aFrame->Preserves3D() && nsLayoutUtils::Are3DTransformsEnabled()) {
    2579                 :       // Include the transform set on our parent
    2580               0 :       NS_ASSERTION(aFrame->GetParent() &&
    2581                 :                    aFrame->GetParent()->IsTransformed() &&
    2582                 :                    aFrame->GetParent()->Preserves3DChildren(),
    2583                 :                    "Preserve3D mismatch!");
    2584               0 :       gfx3DMatrix parent = GetResultingTransformMatrix(aFrame->GetParent(), aOrigin - aFrame->GetPosition(),
    2585               0 :                                                        aAppUnitsPerPixel, nsnull, aOutAncestor);
    2586               0 :       return nsLayoutUtils::ChangeMatrixBasis(newOrigin + toMozOrigin, result) * parent;
    2587                 :   }
    2588                 : 
    2589                 :   return nsLayoutUtils::ChangeMatrixBasis
    2590               0 :     (newOrigin + toMozOrigin, result);
    2591                 : }
    2592                 : 
    2593                 : bool
    2594               0 : nsDisplayTransform::ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBuilder,
    2595                 :                                                       nsIFrame* aFrame)
    2596                 : {
    2597               0 :   if (aFrame->AreLayersMarkedActive(nsChangeHint_UpdateTransformLayer)) {
    2598               0 :     nsSize refSize = aBuilder->ReferenceFrame()->GetSize();
    2599                 :     // Only prerender if the transformed frame's size is <= the
    2600                 :     // reference frame size (~viewport), allowing a 1/8th fuzz factor
    2601                 :     // for shadows, borders, etc.
    2602               0 :     refSize += nsSize(refSize.width / 8, refSize.height / 8);
    2603               0 :     if (aFrame->GetVisualOverflowRectRelativeToSelf().Size() <= refSize) {
    2604                 :       // Bug 717521 - pre-render max 4096 x 4096 device pixels.
    2605               0 :       nscoord max = aFrame->PresContext()->DevPixelsToAppUnits(4096);
    2606               0 :       nsRect visual = aFrame->GetVisualOverflowRect();
    2607               0 :       if (visual.width <= max && visual.height <= max) {
    2608               0 :         return true;
    2609                 :       }
    2610                 :     }
    2611                 :   }
    2612               0 :   return false;
    2613                 : }
    2614                 : 
    2615                 : /* If the matrix is singular, or a hidden backface is shown, the frame won't be visible or hit. */
    2616               0 : static bool IsFrameVisible(nsIFrame* aFrame, const gfx3DMatrix& aMatrix) 
    2617                 : {
    2618               0 :   if (aMatrix.IsSingular()) {
    2619               0 :     return false;
    2620                 :   }
    2621               0 :   if (aFrame->GetStyleDisplay()->mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN &&
    2622               0 :       aMatrix.IsBackfaceVisible()) {
    2623               0 :     return false;
    2624                 :   }
    2625               0 :   return true;
    2626                 : }
    2627                 : 
    2628                 : const gfx3DMatrix&
    2629               0 : nsDisplayTransform::GetTransform(float aAppUnitsPerPixel)
    2630                 : {
    2631               0 :   if (mTransform.IsIdentity() || mCachedAppUnitsPerPixel != aAppUnitsPerPixel) {
    2632                 :     mTransform =
    2633               0 :       GetResultingTransformMatrix(mFrame, ToReferenceFrame(),
    2634                 :                                   aAppUnitsPerPixel,
    2635               0 :                                   nsnull);
    2636               0 :     mCachedAppUnitsPerPixel = aAppUnitsPerPixel;
    2637                 :   }
    2638               0 :   return mTransform;
    2639                 : }
    2640                 : 
    2641               0 : already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBuilder,
    2642                 :                                                        LayerManager *aManager,
    2643                 :                                                        const ContainerParameters& aContainerParameters)
    2644                 : {
    2645                 :   const gfx3DMatrix& newTransformMatrix = 
    2646               0 :     GetTransform(mFrame->PresContext()->AppUnitsPerDevPixel());
    2647                 : 
    2648               0 :   if (!IsFrameVisible(mFrame, newTransformMatrix)) {
    2649               0 :     return nsnull;
    2650                 :   }
    2651                 : 
    2652                 :   nsRefPtr<ContainerLayer> container = aBuilder->LayerBuilder()->
    2653               0 :     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, *mStoredList.GetList(),
    2654               0 :                            aContainerParameters, &newTransformMatrix);
    2655                 : 
    2656                 :   // Add the preserve-3d flag for this layer, BuildContainerLayerFor clears all flags,
    2657                 :   // so we never need to explicitely unset this flag.
    2658               0 :   if (mFrame->Preserves3D() || mFrame->Preserves3DChildren()) {
    2659               0 :     container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_PRESERVE_3D);
    2660                 :   }
    2661               0 :   return container.forget();
    2662                 : }
    2663                 : 
    2664                 : nsDisplayItem::LayerState
    2665               0 : nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
    2666                 :                                   LayerManager* aManager) {
    2667                 :   // Here we check if the *post-transform* bounds of this item are big enough
    2668                 :   // to justify an active layer.
    2669               0 :   if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateTransformLayer) &&
    2670               0 :       !IsItemTooSmallForActiveLayer(this))
    2671               0 :     return LAYER_ACTIVE;
    2672               0 :   if (!GetTransform(mFrame->PresContext()->AppUnitsPerDevPixel()).Is2D() || mFrame->Preserves3D())
    2673               0 :     return LAYER_ACTIVE;
    2674                 :   nsIFrame* activeScrolledRoot =
    2675               0 :     nsLayoutUtils::GetActiveScrolledRootFor(mFrame, nsnull);
    2676                 :   return !mStoredList.ChildrenCanBeInactive(aBuilder, 
    2677                 :                                              aManager, 
    2678               0 :                                              *mStoredList.GetList(), 
    2679               0 :                                              activeScrolledRoot)
    2680               0 :       ? LAYER_ACTIVE : LAYER_INACTIVE;
    2681                 : }
    2682                 : 
    2683               0 : bool nsDisplayTransform::ComputeVisibility(nsDisplayListBuilder *aBuilder,
    2684                 :                                              nsRegion *aVisibleRegion,
    2685                 :                                              const nsRect& aAllowVisibleRegionExpansion)
    2686                 : {
    2687                 :   /* As we do this, we need to be sure to
    2688                 :    * untransform the visible rect, since we want everything that's painting to
    2689                 :    * think that it's painting in its original rectangular coordinate space.
    2690                 :    * If we can't untransform, take the entire overflow rect */
    2691               0 :   nsRect untransformedVisibleRect;
    2692               0 :   float factor = nsPresContext::AppUnitsPerCSSPixel();
    2693               0 :   if (ShouldPrerenderTransformedContent(aBuilder, mFrame) ||
    2694                 :       !UntransformRectMatrix(mVisibleRect,
    2695               0 :                              GetTransform(factor),
    2696                 :                              factor,
    2697               0 :                              &untransformedVisibleRect)) 
    2698                 :   {
    2699               0 :     untransformedVisibleRect = mFrame->GetVisualOverflowRectRelativeToSelf() +  
    2700               0 :                                aBuilder->ToReferenceFrame(mFrame);
    2701                 :   }
    2702               0 :   nsRegion untransformedVisible = untransformedVisibleRect;
    2703                 :   // Call RecomputeVisiblity instead of ComputeVisibility since
    2704                 :   // nsDisplayItem::ComputeVisibility should only be called from
    2705                 :   // nsDisplayList::ComputeVisibility (which sets mVisibleRect on the item)
    2706               0 :   mStoredList.RecomputeVisibility(aBuilder, &untransformedVisible);
    2707               0 :   return true;
    2708                 : }
    2709                 : 
    2710                 : #ifdef DEBUG_HIT
    2711                 : #include <time.h>
    2712                 : #endif
    2713                 : 
    2714                 : /* HitTest does some fun stuff with matrix transforms to obtain the answer. */
    2715               0 : void nsDisplayTransform::HitTest(nsDisplayListBuilder *aBuilder,
    2716                 :                                  const nsRect& aRect,
    2717                 :                                  HitTestState *aState,
    2718                 :                                  nsTArray<nsIFrame*> *aOutFrames)
    2719                 : {
    2720                 :   /* Here's how this works:
    2721                 :    * 1. Get the matrix.  If it's singular, abort (clearly we didn't hit
    2722                 :    *    anything).
    2723                 :    * 2. Invert the matrix.
    2724                 :    * 3. Use it to transform the rect into the correct space.
    2725                 :    * 4. Pass that rect down through to the list's version of HitTest.
    2726                 :    */
    2727               0 :   float factor = nsPresContext::AppUnitsPerCSSPixel();
    2728               0 :   gfx3DMatrix matrix = GetTransform(factor);
    2729                 : 
    2730               0 :   if (!IsFrameVisible(mFrame, matrix)) {
    2731               0 :     return;
    2732                 :   }
    2733                 : 
    2734                 :   /* We want to go from transformed-space to regular space.
    2735                 :    * Thus we have to invert the matrix, which normally does
    2736                 :    * the reverse operation (e.g. regular->transformed)
    2737                 :    */
    2738                 : 
    2739                 :   /* Now, apply the transform and pass it down the channel. */
    2740               0 :   nsRect resultingRect;
    2741               0 :   if (aRect.width == 1 && aRect.height == 1) {
    2742                 :     // Magic width/height indicating we're hit testing a point, not a rect
    2743                 :     gfxPoint point = matrix.Inverse().ProjectPoint(
    2744               0 :                        gfxPoint(NSAppUnitsToFloatPixels(aRect.x, factor),
    2745               0 :                                 NSAppUnitsToFloatPixels(aRect.y, factor)));
    2746                 : 
    2747                 :     resultingRect = nsRect(NSFloatPixelsToAppUnits(float(point.x), factor),
    2748                 :                            NSFloatPixelsToAppUnits(float(point.y), factor),
    2749               0 :                            1, 1);
    2750                 : 
    2751                 :   } else {
    2752               0 :     gfxRect originalRect(NSAppUnitsToFloatPixels(aRect.x, factor),
    2753               0 :                          NSAppUnitsToFloatPixels(aRect.y, factor),
    2754               0 :                          NSAppUnitsToFloatPixels(aRect.width, factor),
    2755               0 :                          NSAppUnitsToFloatPixels(aRect.height, factor));
    2756                 : 
    2757               0 :     gfxRect rect = matrix.Inverse().ProjectRectBounds(originalRect);;
    2758                 : 
    2759               0 :     resultingRect = nsRect(NSFloatPixelsToAppUnits(float(rect.X()), factor),
    2760               0 :                            NSFloatPixelsToAppUnits(float(rect.Y()), factor),
    2761               0 :                            NSFloatPixelsToAppUnits(float(rect.Width()), factor),
    2762               0 :                            NSFloatPixelsToAppUnits(float(rect.Height()), factor));
    2763                 :   }
    2764                 :   
    2765                 : 
    2766                 : #ifdef DEBUG_HIT
    2767                 :   printf("Frame: %p\n", dynamic_cast<void *>(mFrame));
    2768                 :   printf("  Untransformed point: (%f, %f)\n", resultingRect.X(), resultingRect.Y());
    2769                 :   PRUint32 originalFrameCount = aOutFrames.Length();
    2770                 : #endif
    2771                 : 
    2772               0 :   mStoredList.HitTest(aBuilder, resultingRect, aState, aOutFrames);
    2773                 : 
    2774                 : #ifdef DEBUG_HIT
    2775                 :   if (originalFrameCount != aOutFrames.Length())
    2776                 :     printf("  Hit! Time: %f, first frame: %p\n", static_cast<double>(clock()),
    2777                 :            dynamic_cast<void *>(aOutFrames.ElementAt(0)));
    2778                 :   printf("=== end of hit test ===\n");
    2779                 : #endif
    2780                 : 
    2781                 : }
    2782                 : 
    2783                 : float
    2784               0 : nsDisplayTransform::GetHitDepthAtPoint(const nsPoint& aPoint)
    2785                 : {
    2786               0 :   float factor = nsPresContext::AppUnitsPerCSSPixel();
    2787               0 :   gfx3DMatrix matrix = GetTransform(factor);
    2788                 : 
    2789               0 :   NS_ASSERTION(IsFrameVisible(mFrame, matrix), "We can't have hit a frame that isn't visible!");
    2790                 :     
    2791                 :   gfxPoint point = 
    2792               0 :     matrix.Inverse().ProjectPoint(gfxPoint(NSAppUnitsToFloatPixels(aPoint.x, factor),
    2793               0 :                                            NSAppUnitsToFloatPixels(aPoint.y, factor)));
    2794                 : 
    2795               0 :   gfxPoint3D transformed = matrix.Transform3D(gfxPoint3D(point.x, point.y, 0));
    2796               0 :   return transformed.z;
    2797                 : }
    2798                 : 
    2799                 : /* The bounding rectangle for the object is the overflow rectangle translated
    2800                 :  * by the reference point.
    2801                 :  */
    2802               0 : nsRect nsDisplayTransform::GetBounds(nsDisplayListBuilder *aBuilder)
    2803                 : {
    2804                 :   nsRect untransformedBounds =
    2805               0 :     ShouldPrerenderTransformedContent(aBuilder, mFrame) ?
    2806               0 :     mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame() :
    2807               0 :     mStoredList.GetBounds(aBuilder);
    2808               0 :   float factor = nsPresContext::AppUnitsPerCSSPixel();
    2809                 :   return nsLayoutUtils::MatrixTransformRect(untransformedBounds,
    2810               0 :                                             GetTransform(factor),
    2811               0 :                                             factor);
    2812                 : }
    2813                 : 
    2814                 : /* The transform is opaque iff the transform consists solely of scales and
    2815                 :  * translations and if the underlying content is opaque.  Thus if the transform
    2816                 :  * is of the form
    2817                 :  *
    2818                 :  * |a c e|
    2819                 :  * |b d f|
    2820                 :  * |0 0 1|
    2821                 :  *
    2822                 :  * We need b and c to be zero.
    2823                 :  *
    2824                 :  * We also need to check whether the underlying opaque content completely fills
    2825                 :  * our visible rect. We use UntransformRect which expands to the axis-aligned
    2826                 :  * bounding rect, but that's OK since if
    2827                 :  * mStoredList.GetVisibleRect().Contains(untransformedVisible), then it
    2828                 :  * certainly contains the actual (non-axis-aligned) untransformed rect.
    2829                 :  */
    2830               0 : nsRegion nsDisplayTransform::GetOpaqueRegion(nsDisplayListBuilder *aBuilder,
    2831                 :                                              bool* aForceTransparentSurface)
    2832                 : {
    2833               0 :   if (aForceTransparentSurface) {
    2834               0 :     *aForceTransparentSurface = false;
    2835                 :   }
    2836               0 :   nsRect untransformedVisible;
    2837               0 :   float factor = nsPresContext::AppUnitsPerCSSPixel();
    2838               0 :   if (!UntransformRectMatrix(mVisibleRect, GetTransform(factor), factor, &untransformedVisible)) {
    2839               0 :       return nsRegion();
    2840                 :   }
    2841                 :   
    2842               0 :   const gfx3DMatrix& matrix = GetTransform(nsPresContext::AppUnitsPerCSSPixel());
    2843                 :                 
    2844               0 :   nsRegion result;
    2845               0 :   gfxMatrix matrix2d;
    2846               0 :   if (matrix.Is2D(&matrix2d) &&
    2847               0 :       matrix2d.PreservesAxisAlignedRectangles() &&
    2848               0 :       mStoredList.GetOpaqueRegion(aBuilder).Contains(untransformedVisible)) {
    2849               0 :     result = mVisibleRect;
    2850                 :   }
    2851               0 :   return result;
    2852                 : }
    2853                 : 
    2854                 : /* The transform is uniform if it fills the entire bounding rect and the
    2855                 :  * wrapped list is uniform.  See GetOpaqueRegion for discussion of why this
    2856                 :  * works.
    2857                 :  */
    2858               0 : bool nsDisplayTransform::IsUniform(nsDisplayListBuilder *aBuilder, nscolor* aColor)
    2859                 : {
    2860               0 :   nsRect untransformedVisible;
    2861               0 :   float factor = nsPresContext::AppUnitsPerCSSPixel();
    2862               0 :   if (!UntransformRectMatrix(mVisibleRect, GetTransform(factor), factor, &untransformedVisible)) {
    2863               0 :     return false;
    2864                 :   }
    2865               0 :   const gfx3DMatrix& matrix = GetTransform(nsPresContext::AppUnitsPerCSSPixel());
    2866                 : 
    2867               0 :   gfxMatrix matrix2d;
    2868               0 :   return matrix.Is2D(&matrix2d) &&
    2869               0 :          matrix2d.PreservesAxisAlignedRectangles() &&
    2870               0 :          mStoredList.GetVisibleRect().Contains(untransformedVisible) &&
    2871               0 :          mStoredList.IsUniform(aBuilder, aColor);
    2872                 : }
    2873                 : 
    2874                 : /* If UNIFIED_CONTINUATIONS is defined, we can merge two display lists that
    2875                 :  * share the same underlying content.  Otherwise, doing so results in graphical
    2876                 :  * glitches.
    2877                 :  */
    2878                 : #ifndef UNIFIED_CONTINUATIONS
    2879                 : 
    2880                 : bool
    2881               0 : nsDisplayTransform::TryMerge(nsDisplayListBuilder *aBuilder,
    2882                 :                              nsDisplayItem *aItem)
    2883                 : {
    2884               0 :   return false;
    2885                 : }
    2886                 : 
    2887                 : #else
    2888                 : 
    2889                 : bool
    2890                 : nsDisplayTransform::TryMerge(nsDisplayListBuilder *aBuilder,
    2891                 :                              nsDisplayItem *aItem)
    2892                 : {
    2893                 :   NS_PRECONDITION(aItem, "Why did you try merging with a null item?");
    2894                 :   NS_PRECONDITION(aBuilder, "Why did you try merging with a null builder?");
    2895                 : 
    2896                 :   /* Make sure that we're dealing with two transforms. */
    2897                 :   if (aItem->GetType() != TYPE_TRANSFORM)
    2898                 :     return false;
    2899                 : 
    2900                 :   /* Check to see that both frames are part of the same content. */
    2901                 :   if (aItem->GetUnderlyingFrame()->GetContent() != mFrame->GetContent())
    2902                 :     return false;
    2903                 : 
    2904                 :   /* Now, move everything over to this frame and signal that
    2905                 :    * we merged things!
    2906                 :    */
    2907                 :   mStoredList.GetList()->
    2908                 :     AppendToBottom(&static_cast<nsDisplayTransform *>(aItem)->mStoredList);
    2909                 :   return true;
    2910                 : }
    2911                 : 
    2912                 : #endif
    2913                 : 
    2914                 : /* TransformRect takes in as parameters a rectangle (in app space) and returns
    2915                 :  * the smallest rectangle (in app space) containing the transformed image of
    2916                 :  * that rectangle.  That is, it takes the four corners of the rectangle,
    2917                 :  * transforms them according to the matrix associated with the specified frame,
    2918                 :  * then returns the smallest rectangle containing the four transformed points.
    2919                 :  *
    2920                 :  * @param aUntransformedBounds The rectangle (in app units) to transform.
    2921                 :  * @param aFrame The frame whose transformation should be applied.
    2922                 :  * @param aOrigin The delta from the frame origin to the coordinate space origin
    2923                 :  * @param aBoundsOverride (optional) Force the frame bounds to be the
    2924                 :  *        specified bounds.
    2925                 :  * @return The smallest rectangle containing the image of the transformed
    2926                 :  *         rectangle.
    2927                 :  */
    2928               0 : nsRect nsDisplayTransform::TransformRect(const nsRect &aUntransformedBounds,
    2929                 :                                          const nsIFrame* aFrame,
    2930                 :                                          const nsPoint &aOrigin,
    2931                 :                                          const nsRect* aBoundsOverride)
    2932                 : {
    2933               0 :   NS_PRECONDITION(aFrame, "Can't take the transform based on a null frame!");
    2934                 : 
    2935               0 :   float factor = nsPresContext::AppUnitsPerCSSPixel();
    2936                 :   return nsLayoutUtils::MatrixTransformRect
    2937                 :     (aUntransformedBounds,
    2938                 :      GetResultingTransformMatrix(aFrame, aOrigin, factor, aBoundsOverride),
    2939               0 :      factor);
    2940                 : }
    2941                 : 
    2942               0 : nsRect nsDisplayTransform::TransformRectOut(const nsRect &aUntransformedBounds,
    2943                 :                                             const nsIFrame* aFrame,
    2944                 :                                             const nsPoint &aOrigin,
    2945                 :                                             const nsRect* aBoundsOverride)
    2946                 : {
    2947               0 :   NS_PRECONDITION(aFrame, "Can't take the transform based on a null frame!");
    2948                 : 
    2949               0 :   float factor = nsPresContext::AppUnitsPerCSSPixel();
    2950                 :   return nsLayoutUtils::MatrixTransformRectOut
    2951                 :     (aUntransformedBounds,
    2952                 :      GetResultingTransformMatrix(aFrame, aOrigin, factor, aBoundsOverride),
    2953               0 :      factor);
    2954                 : }
    2955                 : 
    2956               0 : bool nsDisplayTransform::UntransformRectMatrix(const nsRect &aUntransformedBounds,
    2957                 :                                                const gfx3DMatrix& aMatrix,
    2958                 :                                                float aAppUnitsPerPixel,
    2959                 :                                                nsRect *aOutRect)
    2960                 : {
    2961               0 :   if (aMatrix.IsSingular())
    2962               0 :     return false;
    2963                 : 
    2964               0 :   gfxRect result(NSAppUnitsToFloatPixels(aUntransformedBounds.x, aAppUnitsPerPixel),
    2965               0 :                  NSAppUnitsToFloatPixels(aUntransformedBounds.y, aAppUnitsPerPixel),
    2966               0 :                  NSAppUnitsToFloatPixels(aUntransformedBounds.width, aAppUnitsPerPixel),
    2967               0 :                  NSAppUnitsToFloatPixels(aUntransformedBounds.height, aAppUnitsPerPixel));
    2968                 : 
    2969                 :   /* We want to untransform the matrix, so invert the transformation first! */
    2970               0 :   result = aMatrix.Inverse().ProjectRectBounds(result);
    2971                 : 
    2972               0 :   *aOutRect = nsLayoutUtils::RoundGfxRectToAppRect(result, aAppUnitsPerPixel);
    2973                 : 
    2974               0 :   return true;
    2975                 : }
    2976                 : 
    2977               0 : bool nsDisplayTransform::UntransformRect(const nsRect &aUntransformedBounds,
    2978                 :                                            const nsIFrame* aFrame,
    2979                 :                                            const nsPoint &aOrigin,
    2980                 :                                            nsRect* aOutRect)
    2981                 : {
    2982               0 :   NS_PRECONDITION(aFrame, "Can't take the transform based on a null frame!");
    2983                 : 
    2984                 :   /* Grab the matrix.  If the transform is degenerate, just hand back the
    2985                 :    * empty rect.
    2986                 :    */
    2987               0 :   float factor = nsPresContext::AppUnitsPerCSSPixel();
    2988               0 :   gfx3DMatrix matrix = GetResultingTransformMatrix(aFrame, aOrigin, factor, nsnull);
    2989                 : 
    2990               0 :   return UntransformRectMatrix(aUntransformedBounds, matrix, factor, aOutRect);
    2991                 : }
    2992                 : 
    2993               0 : nsDisplaySVGEffects::nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder,
    2994                 :                                          nsIFrame* aFrame, nsDisplayList* aList)
    2995                 :     : nsDisplayWrapList(aBuilder, aFrame, aList), mEffectsFrame(aFrame),
    2996               0 :       mBounds(aFrame->GetVisualOverflowRectRelativeToSelf())
    2997                 : {
    2998               0 :   MOZ_COUNT_CTOR(nsDisplaySVGEffects);
    2999               0 : }
    3000                 : 
    3001                 : #ifdef NS_BUILD_REFCNT_LOGGING
    3002               0 : nsDisplaySVGEffects::~nsDisplaySVGEffects()
    3003                 : {
    3004               0 :   MOZ_COUNT_DTOR(nsDisplaySVGEffects);
    3005               0 : }
    3006                 : #endif
    3007                 : 
    3008               0 : nsRegion nsDisplaySVGEffects::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
    3009                 :                                               bool* aForceTransparentSurface)
    3010                 : {
    3011               0 :   if (aForceTransparentSurface) {
    3012               0 :     *aForceTransparentSurface = false;
    3013                 :   }
    3014               0 :   return nsRegion();
    3015                 : }
    3016                 : 
    3017                 : void
    3018               0 : nsDisplaySVGEffects::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
    3019                 :                              HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
    3020                 : {
    3021               0 :   nsPoint rectCenter(aRect.x + aRect.width / 2, aRect.y + aRect.height / 2);
    3022               0 :   if (nsSVGIntegrationUtils::HitTestFrameForEffects(mEffectsFrame,
    3023               0 :       rectCenter - aBuilder->ToReferenceFrame(mEffectsFrame))) {
    3024               0 :     mList.HitTest(aBuilder, aRect, aState, aOutFrames);
    3025                 :   }
    3026               0 : }
    3027                 : 
    3028               0 : void nsDisplaySVGEffects::Paint(nsDisplayListBuilder* aBuilder,
    3029                 :                                 nsRenderingContext* aCtx)
    3030                 : {
    3031                 :   nsSVGIntegrationUtils::PaintFramesWithEffects(aCtx,
    3032               0 :           mEffectsFrame, mVisibleRect, aBuilder, &mList);
    3033               0 : }
    3034                 : 
    3035               0 : bool nsDisplaySVGEffects::ComputeVisibility(nsDisplayListBuilder* aBuilder,
    3036                 :                                               nsRegion* aVisibleRegion,
    3037                 :                                               const nsRect& aAllowVisibleRegionExpansion) {
    3038               0 :   nsPoint offset = aBuilder->ToReferenceFrame(mEffectsFrame);
    3039                 :   nsRect dirtyRect =
    3040                 :     nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(mEffectsFrame,
    3041               0 :                                                            mVisibleRect - offset) +
    3042               0 :     offset;
    3043                 : 
    3044                 :   // Our children may be made translucent or arbitrarily deformed so we should
    3045                 :   // not allow them to subtract area from aVisibleRegion.
    3046               0 :   nsRegion childrenVisible(dirtyRect);
    3047               0 :   nsRect r;
    3048               0 :   r.IntersectRect(dirtyRect, mList.GetBounds(aBuilder));
    3049               0 :   mList.ComputeVisibilityForSublist(aBuilder, &childrenVisible, r, nsRect());
    3050               0 :   return true;
    3051                 : }
    3052                 : 
    3053               0 : bool nsDisplaySVGEffects::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem)
    3054                 : {
    3055               0 :   if (aItem->GetType() != TYPE_SVG_EFFECTS)
    3056               0 :     return false;
    3057                 :   // items for the same content element should be merged into a single
    3058                 :   // compositing group
    3059                 :   // aItem->GetUnderlyingFrame() returns non-null because it's nsDisplaySVGEffects
    3060               0 :   if (aItem->GetUnderlyingFrame()->GetContent() != mFrame->GetContent())
    3061               0 :     return false;
    3062               0 :   nsDisplaySVGEffects* other = static_cast<nsDisplaySVGEffects*>(aItem);
    3063               0 :   mList.AppendToBottom(&other->mList);
    3064                 :   mBounds.UnionRect(mBounds,
    3065               0 :     other->mBounds + other->mEffectsFrame->GetOffsetTo(mEffectsFrame));
    3066               0 :   return true;
    3067                 : }
    3068                 : 
    3069                 : #ifdef MOZ_DUMP_PAINTING
    3070                 : void
    3071               0 : nsDisplaySVGEffects::PrintEffects(FILE* aOutput)
    3072                 : {
    3073                 :   nsIFrame* firstFrame =
    3074               0 :     nsLayoutUtils::GetFirstContinuationOrSpecialSibling(mEffectsFrame);
    3075                 :   nsSVGEffects::EffectProperties effectProperties =
    3076               0 :     nsSVGEffects::GetEffectProperties(firstFrame);
    3077               0 :   bool isOK = true;
    3078               0 :   nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK);
    3079               0 :   bool first = true;
    3080               0 :   fprintf(aOutput, " effects=(");
    3081               0 :   if (mEffectsFrame->GetStyleDisplay()->mOpacity != 1.0f) {
    3082               0 :     first = false;
    3083               0 :     fprintf(aOutput, "opacity(%f)", mEffectsFrame->GetStyleDisplay()->mOpacity);
    3084                 :   }
    3085               0 :   if (clipPathFrame) {
    3086               0 :     if (!first) {
    3087               0 :       fprintf(aOutput, ", ");
    3088                 :     }
    3089               0 :     fprintf(aOutput, "clip(%s)", clipPathFrame->IsTrivial() ? "trivial" : "non-trivial");
    3090               0 :     first = false;
    3091                 :   }
    3092               0 :   if (effectProperties.GetFilterFrame(&isOK)) {
    3093               0 :     if (!first) {
    3094               0 :       fprintf(aOutput, ", ");
    3095                 :     }
    3096               0 :     fprintf(aOutput, "filter");
    3097               0 :     first = false;
    3098                 :   }
    3099               0 :   if (effectProperties.GetMaskFrame(&isOK)) {
    3100               0 :     if (!first) {
    3101               0 :       fprintf(aOutput, ", ");
    3102                 :     }
    3103               0 :     fprintf(aOutput, "mask");
    3104                 :   }
    3105               0 :   fprintf(aOutput, ")");
    3106               0 : }
    3107                 : #endif
    3108                 : 

Generated by: LCOV version 1.7