LCOV - code coverage report
Current view: directory - layout/generic - nsInlineFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 452 0 0.0 %
Date: 2012-06-02 Functions: 37 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 Communicator client 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 for CSS display:inline objects */
      39                 : 
      40                 : #include "nsCOMPtr.h"
      41                 : #include "nsInlineFrame.h"
      42                 : #include "nsBlockFrame.h"
      43                 : #include "nsPlaceholderFrame.h"
      44                 : #include "nsGkAtoms.h"
      45                 : #include "nsHTMLParts.h"
      46                 : #include "nsStyleContext.h"
      47                 : #include "nsIPresShell.h"
      48                 : #include "nsPresContext.h"
      49                 : #include "nsRenderingContext.h"
      50                 : #include "nsCSSAnonBoxes.h"
      51                 : #include "nsAutoPtr.h"
      52                 : #include "nsFrameManager.h"
      53                 : #ifdef ACCESSIBILITY
      54                 : #include "nsIServiceManager.h"
      55                 : #include "nsAccessibilityService.h"
      56                 : #endif
      57                 : #include "nsDisplayList.h"
      58                 : 
      59                 : #ifdef DEBUG
      60                 : #undef NOISY_PUSHING
      61                 : #endif
      62                 : 
      63                 : 
      64                 : //////////////////////////////////////////////////////////////////////
      65                 : 
      66                 : // Basic nsInlineFrame methods
      67                 : 
      68                 : nsIFrame*
      69               0 : NS_NewInlineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
      70                 : {
      71               0 :   return new (aPresShell) nsInlineFrame(aContext);
      72                 : }
      73                 : 
      74                 : NS_IMETHODIMP
      75               0 : nsInlineFrame::Init(nsIContent*      aContent,
      76                 :                     nsIFrame*        aParent,
      77                 :                     nsIFrame*        aPrevInFlow)
      78                 : {
      79                 :   // Let the base class do its processing
      80               0 :   nsresult rv = nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
      81                 : 
      82                 :   // Transforms do not affect regular inline elements (bug 722463)
      83               0 :   mState &= ~NS_FRAME_MAY_BE_TRANSFORMED;
      84                 : 
      85               0 :   return rv;
      86                 : }
      87                 : 
      88               0 : NS_IMPL_FRAMEARENA_HELPERS(nsInlineFrame)
      89                 : 
      90               0 : NS_QUERYFRAME_HEAD(nsInlineFrame)
      91               0 :   NS_QUERYFRAME_ENTRY(nsInlineFrame)
      92               0 : NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
      93                 : 
      94                 : #ifdef DEBUG
      95                 : NS_IMETHODIMP
      96               0 : nsInlineFrame::GetFrameName(nsAString& aResult) const
      97                 : {
      98               0 :   return MakeFrameName(NS_LITERAL_STRING("Inline"), aResult);
      99                 : }
     100                 : #endif
     101                 : 
     102                 : nsIAtom*
     103               0 : nsInlineFrame::GetType() const
     104                 : {
     105               0 :   return nsGkAtoms::inlineFrame;
     106                 : }
     107                 : 
     108                 : static inline bool
     109               0 : IsMarginZero(const nsStyleCoord &aCoord)
     110                 : {
     111               0 :   return aCoord.GetUnit() == eStyleUnit_Auto ||
     112               0 :          nsLayoutUtils::IsMarginZero(aCoord);
     113                 : }
     114                 : 
     115                 : /* virtual */ bool
     116               0 : nsInlineFrame::IsSelfEmpty()
     117                 : {
     118                 : #if 0
     119                 :   // I used to think inline frames worked this way, but it seems they
     120                 :   // don't.  At least not in our codebase.
     121                 :   if (GetPresContext()->CompatibilityMode() == eCompatibility_FullStandards) {
     122                 :     return false;
     123                 :   }
     124                 : #endif
     125               0 :   const nsStyleMargin* margin = GetStyleMargin();
     126               0 :   const nsStyleBorder* border = GetStyleBorder();
     127               0 :   const nsStylePadding* padding = GetStylePadding();
     128                 :   // XXX Top and bottom removed, since they shouldn't affect things, but this
     129                 :   // doesn't really match with nsLineLayout.cpp's setting of
     130                 :   // ZeroEffectiveSpanBox, anymore, so what should this really be?
     131                 :   bool haveRight =
     132               0 :     border->GetActualBorderWidth(NS_SIDE_RIGHT) != 0 ||
     133               0 :     !nsLayoutUtils::IsPaddingZero(padding->mPadding.GetRight()) ||
     134               0 :     !IsMarginZero(margin->mMargin.GetRight());
     135                 :   bool haveLeft =
     136               0 :     border->GetActualBorderWidth(NS_SIDE_LEFT) != 0 ||
     137               0 :     !nsLayoutUtils::IsPaddingZero(padding->mPadding.GetLeft()) ||
     138               0 :     !IsMarginZero(margin->mMargin.GetLeft());
     139               0 :   if (haveLeft || haveRight) {
     140               0 :     if (GetStateBits() & NS_FRAME_IS_SPECIAL) {
     141                 :       bool haveStart, haveEnd;
     142               0 :       if (NS_STYLE_DIRECTION_LTR == GetStyleVisibility()->mDirection) {
     143               0 :         haveStart = haveLeft;
     144               0 :         haveEnd = haveRight;
     145                 :       } else {
     146               0 :         haveStart = haveRight;
     147               0 :         haveEnd = haveLeft;
     148                 :       }
     149                 :       // For special frames, ignore things we know we'll skip in GetSkipSides.
     150                 :       // XXXbz should we be doing this for non-special frames too, in a more
     151                 :       // general way?
     152                 : 
     153                 :       // Get the first continuation eagerly, as a performance optimization, to
     154                 :       // avoid having to get it twice..
     155               0 :       nsIFrame* firstCont = GetFirstContinuation();
     156                 :       return
     157               0 :         (!haveStart || nsLayoutUtils::FrameIsNonFirstInIBSplit(firstCont)) &&
     158               0 :         (!haveEnd || nsLayoutUtils::FrameIsNonLastInIBSplit(firstCont));
     159                 :     }
     160               0 :     return false;
     161                 :   }
     162               0 :   return true;
     163                 : }
     164                 : 
     165                 : bool
     166               0 : nsInlineFrame::IsEmpty()
     167                 : {
     168               0 :   if (!IsSelfEmpty()) {
     169               0 :     return false;
     170                 :   }
     171                 : 
     172               0 :   for (nsIFrame *kid = mFrames.FirstChild(); kid; kid = kid->GetNextSibling()) {
     173               0 :     if (!kid->IsEmpty())
     174               0 :       return false;
     175                 :   }
     176                 : 
     177               0 :   return true;
     178                 : }
     179                 : 
     180                 : bool
     181               0 : nsInlineFrame::PeekOffsetCharacter(bool aForward, PRInt32* aOffset,
     182                 :                                    bool aRespectClusters)
     183                 : {
     184                 :   // Override the implementation in nsFrame, to skip empty inline frames
     185               0 :   NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
     186               0 :   PRInt32 startOffset = *aOffset;
     187               0 :   if (startOffset < 0)
     188               0 :     startOffset = 1;
     189               0 :   if (aForward == (startOffset == 0)) {
     190                 :     // We're before the frame and moving forward, or after it and moving backwards:
     191                 :     // skip to the other side, but keep going.
     192               0 :     *aOffset = 1 - startOffset;
     193                 :   }
     194               0 :   return false;
     195                 : }
     196                 : 
     197                 : NS_IMETHODIMP
     198               0 : nsInlineFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     199                 :                                 const nsRect&           aDirtyRect,
     200                 :                                 const nsDisplayListSet& aLists)
     201                 : {
     202               0 :   nsresult rv = BuildDisplayListForInline(aBuilder, aDirtyRect, aLists);
     203               0 :   NS_ENSURE_SUCCESS(rv, rv);
     204                 : 
     205                 :   // The sole purpose of this is to trigger display of the selection
     206                 :   // window for Named Anchors, which don't have any children and
     207                 :   // normally don't have any size, but in Editor we use CSS to display
     208                 :   // an image to represent this "hidden" element.
     209               0 :   if (!mFrames.FirstChild()) {
     210               0 :     rv = DisplaySelectionOverlay(aBuilder, aLists.Content());
     211                 :   }
     212               0 :   return rv;
     213                 : }
     214                 : 
     215                 : //////////////////////////////////////////////////////////////////////
     216                 : // Reflow methods
     217                 : 
     218                 : /* virtual */ void
     219               0 : nsInlineFrame::AddInlineMinWidth(nsRenderingContext *aRenderingContext,
     220                 :                                  nsIFrame::InlineMinWidthData *aData)
     221                 : {
     222               0 :   DoInlineIntrinsicWidth(aRenderingContext, aData, nsLayoutUtils::MIN_WIDTH);
     223               0 : }
     224                 : 
     225                 : /* virtual */ void
     226               0 : nsInlineFrame::AddInlinePrefWidth(nsRenderingContext *aRenderingContext,
     227                 :                                   nsIFrame::InlinePrefWidthData *aData)
     228                 : {
     229               0 :   DoInlineIntrinsicWidth(aRenderingContext, aData, nsLayoutUtils::PREF_WIDTH);
     230               0 : }
     231                 : 
     232                 : /* virtual */ nsSize
     233               0 : nsInlineFrame::ComputeSize(nsRenderingContext *aRenderingContext,
     234                 :                            nsSize aCBSize, nscoord aAvailableWidth,
     235                 :                            nsSize aMargin, nsSize aBorder, nsSize aPadding,
     236                 :                            bool aShrinkWrap)
     237                 : {
     238                 :   // Inlines and text don't compute size before reflow.
     239               0 :   return nsSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
     240                 : }
     241                 : 
     242                 : nsRect
     243               0 : nsInlineFrame::ComputeTightBounds(gfxContext* aContext) const
     244                 : {
     245                 :   // be conservative
     246               0 :   if (GetStyleContext()->HasTextDecorationLines()) {
     247               0 :     return GetVisualOverflowRect();
     248                 :   }
     249               0 :   return ComputeSimpleTightBounds(aContext);
     250                 : }
     251                 : 
     252                 : void
     253               0 : nsInlineFrame::ReparentFloatsForInlineChild(nsIFrame* aOurLineContainer,
     254                 :                                             nsIFrame* aFrame,
     255                 :                                             bool aReparentSiblings)
     256                 : {
     257                 :   // XXXbz this would be better if it took a nsFrameList or a frame
     258                 :   // list slice....
     259               0 :   NS_ASSERTION(aOurLineContainer->GetNextContinuation() ||
     260                 :                aOurLineContainer->GetPrevContinuation(),
     261                 :                "Don't call this when we have no continuation, it's a waste");
     262               0 :   if (!aFrame) {
     263               0 :     NS_ASSERTION(aReparentSiblings, "Why did we get called?");
     264               0 :     return;
     265                 :   }
     266                 : 
     267               0 :   nsIFrame* ancestor = aFrame;
     268                 :   nsIFrame* ancestorBlockChild;
     269               0 :   do {
     270               0 :     ancestorBlockChild = ancestor;
     271               0 :     ancestor = ancestor->GetParent();
     272               0 :     if (!ancestor)
     273               0 :       return;
     274               0 :   } while (!ancestor->IsFloatContainingBlock());
     275                 : 
     276               0 :   if (ancestor == aOurLineContainer)
     277               0 :     return;
     278                 : 
     279               0 :   nsBlockFrame* ourBlock = nsLayoutUtils::GetAsBlock(aOurLineContainer);
     280               0 :   NS_ASSERTION(ourBlock, "Not a block, but broke vertically?");
     281               0 :   nsBlockFrame* frameBlock = nsLayoutUtils::GetAsBlock(ancestor);
     282               0 :   NS_ASSERTION(frameBlock, "ancestor not a block");
     283                 : 
     284               0 :   const nsFrameList& blockChildren(ancestor->PrincipalChildList());
     285               0 :   bool isOverflow = !blockChildren.ContainsFrame(ancestorBlockChild);
     286                 : 
     287               0 :   while (true) {
     288               0 :     ourBlock->ReparentFloats(aFrame, frameBlock, isOverflow, false);
     289                 : 
     290               0 :     if (!aReparentSiblings)
     291               0 :       return;
     292               0 :     nsIFrame* next = aFrame->GetNextSibling();
     293               0 :     if (!next)
     294               0 :       return;
     295               0 :     if (next->GetParent() == aFrame->GetParent()) {
     296               0 :       aFrame = next;
     297               0 :       continue;
     298                 :     }
     299                 :     // This is paranoid and will hardly ever get hit ... but we can't actually
     300                 :     // trust that the frames in the sibling chain all have the same parent,
     301                 :     // because lazy reparenting may be going on. If we find a different
     302                 :     // parent we need to redo our analysis.
     303               0 :     ReparentFloatsForInlineChild(aOurLineContainer, next, aReparentSiblings);
     304               0 :     return;
     305                 :   }
     306                 : }
     307                 : 
     308                 : static void
     309               0 : ReparentChildListStyle(nsPresContext* aPresContext,
     310                 :                        const nsFrameList::Slice& aFrames,
     311                 :                        nsIFrame* aParentFrame)
     312                 : {
     313               0 :   nsFrameManager *frameManager = aPresContext->FrameManager();
     314                 : 
     315               0 :   for (nsFrameList::Enumerator e(aFrames); !e.AtEnd(); e.Next()) {
     316               0 :     NS_ASSERTION(e.get()->GetParent() == aParentFrame, "Bogus parentage");
     317               0 :     frameManager->ReparentStyleContext(e.get());
     318                 :   }
     319               0 : }
     320                 : 
     321                 : NS_IMETHODIMP
     322               0 : nsInlineFrame::Reflow(nsPresContext*          aPresContext,
     323                 :                       nsHTMLReflowMetrics&     aMetrics,
     324                 :                       const nsHTMLReflowState& aReflowState,
     325                 :                       nsReflowStatus&          aStatus)
     326                 : {
     327               0 :   DO_GLOBAL_REFLOW_COUNT("nsInlineFrame");
     328               0 :   DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
     329               0 :   if (nsnull == aReflowState.mLineLayout) {
     330               0 :     return NS_ERROR_INVALID_ARG;
     331                 :   }
     332                 : 
     333               0 :   bool    lazilySetParentPointer = false;
     334                 : 
     335               0 :   nsIFrame* lineContainer = aReflowState.mLineLayout->GetLineContainerFrame();
     336                 : 
     337                 :    // Check for an overflow list with our prev-in-flow
     338               0 :   nsInlineFrame* prevInFlow = (nsInlineFrame*)GetPrevInFlow();
     339               0 :   if (nsnull != prevInFlow) {
     340               0 :     nsAutoPtr<nsFrameList> prevOverflowFrames(prevInFlow->StealOverflowFrames());
     341                 : 
     342               0 :     if (prevOverflowFrames) {
     343                 :       // When pushing and pulling frames we need to check for whether any
     344                 :       // views need to be reparented.
     345                 :       nsContainerFrame::ReparentFrameViewList(aPresContext,
     346               0 :                                               *prevOverflowFrames,
     347               0 :                                               prevInFlow, this);
     348                 : 
     349                 :       // Check if we should do the lazilySetParentPointer optimization.
     350                 :       // Only do it in simple cases where we're being reflowed for the
     351                 :       // first time, nothing (e.g. bidi resolution) has already given
     352                 :       // us children, and there's no next-in-flow, so all our frames
     353                 :       // will be taken from prevOverflowFrames.
     354               0 :       if ((GetStateBits() & NS_FRAME_FIRST_REFLOW) && mFrames.IsEmpty() &&
     355               0 :           !GetNextInFlow()) {
     356                 :         // If our child list is empty, just put the new frames into it.
     357                 :         // Note that we don't set the parent pointer for the new frames. Instead wait
     358                 :         // to do this until we actually reflow the frame. If the overflow list contains
     359                 :         // thousands of frames this is a big performance issue (see bug #5588)
     360               0 :         mFrames.SetFrames(*prevOverflowFrames);
     361               0 :         lazilySetParentPointer = true;
     362                 :       } else {
     363                 :         // Assign all floats to our block if necessary
     364               0 :         if (lineContainer && lineContainer->GetPrevContinuation()) {
     365                 :           ReparentFloatsForInlineChild(lineContainer,
     366                 :                                        prevOverflowFrames->FirstChild(),
     367               0 :                                        true);
     368                 :         }
     369                 :         // Insert the new frames at the beginning of the child list
     370                 :         // and set their parent pointer
     371                 :         const nsFrameList::Slice& newFrames =
     372               0 :           mFrames.InsertFrames(this, nsnull, *prevOverflowFrames);
     373                 :         // If our prev in flow was under the first continuation of a first-line
     374                 :         // frame then we need to reparent the style contexts to remove the
     375                 :         // the special first-line styling. In the lazilySetParentPointer case
     376                 :         // we reparent the style contexts when we set their parents in
     377                 :         // nsInlineFrame::ReflowFrames and nsInlineFrame::ReflowInlineFrame.
     378               0 :         if (aReflowState.mLineLayout->GetInFirstLine()) {
     379               0 :           ReparentChildListStyle(aPresContext, newFrames, this);
     380                 :         }
     381                 :       }
     382                 :     }
     383                 :   }
     384                 : 
     385                 :   // It's also possible that we have an overflow list for ourselves
     386                 : #ifdef DEBUG
     387               0 :   if (GetStateBits() & NS_FRAME_FIRST_REFLOW) {
     388                 :     // If it's our initial reflow, then we should not have an overflow list.
     389                 :     // However, add an assertion in case we get reflowed more than once with
     390                 :     // the initial reflow reason
     391               0 :     nsFrameList* overflowFrames = GetOverflowFrames();
     392               0 :     NS_ASSERTION(!overflowFrames || overflowFrames->IsEmpty(),
     393                 :                  "overflow list is not empty for initial reflow");
     394                 :   }
     395                 : #endif
     396               0 :   if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
     397               0 :     nsAutoPtr<nsFrameList> overflowFrames(StealOverflowFrames());
     398               0 :     if (overflowFrames) {
     399               0 :       NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames");
     400                 : 
     401                 :       // Because we lazily set the parent pointer of child frames we get from
     402                 :       // our prev-in-flow's overflow list, it's possible that we have not set
     403                 :       // the parent pointer for these frames.
     404               0 :       mFrames.AppendFrames(this, *overflowFrames);
     405                 :     }
     406                 :   }
     407                 : 
     408               0 :   if (IsFrameTreeTooDeep(aReflowState, aMetrics, aStatus)) {
     409               0 :     return NS_OK;
     410                 :   }
     411                 : 
     412                 :   // Set our own reflow state (additional state above and beyond
     413                 :   // aReflowState)
     414               0 :   InlineReflowState irs;
     415               0 :   irs.mPrevFrame = nsnull;
     416               0 :   irs.mLineContainer = lineContainer;
     417               0 :   irs.mLineLayout = aReflowState.mLineLayout;
     418               0 :   irs.mNextInFlow = (nsInlineFrame*) GetNextInFlow();
     419               0 :   irs.mSetParentPointer = lazilySetParentPointer;
     420                 : 
     421                 :   nsresult rv;
     422               0 :   if (mFrames.IsEmpty()) {
     423                 :     // Try to pull over one frame before starting so that we know
     424                 :     // whether we have an anonymous block or not.
     425                 :     bool complete;
     426               0 :     (void) PullOneFrame(aPresContext, irs, &complete);
     427                 :   }
     428                 : 
     429               0 :   rv = ReflowFrames(aPresContext, aReflowState, irs, aMetrics, aStatus);
     430                 : 
     431               0 :   ReflowAbsoluteFrames(aPresContext, aMetrics, aReflowState, aStatus);
     432                 : 
     433                 :   // Note: the line layout code will properly compute our
     434                 :   // overflow-rect state for us.
     435                 : 
     436               0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
     437               0 :   return rv;
     438                 : }
     439                 : 
     440                 : /* virtual */ bool
     441               0 : nsInlineFrame::CanContinueTextRun() const
     442                 : {
     443                 :   // We can continue a text run through an inline frame
     444               0 :   return true;
     445                 : }
     446                 : 
     447                 : /* virtual */ void
     448               0 : nsInlineFrame::PullOverflowsFromPrevInFlow()
     449                 : {
     450               0 :   nsInlineFrame* prevInFlow = static_cast<nsInlineFrame*>(GetPrevInFlow());
     451               0 :   if (prevInFlow) {
     452               0 :     nsAutoPtr<nsFrameList> prevOverflowFrames(prevInFlow->StealOverflowFrames());
     453               0 :     if (prevOverflowFrames) {
     454                 :       // Assume that our prev-in-flow has the same line container that we do.
     455                 :       nsContainerFrame::ReparentFrameViewList(PresContext(),
     456               0 :                                               *prevOverflowFrames,
     457               0 :                                               prevInFlow, this);
     458               0 :       mFrames.InsertFrames(this, nsnull, *prevOverflowFrames);
     459                 :     }
     460                 :   }
     461               0 : }
     462                 : 
     463                 : nsresult
     464               0 : nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
     465                 :                             const nsHTMLReflowState& aReflowState,
     466                 :                             InlineReflowState& irs,
     467                 :                             nsHTMLReflowMetrics& aMetrics,
     468                 :                             nsReflowStatus& aStatus)
     469                 : {
     470               0 :   nsresult rv = NS_OK;
     471               0 :   aStatus = NS_FRAME_COMPLETE;
     472                 : 
     473               0 :   nsLineLayout* lineLayout = aReflowState.mLineLayout;
     474               0 :   bool inFirstLine = aReflowState.mLineLayout->GetInFirstLine();
     475               0 :   nsFrameManager* frameManager = aPresContext->FrameManager();
     476               0 :   bool ltr = (NS_STYLE_DIRECTION_LTR == aReflowState.mStyleVisibility->mDirection);
     477               0 :   nscoord leftEdge = 0;
     478                 :   // Don't offset by our start borderpadding if we have a prev continuation or
     479                 :   // if we're in a part of an {ib} split other than the first one.
     480               0 :   if (!GetPrevContinuation() &&
     481               0 :       !nsLayoutUtils::FrameIsNonFirstInIBSplit(this)) {
     482                 :     leftEdge = ltr ? aReflowState.mComputedBorderPadding.left
     483               0 :                    : aReflowState.mComputedBorderPadding.right;
     484                 :   }
     485               0 :   nscoord availableWidth = aReflowState.availableWidth;
     486               0 :   NS_ASSERTION(availableWidth != NS_UNCONSTRAINEDSIZE,
     487                 :                "should no longer use available widths");
     488                 :   // Subtract off left and right border+padding from availableWidth
     489               0 :   availableWidth -= leftEdge;
     490                 :   availableWidth -= ltr ? aReflowState.mComputedBorderPadding.right
     491               0 :                         : aReflowState.mComputedBorderPadding.left;
     492                 :   lineLayout->BeginSpan(this, &aReflowState, leftEdge,
     493               0 :                         leftEdge + availableWidth, &mBaseline);
     494                 : 
     495                 :   // First reflow our current children
     496               0 :   nsIFrame* frame = mFrames.FirstChild();
     497               0 :   bool done = false;
     498               0 :   while (nsnull != frame) {
     499               0 :     bool reflowingFirstLetter = lineLayout->GetFirstLetterStyleOK();
     500                 : 
     501                 :     // Check if we should lazily set the child frame's parent pointer
     502               0 :     if (irs.mSetParentPointer) {
     503                 :       bool havePrevBlock =
     504               0 :         irs.mLineContainer && irs.mLineContainer->GetPrevContinuation();
     505                 :       // If our block is the first in flow, then any floats under the pulled
     506                 :       // frame must already belong to our block.
     507               0 :       if (havePrevBlock) {
     508                 :         // This has to happen before we update frame's parent; we need to
     509                 :         // know frame's ancestry under its old block.
     510                 :         // The blockChildren.ContainsFrame check performed by
     511                 :         // ReparentFloatsForInlineChild here may be slow, but we can't
     512                 :         // easily avoid it because we don't know where 'frame' originally
     513                 :         // came from. If we really really have to optimize this we could
     514                 :         // cache whether frame->GetParent() is under its containing blocks
     515                 :         // overflowList or not.
     516               0 :         ReparentFloatsForInlineChild(irs.mLineContainer, frame, false);
     517                 :       }
     518               0 :       frame->SetParent(this);
     519               0 :       if (inFirstLine) {
     520               0 :         frameManager->ReparentStyleContext(frame);
     521                 :       }
     522                 :       // We also need to check if frame has a next-in-flow. If it does, then set
     523                 :       // its parent frame pointer, too. Otherwise, if we reflow frame and it's
     524                 :       // complete we'll fail when deleting its next-in-flow which is no longer
     525                 :       // needed. This scenario doesn't happen often, but it can happen
     526               0 :       nsIFrame* nextInFlow = frame->GetNextInFlow();
     527               0 :       for ( ; nextInFlow; nextInFlow = nextInFlow->GetNextInFlow()) {
     528                 :         // Since we only do lazy setting of parent pointers for the frame's
     529                 :         // initial reflow, this frame can't have a next-in-flow. That means
     530                 :         // the continuing child frame must be in our child list as well. If
     531                 :         // not, then something is wrong
     532               0 :         NS_ASSERTION(mFrames.ContainsFrame(nextInFlow), "unexpected flow");
     533               0 :         if (havePrevBlock) {
     534               0 :           ReparentFloatsForInlineChild(irs.mLineContainer, nextInFlow, false);
     535                 :         }
     536               0 :         nextInFlow->SetParent(this);
     537               0 :         if (inFirstLine) {
     538               0 :           frameManager->ReparentStyleContext(nextInFlow);
     539                 :         }
     540                 :       }
     541                 : 
     542                 :       // Fix the parent pointer for ::first-letter child frame next-in-flows,
     543                 :       // so nsFirstLetterFrame::Reflow can destroy them safely (bug 401042).
     544               0 :       nsIFrame* realFrame = nsPlaceholderFrame::GetRealFrameFor(frame);
     545               0 :       if (realFrame->GetType() == nsGkAtoms::letterFrame) {
     546               0 :         nsIFrame* child = realFrame->GetFirstPrincipalChild();
     547               0 :         if (child) {
     548               0 :           NS_ASSERTION(child->GetType() == nsGkAtoms::textFrame,
     549                 :                        "unexpected frame type");
     550               0 :           nsIFrame* nextInFlow = child->GetNextInFlow();
     551               0 :           for ( ; nextInFlow; nextInFlow = nextInFlow->GetNextInFlow()) {
     552               0 :             NS_ASSERTION(nextInFlow->GetType() == nsGkAtoms::textFrame,
     553                 :                          "unexpected frame type");
     554               0 :             if (mFrames.ContainsFrame(nextInFlow)) {
     555               0 :               nextInFlow->SetParent(this);
     556               0 :               if (inFirstLine) {
     557               0 :                 frameManager->ReparentStyleContext(nextInFlow);
     558                 :               }
     559                 :             }
     560                 :             else {
     561                 : #ifdef DEBUG              
     562                 :               // Once we find a next-in-flow that isn't ours none of the
     563                 :               // remaining next-in-flows should be either.
     564               0 :               for ( ; nextInFlow; nextInFlow = nextInFlow->GetNextInFlow()) {
     565               0 :                 NS_ASSERTION(!mFrames.ContainsFrame(nextInFlow),
     566                 :                              "unexpected letter frame flow");
     567                 :               }
     568                 : #endif
     569               0 :               break;
     570                 :             }
     571                 :           }
     572                 :         }
     573                 :       }
     574                 :     }
     575               0 :     rv = ReflowInlineFrame(aPresContext, aReflowState, irs, frame, aStatus);
     576               0 :     if (NS_FAILED(rv)) {
     577               0 :       done = true;
     578               0 :       break;
     579                 :     }
     580               0 :     if (NS_INLINE_IS_BREAK(aStatus) || 
     581               0 :         (!reflowingFirstLetter && NS_FRAME_IS_NOT_COMPLETE(aStatus))) {
     582               0 :       done = true;
     583               0 :       break;
     584                 :     }
     585               0 :     irs.mPrevFrame = frame;
     586               0 :     frame = frame->GetNextSibling();
     587                 :   }
     588                 : 
     589                 :   // Attempt to pull frames from our next-in-flow until we can't
     590               0 :   if (!done && (nsnull != GetNextInFlow())) {
     591               0 :     while (!done) {
     592               0 :       bool reflowingFirstLetter = lineLayout->GetFirstLetterStyleOK();
     593                 :       bool isComplete;
     594               0 :       if (!frame) { // Could be non-null if we pulled a first-letter frame and
     595                 :                     // it created a continuation, since we don't push those.
     596               0 :         frame = PullOneFrame(aPresContext, irs, &isComplete);
     597                 :       }
     598                 : #ifdef NOISY_PUSHING
     599                 :       printf("%p pulled up %p\n", this, frame);
     600                 : #endif
     601               0 :       if (nsnull == frame) {
     602               0 :         if (!isComplete) {
     603               0 :           aStatus = NS_FRAME_NOT_COMPLETE;
     604                 :         }
     605               0 :         break;
     606                 :       }
     607               0 :       rv = ReflowInlineFrame(aPresContext, aReflowState, irs, frame, aStatus);
     608               0 :       if (NS_FAILED(rv)) {
     609               0 :         done = true;
     610               0 :         break;
     611                 :       }
     612               0 :       if (NS_INLINE_IS_BREAK(aStatus) || 
     613               0 :           (!reflowingFirstLetter && NS_FRAME_IS_NOT_COMPLETE(aStatus))) {
     614               0 :         done = true;
     615               0 :         break;
     616                 :       }
     617               0 :       irs.mPrevFrame = frame;
     618               0 :       frame = frame->GetNextSibling();
     619                 :     }
     620                 :   }
     621                 : #ifdef DEBUG
     622               0 :   if (NS_FRAME_IS_COMPLETE(aStatus)) {
     623                 :     // We can't be complete AND have overflow frames!
     624               0 :     NS_ASSERTION(!GetOverflowFrames(), "whoops");
     625                 :   }
     626                 : #endif
     627                 : 
     628                 :   // If after reflowing our children they take up no area then make
     629                 :   // sure that we don't either.
     630                 :   //
     631                 :   // Note: CSS demands that empty inline elements still affect the
     632                 :   // line-height calculations. However, continuations of an inline
     633                 :   // that are empty we force to empty so that things like collapsed
     634                 :   // whitespace in an inline element don't affect the line-height.
     635               0 :   aMetrics.width = lineLayout->EndSpan(this);
     636                 : 
     637                 :   // Compute final width.
     638                 : 
     639                 :   // Make sure to not include our start border and padding if we have a prev
     640                 :   // continuation or if we're in a part of an {ib} split other than the first
     641                 :   // one.
     642               0 :   if (!GetPrevContinuation() &&
     643               0 :       !nsLayoutUtils::FrameIsNonFirstInIBSplit(this)) {
     644                 :     aMetrics.width += ltr ? aReflowState.mComputedBorderPadding.left
     645               0 :                           : aReflowState.mComputedBorderPadding.right;
     646                 :   }
     647                 : 
     648                 :   /*
     649                 :    * We want to only apply the end border and padding if we're the last
     650                 :    * continuation and either not in an {ib} split or the last part of it.  To
     651                 :    * be the last continuation we have to be complete (so that we won't get a
     652                 :    * next-in-flow) and have no non-fluid continuations on our continuation
     653                 :    * chain.
     654                 :    */
     655               0 :   if (NS_FRAME_IS_COMPLETE(aStatus) &&
     656               0 :       !GetLastInFlow()->GetNextContinuation() &&
     657               0 :       !nsLayoutUtils::FrameIsNonLastInIBSplit(this)) {
     658                 :     aMetrics.width += ltr ? aReflowState.mComputedBorderPadding.right
     659               0 :                           : aReflowState.mComputedBorderPadding.left;
     660                 :   }
     661                 : 
     662               0 :   nsRefPtr<nsFontMetrics> fm;
     663                 :   float inflation =
     664               0 :     nsLayoutUtils::FontSizeInflationFor(this, nsLayoutUtils::eInReflow);
     665               0 :   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm), inflation);
     666               0 :   aReflowState.rendContext->SetFont(fm);
     667                 : 
     668               0 :   if (fm) {
     669                 :     // Compute final height of the frame.
     670                 :     //
     671                 :     // Do things the standard css2 way -- though it's hard to find it
     672                 :     // in the css2 spec! It's actually found in the css1 spec section
     673                 :     // 4.4 (you will have to read between the lines to really see
     674                 :     // it).
     675                 :     //
     676                 :     // The height of our box is the sum of our font size plus the top
     677                 :     // and bottom border and padding. The height of children do not
     678                 :     // affect our height.
     679               0 :     aMetrics.ascent = fm->MaxAscent();
     680               0 :     aMetrics.height = fm->MaxHeight();
     681                 :   } else {
     682               0 :     NS_WARNING("Cannot get font metrics - defaulting sizes to 0");
     683               0 :     aMetrics.ascent = aMetrics.height = 0;
     684                 :   }
     685               0 :   aMetrics.ascent += aReflowState.mComputedBorderPadding.top;
     686                 :   aMetrics.height += aReflowState.mComputedBorderPadding.top +
     687               0 :     aReflowState.mComputedBorderPadding.bottom;
     688                 : 
     689                 :   // For now our overflow area is zero. The real value will be
     690                 :   // computed in |nsLineLayout::RelativePositionFrames|.
     691               0 :   aMetrics.mOverflowAreas.Clear();
     692                 : 
     693                 : #ifdef NOISY_FINAL_SIZE
     694                 :   ListTag(stdout);
     695                 :   printf(": metrics=%d,%d ascent=%d\n",
     696                 :          aMetrics.width, aMetrics.height, aMetrics.ascent);
     697                 : #endif
     698                 : 
     699               0 :   return rv;
     700                 : }
     701                 : 
     702                 : nsresult
     703               0 : nsInlineFrame::ReflowInlineFrame(nsPresContext* aPresContext,
     704                 :                                  const nsHTMLReflowState& aReflowState,
     705                 :                                  InlineReflowState& irs,
     706                 :                                  nsIFrame* aFrame,
     707                 :                                  nsReflowStatus& aStatus)
     708                 : {
     709               0 :   nsLineLayout* lineLayout = aReflowState.mLineLayout;
     710               0 :   bool reflowingFirstLetter = lineLayout->GetFirstLetterStyleOK();
     711                 :   bool pushedFrame;
     712                 :   nsresult rv =
     713               0 :     lineLayout->ReflowFrame(aFrame, aStatus, nsnull, pushedFrame);
     714                 :   
     715               0 :   if (NS_FAILED(rv)) {
     716               0 :     return rv;
     717                 :   }
     718                 : 
     719               0 :   if (NS_INLINE_IS_BREAK_BEFORE(aStatus)) {
     720               0 :     if (aFrame != mFrames.FirstChild()) {
     721                 :       // Change break-before status into break-after since we have
     722                 :       // already placed at least one child frame. This preserves the
     723                 :       // break-type so that it can be propagated upward.
     724                 :       aStatus = NS_FRAME_NOT_COMPLETE |
     725                 :         NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER |
     726               0 :         (aStatus & NS_INLINE_BREAK_TYPE_MASK);
     727               0 :       PushFrames(aPresContext, aFrame, irs.mPrevFrame, irs);
     728                 :     }
     729                 :     else {
     730                 :       // Preserve reflow status when breaking-before our first child
     731                 :       // and propagate it upward without modification.
     732                 :       // Note: if we're lazily setting the frame pointer for our child 
     733                 :       // frames, then we need to set it now. Don't return and leave the
     734                 :       // remaining child frames in our child list with the wrong parent
     735                 :       // frame pointer...
     736               0 :       if (irs.mSetParentPointer) {
     737               0 :         if (irs.mLineContainer && irs.mLineContainer->GetPrevContinuation()) {
     738                 :           ReparentFloatsForInlineChild(irs.mLineContainer, aFrame->GetNextSibling(),
     739               0 :                                        true);
     740                 :         }
     741               0 :         for (nsIFrame* f = aFrame->GetNextSibling(); f; f = f->GetNextSibling()) {
     742               0 :           f->SetParent(this);
     743               0 :           if (lineLayout->GetInFirstLine()) {
     744               0 :             aPresContext->FrameManager()->ReparentStyleContext(f);
     745                 :           }
     746                 :         }
     747                 :       }
     748                 :     }
     749               0 :     return NS_OK;
     750                 :   }
     751                 : 
     752                 :   // Create a next-in-flow if needed.
     753               0 :   if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
     754                 :     nsIFrame* newFrame;
     755               0 :     rv = CreateNextInFlow(aPresContext, aFrame, newFrame);
     756               0 :     if (NS_FAILED(rv)) {
     757               0 :       return rv;
     758                 :     }
     759                 :   }
     760                 : 
     761               0 :   if (NS_INLINE_IS_BREAK_AFTER(aStatus)) {
     762               0 :     nsIFrame* nextFrame = aFrame->GetNextSibling();
     763               0 :     if (nextFrame) {
     764               0 :       NS_FRAME_SET_INCOMPLETE(aStatus);
     765               0 :       PushFrames(aPresContext, nextFrame, aFrame, irs);
     766                 :     }
     767                 :     else {
     768                 :       // We must return an incomplete status if there are more child
     769                 :       // frames remaining in a next-in-flow that follows this frame.
     770               0 :       nsInlineFrame* nextInFlow = static_cast<nsInlineFrame*>(GetNextInFlow());
     771               0 :       while (nextInFlow) {
     772               0 :         if (nextInFlow->mFrames.NotEmpty()) {
     773               0 :           NS_FRAME_SET_INCOMPLETE(aStatus);
     774               0 :           break;
     775                 :         }
     776               0 :         nextInFlow = static_cast<nsInlineFrame*>(nextInFlow->GetNextInFlow());
     777                 :       }
     778                 :     }
     779               0 :     return NS_OK;
     780                 :   }
     781                 : 
     782               0 :   if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus) && !reflowingFirstLetter) {
     783               0 :     nsIFrame* nextFrame = aFrame->GetNextSibling();
     784               0 :     if (nextFrame) {
     785               0 :       PushFrames(aPresContext, nextFrame, aFrame, irs);
     786                 :     }
     787                 :   }
     788               0 :   return NS_OK;
     789                 : }
     790                 : 
     791                 : nsIFrame*
     792               0 : nsInlineFrame::PullOneFrame(nsPresContext* aPresContext,
     793                 :                             InlineReflowState& irs,
     794                 :                             bool* aIsComplete)
     795                 : {
     796               0 :   bool isComplete = true;
     797                 : 
     798               0 :   nsIFrame* frame = nsnull;
     799               0 :   nsInlineFrame* nextInFlow = irs.mNextInFlow;
     800               0 :   while (nsnull != nextInFlow) {
     801               0 :     frame = nextInFlow->mFrames.FirstChild();
     802                 : 
     803               0 :     if (!frame) {
     804                 :       // If the principal childlist has no frames, then try moving the overflow
     805                 :       // frames to it.
     806               0 :       nsAutoPtr<nsFrameList> overflowFrames(nextInFlow->StealOverflowFrames());
     807               0 :       if (overflowFrames) {
     808               0 :         nextInFlow->mFrames.SetFrames(*overflowFrames);
     809               0 :         frame = nextInFlow->mFrames.FirstChild();
     810                 :       }
     811                 :     }
     812                 : 
     813               0 :     if (nsnull != frame) {
     814                 :       // If our block has no next continuation, then any floats belonging to
     815                 :       // the pulled frame must belong to our block already. This check ensures
     816                 :       // we do no extra work in the common non-vertical-breaking case.
     817               0 :       if (irs.mLineContainer && irs.mLineContainer->GetNextContinuation()) {
     818                 :         // The blockChildren.ContainsFrame check performed by
     819                 :         // ReparentFloatsForInlineChild will be fast because frame's ancestor
     820                 :         // will be the first child of its containing block.
     821               0 :         ReparentFloatsForInlineChild(irs.mLineContainer, frame, false);
     822                 :       }
     823               0 :       nextInFlow->mFrames.RemoveFirstChild();
     824                 : 
     825                 :       // If we removed the last frame from the principal child list then move
     826                 :       // any overflow frames to it.
     827               0 :       if (!nextInFlow->mFrames.FirstChild()) {
     828               0 :         nsAutoPtr<nsFrameList> overflowFrames(nextInFlow->StealOverflowFrames());
     829               0 :         if (overflowFrames) {
     830               0 :           nextInFlow->mFrames.SetFrames(*overflowFrames);
     831                 :         }
     832                 :       }
     833                 : 
     834               0 :       mFrames.InsertFrame(this, irs.mPrevFrame, frame);
     835               0 :       isComplete = false;
     836               0 :       if (irs.mLineLayout) {
     837               0 :         irs.mLineLayout->SetDirtyNextLine();
     838                 :       }
     839               0 :       nsContainerFrame::ReparentFrameView(aPresContext, frame, nextInFlow, this);
     840               0 :       break;
     841                 :     }
     842               0 :     nextInFlow = (nsInlineFrame*) nextInFlow->GetNextInFlow();
     843               0 :     irs.mNextInFlow = nextInFlow;
     844                 :   }
     845                 : 
     846               0 :   *aIsComplete = isComplete;
     847               0 :   return frame;
     848                 : }
     849                 : 
     850                 : void
     851               0 : nsInlineFrame::PushFrames(nsPresContext* aPresContext,
     852                 :                           nsIFrame* aFromChild,
     853                 :                           nsIFrame* aPrevSibling,
     854                 :                           InlineReflowState& aState)
     855                 : {
     856               0 :   NS_PRECONDITION(aFromChild, "null pointer");
     857               0 :   NS_PRECONDITION(aPrevSibling, "pushing first child");
     858               0 :   NS_PRECONDITION(aPrevSibling->GetNextSibling() == aFromChild, "bad prev sibling");
     859                 : 
     860                 : #ifdef NOISY_PUSHING
     861                 :   printf("%p pushing aFromChild %p, disconnecting from prev sib %p\n", 
     862                 :          this, aFromChild, aPrevSibling);
     863                 : #endif
     864                 : 
     865                 :   // Add the frames to our overflow list (let our next in flow drain
     866                 :   // our overflow list when it is ready)
     867               0 :   SetOverflowFrames(aPresContext, mFrames.RemoveFramesAfter(aPrevSibling));
     868               0 :   if (aState.mLineLayout) {
     869               0 :     aState.mLineLayout->SetDirtyNextLine();
     870                 :   }
     871               0 : }
     872                 : 
     873                 : 
     874                 : //////////////////////////////////////////////////////////////////////
     875                 : 
     876                 : PRIntn
     877               0 : nsInlineFrame::GetSkipSides() const
     878                 : {
     879               0 :   PRIntn skip = 0;
     880               0 :   if (!IsLeftMost()) {
     881               0 :     nsInlineFrame* prev = (nsInlineFrame*) GetPrevContinuation();
     882               0 :     if ((GetStateBits() & NS_INLINE_FRAME_BIDI_VISUAL_STATE_IS_SET) ||
     883                 :         (prev && (prev->mRect.height || prev->mRect.width))) {
     884                 :       // Prev continuation is not empty therefore we don't render our left
     885                 :       // border edge.
     886               0 :       skip |= 1 << NS_SIDE_LEFT;
     887                 :     }
     888                 :     else {
     889                 :       // If the prev continuation is empty, then go ahead and let our left
     890                 :       // edge border render.
     891                 :     }
     892                 :   }
     893               0 :   if (!IsRightMost()) {
     894               0 :     nsInlineFrame* next = (nsInlineFrame*) GetNextContinuation();
     895               0 :     if ((GetStateBits() & NS_INLINE_FRAME_BIDI_VISUAL_STATE_IS_SET) ||
     896                 :         (next && (next->mRect.height || next->mRect.width))) {
     897                 :       // Next continuation is not empty therefore we don't render our right
     898                 :       // border edge.
     899               0 :       skip |= 1 << NS_SIDE_RIGHT;
     900                 :     }
     901                 :     else {
     902                 :       // If the next continuation is empty, then go ahead and let our right
     903                 :       // edge border render.
     904                 :     }
     905                 :   }
     906                 : 
     907               0 :   if (GetStateBits() & NS_FRAME_IS_SPECIAL) {
     908                 :     // All but the last part of an {ib} split should skip the "end" side (as
     909                 :     // determined by this frame's direction) and all but the first part of such
     910                 :     // a split should skip the "start" side.  But figuring out which part of
     911                 :     // the split we are involves getting our first continuation, which might be
     912                 :     // expensive.  So don't bother if we already have the relevant bits set.
     913               0 :     bool ltr = (NS_STYLE_DIRECTION_LTR == GetStyleVisibility()->mDirection);
     914               0 :     PRIntn startBit = (1 << (ltr ? NS_SIDE_LEFT : NS_SIDE_RIGHT));
     915               0 :     PRIntn endBit = (1 << (ltr ? NS_SIDE_RIGHT : NS_SIDE_LEFT));
     916               0 :     if (((startBit | endBit) & skip) != (startBit | endBit)) {
     917                 :       // We're missing one of the skip bits, so check whether we need to set it.
     918                 :       // Only get the first continuation once, as an optimization.
     919               0 :       nsIFrame* firstContinuation = GetFirstContinuation();
     920               0 :       if (nsLayoutUtils::FrameIsNonLastInIBSplit(firstContinuation)) {
     921               0 :         skip |= endBit;
     922                 :       }
     923               0 :       if (nsLayoutUtils::FrameIsNonFirstInIBSplit(firstContinuation)) {
     924               0 :         skip |= startBit;
     925                 :       }
     926                 :     }
     927                 :   }
     928                 : 
     929               0 :   return skip;
     930                 : }
     931                 : 
     932                 : nscoord
     933               0 : nsInlineFrame::GetBaseline() const
     934                 : {
     935               0 :   return mBaseline;
     936                 : }
     937                 : 
     938                 : void
     939               0 : nsInlineFrame::DestroyFrom(nsIFrame* aDestructRoot)
     940                 : {
     941               0 :   DestroyAbsoluteFrames(aDestructRoot);
     942               0 :   nsContainerFrame::DestroyFrom(aDestructRoot);
     943               0 : }
     944                 : 
     945                 : #ifdef ACCESSIBILITY
     946                 : already_AddRefed<nsAccessible>
     947               0 : nsInlineFrame::CreateAccessible()
     948                 : {
     949                 :   // Broken image accessibles are created here, because layout
     950                 :   // replaces the image or image control frame with an inline frame
     951               0 :   nsIAtom *tagAtom = mContent->Tag();
     952               0 :   if ((tagAtom == nsGkAtoms::img || tagAtom == nsGkAtoms::input || 
     953               0 :        tagAtom == nsGkAtoms::label) && mContent->IsHTML()) {
     954                 :     // Only get accessibility service if we're going to use it
     955                 : 
     956               0 :     nsAccessibilityService* accService = nsIPresShell::AccService();
     957               0 :     if (!accService)
     958               0 :       return nsnull;
     959               0 :     if (tagAtom == nsGkAtoms::input)  // Broken <input type=image ... />
     960                 :       return accService->CreateHTMLButtonAccessible(mContent,
     961               0 :                                                     PresContext()->PresShell());
     962               0 :     else if (tagAtom == nsGkAtoms::img)  // Create accessible for broken <img>
     963                 :       return accService->CreateHTMLImageAccessible(mContent,
     964               0 :                                                    PresContext()->PresShell());
     965               0 :     else if (tagAtom == nsGkAtoms::label)  // Creat accessible for <label>
     966                 :       return accService->CreateHTMLLabelAccessible(mContent,
     967               0 :                                                    PresContext()->PresShell());
     968                 :   }
     969                 : 
     970               0 :   return nsnull;
     971                 : }
     972                 : #endif
     973                 : 
     974                 : //////////////////////////////////////////////////////////////////////
     975                 : 
     976                 : // nsLineFrame implementation
     977                 : 
     978                 : nsIFrame*
     979               0 : NS_NewFirstLineFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
     980                 : {
     981               0 :   return new (aPresShell) nsFirstLineFrame(aContext);
     982                 : }
     983                 : 
     984               0 : NS_IMPL_FRAMEARENA_HELPERS(nsFirstLineFrame)
     985                 : 
     986                 : #ifdef DEBUG
     987                 : NS_IMETHODIMP
     988               0 : nsFirstLineFrame::GetFrameName(nsAString& aResult) const
     989                 : {
     990               0 :   return MakeFrameName(NS_LITERAL_STRING("Line"), aResult);
     991                 : }
     992                 : #endif
     993                 : 
     994                 : nsIAtom*
     995               0 : nsFirstLineFrame::GetType() const
     996                 : {
     997               0 :   return nsGkAtoms::lineFrame;
     998                 : }
     999                 : 
    1000                 : nsIFrame*
    1001               0 : nsFirstLineFrame::PullOneFrame(nsPresContext* aPresContext, InlineReflowState& irs,
    1002                 :                                bool* aIsComplete)
    1003                 : {
    1004               0 :   nsIFrame* frame = nsInlineFrame::PullOneFrame(aPresContext, irs, aIsComplete);
    1005               0 :   if (frame && !GetPrevInFlow()) {
    1006                 :     // We are a first-line frame. Fixup the child frames
    1007                 :     // style-context that we just pulled.
    1008               0 :     NS_ASSERTION(frame->GetParent() == this, "Incorrect parent?");
    1009               0 :     aPresContext->FrameManager()->ReparentStyleContext(frame);
    1010                 :   }
    1011               0 :   return frame;
    1012                 : }
    1013                 : 
    1014                 : NS_IMETHODIMP
    1015               0 : nsFirstLineFrame::Reflow(nsPresContext* aPresContext,
    1016                 :                          nsHTMLReflowMetrics& aMetrics,
    1017                 :                          const nsHTMLReflowState& aReflowState,
    1018                 :                          nsReflowStatus& aStatus)
    1019                 : {
    1020               0 :   if (nsnull == aReflowState.mLineLayout) {
    1021               0 :     return NS_ERROR_INVALID_ARG;
    1022                 :   }
    1023                 : 
    1024               0 :   nsIFrame* lineContainer = aReflowState.mLineLayout->GetLineContainerFrame();
    1025                 : 
    1026                 :   // Check for an overflow list with our prev-in-flow
    1027               0 :   nsFirstLineFrame* prevInFlow = (nsFirstLineFrame*)GetPrevInFlow();
    1028               0 :   if (nsnull != prevInFlow) {
    1029               0 :     nsAutoPtr<nsFrameList> prevOverflowFrames(prevInFlow->StealOverflowFrames());
    1030               0 :     if (prevOverflowFrames) {
    1031                 :       // Assign all floats to our block if necessary
    1032               0 :       if (lineContainer && lineContainer->GetPrevContinuation()) {
    1033                 :         ReparentFloatsForInlineChild(lineContainer,
    1034                 :                                      prevOverflowFrames->FirstChild(),
    1035               0 :                                      true);
    1036                 :       }
    1037                 :       const nsFrameList::Slice& newFrames =
    1038               0 :         mFrames.InsertFrames(this, nsnull, *prevOverflowFrames);
    1039               0 :       ReparentChildListStyle(aPresContext, newFrames, this);
    1040                 :     }
    1041                 :   }
    1042                 : 
    1043                 :   // It's also possible that we have an overflow list for ourselves
    1044               0 :   nsAutoPtr<nsFrameList> overflowFrames(StealOverflowFrames());
    1045               0 :   if (overflowFrames) {
    1046               0 :     NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames");
    1047                 : 
    1048                 :     const nsFrameList::Slice& newFrames =
    1049               0 :       mFrames.AppendFrames(nsnull, *overflowFrames);
    1050               0 :     ReparentChildListStyle(aPresContext, newFrames, this);
    1051                 :   }
    1052                 : 
    1053                 :   // Set our own reflow state (additional state above and beyond
    1054                 :   // aReflowState)
    1055               0 :   InlineReflowState irs;
    1056               0 :   irs.mPrevFrame = nsnull;
    1057               0 :   irs.mLineContainer = lineContainer;
    1058               0 :   irs.mLineLayout = aReflowState.mLineLayout;
    1059               0 :   irs.mNextInFlow = (nsInlineFrame*) GetNextInFlow();
    1060                 : 
    1061                 :   nsresult rv;
    1062               0 :   bool wasEmpty = mFrames.IsEmpty();
    1063               0 :   if (wasEmpty) {
    1064                 :     // Try to pull over one frame before starting so that we know
    1065                 :     // whether we have an anonymous block or not.
    1066                 :     bool complete;
    1067               0 :     PullOneFrame(aPresContext, irs, &complete);
    1068                 :   }
    1069                 : 
    1070               0 :   if (nsnull == GetPrevInFlow()) {
    1071                 :     // XXX This is pretty sick, but what we do here is to pull-up, in
    1072                 :     // advance, all of the next-in-flows children. We re-resolve their
    1073                 :     // style while we are at at it so that when we reflow they have
    1074                 :     // the right style.
    1075                 :     //
    1076                 :     // All of this is so that text-runs reflow properly.
    1077               0 :     irs.mPrevFrame = mFrames.LastChild();
    1078               0 :     for (;;) {
    1079                 :       bool complete;
    1080               0 :       nsIFrame* frame = PullOneFrame(aPresContext, irs, &complete);
    1081               0 :       if (!frame) {
    1082                 :         break;
    1083                 :       }
    1084               0 :       irs.mPrevFrame = frame;
    1085                 :     }
    1086               0 :     irs.mPrevFrame = nsnull;
    1087                 :   }
    1088                 :   else {
    1089                 : // XXX do this in the Init method instead
    1090                 :     // For continuations, we need to check and see if our style
    1091                 :     // context is right. If its the same as the first-in-flow, then
    1092                 :     // we need to fix it up (that way :first-line style doesn't leak
    1093                 :     // into this continuation since we aren't the first line).
    1094               0 :     nsFirstLineFrame* first = (nsFirstLineFrame*) GetFirstInFlow();
    1095               0 :     if (mStyleContext == first->mStyleContext) {
    1096                 :       // Fixup our style context and our children. First get the
    1097                 :       // proper parent context.
    1098               0 :       nsStyleContext* parentContext = first->GetParent()->GetStyleContext();
    1099               0 :       if (parentContext) {
    1100                 :         // Create a new style context that is a child of the parent
    1101                 :         // style context thus removing the :first-line style. This way
    1102                 :         // we behave as if an anonymous (unstyled) span was the child
    1103                 :         // of the parent frame.
    1104               0 :         nsRefPtr<nsStyleContext> newSC;
    1105                 :         newSC = aPresContext->StyleSet()->
    1106               0 :           ResolveAnonymousBoxStyle(nsCSSAnonBoxes::mozLineFrame, parentContext);
    1107               0 :         if (newSC) {
    1108                 :           // Switch to the new style context.
    1109               0 :           SetStyleContext(newSC);
    1110                 : 
    1111                 :           // Re-resolve all children
    1112               0 :           ReparentChildListStyle(aPresContext, mFrames, this);
    1113                 :         }
    1114                 :       }
    1115                 :     }
    1116                 :   }
    1117                 : 
    1118               0 :   NS_ASSERTION(!aReflowState.mLineLayout->GetInFirstLine(),
    1119                 :                "Nested first-line frames? BOGUS");
    1120               0 :   aReflowState.mLineLayout->SetInFirstLine(true);
    1121               0 :   rv = ReflowFrames(aPresContext, aReflowState, irs, aMetrics, aStatus);
    1122               0 :   aReflowState.mLineLayout->SetInFirstLine(false);
    1123                 : 
    1124               0 :   ReflowAbsoluteFrames(aPresContext, aMetrics, aReflowState, aStatus);
    1125                 : 
    1126                 :   // Note: the line layout code will properly compute our overflow state for us
    1127                 : 
    1128               0 :   return rv;
    1129                 : }
    1130                 : 
    1131                 : /* virtual */ void
    1132               0 : nsFirstLineFrame::PullOverflowsFromPrevInFlow()
    1133                 : {
    1134               0 :   nsFirstLineFrame* prevInFlow = static_cast<nsFirstLineFrame*>(GetPrevInFlow());
    1135               0 :   if (prevInFlow) {
    1136               0 :     nsAutoPtr<nsFrameList> prevOverflowFrames(prevInFlow->StealOverflowFrames());
    1137               0 :     if (prevOverflowFrames) {
    1138                 :       // Assume that our prev-in-flow has the same line container that we do.
    1139                 :       const nsFrameList::Slice& newFrames =
    1140               0 :         mFrames.InsertFrames(this, nsnull, *prevOverflowFrames);
    1141               0 :       ReparentChildListStyle(PresContext(), newFrames, this);
    1142                 :     }
    1143                 :   }
    1144               0 : }
    1145                 : 

Generated by: LCOV version 1.7