LCOV - code coverage report
Current view: top level - layout/generic - nsCanvasFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 134 400 33.5 %
Date: 2017-07-14 16:53:18 Functions: 12 38 31.6 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       5             : 
       6             : /* rendering object that goes directly inside the document's scrollbars */
       7             : 
       8             : #include "nsCanvasFrame.h"
       9             : 
      10             : #include "AccessibleCaretEventHub.h"
      11             : #include "gfxContext.h"
      12             : #include "gfxUtils.h"
      13             : #include "nsContainerFrame.h"
      14             : #include "nsCSSRendering.h"
      15             : #include "nsPresContext.h"
      16             : #include "nsStyleContext.h"
      17             : #include "nsGkAtoms.h"
      18             : #include "nsIFrameInlines.h"
      19             : #include "nsIPresShell.h"
      20             : #include "nsDisplayList.h"
      21             : #include "nsCSSFrameConstructor.h"
      22             : #include "nsFrameManager.h"
      23             : #include "gfxPlatform.h"
      24             : #include "nsPrintfCString.h"
      25             : #include "mozilla/dom/AnonymousContent.h"
      26             : #include "mozilla/layers/StackingContextHelper.h"
      27             : #include "mozilla/PresShell.h"
      28             : // for focus
      29             : #include "nsIScrollableFrame.h"
      30             : #ifdef DEBUG_CANVAS_FOCUS
      31             : #include "nsIDocShell.h"
      32             : #endif
      33             : 
      34             : //#define DEBUG_CANVAS_FOCUS
      35             : 
      36             : using namespace mozilla;
      37             : using namespace mozilla::dom;
      38             : using namespace mozilla::layout;
      39             : using namespace mozilla::gfx;
      40             : using namespace mozilla::layers;
      41             : 
      42             : nsCanvasFrame*
      43          23 : NS_NewCanvasFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
      44             : {
      45          23 :   return new (aPresShell) nsCanvasFrame(aContext);
      46             : }
      47             : 
      48          23 : NS_IMPL_FRAMEARENA_HELPERS(nsCanvasFrame)
      49             : 
      50         230 : NS_QUERYFRAME_HEAD(nsCanvasFrame)
      51          40 :   NS_QUERYFRAME_ENTRY(nsCanvasFrame)
      52          23 :   NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
      53         167 : NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
      54             : 
      55             : void
      56           0 : nsCanvasFrame::ShowCustomContentContainer()
      57             : {
      58           0 :   if (mCustomContentContainer) {
      59           0 :     mCustomContentContainer->UnsetAttr(kNameSpaceID_None, nsGkAtoms::hidden, true);
      60             :   }
      61           0 : }
      62             : 
      63             : void
      64          23 : nsCanvasFrame::HideCustomContentContainer()
      65             : {
      66          23 :   if (mCustomContentContainer) {
      67          46 :     mCustomContentContainer->SetAttr(kNameSpaceID_None, nsGkAtoms::hidden,
      68          46 :                                      NS_LITERAL_STRING("true"),
      69          69 :                                      true);
      70             :   }
      71          23 : }
      72             : 
      73             : nsresult
      74          23 : nsCanvasFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
      75             : {
      76          23 :   if (!mContent) {
      77           0 :     return NS_OK;
      78             :   }
      79             : 
      80          46 :   nsCOMPtr<nsIDocument> doc = mContent->OwnerDoc();
      81          23 :   nsresult rv = NS_OK;
      82             : 
      83             :   // Create the custom content container.
      84          23 :   mCustomContentContainer = doc->CreateHTMLElement(nsGkAtoms::div);
      85             : #ifdef DEBUG
      86             :   // We restyle our mCustomContentContainer, even though it's root anonymous
      87             :   // content.  Normally that's not OK because the frame constructor doesn't know
      88             :   // how to order the frame tree in such cases, but we make this work for this
      89             :   // particular case, so it's OK.
      90          23 :   mCustomContentContainer->SetProperty(nsGkAtoms::restylableAnonymousNode,
      91          46 :                                        reinterpret_cast<void*>(true));
      92             : #endif // DEBUG
      93             : 
      94          23 :   aElements.AppendElement(mCustomContentContainer);
      95             : 
      96             :   // XXX add :moz-native-anonymous or will that be automatically set?
      97          23 :   rv = mCustomContentContainer->SetAttr(kNameSpaceID_None, nsGkAtoms::_class,
      98          46 :                                         NS_LITERAL_STRING("moz-custom-content-container"),
      99          46 :                                         true);
     100          23 :   NS_ENSURE_SUCCESS(rv, rv);
     101             : 
     102             :   // Append all existing AnonymousContent nodes stored at document level if any.
     103          23 :   size_t len = doc->GetAnonymousContents().Length();
     104          23 :   for (size_t i = 0; i < len; ++i) {
     105           0 :     nsCOMPtr<Element> node = doc->GetAnonymousContents()[i]->GetContentNode();
     106           0 :     mCustomContentContainer->AppendChildTo(node->AsContent(), true);
     107             :   }
     108             : 
     109             :   // Only create a frame for mCustomContentContainer if it has some children.
     110          23 :   if (len == 0) {
     111          23 :     HideCustomContentContainer();
     112             :   }
     113             : 
     114             :   RefPtr<AccessibleCaretEventHub> eventHub =
     115          46 :     PresContext()->GetPresShell()->GetAccessibleCaretEventHub();
     116          23 :   if (eventHub) {
     117             :     // AccessibleCaret will insert anonymous caret elements.
     118           0 :     eventHub->Init();
     119             :   }
     120             : 
     121          23 :   return NS_OK;
     122             : }
     123             : 
     124             : void
     125           0 : nsCanvasFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements, uint32_t aFilter)
     126             : {
     127           0 :   if (mCustomContentContainer) {
     128           0 :     aElements.AppendElement(mCustomContentContainer);
     129             :   }
     130           0 : }
     131             : 
     132             : void
     133           0 : nsCanvasFrame::DestroyFrom(nsIFrame* aDestructRoot)
     134             : {
     135             :   nsIScrollableFrame* sf =
     136           0 :     PresContext()->GetPresShell()->GetRootScrollFrameAsScrollable();
     137           0 :   if (sf) {
     138           0 :     sf->RemoveScrollPositionListener(this);
     139             :   }
     140             : 
     141             :   // Elements inserted in the custom content container have the same lifetime as
     142             :   // the document, so before destroying the container, make sure to keep a clone
     143             :   // of each of them at document level so they can be re-appended on reframe.
     144           0 :   if (mCustomContentContainer) {
     145           0 :     nsCOMPtr<nsIDocument> doc = mContent->OwnerDoc();
     146           0 :     ErrorResult rv;
     147             : 
     148             :     nsTArray<RefPtr<mozilla::dom::AnonymousContent>>& docAnonContents =
     149           0 :       doc->GetAnonymousContents();
     150           0 :     for (size_t i = 0, len = docAnonContents.Length(); i < len; ++i) {
     151           0 :       AnonymousContent* content = docAnonContents[i];
     152           0 :       nsCOMPtr<nsINode> clonedElement = content->GetContentNode()->CloneNode(true, rv);
     153           0 :       content->SetContentNode(clonedElement->AsElement());
     154             :     }
     155             :   }
     156           0 :   nsContentUtils::DestroyAnonymousContent(&mCustomContentContainer);
     157             : 
     158           0 :   nsContainerFrame::DestroyFrom(aDestructRoot);
     159           0 : }
     160             : 
     161             : void
     162           0 : nsCanvasFrame::ScrollPositionWillChange(nscoord aX, nscoord aY)
     163             : {
     164           0 :   if (mDoPaintFocus) {
     165           0 :     mDoPaintFocus = false;
     166           0 :     PresContext()->FrameManager()->GetRootFrame()->InvalidateFrameSubtree();
     167             :   }
     168           0 : }
     169             : 
     170             : NS_IMETHODIMP
     171           0 : nsCanvasFrame::SetHasFocus(bool aHasFocus)
     172             : {
     173           0 :   if (mDoPaintFocus != aHasFocus) {
     174           0 :     mDoPaintFocus = aHasFocus;
     175           0 :     PresContext()->FrameManager()->GetRootFrame()->InvalidateFrameSubtree();
     176             : 
     177           0 :     if (!mAddedScrollPositionListener) {
     178             :       nsIScrollableFrame* sf =
     179           0 :         PresContext()->GetPresShell()->GetRootScrollFrameAsScrollable();
     180           0 :       if (sf) {
     181           0 :         sf->AddScrollPositionListener(this);
     182           0 :         mAddedScrollPositionListener = true;
     183             :       }
     184             :     }
     185             :   }
     186           0 :   return NS_OK;
     187             : }
     188             : 
     189             : void
     190          23 : nsCanvasFrame::SetInitialChildList(ChildListID     aListID,
     191             :                                    nsFrameList&    aChildList)
     192             : {
     193          23 :   NS_ASSERTION(aListID != kPrincipalList ||
     194             :                aChildList.IsEmpty() || aChildList.OnlyChild(),
     195             :                "Primary child list can have at most one frame in it");
     196          23 :   nsContainerFrame::SetInitialChildList(aListID, aChildList);
     197          23 :   MaybePropagateRootElementWritingMode();
     198          23 : }
     199             : 
     200             : void
     201          23 : nsCanvasFrame::AppendFrames(ChildListID     aListID,
     202             :                             nsFrameList&    aFrameList)
     203             : {
     204             : #ifdef DEBUG
     205          23 :   MOZ_ASSERT(aListID == kPrincipalList, "unexpected child list");
     206          23 :   if (!mFrames.IsEmpty()) {
     207          23 :     for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
     208             :       // We only allow native anonymous child frames to be in principal child
     209             :       // list in canvas frame.
     210           0 :       MOZ_ASSERT(e.get()->GetContent()->IsInNativeAnonymousSubtree(),
     211             :                  "invalid child list");
     212             :     }
     213             :   }
     214          23 :   nsFrame::VerifyDirtyBitSet(aFrameList);
     215             : #endif
     216          23 :   nsContainerFrame::AppendFrames(aListID, aFrameList);
     217          23 :   MaybePropagateRootElementWritingMode();
     218          23 : }
     219             : 
     220             : void
     221           0 : nsCanvasFrame::InsertFrames(ChildListID     aListID,
     222             :                             nsIFrame*       aPrevFrame,
     223             :                             nsFrameList&    aFrameList)
     224             : {
     225             :   // Because we only support a single child frame inserting is the same
     226             :   // as appending
     227           0 :   MOZ_ASSERT(!aPrevFrame, "unexpected previous sibling frame");
     228           0 :   AppendFrames(aListID, aFrameList);
     229           0 :   MaybePropagateRootElementWritingMode();
     230           0 : }
     231             : 
     232             : #ifdef DEBUG
     233             : void
     234           0 : nsCanvasFrame::RemoveFrame(ChildListID     aListID,
     235             :                            nsIFrame*       aOldFrame)
     236             : {
     237           0 :   MOZ_ASSERT(aListID == kPrincipalList, "unexpected child list");
     238           0 :   nsContainerFrame::RemoveFrame(aListID, aOldFrame);
     239           0 : }
     240             : #endif
     241             : 
     242          69 : nsRect nsCanvasFrame::CanvasArea() const
     243             : {
     244             :   // Not clear which overflow rect we want here, but it probably doesn't
     245             :   // matter.
     246          69 :   nsRect result(GetVisualOverflowRect());
     247             : 
     248          69 :   nsIScrollableFrame *scrollableFrame = do_QueryFrame(GetParent());
     249          69 :   if (scrollableFrame) {
     250         138 :     nsRect portRect = scrollableFrame->GetScrollPortRect();
     251          69 :     result.UnionRect(result, nsRect(nsPoint(0, 0), portRect.Size()));
     252             :   }
     253          69 :   return result;
     254             : }
     255             : 
     256             : void
     257           1 : nsDisplayCanvasBackgroundColor::Paint(nsDisplayListBuilder* aBuilder,
     258             :                                       gfxContext* aCtx)
     259             : {
     260           1 :   nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
     261           1 :   nsPoint offset = ToReferenceFrame();
     262           2 :   nsRect bgClipRect = frame->CanvasArea() + offset;
     263           1 :   if (NS_GET_A(mColor) > 0) {
     264           1 :     DrawTarget* drawTarget = aCtx->GetDrawTarget();
     265           1 :     int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
     266             :     Rect devPxRect =
     267           1 :       NSRectToSnappedRect(bgClipRect, appUnitsPerDevPixel, *drawTarget);
     268           1 :     drawTarget->FillRect(devPxRect, ColorPattern(ToDeviceColor(mColor)));
     269             :   }
     270           1 : }
     271             : 
     272             : already_AddRefed<Layer>
     273           0 : nsDisplayCanvasBackgroundColor::BuildLayer(nsDisplayListBuilder* aBuilder,
     274             :                                            LayerManager* aManager,
     275             :                                            const ContainerLayerParameters& aContainerParameters)
     276             : {
     277           0 :   if (NS_GET_A(mColor) == 0) {
     278           0 :     return nullptr;
     279             :   }
     280             : 
     281           0 :   if (aManager->GetBackendType() == layers::LayersBackend::LAYERS_WR) {
     282           0 :     return BuildDisplayItemLayer(aBuilder, aManager, aContainerParameters);
     283             :   }
     284             : 
     285             :   RefPtr<ColorLayer> layer = static_cast<ColorLayer*>
     286           0 :     (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this));
     287           0 :   if (!layer) {
     288           0 :     layer = aManager->CreateColorLayer();
     289           0 :     if (!layer) {
     290           0 :       return nullptr;
     291             :     }
     292             :   }
     293           0 :   layer->SetColor(ToDeviceColor(mColor));
     294             : 
     295           0 :   nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
     296           0 :   nsPoint offset = ToReferenceFrame();
     297           0 :   nsRect bgClipRect = frame->CanvasArea() + offset;
     298             : 
     299           0 :   int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
     300             : 
     301           0 :   layer->SetBounds(bgClipRect.ToNearestPixels(appUnitsPerDevPixel));
     302           0 :   layer->SetBaseTransform(gfx::Matrix4x4::Translation(aContainerParameters.mOffset.x,
     303           0 :                                                       aContainerParameters.mOffset.y, 0));
     304             : 
     305           0 :   return layer.forget();
     306             : }
     307             : 
     308             : bool
     309           0 : nsDisplayCanvasBackgroundColor::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
     310             :                                                         const StackingContextHelper& aSc,
     311             :                                                         nsTArray<WebRenderParentCommand>& aParentCommands,
     312             :                                                         WebRenderLayerManager* aManager,
     313             :                                                         nsDisplayListBuilder* aDisplayListBuilder)
     314             : {
     315           0 :   if (aManager->IsLayersFreeTransaction()) {
     316           0 :     ContainerLayerParameters parameter;
     317           0 :     if (GetLayerState(aDisplayListBuilder, aManager, parameter) != LAYER_ACTIVE) {
     318           0 :       return false;
     319             :     }
     320             :   }
     321             : 
     322           0 :   nsCanvasFrame *frame = static_cast<nsCanvasFrame *>(mFrame);
     323           0 :   nsPoint offset = ToReferenceFrame();
     324           0 :   nsRect bgClipRect = frame->CanvasArea() + offset;
     325           0 :   int32_t appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
     326             : 
     327             :   LayoutDeviceRect rect = LayoutDeviceRect::FromAppUnits(
     328           0 :           bgClipRect, appUnitsPerDevPixel);
     329             : 
     330           0 :   WrRect transformedRect = aSc.ToRelativeWrRect(rect);
     331             :   aBuilder.PushRect(transformedRect,
     332             :                     transformedRect,
     333           0 :                     wr::ToWrColor(ToDeviceColor(mColor)));
     334           0 :   return true;
     335             : }
     336             : 
     337             : #ifdef MOZ_DUMP_PAINTING
     338             : void
     339           0 : nsDisplayCanvasBackgroundColor::WriteDebugInfo(std::stringstream& aStream)
     340             : {
     341           0 :   aStream << " (rgba "
     342           0 :           << (int)NS_GET_R(mColor) << ","
     343           0 :           << (int)NS_GET_G(mColor) << ","
     344           0 :           << (int)NS_GET_B(mColor) << ","
     345           0 :           << (int)NS_GET_A(mColor) << ")";
     346           0 : }
     347             : #endif
     348             : 
     349             : #ifndef MOZ_GFX_OPTIMIZE_MOBILE
     350           0 : static void BlitSurface(DrawTarget* aDest, const gfxRect& aRect, DrawTarget* aSource)
     351             : {
     352           0 :   RefPtr<SourceSurface> source = aSource->Snapshot();
     353           0 :   aDest->DrawSurface(source,
     354           0 :                      Rect(aRect.x, aRect.y, aRect.width, aRect.height),
     355           0 :                      Rect(0, 0, aRect.width, aRect.height));
     356           0 : }
     357             : #endif
     358             : 
     359             : void
     360           0 : nsDisplayCanvasBackgroundImage::Paint(nsDisplayListBuilder* aBuilder,
     361             :                                       gfxContext* aCtx)
     362             : {
     363           0 :   nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
     364           0 :   nsPoint offset = ToReferenceFrame();
     365           0 :   nsRect bgClipRect = frame->CanvasArea() + offset;
     366             : 
     367             : #ifndef MOZ_GFX_OPTIMIZE_MOBILE
     368           0 :   RefPtr<gfxContext> dest = aCtx;
     369           0 :   gfxRect destRect;
     370           0 :   if (IsSingleFixedPositionImage(aBuilder, bgClipRect, &destRect) &&
     371           0 :       aBuilder->IsPaintingToWindow() && !aBuilder->IsCompositingCheap() &&
     372           0 :       !dest->CurrentMatrix().HasNonIntegerTranslation()) {
     373             :     // Snap image rectangle to nearest pixel boundaries. This is the right way
     374             :     // to snap for this context, because we checked HasNonIntegerTranslation
     375             :     // above.
     376           0 :     destRect.Round();
     377             :     RefPtr<DrawTarget> dt =
     378           0 :       Frame()->GetProperty(nsIFrame::CachedBackgroundImageDT());
     379           0 :     DrawTarget* destDT = dest->GetDrawTarget();
     380           0 :     if (dt) {
     381           0 :       BlitSurface(destDT, destRect, dt);
     382           0 :       return;
     383             :     }
     384             : 
     385           0 :     dt = destDT->CreateSimilarDrawTarget(IntSize::Ceil(destRect.width,
     386           0 :                                                        destRect.height),
     387           0 :                                          SurfaceFormat::B8G8R8A8);
     388           0 :     if (dt && dt->IsValid()) {
     389           0 :       RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(dt);
     390           0 :       MOZ_ASSERT(ctx); // already checked draw target above
     391           0 :       ctx->SetMatrix(ctx->CurrentMatrix().PreTranslate(-destRect.x, -destRect.y));
     392           0 :       PaintInternal(aBuilder, ctx, bgClipRect, &bgClipRect);
     393           0 :       BlitSurface(dest->GetDrawTarget(), destRect, dt);
     394           0 :       frame->SetProperty(nsIFrame::CachedBackgroundImageDT(),
     395           0 :                               dt.forget().take());
     396           0 :       return;
     397             :     }
     398             :   }
     399             : #endif
     400           0 :   PaintInternal(aBuilder, aCtx, mVisibleRect, &bgClipRect);
     401             : }
     402             : 
     403             : bool
     404           0 : nsDisplayCanvasBackgroundImage::IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder,
     405             :                                                            const nsRect& aClipRect,
     406             :                                                            gfxRect* aDestRect)
     407             : {
     408           0 :   if (!mBackgroundStyle)
     409           0 :     return false;
     410             : 
     411           0 :   if (mBackgroundStyle->mImage.mLayers.Length() != 1)
     412           0 :     return false;
     413             : 
     414             : 
     415           0 :   nsPresContext* presContext = mFrame->PresContext();
     416           0 :   uint32_t flags = aBuilder->GetBackgroundPaintFlags();
     417           0 :   nsRect borderArea = nsRect(ToReferenceFrame(), mFrame->GetSize());
     418           0 :   const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mImage.mLayers[mLayer];
     419             : 
     420           0 :   if (layer.mAttachment != NS_STYLE_IMAGELAYER_ATTACHMENT_FIXED)
     421           0 :     return false;
     422             : 
     423             :    nsBackgroundLayerState state =
     424             :      nsCSSRendering::PrepareImageLayer(presContext, mFrame, flags,
     425           0 :                                        borderArea, aClipRect, layer);
     426             : 
     427             : 
     428             :   // We only care about images here, not gradients.
     429           0 :   if (!mIsRasterImage)
     430           0 :     return false;
     431             : 
     432           0 :   int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
     433           0 :   *aDestRect = nsLayoutUtils::RectToGfxRect(state.mFillArea, appUnitsPerDevPixel);
     434             : 
     435           0 :   return true;
     436             : }
     437             : 
     438             : 
     439             : void
     440           0 : nsDisplayCanvasThemedBackground::Paint(nsDisplayListBuilder* aBuilder,
     441             :                                        gfxContext* aCtx)
     442             : {
     443           0 :   nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
     444           0 :   nsPoint offset = ToReferenceFrame();
     445           0 :   nsRect bgClipRect = frame->CanvasArea() + offset;
     446             : 
     447           0 :   PaintInternal(aBuilder, aCtx, mVisibleRect, &bgClipRect);
     448           0 : }
     449             : 
     450             : /**
     451             :  * A display item to paint the focus ring for the document.
     452             :  *
     453             :  * The only reason this can't use nsDisplayGeneric is overriding GetBounds.
     454             :  */
     455             : class nsDisplayCanvasFocus : public nsDisplayItem {
     456             : public:
     457           0 :   nsDisplayCanvasFocus(nsDisplayListBuilder* aBuilder, nsCanvasFrame *aFrame)
     458           0 :     : nsDisplayItem(aBuilder, aFrame)
     459             :   {
     460           0 :     MOZ_COUNT_CTOR(nsDisplayCanvasFocus);
     461           0 :   }
     462           0 :   virtual ~nsDisplayCanvasFocus() {
     463           0 :     MOZ_COUNT_DTOR(nsDisplayCanvasFocus);
     464           0 :   }
     465             : 
     466           0 :   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
     467             :                            bool* aSnap) override
     468             :   {
     469           0 :     *aSnap = false;
     470             :     // This is an overestimate, but that's not a problem.
     471           0 :     nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
     472           0 :     return frame->CanvasArea() + ToReferenceFrame();
     473             :   }
     474             : 
     475           0 :   virtual void Paint(nsDisplayListBuilder* aBuilder,
     476             :                      gfxContext* aCtx) override
     477             :   {
     478           0 :     nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
     479           0 :     frame->PaintFocus(aCtx->GetDrawTarget(), ToReferenceFrame());
     480           0 :   }
     481             : 
     482           0 :   NS_DISPLAY_DECL_NAME("CanvasFocus", TYPE_CANVAS_FOCUS)
     483             : };
     484             : 
     485             : void
     486          20 : nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     487             :                                 const nsRect&           aDirtyRect,
     488             :                                 const nsDisplayListSet& aLists)
     489             : {
     490          20 :   if (GetPrevInFlow()) {
     491           0 :     DisplayOverflowContainers(aBuilder, aDirtyRect, aLists);
     492             :   }
     493             : 
     494             :   // Force a background to be shown. We may have a background propagated to us,
     495             :   // in which case StyleBackground wouldn't have the right background
     496             :   // and the code in nsFrame::DisplayBorderBackgroundOutline might not give us
     497             :   // a background.
     498             :   // We don't have any border or outline, and our background draws over
     499             :   // the overflow area, so just add nsDisplayCanvasBackground instead of
     500             :   // calling DisplayBorderBackgroundOutline.
     501          20 :   if (IsVisibleForPainting(aBuilder)) {
     502             :     nsStyleContext* bgSC;
     503          20 :     const nsStyleBackground* bg = nullptr;
     504          20 :     bool isThemed = IsThemed();
     505          20 :     if (!isThemed && nsCSSRendering::FindBackground(this, &bgSC)) {
     506          20 :       bg = bgSC->StyleBackground();
     507             :     }
     508          20 :     aLists.BorderBackground()->AppendNewToTop(
     509          40 :         new (aBuilder) nsDisplayCanvasBackgroundColor(aBuilder, this));
     510             : 
     511          20 :     if (isThemed) {
     512           0 :       aLists.BorderBackground()->AppendNewToTop(
     513           0 :         new (aBuilder) nsDisplayCanvasThemedBackground(aBuilder, this));
     514           0 :       return;
     515             :     }
     516             : 
     517          20 :     if (!bg) {
     518           0 :       return;
     519             :     }
     520             : 
     521             :     const ActiveScrolledRoot* asr =
     522          20 :       aBuilder->CurrentActiveScrolledRoot();
     523             : 
     524          20 :     bool needBlendContainer = false;
     525          40 :     nsDisplayListBuilder::AutoContainerASRTracker contASRTracker(aBuilder);
     526             : 
     527             :     // Create separate items for each background layer.
     528          20 :     const nsStyleImageLayers& layers = bg->mImage;
     529          40 :     NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, layers) {
     530          20 :       if (layers.mLayers[i].mImage.IsEmpty()) {
     531          20 :         continue;
     532             :       }
     533           0 :       if (layers.mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) {
     534           0 :         needBlendContainer = true;
     535             :       }
     536             : 
     537           0 :       nsRect bgRect = GetRectRelativeToSelf() + aBuilder->ToReferenceFrame(this);
     538             : 
     539           0 :       const ActiveScrolledRoot* thisItemASR = asr;
     540           0 :       nsDisplayList thisItemList;
     541             :       nsDisplayBackgroundImage::InitData bgData =
     542             :         nsDisplayBackgroundImage::GetInitData(aBuilder, this, i, bgRect, bg,
     543           0 :                                               nsDisplayBackgroundImage::LayerizeFixed::ALWAYS_LAYERIZE_FIXED_BACKGROUND);
     544             : 
     545           0 :       if (bgData.shouldFixToViewport) {
     546             : 
     547           0 :         auto* displayData = aBuilder->GetCurrentFixedBackgroundDisplayData();
     548             :         nsDisplayListBuilder::AutoBuildingDisplayList
     549           0 :           buildingDisplayList(aBuilder, this, aBuilder->GetDirtyRect(), false);
     550             : 
     551           0 :         DisplayListClipState::AutoSaveRestore clipState(aBuilder);
     552           0 :         nsDisplayListBuilder::AutoCurrentActiveScrolledRootSetter asrSetter(aBuilder);
     553           0 :         if (displayData) {
     554           0 :           nsRect dirtyRect = displayData->mDirtyRect + GetOffsetTo(PresContext()->GetPresShell()->GetRootFrame());
     555           0 :           buildingDisplayList.SetDirtyRect(dirtyRect);
     556           0 :           clipState.SetClipChainForContainingBlockDescendants(
     557           0 :             displayData->mContainingBlockClipChain);
     558           0 :           asrSetter.SetCurrentActiveScrolledRoot(
     559           0 :             displayData->mContainingBlockActiveScrolledRoot);
     560           0 :           thisItemASR = displayData->mContainingBlockActiveScrolledRoot;
     561             :         }
     562           0 :         nsDisplayCanvasBackgroundImage* bgItem = nullptr;
     563             :         {
     564           0 :           DisplayListClipState::AutoSaveRestore bgImageClip(aBuilder);
     565           0 :           bgImageClip.Clear();
     566           0 :           bgItem = new (aBuilder) nsDisplayCanvasBackgroundImage(bgData);
     567             :         }
     568             :         thisItemList.AppendNewToTop(
     569           0 :           nsDisplayFixedPosition::CreateForFixedBackground(aBuilder, this, bgItem, i));
     570             : 
     571             :       } else {
     572           0 :         thisItemList.AppendNewToTop(new (aBuilder) nsDisplayCanvasBackgroundImage(bgData));
     573             :       }
     574             : 
     575           0 :       if (layers.mLayers[i].mBlendMode != NS_STYLE_BLEND_NORMAL) {
     576           0 :         DisplayListClipState::AutoSaveRestore blendClip(aBuilder);
     577           0 :         blendClip.ClearUpToASR(thisItemASR);
     578             :         thisItemList.AppendNewToTop(
     579             :           new (aBuilder) nsDisplayBlendMode(aBuilder, this, &thisItemList,
     580           0 :                                             layers.mLayers[i].mBlendMode,
     581           0 :                                             thisItemASR, i + 1));
     582             :       }
     583           0 :       aLists.BorderBackground()->AppendToTop(&thisItemList);
     584             :     }
     585             : 
     586          20 :     if (needBlendContainer) {
     587           0 :       const ActiveScrolledRoot* containerASR = contASRTracker.GetContainerASR();
     588           0 :       DisplayListClipState::AutoSaveRestore blendContainerClip(aBuilder);
     589           0 :       blendContainerClip.ClearUpToASR(containerASR);
     590           0 :       aLists.BorderBackground()->AppendNewToTop(
     591           0 :         nsDisplayBlendContainer::CreateForBackgroundBlendMode(aBuilder, this,
     592             :                                                               aLists.BorderBackground(),
     593           0 :                                                               containerASR));
     594             :     }
     595             :   }
     596             : 
     597          40 :   for (nsIFrame* kid : PrincipalChildList()) {
     598             :     // Put our child into its own pseudo-stack.
     599          20 :     BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
     600             :   }
     601             : 
     602             : #ifdef DEBUG_CANVAS_FOCUS
     603             :   nsCOMPtr<nsIContent> focusContent;
     604             :   aPresContext->EventStateManager()->
     605             :     GetFocusedContent(getter_AddRefs(focusContent));
     606             : 
     607             :   bool hasFocus = false;
     608             :   nsCOMPtr<nsISupports> container;
     609             :   aPresContext->GetContainer(getter_AddRefs(container));
     610             :   nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
     611             :   if (docShell) {
     612             :     docShell->GetHasFocus(&hasFocus);
     613             :     printf("%p - nsCanvasFrame::Paint R:%d,%d,%d,%d  DR: %d,%d,%d,%d\n", this,
     614             :             mRect.x, mRect.y, mRect.width, mRect.height,
     615             :             aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
     616             :   }
     617             :   printf("%p - Focus: %s   c: %p  DoPaint:%s\n", docShell.get(), hasFocus?"Y":"N",
     618             :          focusContent.get(), mDoPaintFocus?"Y":"N");
     619             : #endif
     620             : 
     621          20 :   if (!mDoPaintFocus)
     622          20 :     return;
     623             :   // Only paint the focus if we're visible
     624           0 :   if (!StyleVisibility()->IsVisible())
     625           0 :     return;
     626             : 
     627           0 :   aLists.Outlines()->AppendNewToTop(new (aBuilder)
     628           0 :     nsDisplayCanvasFocus(aBuilder, this));
     629             : }
     630             : 
     631             : void
     632           0 : nsCanvasFrame::PaintFocus(DrawTarget* aDrawTarget, nsPoint aPt)
     633             : {
     634           0 :   nsRect focusRect(aPt, GetSize());
     635             : 
     636           0 :   nsIScrollableFrame *scrollableFrame = do_QueryFrame(GetParent());
     637           0 :   if (scrollableFrame) {
     638           0 :     nsRect portRect = scrollableFrame->GetScrollPortRect();
     639           0 :     focusRect.width = portRect.width;
     640           0 :     focusRect.height = portRect.height;
     641           0 :     focusRect.MoveBy(scrollableFrame->GetScrollPosition());
     642             :   }
     643             : 
     644             :  // XXX use the root frame foreground color, but should we find BODY frame
     645             :  // for HTML documents?
     646           0 :   nsIFrame* root = mFrames.FirstChild();
     647           0 :   const nsStyleColor* color = root ? root->StyleColor() : StyleColor();
     648           0 :   if (!color) {
     649           0 :     NS_ERROR("current color cannot be found");
     650           0 :     return;
     651             :   }
     652             : 
     653           0 :   nsCSSRendering::PaintFocus(PresContext(), aDrawTarget,
     654           0 :                              focusRect, color->mColor);
     655             : }
     656             : 
     657             : /* virtual */ nscoord
     658           0 : nsCanvasFrame::GetMinISize(gfxContext *aRenderingContext)
     659             : {
     660             :   nscoord result;
     661           0 :   DISPLAY_MIN_WIDTH(this, result);
     662           0 :   if (mFrames.IsEmpty())
     663           0 :     result = 0;
     664             :   else
     665           0 :     result = mFrames.FirstChild()->GetMinISize(aRenderingContext);
     666           0 :   return result;
     667             : }
     668             : 
     669             : /* virtual */ nscoord
     670           0 : nsCanvasFrame::GetPrefISize(gfxContext *aRenderingContext)
     671             : {
     672             :   nscoord result;
     673           0 :   DISPLAY_PREF_WIDTH(this, result);
     674           0 :   if (mFrames.IsEmpty())
     675           0 :     result = 0;
     676             :   else
     677           0 :     result = mFrames.FirstChild()->GetPrefISize(aRenderingContext);
     678           0 :   return result;
     679             : }
     680             : 
     681             : void
     682          45 : nsCanvasFrame::Reflow(nsPresContext*           aPresContext,
     683             :                       ReflowOutput&     aDesiredSize,
     684             :                       const ReflowInput& aReflowInput,
     685             :                       nsReflowStatus&          aStatus)
     686             : {
     687          45 :   MarkInReflow();
     688          45 :   DO_GLOBAL_REFLOW_COUNT("nsCanvasFrame");
     689          90 :   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
     690          45 :   NS_FRAME_TRACE_REFLOW_IN("nsCanvasFrame::Reflow");
     691             : 
     692             :   // Initialize OUT parameter
     693          45 :   aStatus.Reset();
     694             : 
     695             :   nsCanvasFrame* prevCanvasFrame = static_cast<nsCanvasFrame*>
     696          45 :                                                (GetPrevInFlow());
     697          45 :   if (prevCanvasFrame) {
     698             :     AutoFrameListPtr overflow(aPresContext,
     699           0 :                               prevCanvasFrame->StealOverflowFrames());
     700           0 :     if (overflow) {
     701           0 :       NS_ASSERTION(overflow->OnlyChild(),
     702             :                    "must have doc root as canvas frame's only child");
     703           0 :       nsContainerFrame::ReparentFrameViewList(*overflow, prevCanvasFrame, this);
     704             :       // Prepend overflow to the our child list. There may already be
     705             :       // children placeholders for fixed-pos elements, which don't get
     706             :       // reflowed but must not be lost until the canvas frame is destroyed.
     707           0 :       mFrames.InsertFrames(this, nullptr, *overflow);
     708             :     }
     709             :   }
     710             : 
     711             :   // Set our size up front, since some parts of reflow depend on it
     712             :   // being already set.  Note that the computed height may be
     713             :   // unconstrained; that's ok.  Consumers should watch out for that.
     714          45 :   SetSize(nsSize(aReflowInput.ComputedWidth(), aReflowInput.ComputedHeight()));
     715             : 
     716             :   // Reflow our one and only normal child frame. It's either the root
     717             :   // element's frame or a placeholder for that frame, if the root element
     718             :   // is abs-pos or fixed-pos. We may have additional children which
     719             :   // are placeholders for continuations of fixed-pos content, but those
     720             :   // don't need to be reflowed. The normal child is always comes before
     721             :   // the fixed-pos placeholders, because we insert it at the start
     722             :   // of the child list, above.
     723          90 :   ReflowOutput kidDesiredSize(aReflowInput);
     724          45 :   if (mFrames.IsEmpty()) {
     725             :     // We have no child frame, so return an empty size
     726           0 :     aDesiredSize.Width() = aDesiredSize.Height() = 0;
     727             :   } else {
     728          45 :     nsIFrame* kidFrame = mFrames.FirstChild();
     729          45 :     bool kidDirty = (kidFrame->GetStateBits() & NS_FRAME_IS_DIRTY) != 0;
     730             : 
     731             :     ReflowInput
     732             :       kidReflowInput(aPresContext, aReflowInput, kidFrame,
     733          45 :                      aReflowInput.AvailableSize(kidFrame->GetWritingMode()));
     734             : 
     735          67 :     if (aReflowInput.IsBResizeForWM(kidReflowInput.GetWritingMode()) &&
     736          22 :         (kidFrame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_BSIZE)) {
     737             :       // Tell our kid it's being block-dir resized too.  Bit of a
     738             :       // hack for framesets.
     739           0 :       kidReflowInput.SetBResize(true);
     740             :     }
     741             : 
     742          45 :     WritingMode wm = aReflowInput.GetWritingMode();
     743          45 :     WritingMode kidWM = kidReflowInput.GetWritingMode();
     744          45 :     nsSize containerSize = aReflowInput.ComputedPhysicalSize();
     745             : 
     746          45 :     LogicalMargin margin = kidReflowInput.ComputedLogicalMargin();
     747          45 :     LogicalPoint kidPt(kidWM, margin.IStart(kidWM), margin.BStart(kidWM));
     748             : 
     749          45 :     kidReflowInput.ApplyRelativePositioning(&kidPt, containerSize);
     750             : 
     751             :     // Reflow the frame
     752          45 :     ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowInput,
     753          45 :                 kidWM, kidPt, containerSize, 0, aStatus);
     754             : 
     755             :     // Complete the reflow and position and size the child frame
     756             :     FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, &kidReflowInput,
     757          45 :                       kidWM, kidPt, containerSize, 0);
     758             : 
     759          45 :     if (!aStatus.IsFullyComplete()) {
     760           0 :       nsIFrame* nextFrame = kidFrame->GetNextInFlow();
     761           0 :       NS_ASSERTION(nextFrame || aStatus.NextInFlowNeedsReflow(),
     762             :         "If it's incomplete and has no nif yet, it must flag a nif reflow.");
     763           0 :       if (!nextFrame) {
     764             :         nextFrame = aPresContext->PresShell()->FrameConstructor()->
     765           0 :           CreateContinuingFrame(aPresContext, kidFrame, this);
     766           0 :         SetOverflowFrames(nsFrameList(nextFrame, nextFrame));
     767             :         // Root overflow containers will be normal children of
     768             :         // the canvas frame, but that's ok because there
     769             :         // aren't any other frames we need to isolate them from
     770             :         // during reflow.
     771             :       }
     772           0 :       if (aStatus.IsOverflowIncomplete()) {
     773           0 :         nextFrame->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
     774             :       }
     775             :     }
     776             : 
     777             :     // If the child frame was just inserted, then we're responsible for making sure
     778             :     // it repaints
     779          45 :     if (kidDirty) {
     780             :       // But we have a new child, which will affect our background, so
     781             :       // invalidate our whole rect.
     782             :       // Note: Even though we request to be sized to our child's size, our
     783             :       // scroll frame ensures that we are always the size of the viewport.
     784             :       // Also note: GetPosition() on a CanvasFrame is always going to return
     785             :       // (0, 0). We only want to invalidate GetRect() since Get*OverflowRect()
     786             :       // could also include overflow to our top and left (out of the viewport)
     787             :       // which doesn't need to be painted.
     788          24 :       nsIFrame* viewport = PresContext()->GetPresShell()->GetRootFrame();
     789          24 :       viewport->InvalidateFrame();
     790             :     }
     791             : 
     792             :     // Return our desired size. Normally it's what we're told, but
     793             :     // sometimes we can be given an unconstrained height (when a window
     794             :     // is sizing-to-content), and we should compute our desired height.
     795          45 :     LogicalSize finalSize(wm);
     796          45 :     finalSize.ISize(wm) = aReflowInput.ComputedISize();
     797          45 :     if (aReflowInput.ComputedBSize() == NS_UNCONSTRAINEDSIZE) {
     798           0 :       finalSize.BSize(wm) = kidFrame->GetLogicalSize(wm).BSize(wm) +
     799           0 :         kidReflowInput.ComputedLogicalMargin().BStartEnd(wm);
     800             :     } else {
     801          45 :       finalSize.BSize(wm) = aReflowInput.ComputedBSize();
     802             :     }
     803             : 
     804          45 :     aDesiredSize.SetSize(wm, finalSize);
     805          45 :     aDesiredSize.SetOverflowAreasToDesiredBounds();
     806          45 :     aDesiredSize.mOverflowAreas.UnionWith(
     807          90 :       kidDesiredSize.mOverflowAreas + kidFrame->GetPosition());
     808             :   }
     809             : 
     810          45 :   if (prevCanvasFrame) {
     811           0 :     ReflowOverflowContainerChildren(aPresContext, aReflowInput,
     812             :                                     aDesiredSize.mOverflowAreas, 0,
     813           0 :                                     aStatus);
     814             :   }
     815             : 
     816          45 :   FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, aReflowInput, aStatus);
     817             : 
     818          45 :   NS_FRAME_TRACE_REFLOW_OUT("nsCanvasFrame::Reflow", aStatus);
     819          45 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
     820          45 : }
     821             : 
     822             : nsresult
     823           0 : nsCanvasFrame::GetContentForEvent(WidgetEvent* aEvent, nsIContent** aContent)
     824             : {
     825           0 :   NS_ENSURE_ARG_POINTER(aContent);
     826           0 :   nsresult rv = nsFrame::GetContentForEvent(aEvent,
     827           0 :                                             aContent);
     828           0 :   if (NS_FAILED(rv) || !*aContent) {
     829           0 :     nsIFrame* kid = mFrames.FirstChild();
     830           0 :     if (kid) {
     831             :       rv = kid->GetContentForEvent(aEvent,
     832           0 :                                    aContent);
     833             :     }
     834             :   }
     835             : 
     836           0 :   return rv;
     837             : }
     838             : 
     839             : void
     840          46 : nsCanvasFrame::MaybePropagateRootElementWritingMode()
     841             : {
     842          46 :   nsIFrame* child = PrincipalChildList().FirstChild();
     843          92 :   if (child && child->GetContent() &&
     844          46 :       child->GetContent() == PresContext()->Document()->GetRootElement()) {
     845          46 :     nsIFrame* childPrimary = child->GetContent()->GetPrimaryFrame();
     846          46 :     PropagateRootElementWritingMode(childPrimary->GetWritingMode());
     847             :   }
     848          46 : }
     849             : 
     850             : #ifdef DEBUG_FRAME_DUMP
     851             : nsresult
     852           0 : nsCanvasFrame::GetFrameName(nsAString& aResult) const
     853             : {
     854           0 :   return MakeFrameName(NS_LITERAL_STRING("Canvas"), aResult);
     855             : }
     856             : #endif

Generated by: LCOV version 1.13