layout/generic/nsCanvasFrame.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /* rendering object that goes directly inside the document's scrollbars */
     8 #include "nsCanvasFrame.h"
     9 #include "nsContainerFrame.h"
    10 #include "nsCSSRendering.h"
    11 #include "nsPresContext.h"
    12 #include "nsStyleContext.h"
    13 #include "nsRenderingContext.h"
    14 #include "nsGkAtoms.h"
    15 #include "nsIPresShell.h"
    16 #include "nsDisplayList.h"
    17 #include "nsCSSFrameConstructor.h"
    18 #include "nsFrameManager.h"
    19 #include "gfxPlatform.h"
    21 // for focus
    22 #include "nsIScrollableFrame.h"
    23 #ifdef DEBUG_CANVAS_FOCUS
    24 #include "nsIDocShell.h"
    25 #endif
    27 //#define DEBUG_CANVAS_FOCUS
    29 using namespace mozilla;
    30 using namespace mozilla::layout;
    31 using namespace mozilla::gfx;
    33 nsIFrame*
    34 NS_NewCanvasFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
    35 {
    36   return new (aPresShell) nsCanvasFrame(aContext);
    37 }
    39 NS_IMPL_FRAMEARENA_HELPERS(nsCanvasFrame)
    41 NS_QUERYFRAME_HEAD(nsCanvasFrame)
    42   NS_QUERYFRAME_ENTRY(nsCanvasFrame)
    43 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
    45 void
    46 nsCanvasFrame::DestroyFrom(nsIFrame* aDestructRoot)
    47 {
    48   nsIScrollableFrame* sf =
    49     PresContext()->GetPresShell()->GetRootScrollFrameAsScrollable();
    50   if (sf) {
    51     sf->RemoveScrollPositionListener(this);
    52   }
    54   nsContainerFrame::DestroyFrom(aDestructRoot);
    55 }
    57 void
    58 nsCanvasFrame::ScrollPositionWillChange(nscoord aX, nscoord aY)
    59 {
    60   if (mDoPaintFocus) {
    61     mDoPaintFocus = false;
    62     PresContext()->FrameManager()->GetRootFrame()->InvalidateFrameSubtree();
    63   }
    64 }
    66 NS_IMETHODIMP
    67 nsCanvasFrame::SetHasFocus(bool aHasFocus)
    68 {
    69   if (mDoPaintFocus != aHasFocus) {
    70     mDoPaintFocus = aHasFocus;
    71     PresContext()->FrameManager()->GetRootFrame()->InvalidateFrameSubtree();
    73     if (!mAddedScrollPositionListener) {
    74       nsIScrollableFrame* sf =
    75         PresContext()->GetPresShell()->GetRootScrollFrameAsScrollable();
    76       if (sf) {
    77         sf->AddScrollPositionListener(this);
    78         mAddedScrollPositionListener = true;
    79       }
    80     }
    81   }
    82   return NS_OK;
    83 }
    85 nsresult
    86 nsCanvasFrame::SetInitialChildList(ChildListID     aListID,
    87                                    nsFrameList&    aChildList)
    88 {
    89   NS_ASSERTION(aListID != kPrincipalList ||
    90                aChildList.IsEmpty() || aChildList.OnlyChild(),
    91                "Primary child list can have at most one frame in it");
    92   return nsContainerFrame::SetInitialChildList(aListID, aChildList);
    93 }
    95 nsresult
    96 nsCanvasFrame::AppendFrames(ChildListID     aListID,
    97                             nsFrameList&    aFrameList)
    98 {
    99   NS_ASSERTION(aListID == kPrincipalList ||
   100                aListID == kAbsoluteList, "unexpected child list ID");
   101   NS_PRECONDITION(aListID != kAbsoluteList ||
   102                   mFrames.IsEmpty(), "already have a child frame");
   103   if (aListID != kPrincipalList) {
   104     // We only support the Principal and Absolute child lists.
   105     return NS_ERROR_INVALID_ARG;
   106   }
   108   if (!mFrames.IsEmpty()) {
   109     // We only allow a single principal child frame.
   110     return NS_ERROR_INVALID_ARG;
   111   }
   113   // Insert the new frames
   114   NS_ASSERTION(aFrameList.FirstChild() == aFrameList.LastChild(),
   115                "Only one principal child frame allowed");
   116 #ifdef DEBUG
   117   nsFrame::VerifyDirtyBitSet(aFrameList);
   118 #endif
   119   mFrames.AppendFrames(nullptr, aFrameList);
   121   PresContext()->PresShell()->
   122     FrameNeedsReflow(this, nsIPresShell::eTreeChange,
   123                      NS_FRAME_HAS_DIRTY_CHILDREN);
   125   return NS_OK;
   126 }
   128 nsresult
   129 nsCanvasFrame::InsertFrames(ChildListID     aListID,
   130                             nsIFrame*       aPrevFrame,
   131                             nsFrameList&    aFrameList)
   132 {
   133   // Because we only support a single child frame inserting is the same
   134   // as appending
   135   NS_PRECONDITION(!aPrevFrame, "unexpected previous sibling frame");
   136   if (aPrevFrame)
   137     return NS_ERROR_UNEXPECTED;
   139   return AppendFrames(aListID, aFrameList);
   140 }
   142 nsresult
   143 nsCanvasFrame::RemoveFrame(ChildListID     aListID,
   144                            nsIFrame*       aOldFrame)
   145 {
   146   NS_ASSERTION(aListID == kPrincipalList ||
   147                aListID == kAbsoluteList, "unexpected child list ID");
   148   if (aListID != kPrincipalList && aListID != kAbsoluteList) {
   149     // We only support the Principal and Absolute child lists.
   150     return NS_ERROR_INVALID_ARG;
   151   }
   153   if (aOldFrame != mFrames.FirstChild())
   154     return NS_ERROR_FAILURE;
   156   // Remove the frame and destroy it
   157   mFrames.DestroyFrame(aOldFrame);
   159   PresContext()->PresShell()->
   160     FrameNeedsReflow(this, nsIPresShell::eTreeChange,
   161                      NS_FRAME_HAS_DIRTY_CHILDREN);
   162   return NS_OK;
   163 }
   165 nsRect nsCanvasFrame::CanvasArea() const
   166 {
   167   // Not clear which overflow rect we want here, but it probably doesn't
   168   // matter.
   169   nsRect result(GetVisualOverflowRect());
   171   nsIScrollableFrame *scrollableFrame = do_QueryFrame(GetParent());
   172   if (scrollableFrame) {
   173     nsRect portRect = scrollableFrame->GetScrollPortRect();
   174     result.UnionRect(result, nsRect(nsPoint(0, 0), portRect.Size()));
   175   }
   176   return result;
   177 }
   179 void
   180 nsDisplayCanvasBackgroundColor::Paint(nsDisplayListBuilder* aBuilder,
   181                                       nsRenderingContext* aCtx)
   182 {
   183   nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
   184   nsPoint offset = ToReferenceFrame();
   185   nsRect bgClipRect = frame->CanvasArea() + offset;
   186   if (NS_GET_A(mColor) > 0) {
   187     aCtx->SetColor(mColor);
   188     aCtx->FillRect(bgClipRect);
   189   }
   190 }
   192 static void BlitSurface(gfxContext* aDest, const gfxRect& aRect, gfxASurface* aSource)
   193 {
   194   aDest->Translate(gfxPoint(aRect.x, aRect.y));
   195   aDest->SetSource(aSource);
   196   aDest->NewPath();
   197   aDest->Rectangle(gfxRect(0, 0, aRect.width, aRect.height));
   198   aDest->Fill();
   199   aDest->Translate(-gfxPoint(aRect.x, aRect.y));
   200 }
   202 static void BlitSurface(DrawTarget* aDest, const gfxRect& aRect, DrawTarget* aSource)
   203 {
   204   RefPtr<SourceSurface> source = aSource->Snapshot();
   205   aDest->DrawSurface(source,
   206                      Rect(aRect.x, aRect.y, aRect.width, aRect.height),
   207                      Rect(0, 0, aRect.width, aRect.height));
   208 }
   210 void
   211 nsDisplayCanvasBackgroundImage::Paint(nsDisplayListBuilder* aBuilder,
   212                                       nsRenderingContext* aCtx)
   213 {
   214   nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
   215   nsPoint offset = ToReferenceFrame();
   216   nsRect bgClipRect = frame->CanvasArea() + offset;
   218   nsRefPtr<nsRenderingContext> context;
   219   nsRefPtr<gfxContext> dest = aCtx->ThebesContext();
   220   nsRefPtr<gfxASurface> surf;
   221   RefPtr<DrawTarget> dt;
   222   nsRefPtr<gfxContext> ctx;
   223   gfxRect destRect;
   224 #ifndef MOZ_GFX_OPTIMIZE_MOBILE
   225   if (IsSingleFixedPositionImage(aBuilder, bgClipRect, &destRect) &&
   226       aBuilder->IsPaintingToWindow() && !aBuilder->IsCompositingCheap() &&
   227       !dest->CurrentMatrix().HasNonIntegerTranslation()) {
   228     // Snap image rectangle to nearest pixel boundaries. This is the right way
   229     // to snap for this context, because we checked HasNonIntegerTranslation above.
   230     destRect.Round();
   231     if (dest->IsCairo()) {
   232       surf = static_cast<gfxASurface*>(Frame()->Properties().Get(nsIFrame::CachedBackgroundImage()));
   233       nsRefPtr<gfxASurface> destSurf = dest->CurrentSurface();
   234       if (surf && surf->GetType() == destSurf->GetType()) {
   235         BlitSurface(dest, destRect, surf);
   236         return;
   237       }
   238       surf = destSurf->CreateSimilarSurface(
   239           gfxContentType::COLOR_ALPHA,
   240           gfxIntSize(ceil(destRect.width), ceil(destRect.height)));
   241     } else {
   242       dt = static_cast<DrawTarget*>(Frame()->Properties().Get(nsIFrame::CachedBackgroundImageDT()));
   243       DrawTarget* destDT = dest->GetDrawTarget();
   244       if (dt) {
   245         BlitSurface(destDT, destRect, dt);
   246         return;
   247       }
   248       dt = destDT->CreateSimilarDrawTarget(IntSize(ceil(destRect.width), ceil(destRect.height)), SurfaceFormat::B8G8R8A8);
   249     }
   250     if (surf || dt) {
   251       if (surf) {
   252         ctx = new gfxContext(surf);
   253       } else {
   254         ctx = new gfxContext(dt);
   255       }
   256       ctx->Translate(-gfxPoint(destRect.x, destRect.y));
   257       context = new nsRenderingContext();
   258       context->Init(aCtx->DeviceContext(), ctx);
   259     }
   260   }
   261 #endif
   263   PaintInternal(aBuilder,
   264                 (surf || dt) ? context.get() : aCtx,
   265                 (surf || dt) ? bgClipRect: mVisibleRect,
   266                 &bgClipRect);
   268   if (surf) {
   269     BlitSurface(dest, destRect, surf);
   270     frame->Properties().Set(nsIFrame::CachedBackgroundImage(),
   271                             surf.forget().take());
   272   }
   273   if (dt) {
   274     BlitSurface(dest->GetDrawTarget(), destRect, dt);
   275     frame->Properties().Set(nsIFrame::CachedBackgroundImageDT(), dt.forget().drop());
   276   }
   277 }
   279 void
   280 nsDisplayCanvasThemedBackground::Paint(nsDisplayListBuilder* aBuilder,
   281                                        nsRenderingContext* aCtx)
   282 {
   283   nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
   284   nsPoint offset = ToReferenceFrame();
   285   nsRect bgClipRect = frame->CanvasArea() + offset;
   287   PaintInternal(aBuilder, aCtx, mVisibleRect, &bgClipRect);
   288 }
   290 /**
   291  * A display item to paint the focus ring for the document.
   292  *
   293  * The only reason this can't use nsDisplayGeneric is overriding GetBounds.
   294  */
   295 class nsDisplayCanvasFocus : public nsDisplayItem {
   296 public:
   297   nsDisplayCanvasFocus(nsDisplayListBuilder* aBuilder, nsCanvasFrame *aFrame)
   298     : nsDisplayItem(aBuilder, aFrame)
   299   {
   300     MOZ_COUNT_CTOR(nsDisplayCanvasFocus);
   301   }
   302   virtual ~nsDisplayCanvasFocus() {
   303     MOZ_COUNT_DTOR(nsDisplayCanvasFocus);
   304   }
   306   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
   307                            bool* aSnap) MOZ_OVERRIDE
   308   {
   309     *aSnap = false;
   310     // This is an overestimate, but that's not a problem.
   311     nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
   312     return frame->CanvasArea() + ToReferenceFrame();
   313   }
   315   virtual void Paint(nsDisplayListBuilder* aBuilder,
   316                      nsRenderingContext* aCtx) MOZ_OVERRIDE
   317   {
   318     nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
   319     frame->PaintFocus(*aCtx, ToReferenceFrame());
   320   }
   322   NS_DISPLAY_DECL_NAME("CanvasFocus", TYPE_CANVAS_FOCUS)
   323 };
   325 void
   326 nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
   327                                 const nsRect&           aDirtyRect,
   328                                 const nsDisplayListSet& aLists)
   329 {
   330   if (GetPrevInFlow()) {
   331     DisplayOverflowContainers(aBuilder, aDirtyRect, aLists);
   332   }
   334   // Force a background to be shown. We may have a background propagated to us,
   335   // in which case StyleBackground wouldn't have the right background
   336   // and the code in nsFrame::DisplayBorderBackgroundOutline might not give us
   337   // a background.
   338   // We don't have any border or outline, and our background draws over
   339   // the overflow area, so just add nsDisplayCanvasBackground instead of
   340   // calling DisplayBorderBackgroundOutline.
   341   if (IsVisibleForPainting(aBuilder)) {
   342     nsStyleContext* bgSC;
   343     const nsStyleBackground* bg = nullptr;
   344     bool isThemed = IsThemed();
   345     if (!isThemed && nsCSSRendering::FindBackground(this, &bgSC)) {
   346       bg = bgSC->StyleBackground();
   347     }
   348     aLists.BorderBackground()->AppendNewToTop(
   349         new (aBuilder) nsDisplayCanvasBackgroundColor(aBuilder, this));
   351     if (isThemed) {
   352       aLists.BorderBackground()->AppendNewToTop(
   353         new (aBuilder) nsDisplayCanvasThemedBackground(aBuilder, this));
   354       return;
   355     }
   357     if (!bg) {
   358       return;
   359     }
   361     // Create separate items for each background layer.
   362     NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
   363       if (bg->mLayers[i].mImage.IsEmpty()) {
   364         continue;
   365       }
   366       aLists.BorderBackground()->AppendNewToTop(
   367         new (aBuilder) nsDisplayCanvasBackgroundImage(aBuilder, this, i, bg));
   368     }
   369   }
   371   nsIFrame* kid;
   372   for (kid = GetFirstPrincipalChild(); kid; kid = kid->GetNextSibling()) {
   373     // Put our child into its own pseudo-stack.
   374     BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
   375   }
   377 #ifdef DEBUG_CANVAS_FOCUS
   378   nsCOMPtr<nsIContent> focusContent;
   379   aPresContext->EventStateManager()->
   380     GetFocusedContent(getter_AddRefs(focusContent));
   382   bool hasFocus = false;
   383   nsCOMPtr<nsISupports> container;
   384   aPresContext->GetContainer(getter_AddRefs(container));
   385   nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
   386   if (docShell) {
   387     docShell->GetHasFocus(&hasFocus);
   388     printf("%p - nsCanvasFrame::Paint R:%d,%d,%d,%d  DR: %d,%d,%d,%d\n", this, 
   389             mRect.x, mRect.y, mRect.width, mRect.height,
   390             aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
   391   }
   392   printf("%p - Focus: %s   c: %p  DoPaint:%s\n", docShell.get(), hasFocus?"Y":"N", 
   393          focusContent.get(), mDoPaintFocus?"Y":"N");
   394 #endif
   396   if (!mDoPaintFocus)
   397     return;
   398   // Only paint the focus if we're visible
   399   if (!StyleVisibility()->IsVisible())
   400     return;
   402   aLists.Outlines()->AppendNewToTop(new (aBuilder)
   403     nsDisplayCanvasFocus(aBuilder, this));
   404 }
   406 void
   407 nsCanvasFrame::PaintFocus(nsRenderingContext& aRenderingContext, nsPoint aPt)
   408 {
   409   nsRect focusRect(aPt, GetSize());
   411   nsIScrollableFrame *scrollableFrame = do_QueryFrame(GetParent());
   412   if (scrollableFrame) {
   413     nsRect portRect = scrollableFrame->GetScrollPortRect();
   414     focusRect.width = portRect.width;
   415     focusRect.height = portRect.height;
   416     focusRect.MoveBy(scrollableFrame->GetScrollPosition());
   417   }
   419  // XXX use the root frame foreground color, but should we find BODY frame
   420  // for HTML documents?
   421   nsIFrame* root = mFrames.FirstChild();
   422   const nsStyleColor* color = root ? root->StyleColor() : StyleColor();
   423   if (!color) {
   424     NS_ERROR("current color cannot be found");
   425     return;
   426   }
   428   nsCSSRendering::PaintFocus(PresContext(), aRenderingContext,
   429                              focusRect, color->mColor);
   430 }
   432 /* virtual */ nscoord
   433 nsCanvasFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
   434 {
   435   nscoord result;
   436   DISPLAY_MIN_WIDTH(this, result);
   437   if (mFrames.IsEmpty())
   438     result = 0;
   439   else
   440     result = mFrames.FirstChild()->GetMinWidth(aRenderingContext);
   441   return result;
   442 }
   444 /* virtual */ nscoord
   445 nsCanvasFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
   446 {
   447   nscoord result;
   448   DISPLAY_PREF_WIDTH(this, result);
   449   if (mFrames.IsEmpty())
   450     result = 0;
   451   else
   452     result = mFrames.FirstChild()->GetPrefWidth(aRenderingContext);
   453   return result;
   454 }
   456 nsresult
   457 nsCanvasFrame::Reflow(nsPresContext*           aPresContext,
   458                       nsHTMLReflowMetrics&     aDesiredSize,
   459                       const nsHTMLReflowState& aReflowState,
   460                       nsReflowStatus&          aStatus)
   461 {
   462   DO_GLOBAL_REFLOW_COUNT("nsCanvasFrame");
   463   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
   464   NS_FRAME_TRACE_REFLOW_IN("nsCanvasFrame::Reflow");
   466   // Initialize OUT parameter
   467   aStatus = NS_FRAME_COMPLETE;
   469   nsCanvasFrame* prevCanvasFrame = static_cast<nsCanvasFrame*>
   470                                                (GetPrevInFlow());
   471   if (prevCanvasFrame) {
   472     AutoFrameListPtr overflow(aPresContext,
   473                               prevCanvasFrame->StealOverflowFrames());
   474     if (overflow) {
   475       NS_ASSERTION(overflow->OnlyChild(),
   476                    "must have doc root as canvas frame's only child");
   477       nsContainerFrame::ReparentFrameViewList(*overflow, prevCanvasFrame, this);
   478       // Prepend overflow to the our child list. There may already be
   479       // children placeholders for fixed-pos elements, which don't get
   480       // reflowed but must not be lost until the canvas frame is destroyed.
   481       mFrames.InsertFrames(this, nullptr, *overflow);
   482     }
   483   }
   485   // Set our size up front, since some parts of reflow depend on it
   486   // being already set.  Note that the computed height may be
   487   // unconstrained; that's ok.  Consumers should watch out for that.
   488   SetSize(nsSize(aReflowState.ComputedWidth(), aReflowState.ComputedHeight())); 
   490   // Reflow our one and only normal child frame. It's either the root
   491   // element's frame or a placeholder for that frame, if the root element
   492   // is abs-pos or fixed-pos. We may have additional children which
   493   // are placeholders for continuations of fixed-pos content, but those
   494   // don't need to be reflowed. The normal child is always comes before
   495   // the fixed-pos placeholders, because we insert it at the start
   496   // of the child list, above.
   497   nsHTMLReflowMetrics kidDesiredSize(aReflowState);
   498   if (mFrames.IsEmpty()) {
   499     // We have no child frame, so return an empty size
   500     aDesiredSize.Width() = aDesiredSize.Height() = 0;
   501   } else {
   502     nsIFrame* kidFrame = mFrames.FirstChild();
   503     bool kidDirty = (kidFrame->GetStateBits() & NS_FRAME_IS_DIRTY) != 0;
   505     nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
   506                                      nsSize(aReflowState.AvailableWidth(),
   507                                             aReflowState.AvailableHeight()));
   509     if (aReflowState.mFlags.mVResize &&
   510         (kidFrame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_HEIGHT)) {
   511       // Tell our kid it's being vertically resized too.  Bit of a
   512       // hack for framesets.
   513       kidReflowState.mFlags.mVResize = true;
   514     }
   516     nsPoint kidPt(kidReflowState.ComputedPhysicalMargin().left,
   517                   kidReflowState.ComputedPhysicalMargin().top);
   519     kidReflowState.ApplyRelativePositioning(&kidPt);
   521     // Reflow the frame
   522     ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState,
   523                 kidPt.x, kidPt.y, 0, aStatus);
   525     // Complete the reflow and position and size the child frame
   526     FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, &kidReflowState,
   527                       kidPt.x, kidPt.y, 0);
   529     if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
   530       nsIFrame* nextFrame = kidFrame->GetNextInFlow();
   531       NS_ASSERTION(nextFrame || aStatus & NS_FRAME_REFLOW_NEXTINFLOW,
   532         "If it's incomplete and has no nif yet, it must flag a nif reflow.");
   533       if (!nextFrame) {
   534         nextFrame = aPresContext->PresShell()->FrameConstructor()->
   535           CreateContinuingFrame(aPresContext, kidFrame, this);
   536         SetOverflowFrames(nsFrameList(nextFrame, nextFrame));
   537         // Root overflow containers will be normal children of
   538         // the canvas frame, but that's ok because there
   539         // aren't any other frames we need to isolate them from
   540         // during reflow.
   541       }
   542       if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) {
   543         nextFrame->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
   544       }
   545     }
   547     // If the child frame was just inserted, then we're responsible for making sure
   548     // it repaints
   549     if (kidDirty) {
   550       // But we have a new child, which will affect our background, so
   551       // invalidate our whole rect.
   552       // Note: Even though we request to be sized to our child's size, our
   553       // scroll frame ensures that we are always the size of the viewport.
   554       // Also note: GetPosition() on a CanvasFrame is always going to return
   555       // (0, 0). We only want to invalidate GetRect() since Get*OverflowRect()
   556       // could also include overflow to our top and left (out of the viewport)
   557       // which doesn't need to be painted.
   558       nsIFrame* viewport = PresContext()->GetPresShell()->GetRootFrame();
   559       viewport->InvalidateFrame();
   560     }
   562     // Return our desired size. Normally it's what we're told, but
   563     // sometimes we can be given an unconstrained height (when a window
   564     // is sizing-to-content), and we should compute our desired height.
   565     aDesiredSize.Width() = aReflowState.ComputedWidth();
   566     if (aReflowState.ComputedHeight() == NS_UNCONSTRAINEDSIZE) {
   567       aDesiredSize.Height() = kidFrame->GetRect().height +
   568         kidReflowState.ComputedPhysicalMargin().TopBottom();
   569     } else {
   570       aDesiredSize.Height() = aReflowState.ComputedHeight();
   571     }
   573     aDesiredSize.SetOverflowAreasToDesiredBounds();
   574     aDesiredSize.mOverflowAreas.UnionWith(
   575       kidDesiredSize.mOverflowAreas + kidPt);
   576   }
   578   if (prevCanvasFrame) {
   579     ReflowOverflowContainerChildren(aPresContext, aReflowState,
   580                                     aDesiredSize.mOverflowAreas, 0,
   581                                     aStatus);
   582   }
   584   FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus);
   586   NS_FRAME_TRACE_REFLOW_OUT("nsCanvasFrame::Reflow", aStatus);
   587   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   588   return NS_OK;
   589 }
   591 nsIAtom*
   592 nsCanvasFrame::GetType() const
   593 {
   594   return nsGkAtoms::canvasFrame;
   595 }
   597 nsresult 
   598 nsCanvasFrame::GetContentForEvent(WidgetEvent* aEvent,
   599                                   nsIContent** aContent)
   600 {
   601   NS_ENSURE_ARG_POINTER(aContent);
   602   nsresult rv = nsFrame::GetContentForEvent(aEvent,
   603                                             aContent);
   604   if (NS_FAILED(rv) || !*aContent) {
   605     nsIFrame* kid = mFrames.FirstChild();
   606     if (kid) {
   607       rv = kid->GetContentForEvent(aEvent,
   608                                    aContent);
   609     }
   610   }
   612   return rv;
   613 }
   615 #ifdef DEBUG_FRAME_DUMP
   616 nsresult
   617 nsCanvasFrame::GetFrameName(nsAString& aResult) const
   618 {
   619   return MakeFrameName(NS_LITERAL_STRING("Canvas"), aResult);
   620 }
   621 #endif

mercurial