OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) |
3 * Copyright (C) 2004, 2006, 2007, 2008 Apple Inc. All right reserved. | 3 * Copyright (C) 2004, 2006, 2007, 2008 Apple Inc. All right reserved. |
4 * | 4 * |
5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
9 * | 9 * |
10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 // these midpoints, so we just keep an array around and never clear it. We trac
k | 82 // these midpoints, so we just keep an array around and never clear it. We trac
k |
83 // the number of items and position using the two other variables. | 83 // the number of items and position using the two other variables. |
84 static Vector<InlineIterator>* smidpoints; | 84 static Vector<InlineIterator>* smidpoints; |
85 static unsigned sNumMidpoints; | 85 static unsigned sNumMidpoints; |
86 static unsigned sCurrMidpoint; | 86 static unsigned sCurrMidpoint; |
87 static bool betweenMidpoints; | 87 static bool betweenMidpoints; |
88 | 88 |
89 static bool isLineEmpty = true; | 89 static bool isLineEmpty = true; |
90 static bool previousLineBrokeCleanly = true; | 90 static bool previousLineBrokeCleanly = true; |
91 | 91 |
92 static int getBorderPaddingMargin(RenderBox* child, bool endOfInline) | 92 static int getBorderPaddingMargin(RenderBoxModelObject* child, bool endOfInline) |
93 { | 93 { |
94 bool leftSide = (child->style()->direction() == LTR) ? !endOfInline : endOfI
nline; | 94 bool leftSide = (child->style()->direction() == LTR) ? !endOfInline : endOfI
nline; |
95 if (leftSide) | 95 if (leftSide) |
96 return child->marginLeft() + child->paddingLeft() + child->borderLeft(); | 96 return child->marginLeft() + child->paddingLeft() + child->borderLeft(); |
97 return child->marginRight() + child->paddingRight() + child->borderRight(); | 97 return child->marginRight() + child->paddingRight() + child->borderRight(); |
98 } | 98 } |
99 | 99 |
100 static int inlineWidth(RenderObject* child, bool start = true, bool end = true) | 100 static int inlineWidth(RenderObject* child, bool start = true, bool end = true) |
101 { | 101 { |
102 unsigned lineDepth = 1; | 102 unsigned lineDepth = 1; |
103 int extraWidth = 0; | 103 int extraWidth = 0; |
104 RenderObject* parent = child->parent(); | 104 RenderObject* parent = child->parent(); |
105 while (parent->isBox() && parent->isInline() && !parent->isInlineBlockOrInli
neTable() && lineDepth++ < cMaxLineDepth) { | 105 while (parent->isInline() && !parent->isInlineBlockOrInlineTable() && lineDe
pth++ < cMaxLineDepth) { |
106 if (start && !child->previousSibling()) | 106 if (start && !child->previousSibling()) |
107 extraWidth += getBorderPaddingMargin(toRenderBox(parent), false); | 107 extraWidth += getBorderPaddingMargin(toRenderBoxModelObject(parent),
false); |
108 if (end && !child->nextSibling()) | 108 if (end && !child->nextSibling()) |
109 extraWidth += getBorderPaddingMargin(toRenderBox(parent), true); | 109 extraWidth += getBorderPaddingMargin(toRenderBoxModelObject(parent),
true); |
110 child = parent; | 110 child = parent; |
111 parent = child->parent(); | 111 parent = child->parent(); |
112 } | 112 } |
113 return extraWidth; | 113 return extraWidth; |
114 } | 114 } |
115 | 115 |
116 #ifndef NDEBUG | 116 #ifndef NDEBUG |
117 static WTF::RefCountedLeakCounter bidiRunCounter("BidiRun"); | 117 static WTF::RefCountedLeakCounter bidiRunCounter("BidiRun"); |
118 | 118 |
119 static bool inBidiRunDestroy; | 119 static bool inBidiRunDestroy; |
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 | 789 |
790 // Walk all the lines and delete our ellipsis line boxes if they exist. | 790 // Walk all the lines and delete our ellipsis line boxes if they exist. |
791 if (hasTextOverflow) | 791 if (hasTextOverflow) |
792 deleteEllipsisLineBoxes(); | 792 deleteEllipsisLineBoxes(); |
793 | 793 |
794 if (firstChild()) { | 794 if (firstChild()) { |
795 // layout replaced elements | 795 // layout replaced elements |
796 bool endOfInline = false; | 796 bool endOfInline = false; |
797 RenderObject* o = bidiFirst(this, 0, false); | 797 RenderObject* o = bidiFirst(this, 0, false); |
798 Vector<FloatWithRect> floats; | 798 Vector<FloatWithRect> floats; |
799 int containerWidth = max(0, containingBlockWidth()); | |
800 while (o) { | 799 while (o) { |
801 o->invalidateVerticalPosition(); | 800 o->invalidateVerticalPosition(); |
802 if (o->isReplaced() || o->isFloating() || o->isPositioned()) { | 801 if (o->isReplaced() || o->isFloating() || o->isPositioned()) { |
803 RenderBox* box = toRenderBox(o); | 802 RenderBox* box = toRenderBox(o); |
804 | 803 |
805 if (relayoutChildren || o->style()->width().isPercent() || o->st
yle()->height().isPercent()) | 804 if (relayoutChildren || o->style()->width().isPercent() || o->st
yle()->height().isPercent()) |
806 o->setChildNeedsLayout(true, false); | 805 o->setChildNeedsLayout(true, false); |
807 | 806 |
808 // If relayoutChildren is set and we have percentage padding, we
also need to invalidate the child's pref widths. | 807 // If relayoutChildren is set and we have percentage padding, we
also need to invalidate the child's pref widths. |
809 if (relayoutChildren && (o->style()->paddingLeft().isPercent() |
| o->style()->paddingRight().isPercent())) | 808 if (relayoutChildren && (o->style()->paddingLeft().isPercent() |
| o->style()->paddingRight().isPercent())) |
810 o->setPrefWidthsDirty(true, false); | 809 o->setPrefWidthsDirty(true, false); |
811 | 810 |
812 if (o->isPositioned()) | 811 if (o->isPositioned()) |
813 o->containingBlock()->insertPositionedObject(box); | 812 o->containingBlock()->insertPositionedObject(box); |
814 else { | 813 else { |
815 if (o->isFloating()) | 814 if (o->isFloating()) |
816 floats.append(FloatWithRect(box)); | 815 floats.append(FloatWithRect(box)); |
817 else if (fullLayout || o->needsLayout()) // Replaced element
s | 816 else if (fullLayout || o->needsLayout()) // Replaced element
s |
818 o->dirtyLineBoxes(fullLayout); | 817 o->dirtyLineBoxes(fullLayout); |
819 | 818 |
820 o->layoutIfNeeded(); | 819 o->layoutIfNeeded(); |
821 } | 820 } |
822 } else if (o->isText() || (o->isRenderInline() && !endOfInline)) { | 821 } else if (o->isText() || (o->isRenderInline() && !endOfInline)) { |
823 if (fullLayout || o->selfNeedsLayout()) | 822 if (fullLayout || o->selfNeedsLayout()) |
824 o->dirtyLineBoxes(fullLayout); | 823 o->dirtyLineBoxes(fullLayout); |
825 | |
826 // Calculate margins of inline flows so that they can be used la
ter by line layout. | |
827 if (o->isRenderInline()) | |
828 toRenderInline(o)->calcMargins(containerWidth); | |
829 o->setNeedsLayout(false); | 824 o->setNeedsLayout(false); |
830 } | 825 } |
831 o = bidiNext(this, o, 0, false, &endOfInline); | 826 o = bidiNext(this, o, 0, false, &endOfInline); |
832 } | 827 } |
833 | 828 |
834 // We want to skip ahead to the first dirty line | 829 // We want to skip ahead to the first dirty line |
835 InlineBidiResolver resolver; | 830 InlineBidiResolver resolver; |
836 unsigned floatIndex; | 831 unsigned floatIndex; |
837 bool firstLine = true; | 832 bool firstLine = true; |
838 RootInlineBox* startLine = determineStartPosition(firstLine, fullLayout,
resolver, floats, floatIndex); | 833 RootInlineBox* startLine = determineStartPosition(firstLine, fullLayout,
resolver, floats, floatIndex); |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1377 static inline bool shouldPreserveNewline(RenderObject* object) | 1372 static inline bool shouldPreserveNewline(RenderObject* object) |
1378 { | 1373 { |
1379 #if ENABLE(SVG) | 1374 #if ENABLE(SVG) |
1380 if (object->isSVGText()) | 1375 if (object->isSVGText()) |
1381 return false; | 1376 return false; |
1382 #endif | 1377 #endif |
1383 | 1378 |
1384 return object->style()->preserveNewline(); | 1379 return object->style()->preserveNewline(); |
1385 } | 1380 } |
1386 | 1381 |
1387 static bool inlineFlowRequiresLineBox(RenderBox* flow) | 1382 static bool inlineFlowRequiresLineBox(RenderInline* flow) |
1388 { | 1383 { |
1389 // FIXME: Right now, we only allow line boxes for inlines that are truly emp
ty. | 1384 // FIXME: Right now, we only allow line boxes for inlines that are truly emp
ty. |
1390 // We need to fix this, though, because at the very least, inlines containin
g only | 1385 // We need to fix this, though, because at the very least, inlines containin
g only |
1391 // ignorable whitespace should should also have line boxes. | 1386 // ignorable whitespace should should also have line boxes. |
1392 return flow->isRenderInline() && !flow->firstChild() && flow->hasHorizontalB
ordersPaddingOrMargin(); | 1387 return !flow->firstChild() && flow->hasHorizontalBordersPaddingOrMargin(); |
1393 } | 1388 } |
1394 | 1389 |
1395 static inline bool requiresLineBox(const InlineIterator& it) | 1390 static inline bool requiresLineBox(const InlineIterator& it) |
1396 { | 1391 { |
1397 if (it.obj->isFloatingOrPositioned()) | 1392 if (it.obj->isFloatingOrPositioned()) |
1398 return false; | 1393 return false; |
1399 | 1394 |
1400 if (it.obj->isRenderInline() && !inlineFlowRequiresLineBox(toRenderBox(it.ob
j))) | 1395 if (it.obj->isRenderInline() && !inlineFlowRequiresLineBox(toRenderInline(it
.obj))) |
1401 return false; | 1396 return false; |
1402 | 1397 |
1403 if (!shouldCollapseWhiteSpace(it.obj->style()) || it.obj->isBR()) | 1398 if (!shouldCollapseWhiteSpace(it.obj->style()) || it.obj->isBR()) |
1404 return true; | 1399 return true; |
1405 | 1400 |
1406 UChar current = it.current(); | 1401 UChar current = it.current(); |
1407 return current != ' ' && current != '\t' && current != softHyphen && (curren
t != '\n' || shouldPreserveNewline(it.obj)) && !skipNonBreakingSpace(it); | 1402 return current != ' ' && current != '\t' && current != softHyphen && (curren
t != '\n' || shouldPreserveNewline(it.obj)) && !skipNonBreakingSpace(it); |
1408 } | 1403 } |
1409 | 1404 |
1410 bool RenderBlock::generatesLineBoxesForInlineChild(RenderObject* inlineObj) | 1405 bool RenderBlock::generatesLineBoxesForInlineChild(RenderObject* inlineObj) |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1473 if (c->isRenderInline()) { | 1468 if (c->isRenderInline()) { |
1474 // A relative positioned inline encloses us. In this case, we a
lso have to determine our | 1469 // A relative positioned inline encloses us. In this case, we a
lso have to determine our |
1475 // position as though we were an inline. Set |staticX| and |sta
ticY| on the relative positioned | 1470 // position as though we were an inline. Set |staticX| and |sta
ticY| on the relative positioned |
1476 // inline so that we can obtain the value later. | 1471 // inline so that we can obtain the value later. |
1477 toRenderInline(c)->layer()->setStaticX(style()->direction() == L
TR ? leftOffset(height(), firstLine) : rightOffset(height(), firstLine)); | 1472 toRenderInline(c)->layer()->setStaticX(style()->direction() == L
TR ? leftOffset(height(), firstLine) : rightOffset(height(), firstLine)); |
1478 toRenderInline(c)->layer()->setStaticY(height()); | 1473 toRenderInline(c)->layer()->setStaticY(height()); |
1479 } | 1474 } |
1480 | 1475 |
1481 RenderBox* box = toRenderBox(object); | 1476 RenderBox* box = toRenderBox(object); |
1482 if (box->style()->hasStaticX()) { | 1477 if (box->style()->hasStaticX()) { |
1483 if (object->style()->isOriginalDisplayInlineType()) | 1478 if (box->style()->isOriginalDisplayInlineType()) |
1484 box->layer()->setStaticX(style()->direction() == LTR ? leftO
ffset(height(), firstLine) : width() - rightOffset(height(), firstLine)); | 1479 box->layer()->setStaticX(style()->direction() == LTR ? leftO
ffset(height(), firstLine) : width() - rightOffset(height(), firstLine)); |
1485 else | 1480 else |
1486 box->layer()->setStaticX(style()->direction() == LTR ? borde
rLeft() + paddingLeft() : borderRight() + paddingRight()); | 1481 box->layer()->setStaticX(style()->direction() == LTR ? borde
rLeft() + paddingLeft() : borderRight() + paddingRight()); |
1487 } | 1482 } |
1488 | 1483 |
1489 if (box->style()->hasStaticY()) | 1484 if (box->style()->hasStaticY()) |
1490 box->layer()->setStaticY(height()); | 1485 box->layer()->setStaticY(height()); |
1491 } | 1486 } |
1492 resolver.increment(); | 1487 resolver.increment(); |
1493 } | 1488 } |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1677 addMidpoint(ignoreStart); // Stop ignoring spaces. | 1672 addMidpoint(ignoreStart); // Stop ignoring spaces. |
1678 addMidpoint(ignoreStart); // Start ignoring again. | 1673 addMidpoint(ignoreStart); // Start ignoring again. |
1679 } | 1674 } |
1680 | 1675 |
1681 } | 1676 } |
1682 } | 1677 } |
1683 } else if (o->isRenderInline()) { | 1678 } else if (o->isRenderInline()) { |
1684 // Right now, we should only encounter empty inlines here. | 1679 // Right now, we should only encounter empty inlines here. |
1685 ASSERT(!o->firstChild()); | 1680 ASSERT(!o->firstChild()); |
1686 | 1681 |
1687 RenderBox* flowBox = toRenderBox(o); | 1682 RenderInline* flowBox = toRenderInline(o); |
1688 | 1683 |
1689 // Now that some inline flows have line boxes, if we are already ign
oring spaces, we need | 1684 // Now that some inline flows have line boxes, if we are already ign
oring spaces, we need |
1690 // to make sure that we stop to include this object and then start i
gnoring spaces again. | 1685 // to make sure that we stop to include this object and then start i
gnoring spaces again. |
1691 // If this object is at the start of the line, we need to behave lik
e list markers and | 1686 // If this object is at the start of the line, we need to behave lik
e list markers and |
1692 // start ignoring spaces. | 1687 // start ignoring spaces. |
1693 if (inlineFlowRequiresLineBox(flowBox)) { | 1688 if (inlineFlowRequiresLineBox(flowBox)) { |
1694 isLineEmpty = false; | 1689 isLineEmpty = false; |
1695 if (ignoringSpaces) { | 1690 if (ignoringSpaces) { |
1696 trailingSpaceObject = 0; | 1691 trailingSpaceObject = 0; |
1697 addMidpoint(InlineIterator(0, o, 0)); // Stop ignoring space
s. | 1692 addMidpoint(InlineIterator(0, o, 0)); // Stop ignoring space
s. |
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2199 // space. | 2194 // space. |
2200 int width = curr == firstRootBox() ? firstLineEllipsisWidth : ellips
isWidth; | 2195 int width = curr == firstRootBox() ? firstLineEllipsisWidth : ellips
isWidth; |
2201 if (curr->canAccommodateEllipsis(ltr, blockEdge, lineBoxEdge, width)
) | 2196 if (curr->canAccommodateEllipsis(ltr, blockEdge, lineBoxEdge, width)
) |
2202 curr->placeEllipsis(ellipsisStr, ltr, blockEdge, width); | 2197 curr->placeEllipsis(ellipsisStr, ltr, blockEdge, width); |
2203 } | 2198 } |
2204 } | 2199 } |
2205 } | 2200 } |
2206 | 2201 |
2207 } | 2202 } |
2208 | 2203 |
OLD | NEW |