layout/generic/nsPlaceholderFrame.cpp

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

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

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

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /*
     7  * rendering object for the point that anchors out-of-flow rendering
     8  * objects such as floats and absolutely positioned elements
     9  */
    11 #include "nsPlaceholderFrame.h"
    13 #include "nsDisplayList.h"
    14 #include "nsFrameManager.h"
    15 #include "nsLayoutUtils.h"
    16 #include "nsPresContext.h"
    17 #include "nsRenderingContext.h"
    18 #include "nsIFrameInlines.h"
    20 nsIFrame*
    21 NS_NewPlaceholderFrame(nsIPresShell* aPresShell, nsStyleContext* aContext,
    22                        nsFrameState aTypeBit)
    23 {
    24   return new (aPresShell) nsPlaceholderFrame(aContext, aTypeBit);
    25 }
    27 NS_IMPL_FRAMEARENA_HELPERS(nsPlaceholderFrame)
    29 #ifdef DEBUG
    30 NS_QUERYFRAME_HEAD(nsPlaceholderFrame)
    31   NS_QUERYFRAME_ENTRY(nsPlaceholderFrame)
    32 NS_QUERYFRAME_TAIL_INHERITING(nsFrame)
    33 #endif
    35 /* virtual */ nsSize
    36 nsPlaceholderFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState)
    37 {
    38   nsSize size(0, 0);
    39   DISPLAY_MIN_SIZE(this, size);
    40   return size;
    41 }
    43 /* virtual */ nsSize
    44 nsPlaceholderFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState)
    45 {
    46   nsSize size(0, 0);
    47   DISPLAY_PREF_SIZE(this, size);
    48   return size;
    49 }
    51 /* virtual */ nsSize
    52 nsPlaceholderFrame::GetMaxSize(nsBoxLayoutState& aBoxLayoutState)
    53 {
    54   nsSize size(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
    55   DISPLAY_MAX_SIZE(this, size);
    56   return size;
    57 }
    59 /* virtual */ void
    60 nsPlaceholderFrame::AddInlineMinWidth(nsRenderingContext* aRenderingContext,
    61                                       nsIFrame::InlineMinWidthData* aData)
    62 {
    63   // Override AddInlineMinWith so that *nothing* happens.  In
    64   // particular, we don't want to zero out |aData->trailingWhitespace|,
    65   // since nsLineLayout skips placeholders when trimming trailing
    66   // whitespace, and we don't want to set aData->skipWhitespace to
    67   // false.
    69   // ...but push floats onto the list
    70   if (mOutOfFlowFrame->IsFloating()) {
    71     nscoord floatWidth =
    72       nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
    73                                            mOutOfFlowFrame,
    74                                            nsLayoutUtils::MIN_WIDTH);
    75     aData->floats.AppendElement(
    76       InlineIntrinsicWidthData::FloatInfo(mOutOfFlowFrame, floatWidth));
    77   }
    78 }
    80 /* virtual */ void
    81 nsPlaceholderFrame::AddInlinePrefWidth(nsRenderingContext* aRenderingContext,
    82                                        nsIFrame::InlinePrefWidthData* aData)
    83 {
    84   // Override AddInlinePrefWith so that *nothing* happens.  In
    85   // particular, we don't want to zero out |aData->trailingWhitespace|,
    86   // since nsLineLayout skips placeholders when trimming trailing
    87   // whitespace, and we don't want to set aData->skipWhitespace to
    88   // false.
    90   // ...but push floats onto the list
    91   if (mOutOfFlowFrame->IsFloating()) {
    92     nscoord floatWidth =
    93       nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
    94                                            mOutOfFlowFrame,
    95                                            nsLayoutUtils::PREF_WIDTH);
    96     aData->floats.AppendElement(
    97       InlineIntrinsicWidthData::FloatInfo(mOutOfFlowFrame, floatWidth));
    98   }
    99 }
   101 nsresult
   102 nsPlaceholderFrame::Reflow(nsPresContext*           aPresContext,
   103                            nsHTMLReflowMetrics&     aDesiredSize,
   104                            const nsHTMLReflowState& aReflowState,
   105                            nsReflowStatus&          aStatus)
   106 {
   107 #ifdef DEBUG
   108   // We should be getting reflowed before our out-of-flow.
   109   // If this is our first reflow, and our out-of-flow has already received its
   110   // first reflow (before us), complain.
   111   // XXXdholbert This "look for a previous continuation or IB-split sibling"
   112   // code could use nsLayoutUtils::GetPrevContinuationOrIBSplitSibling(), if
   113   // we ever add a function like that. (We currently have a "Next" version.)
   114   if ((GetStateBits() & NS_FRAME_FIRST_REFLOW) &&
   115       !(mOutOfFlowFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
   117     // Unfortunately, this can currently happen when the placeholder is in a
   118     // later continuation or later IB-split sibling than its out-of-flow (as
   119     // is the case in some of our existing unit tests). So for now, in that
   120     // case, we'll warn instead of asserting.
   121     bool isInContinuationOrIBSplit = false;
   122     nsIFrame* ancestor = this;
   123     while ((ancestor = ancestor->GetParent())) {
   124       if (ancestor->GetPrevContinuation() ||
   125           ancestor->Properties().Get(IBSplitPrevSibling())) {
   126         isInContinuationOrIBSplit = true;
   127         break;
   128       }
   129     }
   131     if (isInContinuationOrIBSplit) {
   132       NS_WARNING("Out-of-flow frame got reflowed before its placeholder");
   133     } else {
   134       NS_ERROR("Out-of-flow frame got reflowed before its placeholder");
   135     }
   136   }
   137 #endif
   139   DO_GLOBAL_REFLOW_COUNT("nsPlaceholderFrame");
   140   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
   141   aDesiredSize.Width() = 0;
   142   aDesiredSize.Height() = 0;
   144   aStatus = NS_FRAME_COMPLETE;
   145   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   146   return NS_OK;
   147 }
   149 void
   150 nsPlaceholderFrame::DestroyFrom(nsIFrame* aDestructRoot)
   151 {
   152   nsIFrame* oof = mOutOfFlowFrame;
   153   if (oof) {
   154     // Unregister out-of-flow frame
   155     nsFrameManager* fm = PresContext()->GetPresShell()->FrameManager();
   156     fm->UnregisterPlaceholderFrame(this);
   157     mOutOfFlowFrame = nullptr;
   158     // If aDestructRoot is not an ancestor of the out-of-flow frame,
   159     // then call RemoveFrame on it here.
   160     // Also destroy it here if it's a popup frame. (Bug 96291)
   161     if ((GetStateBits() & PLACEHOLDER_FOR_POPUP) ||
   162         !nsLayoutUtils::IsProperAncestorFrame(aDestructRoot, oof)) {
   163       ChildListID listId = nsLayoutUtils::GetChildListNameFor(oof);
   164       fm->RemoveFrame(listId, oof);
   165     }
   166     // else oof will be destroyed by its parent
   167   }
   169   nsFrame::DestroyFrom(aDestructRoot);
   170 }
   172 nsIAtom*
   173 nsPlaceholderFrame::GetType() const
   174 {
   175   return nsGkAtoms::placeholderFrame;
   176 }
   178 /* virtual */ bool
   179 nsPlaceholderFrame::CanContinueTextRun() const
   180 {
   181   if (!mOutOfFlowFrame) {
   182     return false;
   183   }
   184   // first-letter frames can continue text runs, and placeholders for floated
   185   // first-letter frames can too
   186   return mOutOfFlowFrame->CanContinueTextRun();
   187 }
   189 nsIFrame*
   190 nsPlaceholderFrame::GetParentStyleContextFrame() const
   191 {
   192   NS_PRECONDITION(GetParent(), "How can we not have a parent here?");
   194   // Lie about our pseudo so we can step out of all anon boxes and
   195   // pseudo-elements.  The other option would be to reimplement the
   196   // {ib} split gunk here.
   197   return CorrectStyleParentFrame(GetParent(), nsGkAtoms::placeholderFrame);
   198 }
   201 #ifdef DEBUG
   202 static void
   203 PaintDebugPlaceholder(nsIFrame* aFrame, nsRenderingContext* aCtx,
   204                       const nsRect& aDirtyRect, nsPoint aPt)
   205 {
   206   aCtx->SetColor(NS_RGB(0, 255, 255));
   207   nscoord x = nsPresContext::CSSPixelsToAppUnits(-5);
   208   aCtx->FillRect(aPt.x + x, aPt.y,
   209                  nsPresContext::CSSPixelsToAppUnits(13),
   210                  nsPresContext::CSSPixelsToAppUnits(3));
   211   nscoord y = nsPresContext::CSSPixelsToAppUnits(-10);
   212   aCtx->FillRect(aPt.x, aPt.y + y,
   213                  nsPresContext::CSSPixelsToAppUnits(3),
   214                  nsPresContext::CSSPixelsToAppUnits(10));
   215 }
   216 #endif // DEBUG
   218 #if defined(DEBUG) || (defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF))
   220 void
   221 nsPlaceholderFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
   222                                      const nsRect&           aDirtyRect,
   223                                      const nsDisplayListSet& aLists)
   224 {
   225   DO_GLOBAL_REFLOW_COUNT_DSP("nsPlaceholderFrame");
   227 #ifdef DEBUG
   228   if (GetShowFrameBorders()) {
   229     aLists.Outlines()->AppendNewToTop(
   230       new (aBuilder) nsDisplayGeneric(aBuilder, this, PaintDebugPlaceholder,
   231                                       "DebugPlaceholder",
   232                                       nsDisplayItem::TYPE_DEBUG_PLACEHOLDER));
   233   }
   234 #endif
   235 }
   236 #endif // DEBUG || (MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF)
   238 #ifdef DEBUG_FRAME_DUMP
   239 nsresult
   240 nsPlaceholderFrame::GetFrameName(nsAString& aResult) const
   241 {
   242   return MakeFrameName(NS_LITERAL_STRING("Placeholder"), aResult);
   243 }
   245 void
   246 nsPlaceholderFrame::List(FILE* out, const char* aPrefix, uint32_t aFlags) const
   247 {
   248   nsCString str;
   249   ListGeneric(str, aPrefix, aFlags);
   251   if (mOutOfFlowFrame) {
   252     str += " outOfFlowFrame=";
   253     nsFrame::ListTag(str, mOutOfFlowFrame);
   254   }
   255   fprintf_stderr(out, "%s\n", str.get());
   256 }
   257 #endif

mercurial