Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/xul/nsBox.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "nsBoxLayoutState.h"
8
#include "nsBox.h"
9
#include "nsBoxFrame.h"
10
#include "nsDOMAttributeMap.h"
11
#include "nsPresContext.h"
12
#include "nsCOMPtr.h"
13
#include "nsIContent.h"
14
#include "nsContainerFrame.h"
15
#include "nsNameSpaceManager.h"
16
#include "nsGkAtoms.h"
17
#include "nsITheme.h"
18
#include "nsIServiceManager.h"
19
#include "nsBoxLayout.h"
20
#include "FrameLayerBuilder.h"
21
#include "mozilla/dom/Attr.h"
22
#include "mozilla/dom/Element.h"
23
#include <algorithm>
24
25
using namespace mozilla;
26
27
nsresult
28
nsBox::BeginXULLayout(nsBoxLayoutState& aState)
29
0
{
30
0
  // mark ourselves as dirty so no child under us
31
0
  // can post an incremental layout.
32
0
  // XXXldb Is this still needed?
33
0
  AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
34
0
35
0
  if (GetStateBits() & NS_FRAME_IS_DIRTY)
36
0
  {
37
0
    // If the parent is dirty, all the children are dirty (ReflowInput
38
0
    // does this too).
39
0
    nsIFrame* box;
40
0
    for (box = GetChildXULBox(this); box; box = GetNextXULBox(box))
41
0
      box->AddStateBits(NS_FRAME_IS_DIRTY);
42
0
  }
43
0
44
0
  // Another copy-over from ReflowInput.
45
0
  // Since we are in reflow, we don't need to store these properties anymore.
46
0
  DeleteProperty(UsedBorderProperty());
47
0
  DeleteProperty(UsedPaddingProperty());
48
0
  DeleteProperty(UsedMarginProperty());
49
0
50
0
  return NS_OK;
51
0
}
52
53
NS_IMETHODIMP
54
nsBox::DoXULLayout(nsBoxLayoutState& aState)
55
0
{
56
0
  return NS_OK;
57
0
}
58
59
nsresult
60
nsBox::EndXULLayout(nsBoxLayoutState& aState)
61
0
{
62
0
  return SyncLayout(aState);
63
0
}
64
65
bool nsBox::gGotTheme = false;
66
StaticRefPtr<nsITheme> nsBox::gTheme;
67
68
nsBox::nsBox(ClassID aID)
69
  : nsIFrame(aID)
70
0
{
71
0
  MOZ_COUNT_CTOR(nsBox);
72
0
  if (!gGotTheme) {
73
0
    gTheme = do_GetNativeTheme();
74
0
    if (gTheme) {
75
0
      gGotTheme = true;
76
0
    }
77
0
  }
78
0
}
79
80
nsBox::~nsBox()
81
0
{
82
0
  // NOTE:  This currently doesn't get called for |nsBoxToBlockAdaptor|
83
0
  // objects, so don't rely on putting anything here.
84
0
  MOZ_COUNT_DTOR(nsBox);
85
0
}
86
87
/* static */ void
88
nsBox::Shutdown()
89
0
{
90
0
  gGotTheme = false;
91
0
  gTheme = nullptr;
92
0
}
93
94
nsresult
95
nsBox::XULRelayoutChildAtOrdinal(nsIFrame* aChild)
96
0
{
97
0
  return NS_OK;
98
0
}
99
100
nsresult
101
nsIFrame::GetXULClientRect(nsRect& aClientRect)
102
0
{
103
0
  aClientRect = mRect;
104
0
  aClientRect.MoveTo(0,0);
105
0
106
0
  nsMargin borderPadding;
107
0
  GetXULBorderAndPadding(borderPadding);
108
0
109
0
  aClientRect.Deflate(borderPadding);
110
0
111
0
  if (aClientRect.width < 0)
112
0
     aClientRect.width = 0;
113
0
114
0
  if (aClientRect.height < 0)
115
0
     aClientRect.height = 0;
116
0
117
0
  return NS_OK;
118
0
}
119
120
void
121
nsBox::SetXULBounds(nsBoxLayoutState& aState, const nsRect& aRect, bool aRemoveOverflowAreas)
122
0
{
123
0
    nsRect rect(mRect);
124
0
125
0
    uint32_t flags = GetXULLayoutFlags();
126
0
127
0
    uint32_t stateFlags = aState.LayoutFlags();
128
0
129
0
    flags |= stateFlags;
130
0
131
0
    if ((flags & NS_FRAME_NO_MOVE_FRAME) == NS_FRAME_NO_MOVE_FRAME)
132
0
      SetSize(aRect.Size());
133
0
    else
134
0
      SetRect(aRect);
135
0
136
0
    // Nuke the overflow area. The caller is responsible for restoring
137
0
    // it if necessary.
138
0
    if (aRemoveOverflowAreas) {
139
0
      // remove the previously stored overflow area
140
0
      ClearOverflowRects();
141
0
    }
142
0
143
0
    if (!(flags & NS_FRAME_NO_MOVE_VIEW))
144
0
    {
145
0
      nsContainerFrame::PositionFrameView(this);
146
0
      if ((rect.x != aRect.x) || (rect.y != aRect.y))
147
0
        nsContainerFrame::PositionChildViews(this);
148
0
    }
149
0
}
150
151
nsresult
152
nsIFrame::GetXULBorderAndPadding(nsMargin& aBorderAndPadding)
153
0
{
154
0
  aBorderAndPadding.SizeTo(0, 0, 0, 0);
155
0
  nsresult rv = GetXULBorder(aBorderAndPadding);
156
0
  if (NS_FAILED(rv))
157
0
    return rv;
158
0
159
0
  nsMargin padding;
160
0
  rv = GetXULPadding(padding);
161
0
  if (NS_FAILED(rv))
162
0
    return rv;
163
0
164
0
  aBorderAndPadding += padding;
165
0
166
0
  return rv;
167
0
}
168
169
nsresult
170
nsBox::GetXULBorder(nsMargin& aMargin)
171
0
{
172
0
  aMargin.SizeTo(0,0,0,0);
173
0
174
0
  const nsStyleDisplay* disp = StyleDisplay();
175
0
  if (disp->HasAppearance() && gTheme) {
176
0
    // Go to the theme for the border.
177
0
    nsPresContext *context = PresContext();
178
0
    if (gTheme->ThemeSupportsWidget(context, this, disp->mAppearance)) {
179
0
      LayoutDeviceIntMargin margin =
180
0
        gTheme->GetWidgetBorder(context->DeviceContext(), this,
181
0
                                disp->mAppearance);
182
0
      aMargin = LayoutDevicePixel::ToAppUnits(margin,
183
0
                                              context->AppUnitsPerDevPixel());
184
0
      return NS_OK;
185
0
    }
186
0
  }
187
0
188
0
  aMargin = StyleBorder()->GetComputedBorder();
189
0
190
0
  return NS_OK;
191
0
}
192
193
nsresult
194
nsBox::GetXULPadding(nsMargin& aPadding)
195
0
{
196
0
  const nsStyleDisplay *disp = StyleDisplay();
197
0
  if (disp->HasAppearance() && gTheme) {
198
0
    // Go to the theme for the padding.
199
0
    nsPresContext *context = PresContext();
200
0
    if (gTheme->ThemeSupportsWidget(context, this, disp->mAppearance)) {
201
0
      LayoutDeviceIntMargin padding;
202
0
      bool useThemePadding =
203
0
        gTheme->GetWidgetPadding(context->DeviceContext(),
204
0
                                 this, disp->mAppearance, &padding);
205
0
      if (useThemePadding) {
206
0
        aPadding = LayoutDevicePixel::ToAppUnits(padding,
207
0
                                                context->AppUnitsPerDevPixel());
208
0
        return NS_OK;
209
0
      }
210
0
    }
211
0
  }
212
0
213
0
  aPadding.SizeTo(0,0,0,0);
214
0
  StylePadding()->GetPadding(aPadding);
215
0
216
0
  return NS_OK;
217
0
}
218
219
nsresult
220
nsBox::GetXULMargin(nsMargin& aMargin)
221
0
{
222
0
  aMargin.SizeTo(0,0,0,0);
223
0
  StyleMargin()->GetMargin(aMargin);
224
0
225
0
  return NS_OK;
226
0
}
227
228
void
229
nsBox::SizeNeedsRecalc(nsSize& aSize)
230
0
{
231
0
  aSize.width  = -1;
232
0
  aSize.height = -1;
233
0
}
234
235
void
236
nsBox::CoordNeedsRecalc(nscoord& aFlex)
237
0
{
238
0
  aFlex = -1;
239
0
}
240
241
bool
242
nsBox::DoesNeedRecalc(const nsSize& aSize)
243
0
{
244
0
  return (aSize.width == -1 || aSize.height == -1);
245
0
}
246
247
bool
248
nsBox::DoesNeedRecalc(nscoord aCoord)
249
0
{
250
0
  return (aCoord == -1);
251
0
}
252
253
nsSize
254
nsBox::GetXULPrefSize(nsBoxLayoutState& aState)
255
0
{
256
0
  NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context");
257
0
258
0
  nsSize pref(0,0);
259
0
  DISPLAY_PREF_SIZE(this, pref);
260
0
261
0
  if (IsXULCollapsed())
262
0
    return pref;
263
0
264
0
  AddBorderAndPadding(pref);
265
0
  bool widthSet, heightSet;
266
0
  nsIFrame::AddXULPrefSize(this, pref, widthSet, heightSet);
267
0
268
0
  nsSize minSize = GetXULMinSize(aState);
269
0
  nsSize maxSize = GetXULMaxSize(aState);
270
0
  return BoundsCheck(minSize, pref, maxSize);
271
0
}
272
273
nsSize
274
nsBox::GetXULMinSize(nsBoxLayoutState& aState)
275
0
{
276
0
  NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context");
277
0
278
0
  nsSize min(0,0);
279
0
  DISPLAY_MIN_SIZE(this, min);
280
0
281
0
  if (IsXULCollapsed())
282
0
    return min;
283
0
284
0
  AddBorderAndPadding(min);
285
0
  bool widthSet, heightSet;
286
0
  nsIFrame::AddXULMinSize(aState, this, min, widthSet, heightSet);
287
0
  return min;
288
0
}
289
290
nsSize
291
nsBox::GetXULMinSizeForScrollArea(nsBoxLayoutState& aBoxLayoutState)
292
0
{
293
0
  return nsSize(0, 0);
294
0
}
295
296
nsSize
297
nsBox::GetXULMaxSize(nsBoxLayoutState& aState)
298
0
{
299
0
  NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context");
300
0
301
0
  nsSize maxSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
302
0
  DISPLAY_MAX_SIZE(this, maxSize);
303
0
304
0
  if (IsXULCollapsed())
305
0
    return maxSize;
306
0
307
0
  AddBorderAndPadding(maxSize);
308
0
  bool widthSet, heightSet;
309
0
  nsIFrame::AddXULMaxSize(this, maxSize, widthSet, heightSet);
310
0
  return maxSize;
311
0
}
312
313
nscoord
314
nsBox::GetXULFlex()
315
0
{
316
0
  nscoord flex = 0;
317
0
318
0
  nsIFrame::AddXULFlex(this, flex);
319
0
320
0
  return flex;
321
0
}
322
323
uint32_t
324
nsIFrame::GetXULOrdinal()
325
0
{
326
0
  uint32_t ordinal = StyleXUL()->mBoxOrdinal;
327
0
328
0
  // When present, attribute value overrides CSS.
329
0
  nsIContent* content = GetContent();
330
0
  if (content && content->IsXULElement()) {
331
0
    nsresult error;
332
0
    nsAutoString value;
333
0
334
0
    content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::ordinal, value);
335
0
    if (!value.IsEmpty()) {
336
0
      ordinal = value.ToInteger(&error);
337
0
    }
338
0
  }
339
0
340
0
  return ordinal;
341
0
}
342
343
nscoord
344
nsBox::GetXULBoxAscent(nsBoxLayoutState& aState)
345
0
{
346
0
  if (IsXULCollapsed())
347
0
    return 0;
348
0
349
0
  return GetXULPrefSize(aState).height;
350
0
}
351
352
bool
353
nsBox::IsXULCollapsed()
354
0
{
355
0
  return StyleVisibility()->mVisible == NS_STYLE_VISIBILITY_COLLAPSE;
356
0
}
357
358
nsresult
359
nsIFrame::XULLayout(nsBoxLayoutState& aState)
360
0
{
361
0
  NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context");
362
0
363
0
  nsBox *box = static_cast<nsBox*>(this);
364
0
  DISPLAY_LAYOUT(box);
365
0
366
0
  box->BeginXULLayout(aState);
367
0
368
0
  box->DoXULLayout(aState);
369
0
370
0
  box->EndXULLayout(aState);
371
0
372
0
  return NS_OK;
373
0
}
374
375
bool
376
nsBox::DoesClipChildren()
377
0
{
378
0
  const nsStyleDisplay* display = StyleDisplay();
379
0
  NS_ASSERTION((display->mOverflowY == NS_STYLE_OVERFLOW_CLIP) ==
380
0
               (display->mOverflowX == NS_STYLE_OVERFLOW_CLIP),
381
0
               "If one overflow is clip, the other should be too");
382
0
  return display->mOverflowX == NS_STYLE_OVERFLOW_CLIP;
383
0
}
384
385
nsresult
386
nsBox::SyncLayout(nsBoxLayoutState& aState)
387
0
{
388
0
  /*
389
0
  if (IsXULCollapsed()) {
390
0
    CollapseChild(aState, this, true);
391
0
    return NS_OK;
392
0
  }
393
0
  */
394
0
395
0
396
0
  if (GetStateBits() & NS_FRAME_IS_DIRTY)
397
0
     XULRedraw(aState);
398
0
399
0
  RemoveStateBits(NS_FRAME_HAS_DIRTY_CHILDREN | NS_FRAME_IS_DIRTY
400
0
                  | NS_FRAME_FIRST_REFLOW | NS_FRAME_IN_REFLOW);
401
0
402
0
  nsPresContext* presContext = aState.PresContext();
403
0
404
0
  uint32_t flags = GetXULLayoutFlags();
405
0
406
0
  uint32_t stateFlags = aState.LayoutFlags();
407
0
408
0
  flags |= stateFlags;
409
0
410
0
  nsRect visualOverflow;
411
0
412
0
  if (ComputesOwnOverflowArea()) {
413
0
    visualOverflow = GetVisualOverflowRect();
414
0
  }
415
0
  else {
416
0
    nsRect rect(nsPoint(0, 0), GetSize());
417
0
    nsOverflowAreas overflowAreas(rect, rect);
418
0
    if (!DoesClipChildren() && !IsXULCollapsed()) {
419
0
      // See if our child frames caused us to overflow after being laid
420
0
      // out. If so, store the overflow area.  This normally can't happen
421
0
      // in XUL, but it can happen with the CSS 'outline' property and
422
0
      // possibly with other exotic stuff (e.g. relatively positioned
423
0
      // frames in HTML inside XUL).
424
0
      nsLayoutUtils::UnionChildOverflow(this, overflowAreas);
425
0
    }
426
0
427
0
    FinishAndStoreOverflow(overflowAreas, GetSize());
428
0
    visualOverflow = overflowAreas.VisualOverflow();
429
0
  }
430
0
431
0
  nsView* view = GetView();
432
0
  if (view) {
433
0
    // Make sure the frame's view is properly sized and positioned and has
434
0
    // things like opacity correct
435
0
    nsContainerFrame::SyncFrameViewAfterReflow(presContext, this, view,
436
0
                                               visualOverflow, flags);
437
0
  }
438
0
439
0
  return NS_OK;
440
0
}
441
442
nsresult
443
nsIFrame::XULRedraw(nsBoxLayoutState& aState)
444
0
{
445
0
  if (aState.PaintingDisabled())
446
0
    return NS_OK;
447
0
448
0
  // nsStackLayout, at least, expects us to repaint descendants even
449
0
  // if a damage rect is provided
450
0
  InvalidateFrameSubtree();
451
0
452
0
  return NS_OK;
453
0
}
454
455
bool
456
nsIFrame::AddXULPrefSize(nsIFrame* aBox, nsSize& aSize, bool &aWidthSet, bool &aHeightSet)
457
0
{
458
0
    aWidthSet = false;
459
0
    aHeightSet = false;
460
0
461
0
    // add in the css min, max, pref
462
0
    const nsStylePosition* position = aBox->StylePosition();
463
0
464
0
    // see if the width or height was specifically set
465
0
    // XXX Handle eStyleUnit_Enumerated?
466
0
    // (Handling the eStyleUnit_Enumerated types requires
467
0
    // GetXULPrefSize/GetXULMinSize methods that don't consider
468
0
    // (min-/max-/)(width/height) properties.)
469
0
    const nsStyleCoord &width = position->mWidth;
470
0
    if (width.GetUnit() == eStyleUnit_Coord) {
471
0
        aSize.width = width.GetCoordValue();
472
0
        aWidthSet = true;
473
0
    } else if (width.IsCalcUnit()) {
474
0
        if (!width.CalcHasPercent()) {
475
0
            // pass 0 for percentage basis since we know there are no %s
476
0
            aSize.width = width.ComputeComputedCalc(0);
477
0
            if (aSize.width < 0)
478
0
                aSize.width = 0;
479
0
            aWidthSet = true;
480
0
        }
481
0
    }
482
0
483
0
    const nsStyleCoord &height = position->mHeight;
484
0
    if (height.GetUnit() == eStyleUnit_Coord) {
485
0
        aSize.height = height.GetCoordValue();
486
0
        aHeightSet = true;
487
0
    } else if (height.IsCalcUnit()) {
488
0
        if (!height.CalcHasPercent()) {
489
0
            // pass 0 for percentage basis since we know there are no %s
490
0
            aSize.height = height.ComputeComputedCalc(0);
491
0
            if (aSize.height < 0)
492
0
                aSize.height = 0;
493
0
            aHeightSet = true;
494
0
        }
495
0
    }
496
0
497
0
    nsIContent* content = aBox->GetContent();
498
0
    // ignore 'height' and 'width' attributes if the actual element is not XUL
499
0
    // For example, we might be magic XUL frames whose primary content is an HTML
500
0
    // <select>
501
0
    if (content && content->IsXULElement()) {
502
0
        nsAutoString value;
503
0
        nsresult error;
504
0
505
0
        content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::width, value);
506
0
        if (!value.IsEmpty()) {
507
0
            value.Trim("%");
508
0
509
0
            aSize.width =
510
0
              nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
511
0
            aWidthSet = true;
512
0
        }
513
0
514
0
        content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::height, value);
515
0
        if (!value.IsEmpty()) {
516
0
            value.Trim("%");
517
0
518
0
            aSize.height =
519
0
              nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
520
0
            aHeightSet = true;
521
0
        }
522
0
    }
523
0
524
0
    return (aWidthSet && aHeightSet);
525
0
}
526
527
// This returns the scrollbar width we want to use when either native
528
// theme is disabled, or the native theme claims that it doesn't support
529
// scrollbar.
530
static nscoord
531
GetScrollbarWidthNoTheme(nsIFrame* aBox)
532
{
533
    ComputedStyle* scrollbarStyle = nsLayoutUtils::StyleForScrollbar(aBox);
534
    switch (scrollbarStyle->StyleUIReset()->mScrollbarWidth) {
535
      default:
536
      case StyleScrollbarWidth::Auto:
537
        return 12 * AppUnitsPerCSSPixel();
538
      case StyleScrollbarWidth::Thin:
539
        return 6 * AppUnitsPerCSSPixel();
540
      case StyleScrollbarWidth::None:
541
        return 0;
542
    }
543
}
544
545
bool
546
nsIFrame::AddXULMinSize(nsBoxLayoutState& aState, nsIFrame* aBox, nsSize& aSize,
547
                      bool &aWidthSet, bool &aHeightSet)
548
0
{
549
0
    aWidthSet = false;
550
0
    aHeightSet = false;
551
0
552
0
    bool canOverride = true;
553
0
554
0
    // See if a native theme wants to supply a minimum size.
555
0
    const nsStyleDisplay* display = aBox->StyleDisplay();
556
0
    if (display->HasAppearance()) {
557
0
      nsITheme *theme = aState.PresContext()->GetTheme();
558
0
      if (theme && theme->ThemeSupportsWidget(aState.PresContext(), aBox, display->mAppearance)) {
559
0
        LayoutDeviceIntSize size;
560
0
        theme->GetMinimumWidgetSize(aState.PresContext(), aBox,
561
0
                                    display->mAppearance, &size, &canOverride);
562
0
        if (size.width) {
563
0
          aSize.width = aState.PresContext()->DevPixelsToAppUnits(size.width);
564
0
          aWidthSet = true;
565
0
        }
566
0
        if (size.height) {
567
0
          aSize.height = aState.PresContext()->DevPixelsToAppUnits(size.height);
568
0
          aHeightSet = true;
569
0
        }
570
0
      } else {
571
0
        switch (display->mAppearance) {
572
0
          case StyleAppearance::ScrollbarVertical:
573
0
            aSize.width = GetScrollbarWidthNoTheme(aBox);
574
0
            aWidthSet = true;
575
0
            break;
576
0
          case StyleAppearance::ScrollbarHorizontal:
577
0
            aSize.height = GetScrollbarWidthNoTheme(aBox);
578
0
            aHeightSet = true;
579
0
            break;
580
0
          default:
581
0
            break;
582
0
        }
583
0
      }
584
0
    }
585
0
586
0
    // add in the css min, max, pref
587
0
    const nsStylePosition* position = aBox->StylePosition();
588
0
589
0
    // same for min size. Unfortunately min size is always set to 0. So for now
590
0
    // we will assume 0 (as a coord) means not set.
591
0
    const nsStyleCoord &minWidth = position->mMinWidth;
592
0
    if ((minWidth.GetUnit() == eStyleUnit_Coord &&
593
0
         minWidth.GetCoordValue() != 0) ||
594
0
        (minWidth.IsCalcUnit() && !minWidth.CalcHasPercent())) {
595
0
        nscoord min = minWidth.ComputeCoordPercentCalc(0);
596
0
        if (!aWidthSet || (min > aSize.width && canOverride)) {
597
0
           aSize.width = min;
598
0
           aWidthSet = true;
599
0
        }
600
0
    } else if (minWidth.GetUnit() == eStyleUnit_Percent) {
601
0
        NS_ASSERTION(minWidth.GetPercentValue() == 0.0f,
602
0
          "Non-zero percentage values not currently supported");
603
0
        aSize.width = 0;
604
0
        aWidthSet = true; // FIXME: should we really do this for
605
0
                             // nonzero values?
606
0
    }
607
0
    // XXX Handle eStyleUnit_Enumerated?
608
0
    // (Handling the eStyleUnit_Enumerated types requires
609
0
    // GetXULPrefSize/GetXULMinSize methods that don't consider
610
0
    // (min-/max-/)(width/height) properties.
611
0
    // calc() with percentage is treated like '0' (unset)
612
0
613
0
    const nsStyleCoord &minHeight = position->mMinHeight;
614
0
    if ((minHeight.GetUnit() == eStyleUnit_Coord &&
615
0
         minHeight.GetCoordValue() != 0) ||
616
0
        (minHeight.IsCalcUnit() && !minHeight.CalcHasPercent())) {
617
0
        nscoord min = minHeight.ComputeCoordPercentCalc(0);
618
0
        if (!aHeightSet || (min > aSize.height && canOverride)) {
619
0
           aSize.height = min;
620
0
           aHeightSet = true;
621
0
        }
622
0
    } else if (minHeight.GetUnit() == eStyleUnit_Percent) {
623
0
        NS_ASSERTION(position->mMinHeight.GetPercentValue() == 0.0f,
624
0
          "Non-zero percentage values not currently supported");
625
0
        aSize.height = 0;
626
0
        aHeightSet = true; // FIXME: should we really do this for
627
0
                              // nonzero values?
628
0
    }
629
0
    // calc() with percentage is treated like '0' (unset)
630
0
631
0
    nsIContent* content = aBox->GetContent();
632
0
    if (content && content->IsXULElement()) {
633
0
        nsAutoString value;
634
0
        nsresult error;
635
0
636
0
        content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::minwidth, value);
637
0
        if (!value.IsEmpty())
638
0
        {
639
0
            value.Trim("%");
640
0
641
0
            nscoord val =
642
0
              nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
643
0
            if (val > aSize.width)
644
0
              aSize.width = val;
645
0
            aWidthSet = true;
646
0
        }
647
0
648
0
        content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::minheight, value);
649
0
        if (!value.IsEmpty())
650
0
        {
651
0
            value.Trim("%");
652
0
653
0
            nscoord val =
654
0
              nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
655
0
            if (val > aSize.height)
656
0
              aSize.height = val;
657
0
658
0
            aHeightSet = true;
659
0
        }
660
0
    }
661
0
662
0
    return (aWidthSet && aHeightSet);
663
0
}
664
665
bool
666
nsIFrame::AddXULMaxSize(nsIFrame* aBox, nsSize& aSize, bool &aWidthSet, bool &aHeightSet)
667
0
{
668
0
    aWidthSet = false;
669
0
    aHeightSet = false;
670
0
671
0
    // add in the css min, max, pref
672
0
    const nsStylePosition* position = aBox->StylePosition();
673
0
674
0
    // and max
675
0
    // see if the width or height was specifically set
676
0
    // XXX Handle eStyleUnit_Enumerated?
677
0
    // (Handling the eStyleUnit_Enumerated types requires
678
0
    // GetXULPrefSize/GetXULMinSize methods that don't consider
679
0
    // (min-/max-/)(width/height) properties.)
680
0
    const nsStyleCoord maxWidth = position->mMaxWidth;
681
0
    if (maxWidth.ConvertsToLength()) {
682
0
        aSize.width = maxWidth.ComputeCoordPercentCalc(0);
683
0
        aWidthSet = true;
684
0
    }
685
0
    // percentages and calc() with percentages are treated like 'none'
686
0
687
0
    const nsStyleCoord &maxHeight = position->mMaxHeight;
688
0
    if (maxHeight.ConvertsToLength()) {
689
0
        aSize.height = maxHeight.ComputeCoordPercentCalc(0);
690
0
        aHeightSet = true;
691
0
    }
692
0
    // percentages and calc() with percentages are treated like 'none'
693
0
694
0
    nsIContent* content = aBox->GetContent();
695
0
    if (content && content->IsXULElement()) {
696
0
        nsAutoString value;
697
0
        nsresult error;
698
0
699
0
        content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::maxwidth, value);
700
0
        if (!value.IsEmpty()) {
701
0
            value.Trim("%");
702
0
703
0
            nscoord val =
704
0
              nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
705
0
            aSize.width = val;
706
0
            aWidthSet = true;
707
0
        }
708
0
709
0
        content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::maxheight, value);
710
0
        if (!value.IsEmpty()) {
711
0
            value.Trim("%");
712
0
713
0
            nscoord val =
714
0
              nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
715
0
            aSize.height = val;
716
0
717
0
            aHeightSet = true;
718
0
        }
719
0
    }
720
0
721
0
    return (aWidthSet || aHeightSet);
722
0
}
723
724
bool
725
nsIFrame::AddXULFlex(nsIFrame* aBox, nscoord& aFlex)
726
0
{
727
0
    bool flexSet = false;
728
0
729
0
    // get the flexibility
730
0
    aFlex = aBox->StyleXUL()->mBoxFlex;
731
0
732
0
    // attribute value overrides CSS
733
0
    nsIContent* content = aBox->GetContent();
734
0
    if (content && content->IsXULElement()) {
735
0
        nsresult error;
736
0
        nsAutoString value;
737
0
738
0
        content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::flex, value);
739
0
        if (!value.IsEmpty()) {
740
0
            value.Trim("%");
741
0
            aFlex = value.ToInteger(&error);
742
0
            flexSet = true;
743
0
        }
744
0
    }
745
0
746
0
    if (aFlex < 0)
747
0
      aFlex = 0;
748
0
    if (aFlex >= nscoord_MAX)
749
0
      aFlex = nscoord_MAX - 1;
750
0
751
0
    return flexSet || aFlex > 0;
752
0
}
753
754
void
755
nsBox::AddBorderAndPadding(nsSize& aSize)
756
0
{
757
0
  AddBorderAndPadding(this, aSize);
758
0
}
759
760
void
761
nsBox::AddBorderAndPadding(nsIFrame* aBox, nsSize& aSize)
762
0
{
763
0
  nsMargin borderPadding(0,0,0,0);
764
0
  aBox->GetXULBorderAndPadding(borderPadding);
765
0
  AddMargin(aSize, borderPadding);
766
0
}
767
768
void
769
nsBox::AddMargin(nsIFrame* aChild, nsSize& aSize)
770
0
{
771
0
  nsMargin margin(0,0,0,0);
772
0
  aChild->GetXULMargin(margin);
773
0
  AddMargin(aSize, margin);
774
0
}
775
776
void
777
nsBox::AddMargin(nsSize& aSize, const nsMargin& aMargin)
778
0
{
779
0
  if (aSize.width != NS_INTRINSICSIZE)
780
0
    aSize.width += aMargin.left + aMargin.right;
781
0
782
0
  if (aSize.height != NS_INTRINSICSIZE)
783
0
     aSize.height += aMargin.top + aMargin.bottom;
784
0
}
785
786
nscoord
787
nsBox::BoundsCheck(nscoord aMin, nscoord aPref, nscoord aMax)
788
0
{
789
0
   if (aPref > aMax)
790
0
       aPref = aMax;
791
0
792
0
   if (aPref < aMin)
793
0
       aPref = aMin;
794
0
795
0
   return aPref;
796
0
}
797
798
nsSize
799
nsBox::BoundsCheckMinMax(const nsSize& aMinSize, const nsSize& aMaxSize)
800
0
{
801
0
  return nsSize(std::max(aMaxSize.width, aMinSize.width),
802
0
                std::max(aMaxSize.height, aMinSize.height));
803
0
}
804
805
nsSize
806
nsBox::BoundsCheck(const nsSize& aMinSize, const nsSize& aPrefSize, const nsSize& aMaxSize)
807
0
{
808
0
  return nsSize(BoundsCheck(aMinSize.width, aPrefSize.width, aMaxSize.width),
809
0
                BoundsCheck(aMinSize.height, aPrefSize.height, aMaxSize.height));
810
0
}
811
812
/*static*/ nsIFrame*
813
nsBox::GetChildXULBox(const nsIFrame* aFrame)
814
0
{
815
0
  // box layout ends at box-wrapped frames, so don't allow these frames
816
0
  // to report child boxes.
817
0
  return aFrame->IsXULBoxFrame() ? aFrame->PrincipalChildList().FirstChild() : nullptr;
818
0
}
819
820
/*static*/ nsIFrame*
821
nsBox::GetNextXULBox(const nsIFrame* aFrame)
822
0
{
823
0
  return aFrame->GetParent() &&
824
0
    aFrame->GetParent()->IsXULBoxFrame() ? aFrame->GetNextSibling() : nullptr;
825
0
}
826
827
/*static*/ nsIFrame*
828
nsBox::GetParentXULBox(const nsIFrame* aFrame)
829
0
{
830
0
  return aFrame->GetParent() &&
831
0
    aFrame->GetParent()->IsXULBoxFrame() ? aFrame->GetParent() : nullptr;
832
0
}
833