LCOV - code coverage report
Current view: top level - layout/xul - nsBox.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 336 388 86.6 %
Date: 2017-07-14 16:53:18 Functions: 41 44 93.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             : #include "nsBoxLayoutState.h"
       7             : #include "nsBox.h"
       8             : #include "nsBoxFrame.h"
       9             : #include "nsPresContext.h"
      10             : #include "nsCOMPtr.h"
      11             : #include "nsIContent.h"
      12             : #include "nsContainerFrame.h"
      13             : #include "nsNameSpaceManager.h"
      14             : #include "nsGkAtoms.h"
      15             : #include "nsIDOMNode.h"
      16             : #include "nsIDOMMozNamedAttrMap.h"
      17             : #include "nsIDOMAttr.h"
      18             : #include "nsITheme.h"
      19             : #include "nsIServiceManager.h"
      20             : #include "nsBoxLayout.h"
      21             : #include "FrameLayerBuilder.h"
      22             : #include <algorithm>
      23             : 
      24             : using namespace mozilla;
      25             : 
      26             : #ifdef DEBUG_LAYOUT
      27             : int32_t gIndent = 0;
      28             : #endif
      29             : 
      30             : #ifdef DEBUG_LAYOUT
      31             : void
      32             : nsBoxAddIndents()
      33             : {
      34             :     for(int32_t i=0; i < gIndent; i++)
      35             :     {
      36             :         printf(" ");
      37             :     }
      38             : }
      39             : #endif
      40             : 
      41             : #ifdef DEBUG_LAYOUT
      42             : void
      43             : nsBox::AppendAttribute(const nsAutoString& aAttribute, const nsAutoString& aValue, nsAutoString& aResult)
      44             : {
      45             :    aResult.Append(aAttribute);
      46             :    aResult.AppendLiteral("='");
      47             :    aResult.Append(aValue);
      48             :    aResult.AppendLiteral("' ");
      49             : }
      50             : 
      51             : void
      52             : nsBox::ListBox(nsAutoString& aResult)
      53             : {
      54             :     nsAutoString name;
      55             :     GetBoxName(name);
      56             : 
      57             :     char addr[100];
      58             :     sprintf(addr, "[@%p] ", static_cast<void*>(this));
      59             : 
      60             :     aResult.AppendASCII(addr);
      61             :     aResult.Append(name);
      62             :     aResult.Append(' ');
      63             : 
      64             :     nsIContent* content = GetContent();
      65             : 
      66             :     // add on all the set attributes
      67             :     if (content) {
      68             :       nsCOMPtr<nsIDOMNode> node(do_QueryInterface(content));
      69             :       nsCOMPtr<nsIDOMMozNamedAttrMap> namedMap;
      70             : 
      71             :       node->GetAttributes(getter_AddRefs(namedMap));
      72             :       uint32_t length;
      73             :       namedMap->GetLength(&length);
      74             : 
      75             :       nsCOMPtr<nsIDOMAttr> attribute;
      76             :       for (uint32_t i = 0; i < length; ++i)
      77             :       {
      78             :         namedMap->Item(i, getter_AddRefs(attribute));
      79             :         attribute->GetName(name);
      80             :         nsAutoString value;
      81             :         attribute->GetValue(value);
      82             :         AppendAttribute(name, value, aResult);
      83             :       }
      84             :     }
      85             : }
      86             : 
      87             : nsresult
      88             : nsBox::XULDumpBox(FILE* aFile)
      89             : {
      90             :   nsAutoString s;
      91             :   ListBox(s);
      92             :   fprintf(aFile, "%s", NS_LossyConvertUTF16toASCII(s).get());
      93             :   return NS_OK;
      94             : }
      95             : 
      96             : void
      97             : nsBox::PropagateDebug(nsBoxLayoutState& aState)
      98             : {
      99             :   // propagate debug information
     100             :   if (mState & NS_STATE_DEBUG_WAS_SET) {
     101             :     if (mState & NS_STATE_SET_TO_DEBUG)
     102             :       SetXULDebug(aState, true);
     103             :     else
     104             :       SetXULDebug(aState, false);
     105             :   } else if (mState & NS_STATE_IS_ROOT) {
     106             :     SetXULDebug(aState, gDebug);
     107             :   }
     108             : }
     109             : #endif
     110             : 
     111             : #ifdef DEBUG_LAYOUT
     112             : void
     113             : nsBox::GetBoxName(nsAutoString& aName)
     114             : {
     115             :   aName.AssignLiteral("Box");
     116             : }
     117             : #endif
     118             : 
     119             : nsresult
     120         884 : nsBox::BeginXULLayout(nsBoxLayoutState& aState)
     121             : {
     122             : #ifdef DEBUG_LAYOUT
     123             : 
     124             :   nsBoxAddIndents();
     125             :   printf("XULLayout: ");
     126             :   XULDumpBox(stdout);
     127             :   printf("\n");
     128             :   gIndent++;
     129             : #endif
     130             : 
     131             :   // mark ourselves as dirty so no child under us
     132             :   // can post an incremental layout.
     133             :   // XXXldb Is this still needed?
     134         884 :   mState |= NS_FRAME_HAS_DIRTY_CHILDREN;
     135             : 
     136         884 :   if (GetStateBits() & NS_FRAME_IS_DIRTY)
     137             :   {
     138             :     // If the parent is dirty, all the children are dirty (ReflowInput
     139             :     // does this too).
     140             :     nsIFrame* box;
     141         806 :     for (box = GetChildXULBox(this); box; box = GetNextXULBox(box))
     142         361 :       box->AddStateBits(NS_FRAME_IS_DIRTY);
     143             :   }
     144             : 
     145             :   // Another copy-over from ReflowInput.
     146             :   // Since we are in reflow, we don't need to store these properties anymore.
     147         884 :   DeleteProperty(UsedBorderProperty());
     148         884 :   DeleteProperty(UsedPaddingProperty());
     149         884 :   DeleteProperty(UsedMarginProperty());
     150             : 
     151             : #ifdef DEBUG_LAYOUT
     152             :   PropagateDebug(aState);
     153             : #endif
     154             : 
     155         884 :   return NS_OK;
     156             : }
     157             : 
     158             : NS_IMETHODIMP
     159         203 : nsBox::DoXULLayout(nsBoxLayoutState& aState)
     160             : {
     161         203 :   return NS_OK;
     162             : }
     163             : 
     164             : nsresult
     165         884 : nsBox::EndXULLayout(nsBoxLayoutState& aState)
     166             : {
     167             : 
     168             :   #ifdef DEBUG_LAYOUT
     169             :       --gIndent;
     170             :   #endif
     171             : 
     172         884 :   return SyncLayout(aState);
     173             : }
     174             : 
     175             : bool nsBox::gGotTheme = false;
     176             : nsITheme* nsBox::gTheme = nullptr;
     177             : 
     178         666 : nsBox::nsBox(ClassID aID)
     179         666 :   : nsIFrame(aID)
     180             : {
     181         666 :   MOZ_COUNT_CTOR(nsBox);
     182             :   //mX = 0;
     183             :   //mY = 0;
     184         666 :   if (!gGotTheme) {
     185           2 :     gGotTheme = true;
     186           2 :     CallGetService("@mozilla.org/chrome/chrome-native-theme;1", &gTheme);
     187             :   }
     188         666 : }
     189             : 
     190         252 : nsBox::~nsBox()
     191             : {
     192             :   // NOTE:  This currently doesn't get called for |nsBoxToBlockAdaptor|
     193             :   // objects, so don't rely on putting anything here.
     194         126 :   MOZ_COUNT_DTOR(nsBox);
     195         126 : }
     196             : 
     197             : /* static */ void
     198           0 : nsBox::Shutdown()
     199             : {
     200           0 :   gGotTheme = false;
     201           0 :   NS_IF_RELEASE(gTheme);
     202           0 : }
     203             : 
     204             : nsresult
     205           0 : nsBox::XULRelayoutChildAtOrdinal(nsIFrame* aChild)
     206             : {
     207           0 :   return NS_OK;
     208             : }
     209             : 
     210             : nsresult
     211         771 : nsIFrame::GetXULClientRect(nsRect& aClientRect)
     212             : {
     213         771 :   aClientRect = mRect;
     214         771 :   aClientRect.MoveTo(0,0);
     215             : 
     216         771 :   nsMargin borderPadding;
     217         771 :   GetXULBorderAndPadding(borderPadding);
     218             : 
     219         771 :   aClientRect.Deflate(borderPadding);
     220             : 
     221         771 :   if (aClientRect.width < 0)
     222           0 :      aClientRect.width = 0;
     223             : 
     224         771 :   if (aClientRect.height < 0)
     225           0 :      aClientRect.height = 0;
     226             : 
     227             :  // NS_ASSERTION(aClientRect.width >=0 && aClientRect.height >= 0, "Content Size < 0");
     228             : 
     229         771 :   return NS_OK;
     230             : }
     231             : 
     232             : void
     233        1935 : nsBox::SetXULBounds(nsBoxLayoutState& aState, const nsRect& aRect, bool aRemoveOverflowAreas)
     234             : {
     235             :     NS_BOX_ASSERTION(this, aRect.width >=0 && aRect.height >= 0, "SetXULBounds Size < 0");
     236             : 
     237        3870 :     nsRect rect(mRect);
     238             : 
     239        1935 :     uint32_t flags = GetXULLayoutFlags();
     240             : 
     241        1935 :     uint32_t stateFlags = aState.LayoutFlags();
     242             : 
     243        1935 :     flags |= stateFlags;
     244             : 
     245        1935 :     if ((flags & NS_FRAME_NO_MOVE_FRAME) == NS_FRAME_NO_MOVE_FRAME)
     246           0 :       SetSize(aRect.Size());
     247             :     else
     248        1935 :       SetRect(aRect);
     249             : 
     250             :     // Nuke the overflow area. The caller is responsible for restoring
     251             :     // it if necessary.
     252        1935 :     if (aRemoveOverflowAreas) {
     253             :       // remove the previously stored overflow area
     254           0 :       ClearOverflowRects();
     255             :     }
     256             : 
     257        1935 :     if (!(flags & NS_FRAME_NO_MOVE_VIEW))
     258             :     {
     259        1897 :       nsContainerFrame::PositionFrameView(this);
     260        1897 :       if ((rect.x != aRect.x) || (rect.y != aRect.y))
     261         350 :         nsContainerFrame::PositionChildViews(this);
     262             :     }
     263             : 
     264             : 
     265             :    /*
     266             :     // only if the origin changed
     267             :     if ((rect.x != aRect.x) || (rect.y != aRect.y))  {
     268             :       if (frame->HasView()) {
     269             :         nsContainerFrame::PositionFrameView(presContext, frame,
     270             :                                             frame->GetView());
     271             :       } else {
     272             :         nsContainerFrame::PositionChildViews(presContext, frame);
     273             :       }
     274             :     }
     275             :     */
     276        1935 : }
     277             : 
     278             : nsresult
     279        5883 : nsIFrame::GetXULBorderAndPadding(nsMargin& aBorderAndPadding)
     280             : {
     281        5883 :   aBorderAndPadding.SizeTo(0, 0, 0, 0);
     282        5883 :   nsresult rv = GetXULBorder(aBorderAndPadding);
     283        5883 :   if (NS_FAILED(rv))
     284           0 :     return rv;
     285             : 
     286        5883 :   nsMargin padding;
     287        5883 :   rv = GetXULPadding(padding);
     288        5883 :   if (NS_FAILED(rv))
     289           0 :     return rv;
     290             : 
     291        5883 :   aBorderAndPadding += padding;
     292             : 
     293        5883 :   return rv;
     294             : }
     295             : 
     296             : nsresult
     297        6009 : nsBox::GetXULBorder(nsMargin& aMargin)
     298             : {
     299        6009 :   aMargin.SizeTo(0,0,0,0);
     300             : 
     301        6009 :   const nsStyleDisplay* disp = StyleDisplay();
     302        6009 :   if (disp->mAppearance && gTheme) {
     303             :     // Go to the theme for the border.
     304         317 :     nsPresContext *context = PresContext();
     305         317 :     if (gTheme->ThemeSupportsWidget(context, this, disp->mAppearance)) {
     306         317 :       nsIntMargin margin(0, 0, 0, 0);
     307         317 :       gTheme->GetWidgetBorder(context->DeviceContext(), this,
     308         634 :                               disp->mAppearance, &margin);
     309         317 :       aMargin.top = context->DevPixelsToAppUnits(margin.top);
     310         317 :       aMargin.right = context->DevPixelsToAppUnits(margin.right);
     311         317 :       aMargin.bottom = context->DevPixelsToAppUnits(margin.bottom);
     312         317 :       aMargin.left = context->DevPixelsToAppUnits(margin.left);
     313         317 :       return NS_OK;
     314             :     }
     315             :   }
     316             : 
     317        5692 :   aMargin = StyleBorder()->GetComputedBorder();
     318             : 
     319        5692 :   return NS_OK;
     320             : }
     321             : 
     322             : nsresult
     323        5185 : nsBox::GetXULPadding(nsMargin& aMargin)
     324             : {
     325        5185 :   const nsStyleDisplay *disp = StyleDisplay();
     326        5185 :   if (disp->mAppearance && gTheme) {
     327             :     // Go to the theme for the padding.
     328         317 :     nsPresContext *context = PresContext();
     329         317 :     if (gTheme->ThemeSupportsWidget(context, this, disp->mAppearance)) {
     330         317 :       nsIntMargin margin(0, 0, 0, 0);
     331             :       bool useThemePadding;
     332             : 
     333         634 :       useThemePadding = gTheme->GetWidgetPadding(context->DeviceContext(),
     334         317 :                                                  this, disp->mAppearance,
     335         634 :                                                  &margin);
     336         317 :       if (useThemePadding) {
     337          10 :         aMargin.top = context->DevPixelsToAppUnits(margin.top);
     338          10 :         aMargin.right = context->DevPixelsToAppUnits(margin.right);
     339          10 :         aMargin.bottom = context->DevPixelsToAppUnits(margin.bottom);
     340          10 :         aMargin.left = context->DevPixelsToAppUnits(margin.left);
     341          10 :         return NS_OK;
     342             :       }
     343             :     }
     344             :   }
     345             : 
     346        5175 :   aMargin.SizeTo(0,0,0,0);
     347        5175 :   StylePadding()->GetPadding(aMargin);
     348             : 
     349        5175 :   return NS_OK;
     350             : }
     351             : 
     352             : nsresult
     353       10005 : nsBox::GetXULMargin(nsMargin& aMargin)
     354             : {
     355       10005 :   aMargin.SizeTo(0,0,0,0);
     356       10005 :   StyleMargin()->GetMargin(aMargin);
     357             : 
     358       10005 :   return NS_OK;
     359             : }
     360             : 
     361             : void
     362        4433 : nsBox::SizeNeedsRecalc(nsSize& aSize)
     363             : {
     364        4433 :   aSize.width  = -1;
     365        4433 :   aSize.height = -1;
     366        4433 : }
     367             : 
     368             : void
     369        3344 : nsBox::CoordNeedsRecalc(nscoord& aFlex)
     370             : {
     371        3344 :   aFlex = -1;
     372        3344 : }
     373             : 
     374             : bool
     375        7256 : nsBox::DoesNeedRecalc(const nsSize& aSize)
     376             : {
     377        7256 :   return (aSize.width == -1 || aSize.height == -1);
     378             : }
     379             : 
     380             : bool
     381        3903 : nsBox::DoesNeedRecalc(nscoord aCoord)
     382             : {
     383        3903 :   return (aCoord == -1);
     384             : }
     385             : 
     386             : nsSize
     387          67 : nsBox::GetXULPrefSize(nsBoxLayoutState& aState)
     388             : {
     389          67 :   NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context");
     390             : 
     391          67 :   nsSize pref(0,0);
     392         134 :   DISPLAY_PREF_SIZE(this, pref);
     393             : 
     394          67 :   if (IsXULCollapsed())
     395           0 :     return pref;
     396             : 
     397          67 :   AddBorderAndPadding(pref);
     398             :   bool widthSet, heightSet;
     399          67 :   nsIFrame::AddXULPrefSize(this, pref, widthSet, heightSet);
     400             : 
     401          67 :   nsSize minSize = GetXULMinSize(aState);
     402          67 :   nsSize maxSize = GetXULMaxSize(aState);
     403          67 :   return BoundsCheck(minSize, pref, maxSize);
     404             : }
     405             : 
     406             : nsSize
     407         189 : nsBox::GetXULMinSize(nsBoxLayoutState& aState)
     408             : {
     409         189 :   NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context");
     410             : 
     411         189 :   nsSize min(0,0);
     412         378 :   DISPLAY_MIN_SIZE(this, min);
     413             : 
     414         189 :   if (IsXULCollapsed())
     415           7 :     return min;
     416             : 
     417         182 :   AddBorderAndPadding(min);
     418             :   bool widthSet, heightSet;
     419         182 :   nsIFrame::AddXULMinSize(aState, this, min, widthSet, heightSet);
     420         182 :   return min;
     421             : }
     422             : 
     423             : nsSize
     424         236 : nsBox::GetXULMinSizeForScrollArea(nsBoxLayoutState& aBoxLayoutState)
     425             : {
     426         236 :   return nsSize(0, 0);
     427             : }
     428             : 
     429             : nsSize
     430         878 : nsBox::GetXULMaxSize(nsBoxLayoutState& aState)
     431             : {
     432         878 :   NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context");
     433             : 
     434         878 :   nsSize maxSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
     435        1756 :   DISPLAY_MAX_SIZE(this, maxSize);
     436             : 
     437         878 :   if (IsXULCollapsed())
     438         129 :     return maxSize;
     439             : 
     440         749 :   AddBorderAndPadding(maxSize);
     441             :   bool widthSet, heightSet;
     442         749 :   nsIFrame::AddXULMaxSize(this, maxSize, widthSet, heightSet);
     443         749 :   return maxSize;
     444             : }
     445             : 
     446             : nscoord
     447         630 : nsBox::GetXULFlex()
     448             : {
     449         630 :   nscoord flex = 0;
     450             : 
     451         630 :   nsIFrame::AddXULFlex(this, flex);
     452             : 
     453         630 :   return flex;
     454             : }
     455             : 
     456             : uint32_t
     457         374 : nsIFrame::GetXULOrdinal()
     458             : {
     459         374 :   uint32_t ordinal = StyleXUL()->mBoxOrdinal;
     460             : 
     461             :   // When present, attribute value overrides CSS.
     462         374 :   nsIContent* content = GetContent();
     463         374 :   if (content && content->IsXULElement()) {
     464             :     nsresult error;
     465         724 :     nsAutoString value;
     466             : 
     467         362 :     content->GetAttr(kNameSpaceID_None, nsGkAtoms::ordinal, value);
     468         362 :     if (!value.IsEmpty()) {
     469           0 :       ordinal = value.ToInteger(&error);
     470             :     }
     471             :   }
     472             : 
     473         374 :   return ordinal;
     474             : }
     475             : 
     476             : nscoord
     477          82 : nsBox::GetXULBoxAscent(nsBoxLayoutState& aState)
     478             : {
     479          82 :   if (IsXULCollapsed())
     480          46 :     return 0;
     481             : 
     482          36 :   return GetXULPrefSize(aState).height;
     483             : }
     484             : 
     485             : bool
     486        8393 : nsBox::IsXULCollapsed()
     487             : {
     488        8393 :   return StyleVisibility()->mVisible == NS_STYLE_VISIBILITY_COLLAPSE;
     489             : }
     490             : 
     491             : nsresult
     492         884 : nsIFrame::XULLayout(nsBoxLayoutState& aState)
     493             : {
     494         884 :   NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context");
     495             : 
     496         884 :   nsBox *box = static_cast<nsBox*>(this);
     497        1768 :   DISPLAY_LAYOUT(box);
     498             : 
     499         884 :   box->BeginXULLayout(aState);
     500             : 
     501         884 :   box->DoXULLayout(aState);
     502             : 
     503         884 :   box->EndXULLayout(aState);
     504             : 
     505        1768 :   return NS_OK;
     506             : }
     507             : 
     508             : bool
     509         745 : nsBox::DoesClipChildren()
     510             : {
     511         745 :   const nsStyleDisplay* display = StyleDisplay();
     512         745 :   NS_ASSERTION((display->mOverflowY == NS_STYLE_OVERFLOW_CLIP) ==
     513             :                (display->mOverflowX == NS_STYLE_OVERFLOW_CLIP),
     514             :                "If one overflow is clip, the other should be too");
     515         745 :   return display->mOverflowX == NS_STYLE_OVERFLOW_CLIP;
     516             : }
     517             : 
     518             : nsresult
     519         971 : nsBox::SyncLayout(nsBoxLayoutState& aState)
     520             : {
     521             :   /*
     522             :   if (IsXULCollapsed()) {
     523             :     CollapseChild(aState, this, true);
     524             :     return NS_OK;
     525             :   }
     526             :   */
     527             : 
     528             : 
     529         971 :   if (GetStateBits() & NS_FRAME_IS_DIRTY)
     530         389 :      XULRedraw(aState);
     531             : 
     532         971 :   RemoveStateBits(NS_FRAME_HAS_DIRTY_CHILDREN | NS_FRAME_IS_DIRTY
     533         971 :                   | NS_FRAME_FIRST_REFLOW | NS_FRAME_IN_REFLOW);
     534             : 
     535         971 :   nsPresContext* presContext = aState.PresContext();
     536             : 
     537         971 :   uint32_t flags = GetXULLayoutFlags();
     538             : 
     539         971 :   uint32_t stateFlags = aState.LayoutFlags();
     540             : 
     541         971 :   flags |= stateFlags;
     542             : 
     543        1942 :   nsRect visualOverflow;
     544             : 
     545         971 :   if (ComputesOwnOverflowArea()) {
     546         178 :     visualOverflow = GetVisualOverflowRect();
     547             :   }
     548             :   else {
     549        1586 :     nsRect rect(nsPoint(0, 0), GetSize());
     550        1586 :     nsOverflowAreas overflowAreas(rect, rect);
     551         793 :     if (!DoesClipChildren() && !IsXULCollapsed()) {
     552             :       // See if our child frames caused us to overflow after being laid
     553             :       // out. If so, store the overflow area.  This normally can't happen
     554             :       // in XUL, but it can happen with the CSS 'outline' property and
     555             :       // possibly with other exotic stuff (e.g. relatively positioned
     556             :       // frames in HTML inside XUL).
     557         567 :       nsLayoutUtils::UnionChildOverflow(this, overflowAreas);
     558             :     }
     559             : 
     560         793 :     FinishAndStoreOverflow(overflowAreas, GetSize());
     561         793 :     visualOverflow = overflowAreas.VisualOverflow();
     562             :   }
     563             : 
     564         971 :   nsView* view = GetView();
     565         971 :   if (view) {
     566             :     // Make sure the frame's view is properly sized and positioned and has
     567             :     // things like opacity correct
     568           6 :     nsContainerFrame::SyncFrameViewAfterReflow(presContext, this, view,
     569           6 :                                                visualOverflow, flags);
     570             :   }
     571             : 
     572        1942 :   return NS_OK;
     573             : }
     574             : 
     575             : nsresult
     576         437 : nsIFrame::XULRedraw(nsBoxLayoutState& aState)
     577             : {
     578         437 :   if (aState.PaintingDisabled())
     579           0 :     return NS_OK;
     580             : 
     581             :   // nsStackLayout, at least, expects us to repaint descendants even
     582             :   // if a damage rect is provided
     583         437 :   InvalidateFrameSubtree();
     584             : 
     585         437 :   return NS_OK;
     586             : }
     587             : 
     588             : bool
     589        1203 : nsIFrame::AddXULPrefSize(nsIFrame* aBox, nsSize& aSize, bool &aWidthSet, bool &aHeightSet)
     590             : {
     591        1203 :     aWidthSet = false;
     592        1203 :     aHeightSet = false;
     593             : 
     594             :     // add in the css min, max, pref
     595        1203 :     const nsStylePosition* position = aBox->StylePosition();
     596             : 
     597             :     // see if the width or height was specifically set
     598             :     // XXX Handle eStyleUnit_Enumerated?
     599             :     // (Handling the eStyleUnit_Enumerated types requires
     600             :     // GetXULPrefSize/GetXULMinSize methods that don't consider
     601             :     // (min-/max-/)(width/height) properties.)
     602        1203 :     const nsStyleCoord &width = position->mWidth;
     603        1203 :     if (width.GetUnit() == eStyleUnit_Coord) {
     604         278 :         aSize.width = width.GetCoordValue();
     605         278 :         aWidthSet = true;
     606         925 :     } else if (width.IsCalcUnit()) {
     607           3 :         if (!width.CalcHasPercent()) {
     608             :             // pass 0 for percentage basis since we know there are no %s
     609           3 :             aSize.width = nsRuleNode::ComputeComputedCalc(width, 0);
     610           3 :             if (aSize.width < 0)
     611           0 :                 aSize.width = 0;
     612           3 :             aWidthSet = true;
     613             :         }
     614             :     }
     615             : 
     616        1203 :     const nsStyleCoord &height = position->mHeight;
     617        1203 :     if (height.GetUnit() == eStyleUnit_Coord) {
     618         287 :         aSize.height = height.GetCoordValue();
     619         287 :         aHeightSet = true;
     620         916 :     } else if (height.IsCalcUnit()) {
     621           0 :         if (!height.CalcHasPercent()) {
     622             :             // pass 0 for percentage basis since we know there are no %s
     623           0 :             aSize.height = nsRuleNode::ComputeComputedCalc(height, 0);
     624           0 :             if (aSize.height < 0)
     625           0 :                 aSize.height = 0;
     626           0 :             aHeightSet = true;
     627             :         }
     628             :     }
     629             : 
     630        1203 :     nsIContent* content = aBox->GetContent();
     631             :     // ignore 'height' and 'width' attributes if the actual element is not XUL
     632             :     // For example, we might be magic XUL frames whose primary content is an HTML
     633             :     // <select>
     634        1203 :     if (content && content->IsXULElement()) {
     635        2358 :         nsAutoString value;
     636             :         nsresult error;
     637             : 
     638        1179 :         content->GetAttr(kNameSpaceID_None, nsGkAtoms::width, value);
     639        1179 :         if (!value.IsEmpty()) {
     640           0 :             value.Trim("%");
     641             : 
     642           0 :             aSize.width =
     643           0 :               nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
     644           0 :             aWidthSet = true;
     645             :         }
     646             : 
     647        1179 :         content->GetAttr(kNameSpaceID_None, nsGkAtoms::height, value);
     648        1179 :         if (!value.IsEmpty()) {
     649           0 :             value.Trim("%");
     650             : 
     651           0 :             aSize.height =
     652           0 :               nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
     653           0 :             aHeightSet = true;
     654             :         }
     655             :     }
     656             : 
     657        1203 :     return (aWidthSet && aHeightSet);
     658             : }
     659             : 
     660             : 
     661             : bool
     662        1673 : nsIFrame::AddXULMinSize(nsBoxLayoutState& aState, nsIFrame* aBox, nsSize& aSize,
     663             :                       bool &aWidthSet, bool &aHeightSet)
     664             : {
     665        1673 :     aWidthSet = false;
     666        1673 :     aHeightSet = false;
     667             : 
     668        1673 :     bool canOverride = true;
     669             : 
     670             :     // See if a native theme wants to supply a minimum size.
     671        1673 :     const nsStyleDisplay* display = aBox->StyleDisplay();
     672        1673 :     if (display->mAppearance) {
     673          82 :       nsITheme *theme = aState.PresContext()->GetTheme();
     674          82 :       if (theme && theme->ThemeSupportsWidget(aState.PresContext(), aBox, display->mAppearance)) {
     675          82 :         LayoutDeviceIntSize size;
     676          82 :         theme->GetMinimumWidgetSize(aState.PresContext(), aBox,
     677         164 :                                     display->mAppearance, &size, &canOverride);
     678          82 :         if (size.width) {
     679          12 :           aSize.width = aState.PresContext()->DevPixelsToAppUnits(size.width);
     680          12 :           aWidthSet = true;
     681             :         }
     682          82 :         if (size.height) {
     683          12 :           aSize.height = aState.PresContext()->DevPixelsToAppUnits(size.height);
     684          12 :           aHeightSet = true;
     685             :         }
     686             :       }
     687             :     }
     688             : 
     689             :     // add in the css min, max, pref
     690        1673 :     const nsStylePosition* position = aBox->StylePosition();
     691             : 
     692             :     // same for min size. Unfortunately min size is always set to 0. So for now
     693             :     // we will assume 0 (as a coord) means not set.
     694        1673 :     const nsStyleCoord &minWidth = position->mMinWidth;
     695        3515 :     if ((minWidth.GetUnit() == eStyleUnit_Coord &&
     696        3349 :          minWidth.GetCoordValue() != 0) ||
     697        1507 :         (minWidth.IsCalcUnit() && !minWidth.CalcHasPercent())) {
     698         172 :         nscoord min = nsRuleNode::ComputeCoordPercentCalc(minWidth, 0);
     699         172 :         if (!aWidthSet || (min > aSize.width && canOverride)) {
     700         170 :            aSize.width = min;
     701         170 :            aWidthSet = true;
     702             :         }
     703        1501 :     } else if (minWidth.GetUnit() == eStyleUnit_Percent) {
     704           4 :         NS_ASSERTION(minWidth.GetPercentValue() == 0.0f,
     705             :           "Non-zero percentage values not currently supported");
     706           4 :         aSize.width = 0;
     707           4 :         aWidthSet = true; // FIXME: should we really do this for
     708             :                              // nonzero values?
     709             :     }
     710             :     // XXX Handle eStyleUnit_Enumerated?
     711             :     // (Handling the eStyleUnit_Enumerated types requires
     712             :     // GetXULPrefSize/GetXULMinSize methods that don't consider
     713             :     // (min-/max-/)(width/height) properties.
     714             :     // calc() with percentage is treated like '0' (unset)
     715             : 
     716        1673 :     const nsStyleCoord &minHeight = position->mMinHeight;
     717        3472 :     if ((minHeight.GetUnit() == eStyleUnit_Coord &&
     718        3346 :          minHeight.GetCoordValue() != 0) ||
     719        1621 :         (minHeight.IsCalcUnit() && !minHeight.CalcHasPercent())) {
     720          52 :         nscoord min = nsRuleNode::ComputeCoordPercentCalc(minHeight, 0);
     721          52 :         if (!aHeightSet || (min > aSize.height && canOverride)) {
     722          48 :            aSize.height = min;
     723          48 :            aHeightSet = true;
     724             :         }
     725        1621 :     } else if (minHeight.GetUnit() == eStyleUnit_Percent) {
     726           4 :         NS_ASSERTION(position->mMinHeight.GetPercentValue() == 0.0f,
     727             :           "Non-zero percentage values not currently supported");
     728           4 :         aSize.height = 0;
     729           4 :         aHeightSet = true; // FIXME: should we really do this for
     730             :                               // nonzero values?
     731             :     }
     732             :     // calc() with percentage is treated like '0' (unset)
     733             : 
     734        1673 :     nsIContent* content = aBox->GetContent();
     735        1673 :     if (content && content->IsXULElement()) {
     736        3198 :         nsAutoString value;
     737             :         nsresult error;
     738             : 
     739        1599 :         content->GetAttr(kNameSpaceID_None, nsGkAtoms::minwidth, value);
     740        1599 :         if (!value.IsEmpty())
     741             :         {
     742           0 :             value.Trim("%");
     743             : 
     744             :             nscoord val =
     745           0 :               nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
     746           0 :             if (val > aSize.width)
     747           0 :               aSize.width = val;
     748           0 :             aWidthSet = true;
     749             :         }
     750             : 
     751        1599 :         content->GetAttr(kNameSpaceID_None, nsGkAtoms::minheight, value);
     752        1599 :         if (!value.IsEmpty())
     753             :         {
     754           0 :             value.Trim("%");
     755             : 
     756             :             nscoord val =
     757           0 :               nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
     758           0 :             if (val > aSize.height)
     759           0 :               aSize.height = val;
     760             : 
     761           0 :             aHeightSet = true;
     762             :         }
     763             :     }
     764             : 
     765        1673 :     return (aWidthSet && aHeightSet);
     766             : }
     767             : 
     768             : bool
     769        1311 : nsIFrame::AddXULMaxSize(nsIFrame* aBox, nsSize& aSize, bool &aWidthSet, bool &aHeightSet)
     770             : {
     771        1311 :     aWidthSet = false;
     772        1311 :     aHeightSet = false;
     773             : 
     774             :     // add in the css min, max, pref
     775        1311 :     const nsStylePosition* position = aBox->StylePosition();
     776             : 
     777             :     // and max
     778             :     // see if the width or height was specifically set
     779             :     // XXX Handle eStyleUnit_Enumerated?
     780             :     // (Handling the eStyleUnit_Enumerated types requires
     781             :     // GetXULPrefSize/GetXULMinSize methods that don't consider
     782             :     // (min-/max-/)(width/height) properties.)
     783        2622 :     const nsStyleCoord maxWidth = position->mMaxWidth;
     784        1311 :     if (maxWidth.ConvertsToLength()) {
     785         302 :         aSize.width = nsRuleNode::ComputeCoordPercentCalc(maxWidth, 0);
     786         302 :         aWidthSet = true;
     787             :     }
     788             :     // percentages and calc() with percentages are treated like 'none'
     789             : 
     790        1311 :     const nsStyleCoord &maxHeight = position->mMaxHeight;
     791        1311 :     if (maxHeight.ConvertsToLength()) {
     792           0 :         aSize.height = nsRuleNode::ComputeCoordPercentCalc(maxHeight, 0);
     793           0 :         aHeightSet = true;
     794             :     }
     795             :     // percentages and calc() with percentages are treated like 'none'
     796             : 
     797        1311 :     nsIContent* content = aBox->GetContent();
     798        1311 :     if (content && content->IsXULElement()) {
     799        2574 :         nsAutoString value;
     800             :         nsresult error;
     801             : 
     802        1287 :         content->GetAttr(kNameSpaceID_None, nsGkAtoms::maxwidth, value);
     803        1287 :         if (!value.IsEmpty()) {
     804           0 :             value.Trim("%");
     805             : 
     806             :             nscoord val =
     807           0 :               nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
     808           0 :             aSize.width = val;
     809           0 :             aWidthSet = true;
     810             :         }
     811             : 
     812        1287 :         content->GetAttr(kNameSpaceID_None, nsGkAtoms::maxheight, value);
     813        1287 :         if (!value.IsEmpty()) {
     814           0 :             value.Trim("%");
     815             : 
     816             :             nscoord val =
     817           0 :               nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
     818           0 :             aSize.height = val;
     819             : 
     820           0 :             aHeightSet = true;
     821             :         }
     822             :     }
     823             : 
     824        2622 :     return (aWidthSet || aHeightSet);
     825             : }
     826             : 
     827             : bool
     828         630 : nsIFrame::AddXULFlex(nsIFrame* aBox, nscoord& aFlex)
     829             : {
     830         630 :     bool flexSet = false;
     831             : 
     832             :     // get the flexibility
     833         630 :     aFlex = aBox->StyleXUL()->mBoxFlex;
     834             : 
     835             :     // attribute value overrides CSS
     836         630 :     nsIContent* content = aBox->GetContent();
     837         630 :     if (content && content->IsXULElement()) {
     838             :         nsresult error;
     839        1212 :         nsAutoString value;
     840             : 
     841         606 :         content->GetAttr(kNameSpaceID_None, nsGkAtoms::flex, value);
     842         606 :         if (!value.IsEmpty()) {
     843         157 :             value.Trim("%");
     844         157 :             aFlex = value.ToInteger(&error);
     845         157 :             flexSet = true;
     846             :         }
     847             :     }
     848             : 
     849         630 :     if (aFlex < 0)
     850           0 :       aFlex = 0;
     851         630 :     if (aFlex >= nscoord_MAX)
     852           0 :       aFlex = nscoord_MAX - 1;
     853             : 
     854         630 :     return flexSet || aFlex > 0;
     855             : }
     856             : 
     857             : void
     858        2541 : nsBox::AddBorderAndPadding(nsSize& aSize)
     859             : {
     860        2541 :   AddBorderAndPadding(this, aSize);
     861        2541 : }
     862             : 
     863             : void
     864        3614 : nsBox::AddBorderAndPadding(nsIFrame* aBox, nsSize& aSize)
     865             : {
     866        3614 :   nsMargin borderPadding(0,0,0,0);
     867        3614 :   aBox->GetXULBorderAndPadding(borderPadding);
     868        3614 :   AddMargin(aSize, borderPadding);
     869        3614 : }
     870             : 
     871             : void
     872        5592 : nsBox::AddMargin(nsIFrame* aChild, nsSize& aSize)
     873             : {
     874        5592 :   nsMargin margin(0,0,0,0);
     875        5592 :   aChild->GetXULMargin(margin);
     876        5592 :   AddMargin(aSize, margin);
     877        5592 : }
     878             : 
     879             : void
     880        9206 : nsBox::AddMargin(nsSize& aSize, const nsMargin& aMargin)
     881             : {
     882        9206 :   if (aSize.width != NS_INTRINSICSIZE)
     883        6242 :     aSize.width += aMargin.left + aMargin.right;
     884             : 
     885        9206 :   if (aSize.height != NS_INTRINSICSIZE)
     886        6100 :      aSize.height += aMargin.top + aMargin.bottom;
     887        9206 : }
     888             : 
     889             : nscoord
     890        3776 : nsBox::BoundsCheck(nscoord aMin, nscoord aPref, nscoord aMax)
     891             : {
     892        3776 :    if (aPref > aMax)
     893           0 :        aPref = aMax;
     894             : 
     895        3776 :    if (aPref < aMin)
     896          51 :        aPref = aMin;
     897             : 
     898        3776 :    return aPref;
     899             : }
     900             : 
     901             : nsSize
     902        2192 : nsBox::BoundsCheckMinMax(const nsSize& aMinSize, const nsSize& aMaxSize)
     903             : {
     904        4384 :   return nsSize(std::max(aMaxSize.width, aMinSize.width),
     905        6576 :                 std::max(aMaxSize.height, aMinSize.height));
     906             : }
     907             : 
     908             : nsSize
     909        1888 : nsBox::BoundsCheck(const nsSize& aMinSize, const nsSize& aPrefSize, const nsSize& aMaxSize)
     910             : {
     911        3776 :   return nsSize(BoundsCheck(aMinSize.width, aPrefSize.width, aMaxSize.width),
     912        5664 :                 BoundsCheck(aMinSize.height, aPrefSize.height, aMaxSize.height));
     913             : }
     914             : 
     915             : /*static*/ nsIFrame*
     916        3823 : nsBox::GetChildXULBox(const nsIFrame* aFrame)
     917             : {
     918             :   // box layout ends at box-wrapped frames, so don't allow these frames
     919             :   // to report child boxes.
     920        3823 :   return aFrame->IsXULBoxFrame() ? aFrame->PrincipalChildList().FirstChild() : nullptr;
     921             : }
     922             : 
     923             : /*static*/ nsIFrame*
     924        7468 : nsBox::GetNextXULBox(const nsIFrame* aFrame)
     925             : {
     926       14936 :   return aFrame->GetParent() &&
     927       14936 :     aFrame->GetParent()->IsXULBoxFrame() ? aFrame->GetNextSibling() : nullptr;
     928             : }
     929             : 
     930             : /*static*/ nsIFrame*
     931         967 : nsBox::GetParentXULBox(const nsIFrame* aFrame)
     932             : {
     933        1934 :   return aFrame->GetParent() &&
     934        1799 :     aFrame->GetParent()->IsXULBoxFrame() ? aFrame->GetParent() : nullptr;
     935             : }
     936             : 
     937             : #ifdef DEBUG_LAYOUT
     938             : nsresult
     939             : nsBox::SetXULDebug(nsBoxLayoutState& aState, bool aDebug)
     940             : {
     941             :     return NS_OK;
     942             : }
     943             : 
     944             : NS_IMETHODIMP
     945             : nsBox::GetDebugBoxAt( const nsPoint& aPoint,
     946             :                       nsIFrame**     aBox)
     947             : {
     948             :   nsRect thisRect(nsPoint(0,0), GetSize());
     949             :   if (!thisRect.Contains(aPoint))
     950             :     return NS_ERROR_FAILURE;
     951             : 
     952             :   nsIFrame* child = nsBox::GetChildXULBox(this);
     953             :   nsIFrame* hit = nullptr;
     954             : 
     955             :   *aBox = nullptr;
     956             :   while (nullptr != child) {
     957             :     nsresult rv = child->GetDebugBoxAt(aPoint - child->GetOffsetTo(this), &hit);
     958             : 
     959             :     if (NS_SUCCEEDED(rv) && hit) {
     960             :       *aBox = hit;
     961             :     }
     962             :     child = GetNextXULBox(child);
     963             :   }
     964             : 
     965             :   // found a child
     966             :   if (*aBox) {
     967             :     return NS_OK;
     968             :   }
     969             : 
     970             :   return NS_ERROR_FAILURE;
     971             : }
     972             : 
     973             : 
     974             : nsresult
     975             : nsBox::GetXULDebug(bool& aDebug)
     976             : {
     977             :   aDebug = false;
     978             :   return NS_OK;
     979             : }
     980             : 
     981             : #endif

Generated by: LCOV version 1.13