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

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : /* rendering object that goes directly inside the document's scrollbars */
      39                 : 
      40                 : #include "nsCanvasFrame.h"
      41                 : #include "nsIServiceManager.h"
      42                 : #include "nsHTMLParts.h"
      43                 : #include "nsContainerFrame.h"
      44                 : #include "nsCSSRendering.h"
      45                 : #include "nsPresContext.h"
      46                 : #include "nsStyleContext.h"
      47                 : #include "nsRenderingContext.h"
      48                 : #include "nsGUIEvent.h"
      49                 : #include "nsStyleConsts.h"
      50                 : #include "nsGkAtoms.h"
      51                 : #include "nsEventStateManager.h"
      52                 : #include "nsIPresShell.h"
      53                 : #include "nsIScrollPositionListener.h"
      54                 : #include "nsDisplayList.h"
      55                 : #include "nsCSSFrameConstructor.h"
      56                 : #include "nsFrameManager.h"
      57                 : 
      58                 : // for focus
      59                 : #include "nsIScrollableFrame.h"
      60                 : #include "nsIDocShell.h"
      61                 : 
      62                 : #ifdef DEBUG_rods
      63                 : //#define DEBUG_CANVAS_FOCUS
      64                 : #endif
      65                 : 
      66                 : 
      67                 : nsIFrame*
      68               0 : NS_NewCanvasFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
      69                 : {
      70               0 :   return new (aPresShell) nsCanvasFrame(aContext);
      71                 : }
      72                 : 
      73               0 : NS_IMPL_FRAMEARENA_HELPERS(nsCanvasFrame)
      74                 : 
      75               0 : NS_QUERYFRAME_HEAD(nsCanvasFrame)
      76               0 :   NS_QUERYFRAME_ENTRY(nsCanvasFrame)
      77               0 : NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
      78                 : 
      79                 : void
      80               0 : nsCanvasFrame::DestroyFrom(nsIFrame* aDestructRoot)
      81                 : {
      82               0 :   DestroyAbsoluteFrames(aDestructRoot);
      83                 :   nsIScrollableFrame* sf =
      84               0 :     PresContext()->GetPresShell()->GetRootScrollFrameAsScrollable();
      85               0 :   if (sf) {
      86               0 :     sf->RemoveScrollPositionListener(this);
      87                 :   }
      88                 : 
      89               0 :   nsContainerFrame::DestroyFrom(aDestructRoot);
      90               0 : }
      91                 : 
      92                 : void
      93               0 : nsCanvasFrame::ScrollPositionWillChange(nscoord aX, nscoord aY)
      94                 : {
      95               0 :   if (mDoPaintFocus) {
      96               0 :     mDoPaintFocus = false;
      97               0 :     PresContext()->FrameManager()->GetRootFrame()->InvalidateFrameSubtree();
      98                 :   }
      99               0 : }
     100                 : 
     101                 : NS_IMETHODIMP
     102               0 : nsCanvasFrame::SetHasFocus(bool aHasFocus)
     103                 : {
     104               0 :   if (mDoPaintFocus != aHasFocus) {
     105               0 :     mDoPaintFocus = aHasFocus;
     106               0 :     PresContext()->FrameManager()->GetRootFrame()->InvalidateFrameSubtree();
     107                 : 
     108               0 :     if (!mAddedScrollPositionListener) {
     109                 :       nsIScrollableFrame* sf =
     110               0 :         PresContext()->GetPresShell()->GetRootScrollFrameAsScrollable();
     111               0 :       if (sf) {
     112               0 :         sf->AddScrollPositionListener(this);
     113               0 :         mAddedScrollPositionListener = true;
     114                 :       }
     115                 :     }
     116                 :   }
     117               0 :   return NS_OK;
     118                 : }
     119                 : 
     120                 : NS_IMETHODIMP
     121               0 : nsCanvasFrame::SetInitialChildList(ChildListID     aListID,
     122                 :                                    nsFrameList&    aChildList)
     123                 : {
     124               0 :   NS_ASSERTION(aListID != kPrincipalList ||
     125                 :                aChildList.IsEmpty() || aChildList.OnlyChild(),
     126                 :                "Primary child list can have at most one frame in it");
     127               0 :   return nsContainerFrame::SetInitialChildList(aListID, aChildList);
     128                 : }
     129                 : 
     130                 : NS_IMETHODIMP
     131               0 : nsCanvasFrame::AppendFrames(ChildListID     aListID,
     132                 :                             nsFrameList&    aFrameList)
     133                 : {
     134               0 :   NS_ASSERTION(aListID == kPrincipalList ||
     135                 :                aListID == kAbsoluteList, "unexpected child list ID");
     136               0 :   NS_PRECONDITION(aListID != kAbsoluteList ||
     137                 :                   mFrames.IsEmpty(), "already have a child frame");
     138               0 :   if (aListID != kPrincipalList) {
     139                 :     // We only support the Principal and Absolute child lists.
     140               0 :     return NS_ERROR_INVALID_ARG;
     141                 :   }
     142                 : 
     143               0 :   if (!mFrames.IsEmpty()) {
     144                 :     // We only allow a single principal child frame.
     145               0 :     return NS_ERROR_INVALID_ARG;
     146                 :   }
     147                 : 
     148                 :   // Insert the new frames
     149               0 :   NS_ASSERTION(aFrameList.FirstChild() == aFrameList.LastChild(),
     150                 :                "Only one principal child frame allowed");
     151                 : #ifdef NS_DEBUG
     152               0 :   nsFrame::VerifyDirtyBitSet(aFrameList);
     153                 : #endif
     154               0 :   mFrames.AppendFrames(nsnull, aFrameList);
     155                 : 
     156               0 :   PresContext()->PresShell()->
     157                 :     FrameNeedsReflow(this, nsIPresShell::eTreeChange,
     158               0 :                      NS_FRAME_HAS_DIRTY_CHILDREN);
     159                 : 
     160               0 :   return NS_OK;
     161                 : }
     162                 : 
     163                 : NS_IMETHODIMP
     164               0 : nsCanvasFrame::InsertFrames(ChildListID     aListID,
     165                 :                             nsIFrame*       aPrevFrame,
     166                 :                             nsFrameList&    aFrameList)
     167                 : {
     168                 :   // Because we only support a single child frame inserting is the same
     169                 :   // as appending
     170               0 :   NS_PRECONDITION(!aPrevFrame, "unexpected previous sibling frame");
     171               0 :   if (aPrevFrame)
     172               0 :     return NS_ERROR_UNEXPECTED;
     173                 : 
     174               0 :   return AppendFrames(aListID, aFrameList);
     175                 : }
     176                 : 
     177                 : NS_IMETHODIMP
     178               0 : nsCanvasFrame::RemoveFrame(ChildListID     aListID,
     179                 :                            nsIFrame*       aOldFrame)
     180                 : {
     181               0 :   NS_ASSERTION(aListID == kPrincipalList ||
     182                 :                aListID == kAbsoluteList, "unexpected child list ID");
     183               0 :   if (aListID != kPrincipalList || aListID != kAbsoluteList) {
     184                 :     // We only support the Principal and Absolute child lists.
     185               0 :     return NS_ERROR_INVALID_ARG;
     186                 :   }
     187                 : 
     188               0 :   if (aOldFrame != mFrames.FirstChild())
     189               0 :     return NS_ERROR_FAILURE;
     190                 : 
     191                 :   // It's our one and only child frame
     192                 :   // Damage the area occupied by the deleted frame
     193                 :   // The child of the canvas probably can't have an outline, but why bother
     194                 :   // thinking about that?
     195               0 :   Invalidate(aOldFrame->GetVisualOverflowRect() + aOldFrame->GetPosition());
     196                 : 
     197                 :   // Remove the frame and destroy it
     198               0 :   mFrames.DestroyFrame(aOldFrame);
     199                 : 
     200               0 :   PresContext()->PresShell()->
     201                 :     FrameNeedsReflow(this, nsIPresShell::eTreeChange,
     202               0 :                      NS_FRAME_HAS_DIRTY_CHILDREN);
     203               0 :   return NS_OK;
     204                 : }
     205                 : 
     206               0 : nsRect nsCanvasFrame::CanvasArea() const
     207                 : {
     208                 :   // Not clear which overflow rect we want here, but it probably doesn't
     209                 :   // matter.
     210               0 :   nsRect result(GetVisualOverflowRect());
     211                 : 
     212               0 :   nsIScrollableFrame *scrollableFrame = do_QueryFrame(GetParent());
     213               0 :   if (scrollableFrame) {
     214               0 :     nsRect portRect = scrollableFrame->GetScrollPortRect();
     215               0 :     result.UnionRect(result, nsRect(nsPoint(0, 0), portRect.Size()));
     216                 :   }
     217                 :   return result;
     218                 : }
     219                 : 
     220                 : void
     221               0 : nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
     222                 :                                  nsRenderingContext* aCtx)
     223                 : {
     224               0 :   nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
     225               0 :   nsPoint offset = ToReferenceFrame();
     226               0 :   nsRect bgClipRect = frame->CanvasArea() + offset;
     227                 : 
     228               0 :   if (NS_GET_A(mExtraBackgroundColor) > 0) {
     229               0 :     aCtx->SetColor(mExtraBackgroundColor);
     230               0 :     aCtx->FillRect(bgClipRect);
     231                 :   }
     232                 : 
     233                 :   nsCSSRendering::PaintBackground(mFrame->PresContext(), *aCtx, mFrame,
     234                 :                                   mVisibleRect,
     235               0 :                                   nsRect(offset, mFrame->GetSize()),
     236                 :                                   aBuilder->GetBackgroundPaintFlags(),
     237               0 :                                   &bgClipRect);
     238               0 : }
     239                 : 
     240                 : /**
     241                 :  * A display item to paint the focus ring for the document.
     242                 :  *
     243                 :  * The only reason this can't use nsDisplayGeneric is overriding GetBounds.
     244                 :  */
     245                 : class nsDisplayCanvasFocus : public nsDisplayItem {
     246                 : public:
     247               0 :   nsDisplayCanvasFocus(nsDisplayListBuilder* aBuilder, nsCanvasFrame *aFrame)
     248               0 :     : nsDisplayItem(aBuilder, aFrame)
     249                 :   {
     250               0 :     MOZ_COUNT_CTOR(nsDisplayCanvasFocus);
     251               0 :   }
     252               0 :   virtual ~nsDisplayCanvasFocus() {
     253               0 :     MOZ_COUNT_DTOR(nsDisplayCanvasFocus);
     254               0 :   }
     255                 : 
     256               0 :   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder)
     257                 :   {
     258                 :     // This is an overestimate, but that's not a problem.
     259               0 :     nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
     260               0 :     return frame->CanvasArea() + ToReferenceFrame();
     261                 :   }
     262                 : 
     263               0 :   virtual void Paint(nsDisplayListBuilder* aBuilder,
     264                 :                      nsRenderingContext* aCtx)
     265                 :   {
     266               0 :     nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
     267               0 :     frame->PaintFocus(*aCtx, ToReferenceFrame());
     268               0 :   }
     269                 : 
     270               0 :   NS_DISPLAY_DECL_NAME("CanvasFocus", TYPE_CANVAS_FOCUS)
     271                 : };
     272                 : 
     273                 : NS_IMETHODIMP
     274               0 : nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     275                 :                                 const nsRect&           aDirtyRect,
     276                 :                                 const nsDisplayListSet& aLists)
     277                 : {
     278                 :   nsresult rv;
     279                 : 
     280               0 :   if (GetPrevInFlow()) {
     281               0 :     DisplayOverflowContainers(aBuilder, aDirtyRect, aLists);
     282                 :   }
     283                 : 
     284                 :   // Force a background to be shown. We may have a background propagated to us,
     285                 :   // in which case GetStyleBackground wouldn't have the right background
     286                 :   // and the code in nsFrame::DisplayBorderBackgroundOutline might not give us
     287                 :   // a background.
     288                 :   // We don't have any border or outline, and our background draws over
     289                 :   // the overflow area, so just add nsDisplayCanvasBackground instead of
     290                 :   // calling DisplayBorderBackgroundOutline.
     291               0 :   if (IsVisibleForPainting(aBuilder)) { 
     292                 :     rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
     293               0 :            nsDisplayCanvasBackground(aBuilder, this));
     294               0 :     NS_ENSURE_SUCCESS(rv, rv);
     295                 :   }
     296                 : 
     297                 :   nsIFrame* kid;
     298               0 :   for (kid = GetFirstPrincipalChild(); kid; kid = kid->GetNextSibling()) {
     299                 :     // Put our child into its own pseudo-stack.
     300               0 :     rv = BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
     301               0 :     NS_ENSURE_SUCCESS(rv, rv);
     302                 :   }
     303                 : 
     304                 : #ifdef DEBUG_CANVAS_FOCUS
     305                 :   nsCOMPtr<nsIContent> focusContent;
     306                 :   aPresContext->EventStateManager()->
     307                 :     GetFocusedContent(getter_AddRefs(focusContent));
     308                 : 
     309                 :   bool hasFocus = false;
     310                 :   nsCOMPtr<nsISupports> container;
     311                 :   aPresContext->GetContainer(getter_AddRefs(container));
     312                 :   nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
     313                 :   if (docShell) {
     314                 :     docShell->GetHasFocus(&hasFocus);
     315                 :     printf("%p - nsCanvasFrame::Paint R:%d,%d,%d,%d  DR: %d,%d,%d,%d\n", this, 
     316                 :             mRect.x, mRect.y, mRect.width, mRect.height,
     317                 :             aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
     318                 :   }
     319                 :   printf("%p - Focus: %s   c: %p  DoPaint:%s\n", docShell.get(), hasFocus?"Y":"N", 
     320                 :          focusContent.get(), mDoPaintFocus?"Y":"N");
     321                 : #endif
     322                 : 
     323               0 :   if (!mDoPaintFocus)
     324               0 :     return NS_OK;
     325                 :   // Only paint the focus if we're visible
     326               0 :   if (!GetStyleVisibility()->IsVisible())
     327               0 :     return NS_OK;
     328                 :   
     329                 :   return aLists.Outlines()->AppendNewToTop(new (aBuilder)
     330               0 :       nsDisplayCanvasFocus(aBuilder, this));
     331                 : }
     332                 : 
     333                 : void
     334               0 : nsCanvasFrame::PaintFocus(nsRenderingContext& aRenderingContext, nsPoint aPt)
     335                 : {
     336               0 :   nsRect focusRect(aPt, GetSize());
     337                 : 
     338               0 :   nsIScrollableFrame *scrollableFrame = do_QueryFrame(GetParent());
     339               0 :   if (scrollableFrame) {
     340               0 :     nsRect portRect = scrollableFrame->GetScrollPortRect();
     341               0 :     focusRect.width = portRect.width;
     342               0 :     focusRect.height = portRect.height;
     343               0 :     focusRect.MoveBy(scrollableFrame->GetScrollPosition());
     344                 :   }
     345                 : 
     346                 :  // XXX use the root frame foreground color, but should we find BODY frame
     347                 :  // for HTML documents?
     348               0 :   nsIFrame* root = mFrames.FirstChild();
     349                 :   const nsStyleColor* color =
     350               0 :     root ? root->GetStyleContext()->GetStyleColor() :
     351               0 :            mStyleContext->GetStyleColor();
     352               0 :   if (!color) {
     353               0 :     NS_ERROR("current color cannot be found");
     354                 :     return;
     355                 :   }
     356                 : 
     357                 :   nsCSSRendering::PaintFocus(PresContext(), aRenderingContext,
     358               0 :                              focusRect, color->mColor);
     359                 : }
     360                 : 
     361                 : /* virtual */ nscoord
     362               0 : nsCanvasFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
     363                 : {
     364                 :   nscoord result;
     365               0 :   DISPLAY_MIN_WIDTH(this, result);
     366               0 :   if (mFrames.IsEmpty())
     367               0 :     result = 0;
     368                 :   else
     369               0 :     result = mFrames.FirstChild()->GetMinWidth(aRenderingContext);
     370               0 :   return result;
     371                 : }
     372                 : 
     373                 : /* virtual */ nscoord
     374               0 : nsCanvasFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
     375                 : {
     376                 :   nscoord result;
     377               0 :   DISPLAY_PREF_WIDTH(this, result);
     378               0 :   if (mFrames.IsEmpty())
     379               0 :     result = 0;
     380                 :   else
     381               0 :     result = mFrames.FirstChild()->GetPrefWidth(aRenderingContext);
     382               0 :   return result;
     383                 : }
     384                 : 
     385                 : NS_IMETHODIMP
     386               0 : nsCanvasFrame::Reflow(nsPresContext*           aPresContext,
     387                 :                     nsHTMLReflowMetrics&     aDesiredSize,
     388                 :                     const nsHTMLReflowState& aReflowState,
     389                 :                     nsReflowStatus&          aStatus)
     390                 : {
     391               0 :   DO_GLOBAL_REFLOW_COUNT("nsCanvasFrame");
     392               0 :   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
     393               0 :   NS_FRAME_TRACE_REFLOW_IN("nsCanvasFrame::Reflow");
     394                 : 
     395                 :   // Initialize OUT parameter
     396               0 :   aStatus = NS_FRAME_COMPLETE;
     397                 : 
     398                 :   nsCanvasFrame* prevCanvasFrame = static_cast<nsCanvasFrame*>
     399               0 :                                                (GetPrevInFlow());
     400               0 :   if (prevCanvasFrame) {
     401               0 :     nsAutoPtr<nsFrameList> overflow(prevCanvasFrame->StealOverflowFrames());
     402               0 :     if (overflow) {
     403               0 :       NS_ASSERTION(overflow->OnlyChild(),
     404                 :                    "must have doc root as canvas frame's only child");
     405               0 :       nsContainerFrame::ReparentFrameViewList(aPresContext, *overflow,
     406               0 :                                               prevCanvasFrame, this);
     407                 :       // Prepend overflow to the our child list. There may already be
     408                 :       // children placeholders for fixed-pos elements, which don't get
     409                 :       // reflowed but must not be lost until the canvas frame is destroyed.
     410               0 :       mFrames.InsertFrames(this, nsnull, *overflow);
     411                 :     }
     412                 :   }
     413                 : 
     414                 :   // Set our size up front, since some parts of reflow depend on it
     415                 :   // being already set.  Note that the computed height may be
     416                 :   // unconstrained; that's ok.  Consumers should watch out for that.
     417               0 :   SetSize(nsSize(aReflowState.ComputedWidth(), aReflowState.ComputedHeight())); 
     418                 : 
     419                 :   // Reflow our one and only normal child frame. It's either the root
     420                 :   // element's frame or a placeholder for that frame, if the root element
     421                 :   // is abs-pos or fixed-pos. We may have additional children which
     422                 :   // are placeholders for continuations of fixed-pos content, but those
     423                 :   // don't need to be reflowed. The normal child is always comes before
     424                 :   // the fixed-pos placeholders, because we insert it at the start
     425                 :   // of the child list, above.
     426               0 :   nsHTMLReflowMetrics kidDesiredSize;
     427               0 :   if (mFrames.IsEmpty()) {
     428                 :     // We have no child frame, so return an empty size
     429               0 :     aDesiredSize.width = aDesiredSize.height = 0;
     430                 :   } else {
     431               0 :     nsIFrame* kidFrame = mFrames.FirstChild();
     432               0 :     nsRect oldKidRect = kidFrame->GetRect();
     433               0 :     bool kidDirty = (kidFrame->GetStateBits() & NS_FRAME_IS_DIRTY) != 0;
     434                 : 
     435                 :     nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
     436                 :                                      nsSize(aReflowState.availableWidth,
     437               0 :                                             aReflowState.availableHeight));
     438                 : 
     439               0 :     if (aReflowState.mFlags.mVResize &&
     440               0 :         (kidFrame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_HEIGHT)) {
     441                 :       // Tell our kid it's being vertically resized too.  Bit of a
     442                 :       // hack for framesets.
     443               0 :       kidReflowState.mFlags.mVResize = true;
     444                 :     }
     445                 : 
     446                 :     nsPoint kidPt(kidReflowState.mComputedMargin.left,
     447               0 :                   kidReflowState.mComputedMargin.top);
     448                 :     // Apply CSS relative positioning
     449               0 :     const nsStyleDisplay* styleDisp = kidFrame->GetStyleDisplay();
     450               0 :     if (NS_STYLE_POSITION_RELATIVE == styleDisp->mPosition) {
     451                 :       kidPt += nsPoint(kidReflowState.mComputedOffsets.left,
     452               0 :                        kidReflowState.mComputedOffsets.top);
     453                 :     }
     454                 : 
     455                 :     // Reflow the frame
     456                 :     ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState,
     457               0 :                 kidPt.x, kidPt.y, 0, aStatus);
     458                 : 
     459                 :     // Complete the reflow and position and size the child frame
     460                 :     FinishReflowChild(kidFrame, aPresContext, &kidReflowState, kidDesiredSize,
     461               0 :                       kidPt.x, kidPt.y, 0);
     462                 : 
     463               0 :     if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
     464               0 :       nsIFrame* nextFrame = kidFrame->GetNextInFlow();
     465               0 :       NS_ASSERTION(nextFrame || aStatus & NS_FRAME_REFLOW_NEXTINFLOW,
     466                 :         "If it's incomplete and has no nif yet, it must flag a nif reflow.");
     467               0 :       if (!nextFrame) {
     468                 :         nsresult rv = aPresContext->PresShell()->FrameConstructor()->
     469               0 :           CreateContinuingFrame(aPresContext, kidFrame, this, &nextFrame);
     470               0 :         NS_ENSURE_SUCCESS(rv, rv);
     471               0 :         SetOverflowFrames(aPresContext, nsFrameList(nextFrame, nextFrame));
     472                 :         // Root overflow containers will be normal children of
     473                 :         // the canvas frame, but that's ok because there
     474                 :         // aren't any other frames we need to isolate them from
     475                 :         // during reflow.
     476                 :       }
     477               0 :       if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) {
     478               0 :         nextFrame->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
     479                 :       }
     480                 :     }
     481                 : 
     482                 :     // If the child frame was just inserted, then we're responsible for making sure
     483                 :     // it repaints
     484               0 :     if (kidDirty) {
     485                 :       // But we have a new child, which will affect our background, so
     486                 :       // invalidate our whole rect.
     487                 :       // Note: Even though we request to be sized to our child's size, our
     488                 :       // scroll frame ensures that we are always the size of the viewport.
     489                 :       // Also note: GetPosition() on a CanvasFrame is always going to return
     490                 :       // (0, 0). We only want to invalidate GetRect() since Get*OverflowRect()
     491                 :       // could also include overflow to our top and left (out of the viewport)
     492                 :       // which doesn't need to be painted.
     493               0 :       nsIFrame* viewport = PresContext()->GetPresShell()->GetRootFrame();
     494               0 :       viewport->Invalidate(nsRect(nsPoint(0, 0), viewport->GetSize()));
     495                 :     } else {
     496               0 :       nsRect newKidRect = kidFrame->GetRect();
     497               0 :       if (newKidRect.TopLeft() == oldKidRect.TopLeft()) {
     498               0 :         InvalidateRectDifference(oldKidRect, kidFrame->GetRect());
     499                 :       } else {
     500               0 :         Invalidate(oldKidRect);
     501               0 :         Invalidate(newKidRect);
     502                 :       }
     503                 :     }
     504                 :     
     505                 :     // Return our desired size. Normally it's what we're told, but
     506                 :     // sometimes we can be given an unconstrained height (when a window
     507                 :     // is sizing-to-content), and we should compute our desired height.
     508               0 :     aDesiredSize.width = aReflowState.ComputedWidth();
     509               0 :     if (aReflowState.ComputedHeight() == NS_UNCONSTRAINEDSIZE) {
     510               0 :       aDesiredSize.height = kidFrame->GetRect().height +
     511               0 :         kidReflowState.mComputedMargin.TopBottom();
     512                 :     } else {
     513               0 :       aDesiredSize.height = aReflowState.ComputedHeight();
     514                 :     }
     515                 : 
     516               0 :     aDesiredSize.SetOverflowAreasToDesiredBounds();
     517                 :     aDesiredSize.mOverflowAreas.UnionWith(
     518               0 :       kidDesiredSize.mOverflowAreas + kidPt);
     519                 : 
     520                 :     // Handle invalidating fixed-attachment backgrounds propagated to the
     521                 :     // canvas when the canvas size (and therefore the background positioning
     522                 :     // area's size) changes.  Such backgrounds are not invalidated in the
     523                 :     // normal manner because the size of the original frame for that background
     524                 :     // may not have changed.
     525                 :     //
     526                 :     // This isn't the right fix for this issue, taken more generally.  In
     527                 :     // particular, this doesn't handle fixed-attachment backgrounds that are *not*
     528                 :     // propagated.  If a layer with the characteristics tested for below exists
     529                 :     // in a non-propagated background, we should invalidate the "corresponding"
     530                 :     // frame (which subsumes this special case if defined broadly).  For now,
     531                 :     // however, this addresses the most common case.  Given that this behavior has
     532                 :     // long been broken (non-zero percent background-size may be a new instance,
     533                 :     // but non-zero percent background-position is longstanding), we defer a
     534                 :     // fully correct fix until later.
     535               0 :     if (nsSize(aDesiredSize.width, aDesiredSize.height) != GetSize()) {
     536                 :       nsIFrame* rootElementFrame =
     537               0 :         aPresContext->PresShell()->FrameConstructor()->GetRootElementStyleFrame();
     538                 :       nsStyleContext* bgSC =
     539               0 :         nsCSSRendering::FindCanvasBackground(this, rootElementFrame);
     540               0 :       const nsStyleBackground* bg = bgSC->GetStyleBackground();
     541               0 :       if (!bg->IsTransparent()) {
     542               0 :         NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, bg) {
     543               0 :           const nsStyleBackground::Layer& layer = bg->mLayers[i];
     544               0 :           if (layer.mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
     545               0 :               layer.RenderingMightDependOnFrameSize()) {
     546               0 :             Invalidate(nsRect(nsPoint(0, 0), GetSize()));
     547               0 :             break;
     548                 :           }
     549                 :         }
     550                 :       }
     551                 :     }
     552                 :   }
     553                 : 
     554               0 :   if (prevCanvasFrame) {
     555                 :     ReflowOverflowContainerChildren(aPresContext, aReflowState,
     556                 :                                     aDesiredSize.mOverflowAreas, 0,
     557               0 :                                     aStatus);
     558                 :   }
     559                 : 
     560               0 :   FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowState, aStatus);
     561                 : 
     562               0 :   NS_FRAME_TRACE_REFLOW_OUT("nsCanvasFrame::Reflow", aStatus);
     563               0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
     564               0 :   return NS_OK;
     565                 : }
     566                 : 
     567                 : PRIntn
     568               0 : nsCanvasFrame::GetSkipSides() const
     569                 : {
     570               0 :   return 0;
     571                 : }
     572                 : 
     573                 : nsIAtom*
     574               0 : nsCanvasFrame::GetType() const
     575                 : {
     576               0 :   return nsGkAtoms::canvasFrame;
     577                 : }
     578                 : 
     579                 : NS_IMETHODIMP 
     580               0 : nsCanvasFrame::GetContentForEvent(nsEvent* aEvent,
     581                 :                                   nsIContent** aContent)
     582                 : {
     583               0 :   NS_ENSURE_ARG_POINTER(aContent);
     584                 :   nsresult rv = nsFrame::GetContentForEvent(aEvent,
     585               0 :                                             aContent);
     586               0 :   if (NS_FAILED(rv) || !*aContent) {
     587               0 :     nsIFrame* kid = mFrames.FirstChild();
     588               0 :     if (kid) {
     589                 :       rv = kid->GetContentForEvent(aEvent,
     590               0 :                                    aContent);
     591                 :     }
     592                 :   }
     593                 : 
     594               0 :   return rv;
     595                 : }
     596                 : 
     597                 : #ifdef DEBUG
     598                 : NS_IMETHODIMP
     599               0 : nsCanvasFrame::GetFrameName(nsAString& aResult) const
     600                 : {
     601               0 :   return MakeFrameName(NS_LITERAL_STRING("Canvas"), aResult);
     602                 : }
     603                 : #endif

Generated by: LCOV version 1.7