LCOV - code coverage report
Current view: top level - layout/generic - nsPlaceholderFrame.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 49 111 44.1 %
Date: 2017-07-14 16:53:18 Functions: 9 16 56.2 %
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             : /*
       7             :  * rendering object for the point that anchors out-of-flow rendering
       8             :  * objects such as floats and absolutely positioned elements
       9             :  */
      10             : 
      11             : #include "nsPlaceholderFrame.h"
      12             : 
      13             : #include "gfxContext.h"
      14             : #include "gfxUtils.h"
      15             : #include "mozilla/gfx/2D.h"
      16             : #include "nsDisplayList.h"
      17             : #include "nsFrameManager.h"
      18             : #include "nsLayoutUtils.h"
      19             : #include "nsPresContext.h"
      20             : #include "nsIFrameInlines.h"
      21             : #include "nsIContentInlines.h"
      22             : 
      23             : using namespace mozilla;
      24             : using namespace mozilla::gfx;
      25             : 
      26             : nsIFrame*
      27          35 : NS_NewPlaceholderFrame(nsIPresShell* aPresShell, nsStyleContext* aContext,
      28             :                        nsFrameState aTypeBit)
      29             : {
      30          35 :   return new (aPresShell) nsPlaceholderFrame(aContext, aTypeBit);
      31             : }
      32             : 
      33          35 : NS_IMPL_FRAMEARENA_HELPERS(nsPlaceholderFrame)
      34             : 
      35             : #ifdef DEBUG
      36         174 : NS_QUERYFRAME_HEAD(nsPlaceholderFrame)
      37           0 :   NS_QUERYFRAME_ENTRY(nsPlaceholderFrame)
      38         174 : NS_QUERYFRAME_TAIL_INHERITING(nsFrame)
      39             : #endif
      40             : 
      41             : /* virtual */ nsSize
      42         262 : nsPlaceholderFrame::GetXULMinSize(nsBoxLayoutState& aBoxLayoutState)
      43             : {
      44         262 :   nsSize size(0, 0);
      45         524 :   DISPLAY_MIN_SIZE(this, size);
      46         524 :   return size;
      47             : }
      48             : 
      49             : /* virtual */ nsSize
      50         235 : nsPlaceholderFrame::GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState)
      51             : {
      52         235 :   nsSize size(0, 0);
      53         470 :   DISPLAY_PREF_SIZE(this, size);
      54         470 :   return size;
      55             : }
      56             : 
      57             : /* virtual */ nsSize
      58         202 : nsPlaceholderFrame::GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState)
      59             : {
      60         202 :   nsSize size(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
      61         404 :   DISPLAY_MAX_SIZE(this, size);
      62         404 :   return size;
      63             : }
      64             : 
      65             : /* virtual */ void
      66           0 : nsPlaceholderFrame::AddInlineMinISize(gfxContext* aRenderingContext,
      67             :                                       nsIFrame::InlineMinISizeData* aData)
      68             : {
      69             :   // Override AddInlineMinWith so that *nothing* happens.  In
      70             :   // particular, we don't want to zero out |aData->mTrailingWhitespace|,
      71             :   // since nsLineLayout skips placeholders when trimming trailing
      72             :   // whitespace, and we don't want to set aData->mSkipWhitespace to
      73             :   // false.
      74             : 
      75             :   // ...but push floats onto the list
      76           0 :   if (mOutOfFlowFrame->IsFloating()) {
      77             :     nscoord floatWidth =
      78           0 :       nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
      79             :                                            mOutOfFlowFrame,
      80           0 :                                            nsLayoutUtils::MIN_ISIZE);
      81           0 :     aData->mFloats.AppendElement(
      82           0 :       InlineIntrinsicISizeData::FloatInfo(mOutOfFlowFrame, floatWidth));
      83             :   }
      84           0 : }
      85             : 
      86             : /* virtual */ void
      87           0 : nsPlaceholderFrame::AddInlinePrefISize(gfxContext* aRenderingContext,
      88             :                                        nsIFrame::InlinePrefISizeData* aData)
      89             : {
      90             :   // Override AddInlinePrefWith so that *nothing* happens.  In
      91             :   // particular, we don't want to zero out |aData->mTrailingWhitespace|,
      92             :   // since nsLineLayout skips placeholders when trimming trailing
      93             :   // whitespace, and we don't want to set aData->mSkipWhitespace to
      94             :   // false.
      95             : 
      96             :   // ...but push floats onto the list
      97           0 :   if (mOutOfFlowFrame->IsFloating()) {
      98             :     nscoord floatWidth =
      99           0 :       nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
     100             :                                            mOutOfFlowFrame,
     101           0 :                                            nsLayoutUtils::PREF_ISIZE);
     102           0 :     aData->mFloats.AppendElement(
     103           0 :       InlineIntrinsicISizeData::FloatInfo(mOutOfFlowFrame, floatWidth));
     104             :   }
     105           0 : }
     106             : 
     107             : void
     108          71 : nsPlaceholderFrame::Reflow(nsPresContext*           aPresContext,
     109             :                            ReflowOutput&     aDesiredSize,
     110             :                            const ReflowInput& aReflowInput,
     111             :                            nsReflowStatus&          aStatus)
     112             : {
     113             :   // NOTE that the ReflowInput passed to this method is not fully initialized,
     114             :   // on the grounds that reflowing a placeholder is a rather trivial operation.
     115             :   // (See bug 1367711.)
     116             : 
     117             : #ifdef DEBUG
     118             :   // We should be getting reflowed before our out-of-flow.
     119             :   // If this is our first reflow, and our out-of-flow has already received its
     120             :   // first reflow (before us), complain.
     121             :   // XXXdholbert This "look for a previous continuation or IB-split sibling"
     122             :   // code could use nsLayoutUtils::GetPrevContinuationOrIBSplitSibling(), if
     123             :   // we ever add a function like that. (We currently have a "Next" version.)
     124         102 :   if ((GetStateBits() & NS_FRAME_FIRST_REFLOW) &&
     125          31 :       !(mOutOfFlowFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
     126             : 
     127             :     // Unfortunately, this can currently happen when the placeholder is in a
     128             :     // later continuation or later IB-split sibling than its out-of-flow (as
     129             :     // is the case in some of our existing unit tests). So for now, in that
     130             :     // case, we'll warn instead of asserting.
     131           0 :     bool isInContinuationOrIBSplit = false;
     132           0 :     nsIFrame* ancestor = this;
     133           0 :     while ((ancestor = ancestor->GetParent())) {
     134           0 :       if (ancestor->GetPrevContinuation() ||
     135           0 :           ancestor->GetProperty(IBSplitPrevSibling())) {
     136           0 :         isInContinuationOrIBSplit = true;
     137           0 :         break;
     138             :       }
     139             :     }
     140             : 
     141           0 :     if (isInContinuationOrIBSplit) {
     142           0 :       NS_WARNING("Out-of-flow frame got reflowed before its placeholder");
     143             :     } else {
     144           0 :       NS_ERROR("Out-of-flow frame got reflowed before its placeholder");
     145             :     }
     146             :   }
     147             : #endif
     148             : 
     149          71 :   MarkInReflow();
     150          71 :   DO_GLOBAL_REFLOW_COUNT("nsPlaceholderFrame");
     151         142 :   DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
     152          71 :   aDesiredSize.ClearSize();
     153             : 
     154          71 :   aStatus.Reset();
     155          71 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
     156          71 : }
     157             : 
     158             : void
     159           8 : nsPlaceholderFrame::DestroyFrom(nsIFrame* aDestructRoot)
     160             : {
     161           8 :   nsIFrame* oof = mOutOfFlowFrame;
     162           8 :   if (oof) {
     163           8 :     mOutOfFlowFrame = nullptr;
     164           8 :     oof->DeleteProperty(nsIFrame::PlaceholderFrameProperty());
     165             :     // If aDestructRoot is not an ancestor of the out-of-flow frame,
     166             :     // then call RemoveFrame on it here.
     167             :     // Also destroy it here if it's a popup frame. (Bug 96291)
     168          10 :     if ((GetStateBits() & PLACEHOLDER_FOR_POPUP) ||
     169           2 :         !nsLayoutUtils::IsProperAncestorFrame(aDestructRoot, oof)) {
     170           8 :       ChildListID listId = nsLayoutUtils::GetChildListNameFor(oof);
     171           8 :       nsFrameManager* fm = PresContext()->GetPresShell()->FrameManager();
     172           8 :       fm->RemoveFrame(listId, oof);
     173             :     }
     174             :     // else oof will be destroyed by its parent
     175             :   }
     176             : 
     177           8 :   nsFrame::DestroyFrom(aDestructRoot);
     178           8 : }
     179             : 
     180             : /* virtual */ bool
     181           0 : nsPlaceholderFrame::CanContinueTextRun() const
     182             : {
     183           0 :   if (!mOutOfFlowFrame) {
     184           0 :     return false;
     185             :   }
     186             :   // first-letter frames can continue text runs, and placeholders for floated
     187             :   // first-letter frames can too
     188           0 :   return mOutOfFlowFrame->CanContinueTextRun();
     189             : }
     190             : 
     191             : nsStyleContext*
     192         127 : nsPlaceholderFrame::GetParentStyleContextForOutOfFlow(nsIFrame** aProviderFrame) const
     193             : {
     194         127 :   NS_PRECONDITION(GetParent(), "How can we not have a parent here?");
     195             : 
     196         127 :   nsIContent* parentContent = mContent ? mContent->GetFlattenedTreeParent() : nullptr;
     197         127 :   if (parentContent) {
     198             :     nsStyleContext* sc =
     199         127 :       PresContext()->FrameManager()->GetDisplayContentsStyleFor(parentContent);
     200         127 :     if (sc) {
     201           0 :       *aProviderFrame = nullptr;
     202           0 :       return sc;
     203             :     }
     204             :   }
     205             : 
     206         127 :   nsIFrame* parentFrame = GetParent();
     207             :   // Placeholder of backdrop frame is a child of the corresponding top
     208             :   // layer frame, and its style context inherits from that frame. In
     209             :   // case of table, the top layer frame is the table wrapper frame.
     210             :   // However, it will be skipped in CorrectStyleParentFrame below, so
     211             :   // we need to handle it specially here.
     212         127 :   if ((GetStateBits() & PLACEHOLDER_FOR_TOPLAYER) &&
     213           0 :       parentFrame->IsTableWrapperFrame()) {
     214           0 :     MOZ_ASSERT(mOutOfFlowFrame->IsBackdropFrame(),
     215             :                "Only placeholder of backdrop frame can be put inside "
     216             :                "a table wrapper frame");
     217           0 :     *aProviderFrame = parentFrame;
     218           0 :     return parentFrame->StyleContext();
     219             :   }
     220             : 
     221             :   // Lie about our pseudo so we can step out of all anon boxes and
     222             :   // pseudo-elements.  The other option would be to reimplement the
     223             :   // {ib} split gunk here.
     224         127 :   *aProviderFrame = CorrectStyleParentFrame(parentFrame,
     225             :                                             nsGkAtoms::placeholderFrame);
     226         127 :   return *aProviderFrame ? (*aProviderFrame)->StyleContext() : nullptr;
     227             : }
     228             : 
     229             : 
     230             : #ifdef DEBUG
     231             : static void
     232           0 : PaintDebugPlaceholder(nsIFrame* aFrame, DrawTarget* aDrawTarget,
     233             :                       const nsRect& aDirtyRect, nsPoint aPt)
     234             : {
     235           0 :   ColorPattern cyan(ToDeviceColor(Color(0.f, 1.f, 1.f, 1.f)));
     236           0 :   int32_t appUnitsPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel();
     237             : 
     238           0 :   nscoord x = nsPresContext::CSSPixelsToAppUnits(-5);
     239           0 :   nsRect r(aPt.x + x, aPt.y,
     240             :            nsPresContext::CSSPixelsToAppUnits(13),
     241           0 :            nsPresContext::CSSPixelsToAppUnits(3));
     242           0 :   aDrawTarget->FillRect(NSRectToRect(r, appUnitsPerDevPixel), cyan);
     243             : 
     244           0 :   nscoord y = nsPresContext::CSSPixelsToAppUnits(-10);
     245           0 :   r = nsRect(aPt.x, aPt.y + y,
     246             :              nsPresContext::CSSPixelsToAppUnits(3),
     247             :              nsPresContext::CSSPixelsToAppUnits(10));
     248           0 :   aDrawTarget->FillRect(NSRectToRect(r, appUnitsPerDevPixel), cyan);
     249           0 : }
     250             : #endif // DEBUG
     251             : 
     252             : #if defined(DEBUG) || (defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF))
     253             : 
     254             : void
     255           0 : nsPlaceholderFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     256             :                                      const nsRect&           aDirtyRect,
     257             :                                      const nsDisplayListSet& aLists)
     258             : {
     259           0 :   DO_GLOBAL_REFLOW_COUNT_DSP("nsPlaceholderFrame");
     260             : 
     261             : #ifdef DEBUG
     262           0 :   if (GetShowFrameBorders()) {
     263           0 :     aLists.Outlines()->AppendNewToTop(
     264             :       new (aBuilder) nsDisplayGeneric(aBuilder, this, PaintDebugPlaceholder,
     265             :                                       "DebugPlaceholder",
     266           0 :                                       nsDisplayItem::TYPE_DEBUG_PLACEHOLDER));
     267             :   }
     268             : #endif
     269           0 : }
     270             : #endif // DEBUG || (MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF)
     271             : 
     272             : #ifdef DEBUG_FRAME_DUMP
     273             : nsresult
     274           0 : nsPlaceholderFrame::GetFrameName(nsAString& aResult) const
     275             : {
     276           0 :   return MakeFrameName(NS_LITERAL_STRING("Placeholder"), aResult);
     277             : }
     278             : 
     279             : void
     280           0 : nsPlaceholderFrame::List(FILE* out, const char* aPrefix, uint32_t aFlags) const
     281             : {
     282           0 :   nsCString str;
     283           0 :   ListGeneric(str, aPrefix, aFlags);
     284             : 
     285           0 :   if (mOutOfFlowFrame) {
     286           0 :     str += " outOfFlowFrame=";
     287           0 :     nsFrame::ListTag(str, mOutOfFlowFrame);
     288             :   }
     289           0 :   fprintf_stderr(out, "%s\n", str.get());
     290           0 : }
     291             : #endif

Generated by: LCOV version 1.13