~ubuntu-branches/ubuntu/raring/qtwebkit-source/raring-proposed

« back to all changes in this revision

Viewing changes to Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-02-18 14:24:18 UTC
  • Revision ID: package-import@ubuntu.com-20130218142418-eon0jmjg3nj438uy
Tags: upstream-2.3
ImportĀ upstreamĀ versionĀ 2.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of the render object implementation for KHTML.
 
3
 *
 
4
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 
5
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 
6
 * Copyright (C) 2003 Apple Computer, Inc.
 
7
 *
 
8
 * This library is free software; you can redistribute it and/or
 
9
 * modify it under the terms of the GNU Library General Public
 
10
 * License as published by the Free Software Foundation; either
 
11
 * version 2 of the License, or (at your option) any later version.
 
12
 *
 
13
 * This library is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
16
 * Library General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU Library General Public License
 
19
 * along with this library; see the file COPYING.LIB.  If not, write to
 
20
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
21
 * Boston, MA 02110-1301, USA.
 
22
 *
 
23
 */
 
24
 
 
25
#include "config.h"
 
26
#include "RenderDeprecatedFlexibleBox.h"
 
27
 
 
28
#include "Font.h"
 
29
#include "LayoutRepainter.h"
 
30
#include "RenderLayer.h"
 
31
#include "RenderView.h"
 
32
#include <wtf/StdLibExtras.h>
 
33
#include <wtf/unicode/CharacterNames.h>
 
34
 
 
35
using namespace std;
 
36
 
 
37
namespace WebCore {
 
38
 
 
39
class FlexBoxIterator {
 
40
public:
 
41
    FlexBoxIterator(RenderDeprecatedFlexibleBox* parent)
 
42
        : m_box(parent)
 
43
        , m_largestOrdinal(1)
 
44
    {
 
45
        if (m_box->style()->boxOrient() == HORIZONTAL && !m_box->style()->isLeftToRightDirection())
 
46
            m_forward = m_box->style()->boxDirection() != BNORMAL;
 
47
        else
 
48
            m_forward = m_box->style()->boxDirection() == BNORMAL;
 
49
        if (!m_forward) {
 
50
            // No choice, since we're going backwards, we have to find out the highest ordinal up front.
 
51
            RenderBox* child = m_box->firstChildBox();
 
52
            while (child) {
 
53
                if (child->style()->boxOrdinalGroup() > m_largestOrdinal)
 
54
                    m_largestOrdinal = child->style()->boxOrdinalGroup();
 
55
                child = child->nextSiblingBox();
 
56
            }
 
57
        }
 
58
 
 
59
        reset();
 
60
    }
 
61
 
 
62
    void reset()
 
63
    {
 
64
        m_currentChild = 0;
 
65
        m_ordinalIteration = -1;
 
66
    }
 
67
 
 
68
    RenderBox* first()
 
69
    {
 
70
        reset();
 
71
        return next();
 
72
    }
 
73
 
 
74
    RenderBox* next()
 
75
    {
 
76
        do {
 
77
            if (!m_currentChild) {
 
78
                ++m_ordinalIteration;
 
79
 
 
80
                if (!m_ordinalIteration)
 
81
                    m_currentOrdinal = m_forward ? 1 : m_largestOrdinal;
 
82
                else {
 
83
                    if (m_ordinalIteration >= m_ordinalValues.size() + 1)
 
84
                        return 0;
 
85
 
 
86
                    // Only copy+sort the values once per layout even if the iterator is reset.
 
87
                    if (static_cast<size_t>(m_ordinalValues.size()) != m_sortedOrdinalValues.size()) {
 
88
                        copyToVector(m_ordinalValues, m_sortedOrdinalValues);
 
89
                        sort(m_sortedOrdinalValues.begin(), m_sortedOrdinalValues.end());
 
90
                    }
 
91
                    m_currentOrdinal = m_forward ? m_sortedOrdinalValues[m_ordinalIteration - 1] : m_sortedOrdinalValues[m_sortedOrdinalValues.size() - m_ordinalIteration];
 
92
                }
 
93
 
 
94
                m_currentChild = m_forward ? m_box->firstChildBox() : m_box->lastChildBox();
 
95
            } else
 
96
                m_currentChild = m_forward ? m_currentChild->nextSiblingBox() : m_currentChild->previousSiblingBox();
 
97
 
 
98
            if (m_currentChild && notFirstOrdinalValue())
 
99
                m_ordinalValues.add(m_currentChild->style()->boxOrdinalGroup());
 
100
        } while (!m_currentChild || (!m_currentChild->isAnonymous()
 
101
                 && m_currentChild->style()->boxOrdinalGroup() != m_currentOrdinal));
 
102
        return m_currentChild;
 
103
    }
 
104
 
 
105
private:
 
106
    bool notFirstOrdinalValue()
 
107
    {
 
108
        unsigned int firstOrdinalValue = m_forward ? 1 : m_largestOrdinal;
 
109
        return m_currentOrdinal == firstOrdinalValue && m_currentChild->style()->boxOrdinalGroup() != firstOrdinalValue;
 
110
    }
 
111
 
 
112
    RenderDeprecatedFlexibleBox* m_box;
 
113
    RenderBox* m_currentChild;
 
114
    bool m_forward;
 
115
    unsigned int m_currentOrdinal;
 
116
    unsigned int m_largestOrdinal;
 
117
    HashSet<unsigned int> m_ordinalValues;
 
118
    Vector<unsigned int> m_sortedOrdinalValues;
 
119
    int m_ordinalIteration;
 
120
};
 
121
 
 
122
RenderDeprecatedFlexibleBox::RenderDeprecatedFlexibleBox(Node* node)
 
123
    : RenderBlock(node)
 
124
{
 
125
    setChildrenInline(false); // All of our children must be block-level
 
126
    m_stretchingChildren = false;
 
127
}
 
128
 
 
129
RenderDeprecatedFlexibleBox::~RenderDeprecatedFlexibleBox()
 
130
{
 
131
}
 
132
 
 
133
static LayoutUnit marginWidthForChild(RenderBox* child)
 
134
{
 
135
    // A margin basically has three types: fixed, percentage, and auto (variable).
 
136
    // Auto and percentage margins simply become 0 when computing min/max width.
 
137
    // Fixed margins can be added in as is.
 
138
    Length marginLeft = child->style()->marginLeft();
 
139
    Length marginRight = child->style()->marginRight();
 
140
    LayoutUnit margin = 0;
 
141
    if (marginLeft.isFixed())
 
142
        margin += marginLeft.value();
 
143
    if (marginRight.isFixed())
 
144
        margin += marginRight.value();
 
145
    return margin;
 
146
}
 
147
 
 
148
static bool childDoesNotAffectWidthOrFlexing(RenderObject* child)
 
149
{
 
150
    // Positioned children and collapsed children don't affect the min/max width.
 
151
    return child->isOutOfFlowPositioned() || child->style()->visibility() == COLLAPSE;
 
152
}
 
153
 
 
154
static LayoutUnit contentWidthForChild(RenderBox* child)
 
155
{
 
156
    if (child->hasOverrideWidth())
 
157
        return child->overrideLogicalContentWidth();
 
158
    return child->logicalWidth() - child->borderAndPaddingLogicalWidth();
 
159
}
 
160
 
 
161
static LayoutUnit contentHeightForChild(RenderBox* child)
 
162
{
 
163
    if (child->hasOverrideHeight())
 
164
        return child->overrideLogicalContentHeight();
 
165
    return child->logicalHeight() - child->borderAndPaddingLogicalHeight();
 
166
}
 
167
 
 
168
void RenderDeprecatedFlexibleBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
 
169
{
 
170
    RenderStyle* oldStyle = style();
 
171
    if (oldStyle && !oldStyle->lineClamp().isNone() && newStyle->lineClamp().isNone())
 
172
        clearLineClamp();
 
173
 
 
174
    RenderBlock::styleWillChange(diff, newStyle);
 
175
}
 
176
 
 
177
void RenderDeprecatedFlexibleBox::calcHorizontalPrefWidths()
 
178
{
 
179
    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
 
180
        if (childDoesNotAffectWidthOrFlexing(child))
 
181
            continue;
 
182
 
 
183
        LayoutUnit margin = marginWidthForChild(child);
 
184
        m_minPreferredLogicalWidth += child->minPreferredLogicalWidth() + margin;
 
185
        m_maxPreferredLogicalWidth += child->maxPreferredLogicalWidth() + margin;
 
186
    }
 
187
}
 
188
 
 
189
void RenderDeprecatedFlexibleBox::calcVerticalPrefWidths()
 
190
{
 
191
    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
 
192
        if (childDoesNotAffectWidthOrFlexing(child))
 
193
            continue;
 
194
 
 
195
        LayoutUnit margin = marginWidthForChild(child);
 
196
        LayoutUnit width = child->minPreferredLogicalWidth() + margin;
 
197
        m_minPreferredLogicalWidth = max(width, m_minPreferredLogicalWidth);
 
198
 
 
199
        width = child->maxPreferredLogicalWidth() + margin;
 
200
        m_maxPreferredLogicalWidth = max(width, m_maxPreferredLogicalWidth);
 
201
    }
 
202
}
 
203
 
 
204
void RenderDeprecatedFlexibleBox::computePreferredLogicalWidths()
 
205
{
 
206
    ASSERT(preferredLogicalWidthsDirty());
 
207
 
 
208
    if (style()->width().isFixed() && style()->width().value() > 0)
 
209
        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style()->width().value());
 
210
    else {
 
211
        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;
 
212
 
 
213
        if (hasMultipleLines() || isVertical())
 
214
            calcVerticalPrefWidths();
 
215
        else
 
216
            calcHorizontalPrefWidths();
 
217
 
 
218
        m_maxPreferredLogicalWidth = max(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
 
219
    }
 
220
 
 
221
    if (hasOverflowClip() && style()->overflowY() == OSCROLL) {
 
222
        layer()->setHasVerticalScrollbar(true);
 
223
        LayoutUnit scrollbarWidth = verticalScrollbarWidth();
 
224
        m_maxPreferredLogicalWidth += scrollbarWidth;
 
225
        m_minPreferredLogicalWidth += scrollbarWidth;
 
226
    }
 
227
 
 
228
    if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
 
229
        m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
 
230
        m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
 
231
    }
 
232
 
 
233
    if (style()->maxWidth().isFixed()) {
 
234
        m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
 
235
        m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
 
236
    }
 
237
 
 
238
    LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth();
 
239
    m_minPreferredLogicalWidth += borderAndPadding;
 
240
    m_maxPreferredLogicalWidth += borderAndPadding;
 
241
 
 
242
    setPreferredLogicalWidthsDirty(false);
 
243
}
 
244
 
 
245
void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
 
246
{
 
247
    ASSERT(needsLayout());
 
248
 
 
249
    if (!relayoutChildren && simplifiedLayout())
 
250
        return;
 
251
 
 
252
    LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
 
253
    LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
 
254
 
 
255
    if (inRenderFlowThread()) {
 
256
        // Regions changing widths can force us to relayout our children.
 
257
        if (logicalWidthChangedInRegions())
 
258
            relayoutChildren = true;
 
259
    }
 
260
    updateRegionsAndExclusionsLogicalSize();
 
261
 
 
262
    LayoutSize previousSize = size();
 
263
 
 
264
    updateLogicalWidth();
 
265
    updateLogicalHeight();
 
266
 
 
267
    m_overflow.clear();
 
268
 
 
269
    if (previousSize != size()
 
270
        || (parent()->isDeprecatedFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL
 
271
        && parent()->style()->boxAlign() == BSTRETCH))
 
272
        relayoutChildren = true;
 
273
 
 
274
    setHeight(0);
 
275
 
 
276
    m_stretchingChildren = false;
 
277
 
 
278
    initMaxMarginValues();
 
279
 
 
280
    if (isHorizontal())
 
281
        layoutHorizontalBox(relayoutChildren);
 
282
    else
 
283
        layoutVerticalBox(relayoutChildren);
 
284
 
 
285
    LayoutUnit oldClientAfterEdge = clientLogicalBottom();
 
286
    updateLogicalHeight();
 
287
 
 
288
    if (previousSize.height() != height())
 
289
        relayoutChildren = true;
 
290
 
 
291
    layoutPositionedObjects(relayoutChildren || isRoot());
 
292
 
 
293
    computeRegionRangeForBlock();
 
294
 
 
295
    if (!isFloatingOrOutOfFlowPositioned() && height() == 0) {
 
296
        // We are a block with no border and padding and a computed height
 
297
        // of 0.  The CSS spec states that zero-height blocks collapse their margins
 
298
        // together.
 
299
        // When blocks are self-collapsing, we just use the top margin values and set the
 
300
        // bottom margin max values to 0.  This way we don't factor in the values
 
301
        // twice when we collapse with our previous vertically adjacent and
 
302
        // following vertically adjacent blocks.
 
303
        LayoutUnit pos = maxPositiveMarginBefore();
 
304
        LayoutUnit neg = maxNegativeMarginBefore();
 
305
        if (maxPositiveMarginAfter() > pos)
 
306
            pos = maxPositiveMarginAfter();
 
307
        if (maxNegativeMarginAfter() > neg)
 
308
            neg = maxNegativeMarginAfter();
 
309
        setMaxMarginBeforeValues(pos, neg);
 
310
        setMaxMarginAfterValues(0, 0);
 
311
    }
 
312
 
 
313
    computeOverflow(oldClientAfterEdge);
 
314
 
 
315
    statePusher.pop();
 
316
 
 
317
    updateLayerTransform();
 
318
 
 
319
    if (view()->layoutState()->pageLogicalHeight())
 
320
        setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(this, logicalTop()));
 
321
 
 
322
    // Update our scrollbars if we're overflow:auto/scroll/hidden now that we know if
 
323
    // we overflow or not.
 
324
    if (hasOverflowClip())
 
325
        layer()->updateScrollInfoAfterLayout();
 
326
 
 
327
    // Repaint with our new bounds if they are different from our old bounds.
 
328
    repainter.repaintAfterLayout();
 
329
 
 
330
    setNeedsLayout(false);
 
331
}
 
332
 
 
333
// The first walk over our kids is to find out if we have any flexible children.
 
334
static void gatherFlexChildrenInfo(FlexBoxIterator& iterator, bool relayoutChildren, unsigned int& highestFlexGroup, unsigned int& lowestFlexGroup, bool& haveFlex)
 
335
{
 
336
    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
 
337
        // Check to see if this child flexes.
 
338
        if (!childDoesNotAffectWidthOrFlexing(child) && child->style()->boxFlex() > 0.0f) {
 
339
            // We always have to lay out flexible objects again, since the flex distribution
 
340
            // may have changed, and we need to reallocate space.
 
341
            child->clearOverrideSize();
 
342
            if (!relayoutChildren)
 
343
                child->setChildNeedsLayout(true, MarkOnlyThis);
 
344
            haveFlex = true;
 
345
            unsigned int flexGroup = child->style()->boxFlexGroup();
 
346
            if (lowestFlexGroup == 0)
 
347
                lowestFlexGroup = flexGroup;
 
348
            if (flexGroup < lowestFlexGroup)
 
349
                lowestFlexGroup = flexGroup;
 
350
            if (flexGroup > highestFlexGroup)
 
351
                highestFlexGroup = flexGroup;
 
352
        }
 
353
    }
 
354
}
 
355
 
 
356
void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
 
357
{
 
358
    LayoutUnit toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
 
359
    LayoutUnit yPos = borderTop() + paddingTop();
 
360
    LayoutUnit xPos = borderLeft() + paddingLeft();
 
361
    bool heightSpecified = false;
 
362
    LayoutUnit oldHeight = 0;
 
363
 
 
364
    LayoutUnit remainingSpace = 0;
 
365
 
 
366
 
 
367
    FlexBoxIterator iterator(this);
 
368
    unsigned int highestFlexGroup = 0;
 
369
    unsigned int lowestFlexGroup = 0;
 
370
    bool haveFlex = false, flexingChildren = false;
 
371
    gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex);
 
372
 
 
373
    RenderBlock::startDelayUpdateScrollInfo();
 
374
 
 
375
    // We do 2 passes.  The first pass is simply to lay everyone out at
 
376
    // their preferred widths.  The second pass handles flexing the children.
 
377
    do {
 
378
        // Reset our height.
 
379
        setHeight(yPos);
 
380
 
 
381
        xPos = borderLeft() + paddingLeft();
 
382
 
 
383
        // Our first pass is done without flexing.  We simply lay the children
 
384
        // out within the box.  We have to do a layout first in order to determine
 
385
        // our box's intrinsic height.
 
386
        LayoutUnit maxAscent = 0, maxDescent = 0;
 
387
        for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
 
388
            // make sure we relayout children if we need it.
 
389
            if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())))
 
390
                child->setChildNeedsLayout(true, MarkOnlyThis);
 
391
 
 
392
            if (child->isOutOfFlowPositioned())
 
393
                continue;
 
394
 
 
395
            // Compute the child's vertical margins.
 
396
            child->computeAndSetBlockDirectionMargins(this);
 
397
 
 
398
            if (!child->needsLayout())
 
399
                child->markForPaginationRelayoutIfNeeded();
 
400
 
 
401
            // Now do the layout.
 
402
            child->layoutIfNeeded();
 
403
 
 
404
            // Update our height and overflow height.
 
405
            if (style()->boxAlign() == BBASELINE) {
 
406
                LayoutUnit ascent = child->firstLineBoxBaseline();
 
407
                if (ascent == -1)
 
408
                    ascent = child->height() + child->marginBottom();
 
409
                ascent += child->marginTop();
 
410
                LayoutUnit descent = (child->height() + child->marginHeight()) - ascent;
 
411
 
 
412
                // Update our maximum ascent.
 
413
                maxAscent = max(maxAscent, ascent);
 
414
 
 
415
                // Update our maximum descent.
 
416
                maxDescent = max(maxDescent, descent);
 
417
 
 
418
                // Now update our height.
 
419
                setHeight(max(yPos + maxAscent + maxDescent, height()));
 
420
            }
 
421
            else
 
422
                setHeight(max(height(), yPos + child->height() + child->marginHeight()));
 
423
        }
 
424
 
 
425
        if (!iterator.first() && hasLineIfEmpty())
 
426
            setHeight(height() + lineHeight(true, style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
 
427
 
 
428
        setHeight(height() + toAdd);
 
429
 
 
430
        oldHeight = height();
 
431
        updateLogicalHeight();
 
432
 
 
433
        relayoutChildren = false;
 
434
        if (oldHeight != height())
 
435
            heightSpecified = true;
 
436
 
 
437
        // Now that our height is actually known, we can place our boxes.
 
438
        m_stretchingChildren = (style()->boxAlign() == BSTRETCH);
 
439
        for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
 
440
            if (child->isOutOfFlowPositioned()) {
 
441
                child->containingBlock()->insertPositionedObject(child);
 
442
                RenderLayer* childLayer = child->layer();
 
443
                childLayer->setStaticInlinePosition(xPos); // FIXME: Not right for regions.
 
444
                if (childLayer->staticBlockPosition() != yPos) {
 
445
                    childLayer->setStaticBlockPosition(yPos);
 
446
                    if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
 
447
                        child->setChildNeedsLayout(true, MarkOnlyThis);
 
448
                }
 
449
                continue;
 
450
            }
 
451
            
 
452
            if (child->style()->visibility() == COLLAPSE) {
 
453
                // visibility: collapsed children do not participate in our positioning.
 
454
                // But we need to lay them down.
 
455
                child->layoutIfNeeded();
 
456
                continue;
 
457
            }
 
458
 
 
459
 
 
460
            // We need to see if this child's height has changed, since we make block elements
 
461
            // fill the height of a containing box by default.
 
462
            // Now do a layout.
 
463
            LayoutUnit oldChildHeight = child->height();
 
464
            child->updateLogicalHeight();
 
465
            if (oldChildHeight != child->height())
 
466
                child->setChildNeedsLayout(true, MarkOnlyThis);
 
467
 
 
468
            if (!child->needsLayout())
 
469
                child->markForPaginationRelayoutIfNeeded();
 
470
 
 
471
            child->layoutIfNeeded();
 
472
 
 
473
            // We can place the child now, using our value of box-align.
 
474
            xPos += child->marginLeft();
 
475
            LayoutUnit childY = yPos;
 
476
            switch (style()->boxAlign()) {
 
477
                case BCENTER:
 
478
                    childY += child->marginTop() + max<LayoutUnit>(0, (contentHeight() - (child->height() + child->marginHeight())) / 2);
 
479
                    break;
 
480
                case BBASELINE: {
 
481
                    LayoutUnit ascent = child->firstLineBoxBaseline();
 
482
                    if (ascent == -1)
 
483
                        ascent = child->height() + child->marginBottom();
 
484
                    ascent += child->marginTop();
 
485
                    childY += child->marginTop() + (maxAscent - ascent);
 
486
                    break;
 
487
                }
 
488
                case BEND:
 
489
                    childY += contentHeight() - child->marginBottom() - child->height();
 
490
                    break;
 
491
                default: // BSTART
 
492
                    childY += child->marginTop();
 
493
                    break;
 
494
            }
 
495
 
 
496
            placeChild(child, LayoutPoint(xPos, childY));
 
497
 
 
498
            xPos += child->width() + child->marginRight();
 
499
        }
 
500
 
 
501
        remainingSpace = borderLeft() + paddingLeft() + contentWidth() - xPos;
 
502
 
 
503
        m_stretchingChildren = false;
 
504
        if (flexingChildren)
 
505
            haveFlex = false; // We're done.
 
506
        else if (haveFlex) {
 
507
            // We have some flexible objects.  See if we need to grow/shrink them at all.
 
508
            if (!remainingSpace)
 
509
                break;
 
510
 
 
511
            // Allocate the remaining space among the flexible objects.  If we are trying to
 
512
            // grow, then we go from the lowest flex group to the highest flex group.  For shrinking,
 
513
            // we go from the highest flex group to the lowest group.
 
514
            bool expanding = remainingSpace > 0;
 
515
            unsigned int start = expanding ? lowestFlexGroup : highestFlexGroup;
 
516
            unsigned int end = expanding? highestFlexGroup : lowestFlexGroup;
 
517
            for (unsigned int i = start; i <= end && remainingSpace; i++) {
 
518
                // Always start off by assuming the group can get all the remaining space.
 
519
                LayoutUnit groupRemainingSpace = remainingSpace;
 
520
                do {
 
521
                    // Flexing consists of multiple passes, since we have to change ratios every time an object hits its max/min-width
 
522
                    // For a given pass, we always start off by computing the totalFlex of all objects that can grow/shrink at all, and
 
523
                    // computing the allowed growth before an object hits its min/max width (and thus
 
524
                    // forces a totalFlex recomputation).
 
525
                    LayoutUnit groupRemainingSpaceAtBeginning = groupRemainingSpace;
 
526
                    float totalFlex = 0.0f;
 
527
                    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
 
528
                        if (allowedChildFlex(child, expanding, i))
 
529
                            totalFlex += child->style()->boxFlex();
 
530
                    }
 
531
                    LayoutUnit spaceAvailableThisPass = groupRemainingSpace;
 
532
                    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
 
533
                        LayoutUnit allowedFlex = allowedChildFlex(child, expanding, i);
 
534
                        if (allowedFlex) {
 
535
                            LayoutUnit projectedFlex = (allowedFlex == LayoutUnit::max()) ? allowedFlex : LayoutUnit(allowedFlex * (totalFlex / child->style()->boxFlex()));
 
536
                            spaceAvailableThisPass = expanding ? min(spaceAvailableThisPass, projectedFlex) : max(spaceAvailableThisPass, projectedFlex);
 
537
                        }
 
538
                    }
 
539
 
 
540
                    // The flex groups may not have any flexible objects this time around.
 
541
                    if (!spaceAvailableThisPass || totalFlex == 0.0f) {
 
542
                        // If we just couldn't grow/shrink any more, then it's time to transition to the next flex group.
 
543
                        groupRemainingSpace = 0;
 
544
                        continue;
 
545
                    }
 
546
 
 
547
                    // Now distribute the space to objects.
 
548
                    for (RenderBox* child = iterator.first(); child && spaceAvailableThisPass && totalFlex; child = iterator.next()) {
 
549
                        if (child->style()->visibility() == COLLAPSE)
 
550
                            continue;
 
551
 
 
552
                        if (allowedChildFlex(child, expanding, i)) {
 
553
                            LayoutUnit spaceAdd = LayoutUnit(spaceAvailableThisPass * (child->style()->boxFlex() / totalFlex));
 
554
                            if (spaceAdd) {
 
555
                                child->setOverrideLogicalContentWidth(contentWidthForChild(child) + spaceAdd);
 
556
                                flexingChildren = true;
 
557
                                relayoutChildren = true;
 
558
                            }
 
559
 
 
560
                            spaceAvailableThisPass -= spaceAdd;
 
561
                            remainingSpace -= spaceAdd;
 
562
                            groupRemainingSpace -= spaceAdd;
 
563
 
 
564
                            totalFlex -= child->style()->boxFlex();
 
565
                        }
 
566
                    }
 
567
                    if (groupRemainingSpace == groupRemainingSpaceAtBeginning) {
 
568
                        // This is not advancing, avoid getting stuck by distributing the remaining pixels.
 
569
                        LayoutUnit spaceAdd = groupRemainingSpace > 0 ? 1 : -1;
 
570
                        for (RenderBox* child = iterator.first(); child && groupRemainingSpace; child = iterator.next()) {
 
571
                            if (allowedChildFlex(child, expanding, i)) {
 
572
                                child->setOverrideLogicalContentWidth(contentWidthForChild(child) + spaceAdd);
 
573
                                flexingChildren = true;
 
574
                                relayoutChildren = true;
 
575
                                remainingSpace -= spaceAdd;
 
576
                                groupRemainingSpace -= spaceAdd;
 
577
                            }
 
578
                        }
 
579
                    }
 
580
                } while (absoluteValue(groupRemainingSpace) >= 1);
 
581
            }
 
582
 
 
583
            // We didn't find any children that could grow.
 
584
            if (haveFlex && !flexingChildren)
 
585
                haveFlex = false;
 
586
        }
 
587
    } while (haveFlex);
 
588
 
 
589
    RenderBlock::finishDelayUpdateScrollInfo();
 
590
 
 
591
    if (remainingSpace > 0 && ((style()->isLeftToRightDirection() && style()->boxPack() != Start)
 
592
        || (!style()->isLeftToRightDirection() && style()->boxPack() != End))) {
 
593
        // Children must be repositioned.
 
594
        LayoutUnit offset = 0;
 
595
        if (style()->boxPack() == Justify) {
 
596
            // Determine the total number of children.
 
597
            int totalChildren = 0;
 
598
            for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
 
599
                if (childDoesNotAffectWidthOrFlexing(child))
 
600
                    continue;
 
601
                ++totalChildren;
 
602
            }
 
603
 
 
604
            // Iterate over the children and space them out according to the
 
605
            // justification level.
 
606
            if (totalChildren > 1) {
 
607
                --totalChildren;
 
608
                bool firstChild = true;
 
609
                for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
 
610
                    if (childDoesNotAffectWidthOrFlexing(child))
 
611
                        continue;
 
612
 
 
613
                    if (firstChild) {
 
614
                        firstChild = false;
 
615
                        continue;
 
616
                    }
 
617
 
 
618
                    offset += remainingSpace/totalChildren;
 
619
                    remainingSpace -= (remainingSpace/totalChildren);
 
620
                    --totalChildren;
 
621
 
 
622
                    placeChild(child, child->location() + LayoutSize(offset, 0));
 
623
                }
 
624
            }
 
625
        } else {
 
626
            if (style()->boxPack() == Center)
 
627
                offset += remainingSpace / 2;
 
628
            else // END for LTR, START for RTL
 
629
                offset += remainingSpace;
 
630
            for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
 
631
                if (childDoesNotAffectWidthOrFlexing(child))
 
632
                    continue;
 
633
 
 
634
                placeChild(child, child->location() + LayoutSize(offset, 0));
 
635
            }
 
636
        }
 
637
    }
 
638
 
 
639
    // So that the computeLogicalHeight in layoutBlock() knows to relayout positioned objects because of
 
640
    // a height change, we revert our height back to the intrinsic height before returning.
 
641
    if (heightSpecified)
 
642
        setHeight(oldHeight);
 
643
}
 
644
 
 
645
void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren)
 
646
{
 
647
    LayoutUnit yPos = borderTop() + paddingTop();
 
648
    LayoutUnit toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
 
649
    bool heightSpecified = false;
 
650
    LayoutUnit oldHeight = 0;
 
651
 
 
652
    LayoutUnit remainingSpace = 0;
 
653
 
 
654
    FlexBoxIterator iterator(this);
 
655
    unsigned int highestFlexGroup = 0;
 
656
    unsigned int lowestFlexGroup = 0;
 
657
    bool haveFlex = false, flexingChildren = false;
 
658
    gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex);
 
659
 
 
660
    // We confine the line clamp ugliness to vertical flexible boxes (thus keeping it out of
 
661
    // mainstream block layout); this is not really part of the XUL box model.
 
662
    bool haveLineClamp = !style()->lineClamp().isNone();
 
663
    if (haveLineClamp)
 
664
        applyLineClamp(iterator, relayoutChildren);
 
665
 
 
666
    RenderBlock::startDelayUpdateScrollInfo();
 
667
 
 
668
    // We do 2 passes.  The first pass is simply to lay everyone out at
 
669
    // their preferred widths.  The second pass handles flexing the children.
 
670
    // Our first pass is done without flexing.  We simply lay the children
 
671
    // out within the box.
 
672
    do {
 
673
        setHeight(borderTop() + paddingTop());
 
674
        LayoutUnit minHeight = height() + toAdd;
 
675
 
 
676
        for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
 
677
            // Make sure we relayout children if we need it.
 
678
            if (!haveLineClamp && (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))))
 
679
                child->setChildNeedsLayout(true, MarkOnlyThis);
 
680
 
 
681
            if (child->isOutOfFlowPositioned()) {
 
682
                child->containingBlock()->insertPositionedObject(child);
 
683
                RenderLayer* childLayer = child->layer();
 
684
                childLayer->setStaticInlinePosition(borderStart() + paddingStart()); // FIXME: Not right for regions.
 
685
                if (childLayer->staticBlockPosition() != height()) {
 
686
                    childLayer->setStaticBlockPosition(height());
 
687
                    if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
 
688
                        child->setChildNeedsLayout(true, MarkOnlyThis);
 
689
                }
 
690
                continue;
 
691
            }
 
692
            
 
693
            if (child->style()->visibility() == COLLAPSE) {
 
694
                // visibility: collapsed children do not participate in our positioning.
 
695
                // But we need to lay them down.
 
696
                child->layoutIfNeeded();
 
697
                continue;
 
698
            }
 
699
 
 
700
            // Compute the child's vertical margins.
 
701
            child->computeAndSetBlockDirectionMargins(this);
 
702
 
 
703
            // Add in the child's marginTop to our height.
 
704
            setHeight(height() + child->marginTop());
 
705
 
 
706
            if (!child->needsLayout())
 
707
                child->markForPaginationRelayoutIfNeeded();
 
708
 
 
709
            // Now do a layout.
 
710
            child->layoutIfNeeded();
 
711
 
 
712
            // We can place the child now, using our value of box-align.
 
713
            LayoutUnit childX = borderLeft() + paddingLeft();
 
714
            switch (style()->boxAlign()) {
 
715
                case BCENTER:
 
716
                case BBASELINE: // Baseline just maps to center for vertical boxes
 
717
                    childX += child->marginLeft() + max<LayoutUnit>(0, (contentWidth() - (child->width() + child->marginWidth())) / 2);
 
718
                    break;
 
719
                case BEND:
 
720
                    if (!style()->isLeftToRightDirection())
 
721
                        childX += child->marginLeft();
 
722
                    else
 
723
                        childX += contentWidth() - child->marginRight() - child->width();
 
724
                    break;
 
725
                default: // BSTART/BSTRETCH
 
726
                    if (style()->isLeftToRightDirection())
 
727
                        childX += child->marginLeft();
 
728
                    else
 
729
                        childX += contentWidth() - child->marginRight() - child->width();
 
730
                    break;
 
731
            }
 
732
 
 
733
            // Place the child.
 
734
            placeChild(child, LayoutPoint(childX, height()));
 
735
            setHeight(height() + child->height() + child->marginBottom());
 
736
        }
 
737
 
 
738
        yPos = height();
 
739
 
 
740
        if (!iterator.first() && hasLineIfEmpty())
 
741
            setHeight(height() + lineHeight(true, style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
 
742
 
 
743
        setHeight(height() + toAdd);
 
744
 
 
745
        // Negative margins can cause our height to shrink below our minimal height (border/padding).
 
746
        // If this happens, ensure that the computed height is increased to the minimal height.
 
747
        if (height() < minHeight)
 
748
            setHeight(minHeight);
 
749
 
 
750
        // Now we have to calc our height, so we know how much space we have remaining.
 
751
        oldHeight = height();
 
752
        updateLogicalHeight();
 
753
        if (oldHeight != height())
 
754
            heightSpecified = true;
 
755
 
 
756
        remainingSpace = borderTop() + paddingTop() + contentHeight() - yPos;
 
757
 
 
758
        if (flexingChildren)
 
759
            haveFlex = false; // We're done.
 
760
        else if (haveFlex) {
 
761
            // We have some flexible objects.  See if we need to grow/shrink them at all.
 
762
            if (!remainingSpace)
 
763
                break;
 
764
 
 
765
            // Allocate the remaining space among the flexible objects.  If we are trying to
 
766
            // grow, then we go from the lowest flex group to the highest flex group.  For shrinking,
 
767
            // we go from the highest flex group to the lowest group.
 
768
            bool expanding = remainingSpace > 0;
 
769
            unsigned int start = expanding ? lowestFlexGroup : highestFlexGroup;
 
770
            unsigned int end = expanding? highestFlexGroup : lowestFlexGroup;
 
771
            for (unsigned int i = start; i <= end && remainingSpace; i++) {
 
772
                // Always start off by assuming the group can get all the remaining space.
 
773
                LayoutUnit groupRemainingSpace = remainingSpace;
 
774
                do {
 
775
                    // Flexing consists of multiple passes, since we have to change ratios every time an object hits its max/min-width
 
776
                    // For a given pass, we always start off by computing the totalFlex of all objects that can grow/shrink at all, and
 
777
                    // computing the allowed growth before an object hits its min/max width (and thus
 
778
                    // forces a totalFlex recomputation).
 
779
                    LayoutUnit groupRemainingSpaceAtBeginning = groupRemainingSpace;
 
780
                    float totalFlex = 0.0f;
 
781
                    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
 
782
                        if (allowedChildFlex(child, expanding, i))
 
783
                            totalFlex += child->style()->boxFlex();
 
784
                    }
 
785
                    LayoutUnit spaceAvailableThisPass = groupRemainingSpace;
 
786
                    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
 
787
                        LayoutUnit allowedFlex = allowedChildFlex(child, expanding, i);
 
788
                        if (allowedFlex) {
 
789
                            LayoutUnit projectedFlex = (allowedFlex == LayoutUnit::max()) ? allowedFlex : static_cast<LayoutUnit>(allowedFlex * (totalFlex / child->style()->boxFlex()));
 
790
                            spaceAvailableThisPass = expanding ? min(spaceAvailableThisPass, projectedFlex) : max(spaceAvailableThisPass, projectedFlex);
 
791
                        }
 
792
                    }
 
793
 
 
794
                    // The flex groups may not have any flexible objects this time around.
 
795
                    if (!spaceAvailableThisPass || totalFlex == 0.0f) {
 
796
                        // If we just couldn't grow/shrink any more, then it's time to transition to the next flex group.
 
797
                        groupRemainingSpace = 0;
 
798
                        continue;
 
799
                    }
 
800
 
 
801
                    // Now distribute the space to objects.
 
802
                    for (RenderBox* child = iterator.first(); child && spaceAvailableThisPass && totalFlex; child = iterator.next()) {
 
803
                        if (allowedChildFlex(child, expanding, i)) {
 
804
                            LayoutUnit spaceAdd = static_cast<LayoutUnit>(spaceAvailableThisPass * (child->style()->boxFlex() / totalFlex));
 
805
                            if (spaceAdd) {
 
806
                                child->setOverrideLogicalContentHeight(contentHeightForChild(child) + spaceAdd);
 
807
                                flexingChildren = true;
 
808
                                relayoutChildren = true;
 
809
                            }
 
810
 
 
811
                            spaceAvailableThisPass -= spaceAdd;
 
812
                            remainingSpace -= spaceAdd;
 
813
                            groupRemainingSpace -= spaceAdd;
 
814
 
 
815
                            totalFlex -= child->style()->boxFlex();
 
816
                        }
 
817
                    }
 
818
                    if (groupRemainingSpace == groupRemainingSpaceAtBeginning) {
 
819
                        // This is not advancing, avoid getting stuck by distributing the remaining pixels.
 
820
                        LayoutUnit spaceAdd = groupRemainingSpace > 0 ? 1 : -1;
 
821
                        for (RenderBox* child = iterator.first(); child && groupRemainingSpace; child = iterator.next()) {
 
822
                            if (allowedChildFlex(child, expanding, i)) {
 
823
                                child->setOverrideLogicalContentHeight(contentHeightForChild(child) + spaceAdd);
 
824
                                flexingChildren = true;
 
825
                                relayoutChildren = true;
 
826
                                remainingSpace -= spaceAdd;
 
827
                                groupRemainingSpace -= spaceAdd;
 
828
                            }
 
829
                        }
 
830
                    }
 
831
                } while (absoluteValue(groupRemainingSpace) >= 1);
 
832
            }
 
833
 
 
834
            // We didn't find any children that could grow.
 
835
            if (haveFlex && !flexingChildren)
 
836
                haveFlex = false;
 
837
        }
 
838
    } while (haveFlex);
 
839
 
 
840
    RenderBlock::finishDelayUpdateScrollInfo();
 
841
 
 
842
    if (style()->boxPack() != Start && remainingSpace > 0) {
 
843
        // Children must be repositioned.
 
844
        LayoutUnit offset = 0;
 
845
        if (style()->boxPack() == Justify) {
 
846
            // Determine the total number of children.
 
847
            int totalChildren = 0;
 
848
            for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
 
849
                if (childDoesNotAffectWidthOrFlexing(child))
 
850
                    continue;
 
851
 
 
852
                ++totalChildren;
 
853
            }
 
854
 
 
855
            // Iterate over the children and space them out according to the
 
856
            // justification level.
 
857
            if (totalChildren > 1) {
 
858
                --totalChildren;
 
859
                bool firstChild = true;
 
860
                for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
 
861
                    if (childDoesNotAffectWidthOrFlexing(child))
 
862
                        continue;
 
863
 
 
864
                    if (firstChild) {
 
865
                        firstChild = false;
 
866
                        continue;
 
867
                    }
 
868
 
 
869
                    offset += remainingSpace/totalChildren;
 
870
                    remainingSpace -= (remainingSpace/totalChildren);
 
871
                    --totalChildren;
 
872
                    placeChild(child, child->location() + LayoutSize(0, offset));
 
873
                }
 
874
            }
 
875
        } else {
 
876
            if (style()->boxPack() == Center)
 
877
                offset += remainingSpace / 2;
 
878
            else // END
 
879
                offset += remainingSpace;
 
880
            for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
 
881
                if (childDoesNotAffectWidthOrFlexing(child))
 
882
                    continue;
 
883
                placeChild(child, child->location() + LayoutSize(0, offset));
 
884
            }
 
885
        }
 
886
    }
 
887
 
 
888
    // So that the computeLogicalHeight in layoutBlock() knows to relayout positioned objects because of
 
889
    // a height change, we revert our height back to the intrinsic height before returning.
 
890
    if (heightSpecified)
 
891
        setHeight(oldHeight);
 
892
}
 
893
 
 
894
void RenderDeprecatedFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool relayoutChildren)
 
895
{
 
896
    int maxLineCount = 0;
 
897
    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
 
898
        if (childDoesNotAffectWidthOrFlexing(child))
 
899
            continue;
 
900
 
 
901
        child->clearOverrideSize();
 
902
        if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))
 
903
            || (child->style()->height().isAuto() && child->isBlockFlow())) {
 
904
            child->setChildNeedsLayout(true, MarkOnlyThis);
 
905
 
 
906
            // Dirty all the positioned objects.
 
907
            if (child->isRenderBlock()) {
 
908
                toRenderBlock(child)->markPositionedObjectsForLayout();
 
909
                toRenderBlock(child)->clearTruncation();
 
910
            }
 
911
        }
 
912
        child->layoutIfNeeded();
 
913
        if (child->style()->height().isAuto() && child->isBlockFlow())
 
914
            maxLineCount = max(maxLineCount, toRenderBlock(child)->lineCount());
 
915
    }
 
916
 
 
917
    // Get the number of lines and then alter all block flow children with auto height to use the
 
918
    // specified height. We always try to leave room for at least one line.
 
919
    LineClampValue lineClamp = style()->lineClamp();
 
920
    int numVisibleLines = lineClamp.isPercentage() ? max(1, (maxLineCount + 1) * lineClamp.value() / 100) : lineClamp.value();
 
921
    if (numVisibleLines >= maxLineCount)
 
922
        return;
 
923
 
 
924
    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
 
925
        if (childDoesNotAffectWidthOrFlexing(child) || !child->style()->height().isAuto() || !child->isBlockFlow())
 
926
            continue;
 
927
 
 
928
        RenderBlock* blockChild = toRenderBlock(child);
 
929
        int lineCount = blockChild->lineCount();
 
930
        if (lineCount <= numVisibleLines)
 
931
            continue;
 
932
 
 
933
        LayoutUnit newHeight = blockChild->heightForLineCount(numVisibleLines);
 
934
        if (newHeight == child->height())
 
935
            continue;
 
936
 
 
937
        child->setChildNeedsLayout(true, MarkOnlyThis);
 
938
        child->setOverrideLogicalContentHeight(newHeight - child->borderAndPaddingHeight());
 
939
        child->layoutIfNeeded();
 
940
 
 
941
        // FIXME: For now don't support RTL.
 
942
        if (style()->direction() != LTR)
 
943
            continue;
 
944
 
 
945
        // Get the last line
 
946
        RootInlineBox* lastLine = blockChild->lineAtIndex(lineCount - 1);
 
947
        if (!lastLine)
 
948
            continue;
 
949
 
 
950
        RootInlineBox* lastVisibleLine = blockChild->lineAtIndex(numVisibleLines - 1);
 
951
        if (!lastVisibleLine)
 
952
            continue;
 
953
 
 
954
        const UChar ellipsisAndSpace[2] = { horizontalEllipsis, ' ' };
 
955
        DEFINE_STATIC_LOCAL(AtomicString, ellipsisAndSpaceStr, (ellipsisAndSpace, 2));
 
956
        DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, (&horizontalEllipsis, 1));
 
957
        const Font& font = style(numVisibleLines == 1)->font();
 
958
 
 
959
        // Get ellipsis width, and if the last child is an anchor, it will go after the ellipsis, so add in a space and the anchor width too
 
960
        LayoutUnit totalWidth;
 
961
        InlineBox* anchorBox = lastLine->lastChild();
 
962
        if (anchorBox && anchorBox->renderer()->style()->isLink())
 
963
            totalWidth = anchorBox->logicalWidth() + font.width(constructTextRun(this, font, ellipsisAndSpace, 2, style()));
 
964
        else {
 
965
            anchorBox = 0;
 
966
            totalWidth = font.width(constructTextRun(this, font, &horizontalEllipsis, 1, style()));
 
967
        }
 
968
 
 
969
        // See if this width can be accommodated on the last visible line
 
970
        RenderBlock* destBlock = toRenderBlock(lastVisibleLine->renderer());
 
971
        RenderBlock* srcBlock = toRenderBlock(lastLine->renderer());
 
972
 
 
973
        // FIXME: Directions of src/destBlock could be different from our direction and from one another.
 
974
        if (!srcBlock->style()->isLeftToRightDirection())
 
975
            continue;
 
976
 
 
977
        bool leftToRight = destBlock->style()->isLeftToRightDirection();
 
978
        if (!leftToRight)
 
979
            continue;
 
980
 
 
981
        LayoutUnit blockRightEdge = destBlock->logicalRightOffsetForLine(lastVisibleLine->y(), false);
 
982
        if (!lastVisibleLine->lineCanAccommodateEllipsis(leftToRight, blockRightEdge, lastVisibleLine->x() + lastVisibleLine->logicalWidth(), totalWidth))
 
983
            continue;
 
984
 
 
985
        // Let the truncation code kick in.
 
986
        // FIXME: the text alignment should be recomputed after the width changes due to truncation.
 
987
        LayoutUnit blockLeftEdge = destBlock->logicalLeftOffsetForLine(lastVisibleLine->y(), false);
 
988
        lastVisibleLine->placeEllipsis(anchorBox ? ellipsisAndSpaceStr : ellipsisStr, leftToRight, blockLeftEdge, blockRightEdge, totalWidth, anchorBox);
 
989
        destBlock->setHasMarkupTruncation(true);
 
990
    }
 
991
}
 
992
 
 
993
void RenderDeprecatedFlexibleBox::clearLineClamp()
 
994
{
 
995
    FlexBoxIterator iterator(this);
 
996
    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
 
997
        if (childDoesNotAffectWidthOrFlexing(child))
 
998
            continue;
 
999
 
 
1000
        child->clearOverrideSize();
 
1001
        if ((child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))
 
1002
            || (child->style()->height().isAuto() && child->isBlockFlow())) {
 
1003
            child->setChildNeedsLayout(true);
 
1004
 
 
1005
            if (child->isRenderBlock()) {
 
1006
                toRenderBlock(child)->markPositionedObjectsForLayout();
 
1007
                toRenderBlock(child)->clearTruncation();
 
1008
            }
 
1009
        }
 
1010
    }
 
1011
}
 
1012
 
 
1013
void RenderDeprecatedFlexibleBox::placeChild(RenderBox* child, const LayoutPoint& location)
 
1014
{
 
1015
    LayoutRect oldRect = child->frameRect();
 
1016
 
 
1017
    // Place the child.
 
1018
    child->setLocation(location);
 
1019
 
 
1020
    // If the child moved, we have to repaint it as well as any floating/positioned
 
1021
    // descendants.  An exception is if we need a layout.  In this case, we know we're going to
 
1022
    // repaint ourselves (and the child) anyway.
 
1023
    if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
 
1024
        child->repaintDuringLayoutIfMoved(oldRect);
 
1025
}
 
1026
 
 
1027
LayoutUnit RenderDeprecatedFlexibleBox::allowedChildFlex(RenderBox* child, bool expanding, unsigned int group)
 
1028
{
 
1029
    if (childDoesNotAffectWidthOrFlexing(child) || child->style()->boxFlex() == 0.0f || child->style()->boxFlexGroup() != group)
 
1030
        return 0;
 
1031
 
 
1032
    if (expanding) {
 
1033
        if (isHorizontal()) {
 
1034
            // FIXME: For now just handle fixed values.
 
1035
            LayoutUnit maxWidth = LayoutUnit::max();
 
1036
            LayoutUnit width = contentWidthForChild(child);
 
1037
            if (!child->style()->maxWidth().isUndefined() && child->style()->maxWidth().isFixed())
 
1038
                maxWidth = child->style()->maxWidth().value();
 
1039
            else if (child->style()->maxWidth().type() == Intrinsic)
 
1040
                maxWidth = child->maxPreferredLogicalWidth();
 
1041
            else if (child->style()->maxWidth().type() == MinIntrinsic)
 
1042
                maxWidth = child->minPreferredLogicalWidth();
 
1043
            if (maxWidth == LayoutUnit::max())
 
1044
                return maxWidth;
 
1045
            return max<LayoutUnit>(0, maxWidth - width);
 
1046
        } else {
 
1047
            // FIXME: For now just handle fixed values.
 
1048
            LayoutUnit maxHeight = LayoutUnit::max();
 
1049
            LayoutUnit height = contentHeightForChild(child);
 
1050
            if (!child->style()->maxHeight().isUndefined() && child->style()->maxHeight().isFixed())
 
1051
                maxHeight = child->style()->maxHeight().value();
 
1052
            if (maxHeight == LayoutUnit::max())
 
1053
                return maxHeight;
 
1054
            return max<LayoutUnit>(0, maxHeight - height);
 
1055
        }
 
1056
    }
 
1057
 
 
1058
    // FIXME: For now just handle fixed values.
 
1059
    if (isHorizontal()) {
 
1060
        LayoutUnit minWidth = child->minPreferredLogicalWidth();
 
1061
        LayoutUnit width = contentWidthForChild(child);
 
1062
        if (child->style()->minWidth().isFixed())
 
1063
            minWidth = child->style()->minWidth().value();
 
1064
        else if (child->style()->minWidth().type() == Intrinsic)
 
1065
            minWidth = child->maxPreferredLogicalWidth();
 
1066
        else if (child->style()->minWidth().type() == MinIntrinsic)
 
1067
            minWidth = child->minPreferredLogicalWidth();
 
1068
        else if (child->style()->minWidth().type() == Auto)
 
1069
            minWidth = 0;
 
1070
 
 
1071
        LayoutUnit allowedShrinkage = min<LayoutUnit>(0, minWidth - width);
 
1072
        return allowedShrinkage;
 
1073
    } else {
 
1074
        Length minHeight = child->style()->minHeight();
 
1075
        if (minHeight.isFixed() || minHeight.isAuto()) {
 
1076
            LayoutUnit minHeight = child->style()->minHeight().value();
 
1077
            LayoutUnit height = contentHeightForChild(child);
 
1078
            LayoutUnit allowedShrinkage = min<LayoutUnit>(0, minHeight - height);
 
1079
            return allowedShrinkage;
 
1080
        }
 
1081
    }
 
1082
 
 
1083
    return 0;
 
1084
}
 
1085
 
 
1086
const char *RenderDeprecatedFlexibleBox::renderName() const
 
1087
{
 
1088
    if (isFloating())
 
1089
        return "RenderDeprecatedFlexibleBox (floating)";
 
1090
    if (isOutOfFlowPositioned())
 
1091
        return "RenderDeprecatedFlexibleBox (positioned)";
 
1092
    if (isAnonymous())
 
1093
        return "RenderDeprecatedFlexibleBox (generated)";
 
1094
    if (isRelPositioned())
 
1095
        return "RenderDeprecatedFlexibleBox (relative positioned)";
 
1096
    return "RenderDeprecatedFlexibleBox";
 
1097
}
 
1098
 
 
1099
} // namespace WebCore