Changeset 83075 in webkit
- Timestamp:
- Apr 6, 2011 11:20:52 AM (13 years ago)
- Location:
- trunk
- Files:
-
- 26 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r83074 r83075 1 2011-04-06 David Hyatt <hyatt@apple.com> 2 3 Reviewed by Dan Bernstein. 4 5 https://bugs.webkit.org/show_bug.cgi?id=57916 6 7 Implement an optimization to the line box tree to cull out most of the intermediate 8 line boxes that can occur between the root line box and the leaves of the tree (images 9 and text). 10 11 RenderInlines now have a boolean member, m_alwaysCreateLineBoxes, 12 that starts off as false. Only if it gets flipped to true will there be any line boxes 13 created for that RenderInline. 14 15 * platform/mac/fast/blockflow/text-orientation-basic-expected.txt: 16 * platform/mac/fast/text/capitalize-empty-generated-string-expected.txt: 17 1 18 2011-04-06 MORITA Hajime <morrita@google.com> 2 19 -
trunk/LayoutTests/platform/mac/fast/blockflow/text-orientation-basic-expected.txt
r80582 r83075 27 27 RenderText {#text} at (44,1) size 40x254 28 28 text run at (44,1) width 254: "Hello world" 29 RenderBR {BR} at ( 64,254) size 0x129 RenderBR {BR} at (52,254) size 0x1 30 30 RenderInline {SPAN} at (0,0) size 36x199 31 31 RenderText {#text} at (94,1) size 36x199 … … 45 45 RenderText {#text} at (44,1) size 40x255 46 46 text run at (44,1) width 255: "Hello world" 47 RenderBR {BR} at ( 64,256) size 0x047 RenderBR {BR} at (52,256) size 0x0 48 48 RenderInline {SPAN} at (0,0) size 36x198 49 49 RenderText {#text} at (94,1) size 36x198 -
trunk/LayoutTests/platform/mac/fast/text/capitalize-empty-generated-string-expected.txt
r30635 r83075 23 23 text run at (0,0) width 46: "Lorem " 24 24 RenderInline {SPAN} at (0,0) size 39x18 25 RenderInline (generated) at (0,0) size 0x 1825 RenderInline (generated) at (0,0) size 0x0 26 26 RenderText at (0,0) size 0x0 27 27 RenderText {#text} at (46,0) size 39x18 … … 39 39 text run at (0,0) width 23: "Lor" 40 40 RenderInline {SPAN} at (0,0) size 62x18 41 RenderInline (generated) at (0,0) size 0x 1841 RenderInline (generated) at (0,0) size 0x0 42 42 RenderText at (0,0) size 0x0 43 43 RenderText {#text} at (23,0) size 62x18 -
trunk/Source/WebCore/ChangeLog
r83070 r83075 1 2011-04-06 David Hyatt <hyatt@apple.com> 2 3 Reviewed by Dan Bernstein. 4 5 https://bugs.webkit.org/show_bug.cgi?id=57916 6 7 Implement an optimization to the line box tree to cull out most of the intermediate 8 line boxes that can occur between the root line box and the leaves of the tree (images 9 and text). 10 11 RenderInlines now have a boolean member, m_alwaysCreateLineBoxes, 12 that starts off as false. Only if it gets flipped to true will there be any line boxes 13 created for that RenderInline. 14 15 * page/FocusController.cpp: 16 (WebCore::FocusController::advanceFocusDirectionally): 17 Adjust the ordering of updateLayout calls to make sure rects aren't queried unless layout 18 is up to date. 19 20 * page/SpatialNavigation.cpp: 21 (WebCore::hasOffscreenRect): 22 (WebCore::nodeRectInAbsoluteCoordinates): 23 Add asserts in spatial navigation code to catch any future bad queries that might be made 24 for rectangles without layout being up to date. 25 26 * platform/graphics/FloatRect.cpp: 27 (WebCore::FloatRect::uniteIfNonZero): 28 * platform/graphics/FloatRect.h: 29 * platform/graphics/IntRect.cpp: 30 (WebCore::IntRect::uniteIfNonZero): 31 * platform/graphics/IntRect.h: 32 Add a new unite function that is useful for the render tree to FloatRect and IntRect. This 33 version allows rect unites to happen if either width or height is nonzero. 34 35 * rendering/HitTestResult.cpp: 36 (WebCore::HitTestResult::addNodeToRectBasedTestResult): 37 Make sure rect-based hit testing properly adds in culled inline ancestors to the set of nodes 38 if content inside those inlines is hit. 39 40 * rendering/InlineBox.h: 41 (WebCore::InlineBox::logicalFrameRect): 42 Fix a bug in this function for obtaining the logical frame rect of an inline box. 43 44 * rendering/InlineFlowBox.cpp: 45 (WebCore::InlineFlowBox::addToLine): 46 addToLine now also checks line gap in the line box tree optimization checks. 47 48 (WebCore::InlineFlowBox::addTextBoxVisualOverflow): 49 (WebCore::InlineFlowBox::computeOverflow): 50 * rendering/InlineFlowBox.h: 51 Rewritten to add the text box overflow to the text box itself. 52 53 * rendering/InlineTextBox.cpp: 54 (WebCore::InlineTextBox::destroy): 55 Destroy has been changed to call a helper function to remove and destroy the line boxes that 56 is now called from one additional spot. 57 58 (WebCore::InlineTextBox::logicalOverflowRect): 59 (WebCore::InlineTextBox::setLogicalOverflowRect): 60 Text boxes now cache their own overflow in a global hash table. 61 62 (WebCore::InlineTextBox::baselinePosition): 63 (WebCore::InlineTextBox::lineHeight): 64 Changed to not assume that the parent line box's renderer is the RenderText's immediate 65 parent, since intermediate line boxes may have been culled. 66 67 (WebCore::InlineTextBox::paint): 68 Paint now properly checks only the text box overflow instead of the parent line box's overflow. 69 70 * rendering/InlineTextBox.h: 71 (WebCore::InlineTextBox::logicalTopVisualOverflow): 72 (WebCore::InlineTextBox::logicalBottomVisualOverflow): 73 (WebCore::InlineTextBox::logicalLeftVisualOverflow): 74 (WebCore::InlineTextBox::logicalRightVisualOverflow): 75 New accessors to obtain overflow for inline text boxes. 76 77 * rendering/RenderBlock.cpp: 78 (WebCore::RenderBlock::updateFirstLetter): 79 updateFirstLetter now removes text boxes from the line box tree before it destroys them, since those 80 text boxes may not have anything in between them and the block that contains the inline first letter 81 container. 82 83 * rendering/RenderBlockLineLayout.cpp: 84 (WebCore::RenderBlock::createLineBoxes): 85 The culling optimization is done here. Only if the RenderInline says that boxes are allowed will they 86 be created. 87 88 (WebCore::RenderBlock::layoutInlineChildren): 89 The state of the RenderInline is updated here, in case it is discovered that line boxes are now needed. 90 This is done before any lines are built. 91 92 * rendering/RenderInline.cpp: 93 (WebCore::RenderInline::RenderInline): 94 The new m_alwaysCreateLineBoxes flag has been added to the constructor. 95 96 (WebCore::RenderInline::styleDidChange): 97 An initial update of the m_alwaysCreateLineBoxes happens here for things that can be checked immediately 98 (like having a layer, borders, padding, margins or backgrounds). Some checks that depend on examining 99 the RenderInline's parent (including first line styles) happen later in layoutInlineChildren. 100 101 (WebCore::RenderInline::updateAlwaysCreateLineBoxes): 102 The function called by layoutInlineChildren to check parent and child style differences (e.g., font, 103 vertical alignment, line height, etc.). 104 105 (WebCore::RenderInline::absoluteRects): 106 (WebCore::RenderInline::culledInlineAbsoluteRects): 107 absoluteRects calls culledInlineAbsoluteRects when m_alwaysCreateLineBoxes is false. 108 109 (WebCore::RenderInline::absoluteQuads): 110 (WebCore::RenderInline::culledInlineAbsoluteQuads): 111 absoluteQuads calls culledInlineAbsoluteQuads when m_alwaysCreateLineBoxes is false. 112 113 (WebCore::RenderInline::offsetLeft): 114 (WebCore::RenderInline::offsetTop): 115 offsetLeft and offsetTop now check descendant renderers when m_alwaysCreateLineBoxes is false. 116 117 (WebCore::RenderInline::linesBoundingBox): 118 (WebCore::RenderInline::culledInlineBoundingBox): 119 lineBoundingBox calls culledInlineBoundingBox when m_alwaysCreateLineBoxes is false. 120 121 (WebCore::RenderInline::culledInlineFirstLineBox): 122 (WebCore::RenderInline::culledInlineLastLineBox): 123 Helpers that return the first and last line box descendants. Used by firstLineBoxIncludingCulling and 124 lastLineBoxIncludingCulling (which are in turn called by offsetLeft and offsetTop). 125 126 (WebCore::RenderInline::culledInlineVisualOverflowBoundingBox): 127 (WebCore::RenderInline::linesVisualOverflowBoundingBox): 128 linesVisualOverflowBoundingBox calls culledInlineVisualOverflowBoundingBox when m_alwaysCreateLineBoxes is false. 129 130 (WebCore::RenderInline::clippedOverflowRectForRepaint): 131 The initial bailout check is now done using firstLineBoxIncludingCulling instead of just firstLineBox. 132 133 (WebCore::RenderInline::dirtyLineBoxes): 134 dirtyLineBoxes now crawls into descendants to figure out which root lines to dirty when 135 m_alwaysCreateLineBoxes is false. 136 137 (WebCore::RenderInline::createAndAppendInlineFlowBox): 138 Clear the m_alwaysCreateLineBoxes if a box gets added anyway. This happens for leaf inline flows and also 139 when line-box-contain is set to an unusual value. 140 141 (WebCore::RenderInline::addFocusRingRects): 142 Used culledInlineAbsoluteRects in place of the line box walk when m_alwaysCreateLineBoxes is false. 143 144 * rendering/RenderInline.h: 145 (WebCore::RenderInline::firstLineBoxIncludingCulling): 146 (WebCore::RenderInline::lastLineBoxIncludingCulling): 147 Helpers used in a few places (like offsetLeft and offsetTop), mostly in places where the existence of a box 148 is all that needs checking. 149 150 (WebCore::RenderInline::alwaysCreateLineBoxes): 151 (WebCore::RenderInline::setAlwaysCreateLineBoxes): 152 Functions for getting and setting the m_alwaysCreateLineBoxes flag. 153 154 * rendering/RenderLineBoxList.cpp: 155 (WebCore::RenderLineBoxList::dirtyLinesFromChangedChild): 156 Modified to use firstLineBoxIncludingCulling and lastLineBoxIncludingCulling to ensure the right set of 157 lines get dirtied. 158 159 * rendering/RenderText.cpp: 160 (WebCore::RenderText::removeAndDestroyTextBoxes): 161 New helper invoked by destroy and also from updateFirstLetter. 162 163 (WebCore::RenderText::destroy): 164 Changed to call removeAndDestroyTextBoxes. 165 166 (WebCore::RenderText::absoluteRects): 167 Fixed to be properly physical instead of logical. 168 169 (WebCore::RenderText::linesVisualOverflowBoundingBox): 170 New implementation for RenderText that gives the bounding box of the text boxes including overflow from 171 shadows, glyphs, text-stroke, etc. Used by RenderInline::culledInlineVisualOverflowBoundingBox. 172 173 * rendering/RenderText.h: 174 * rendering/svg/RenderSVGInline.cpp: 175 (WebCore::RenderSVGInline::RenderSVGInline): 176 RenderSVGInline always sets m_alwaysCreateLineBoxes to true so that SVG is unaffected by this optimization. 177 178 * rendering/svg/SVGRootInlineBox.cpp: 179 (WebCore::SVGRootInlineBox::layoutCharactersInTextBoxes): 180 (WebCore::SVGRootInlineBox::layoutChildBoxes): 181 Move the isInlineFlowBox asserts to after the generated content skips, since the generated content boxes are 182 now InlineTextBoxes (the enclosing InlineFlowBoxes got culled). 183 1 184 2011-04-05 Enrica Casucci <enrica@apple.com> 2 185 -
trunk/Source/WebCore/page/FocusController.cpp
r82525 r83075 598 598 Node* container = focusedDocument; 599 599 600 if (container->isDocumentNode()) 601 static_cast<Document*>(container)->updateLayoutIgnorePendingStylesheets(); 602 600 603 // Figure out the starting rect. 601 604 IntRect startingRect; … … 613 616 bool consumed = false; 614 617 do { 615 if (container->isDocumentNode())616 static_cast<Document*>(container)->updateLayoutIgnorePendingStylesheets();617 618 consumed = advanceFocusDirectionallyInContainer(container, startingRect, direction, event); 618 619 startingRect = nodeRectInAbsoluteCoordinates(container, true /* ignore border */); 619 620 container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, container); 621 if (container && container->isDocumentNode()) 622 static_cast<Document*>(container)->updateLayoutIgnorePendingStylesheets(); 620 623 } while (!consumed && container); 621 624 -
trunk/Source/WebCore/page/SpatialNavigation.cpp
r79021 r83075 301 301 return true; 302 302 303 ASSERT(!frameView->needsLayout()); 304 303 305 IntRect containerViewportRect = frameView->visibleContentRect(); 304 306 // We want to select a node if it is currently off screen, but will be … … 518 520 IntRect nodeRectInAbsoluteCoordinates(Node* node, bool ignoreBorder) 519 521 { 520 ASSERT(node && node->renderer() );522 ASSERT(node && node->renderer() && !node->document()->view()->needsLayout()); 521 523 522 524 if (node->isDocumentNode()) -
trunk/Source/WebCore/platform/graphics/FloatRect.cpp
r77286 r83075 98 98 } 99 99 100 void FloatRect::uniteIfNonZero(const FloatRect& other) 101 { 102 // Handle empty special cases first. 103 if (!other.width() && !other.height()) 104 return; 105 if (!width() && !height()) { 106 *this = other; 107 return; 108 } 109 110 float left = min(x(), other.x()); 111 float top = min(y(), other.y()); 112 float right = max(maxX(), other.maxX()); 113 float bottom = max(maxY(), other.maxY()); 114 115 setLocationAndSizeFromEdges(left, top, right, bottom); 116 } 117 100 118 void FloatRect::scale(float sx, float sy) 101 119 { -
trunk/Source/WebCore/platform/graphics/FloatRect.h
r79578 r83075 113 113 void intersect(const FloatRect&); 114 114 void unite(const FloatRect&); 115 void uniteIfNonZero(const FloatRect&); 115 116 116 117 // Note, this doesn't match what IntRect::contains(IntPoint&) does; the int version -
trunk/Source/WebCore/platform/graphics/FontMetrics.h
r76445 r83075 97 97 int lineSpacing() const { return lroundf(m_lineSpacing); } 98 98 99 bool hasIdenticalAscentDescentAndLineGap(const FontMetrics& other) const 100 { 101 return ascent() == other.ascent() && descent() == other.descent() && lineGap() == other.lineGap(); 102 } 103 99 104 private: 100 105 friend class SimpleFontData; -
trunk/Source/WebCore/platform/graphics/IntRect.cpp
r77286 r83075 97 97 } 98 98 99 void IntRect::uniteIfNonZero(const IntRect& other) 100 { 101 // Handle empty special cases first. 102 if (!other.width() && !other.height()) 103 return; 104 if (!width() && !height()) { 105 *this = other; 106 return; 107 } 108 109 int left = min(x(), other.x()); 110 int top = min(y(), other.y()); 111 int right = max(maxX(), other.maxX()); 112 int bottom = max(maxY(), other.maxY()); 113 114 m_location.setX(left); 115 m_location.setY(top); 116 m_size.setWidth(right - left); 117 m_size.setHeight(bottom - top); 118 } 119 99 120 void IntRect::scale(float s) 100 121 { -
trunk/Source/WebCore/platform/graphics/IntRect.h
r79578 r83075 145 145 void intersect(const IntRect&); 146 146 void unite(const IntRect&); 147 void uniteIfNonZero(const IntRect&); 147 148 148 149 void inflateX(int dx) -
trunk/Source/WebCore/rendering/HitTestResult.cpp
r82340 r83075 33 33 #include "HTMLParserIdioms.h" 34 34 #include "RenderImage.h" 35 #include "RenderInline.h" 35 36 #include "Scrollbar.h" 36 37 #include "SelectionController.h" … … 545 546 mutableRectBasedTestResult().add(node); 546 547 548 if (node->renderer()->isInline()) { 549 for (RenderObject* curr = node->renderer()->parent(); curr; curr = curr->parent()) { 550 if (!curr->isRenderInline()) 551 break; 552 553 // We need to make sure the nodes for culled inlines get included. 554 RenderInline* currInline = toRenderInline(curr); 555 if (currInline->alwaysCreateLineBoxes()) 556 break; 557 558 if (currInline->visibleToHitTesting() && currInline->node()) 559 mutableRectBasedTestResult().add(currInline->node()->shadowAncestorNode()); 560 } 561 } 547 562 return !rect.contains(rectForPoint(x, y)); 548 563 } … … 562 577 mutableRectBasedTestResult().add(node); 563 578 579 if (node->renderer()->isInline()) { 580 for (RenderObject* curr = node->renderer()->parent(); curr; curr = curr->parent()) { 581 if (!curr->isRenderInline()) 582 break; 583 584 // We need to make sure the nodes for culled inlines get included. 585 RenderInline* currInline = toRenderInline(curr); 586 if (currInline->alwaysCreateLineBoxes()) 587 break; 588 589 if (currInline->visibleToHitTesting() && currInline->node()) 590 mutableRectBasedTestResult().add(currInline->node()->shadowAncestorNode()); 591 } 592 } 564 593 return !rect.contains(rectForPoint(x, y)); 565 594 } -
trunk/Source/WebCore/rendering/InlineBox.h
r82611 r83075 264 264 int logicalHeight() const; 265 265 266 FloatRect logicalFrameRect() const { return isHorizontal() ? IntRect(m_x, m_y, m_logicalWidth, logicalHeight()) : IntRect(m_y, m_x, logicalHeight(), m_logicalWidth); }266 FloatRect logicalFrameRect() const { return isHorizontal() ? IntRect(m_x, m_y, m_logicalWidth, logicalHeight()) : IntRect(m_y, m_x, m_logicalWidth, logicalHeight()); } 267 267 268 268 virtual int baselinePosition(FontBaseline baselineType) const { return boxModelObject()->baselinePosition(baselineType, m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine); } -
trunk/Source/WebCore/rendering/InlineFlowBox.cpp
r82611 r83075 98 98 child->setIsHorizontal(isHorizontal()); 99 99 if (child->isText()) { 100 m_hasTextChildren = true; 100 if (child->renderer()->parent() == renderer()) 101 m_hasTextChildren = true; 101 102 m_hasTextDescendants = true; 102 103 } else if (child->isInlineFlowBox()) { … … 112 113 shouldClearDescendantsHaveSameLineHeightAndBaseline = true; 113 114 else if (child->isText()) { 114 if (child->renderer()->isBR() ) {115 if ( parentStyle->font().fontMetrics().ascent() != childStyle->font().fontMetrics().ascent()116 || parentStyle-> font().fontMetrics().descent() != childStyle->font().fontMetrics().descent() || parentStyle->lineHeight() != childStyle->lineHeight()115 if (child->renderer()->isBR() || child->renderer()->parent() != renderer()) { 116 if (!parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics()) 117 || parentStyle->lineHeight() != childStyle->lineHeight() 117 118 || (parentStyle->verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle->verticalAlign() != BASELINE) 118 119 shouldClearDescendantsHaveSameLineHeightAndBaseline = true; 119 } else if (childStyle->hasTextCombine() || childStyle->textEmphasisMark() != TextEmphasisMarkNone) 120 } 121 if (childStyle->hasTextCombine() || childStyle->textEmphasisMark() != TextEmphasisMarkNone) 120 122 shouldClearDescendantsHaveSameLineHeightAndBaseline = true; 121 123 } else { … … 128 130 InlineFlowBox* childFlowBox = static_cast<InlineFlowBox*>(child); 129 131 // Check the child's bit, and then also check for differences in font, line-height, vertical-align 130 if (!childFlowBox->descendantsHaveSameLineHeightAndBaseline() || parentStyle->font().fontMetrics().ascent() != childStyle->font().fontMetrics().ascent() 131 || parentStyle->font().fontMetrics().descent() != childStyle->font().fontMetrics().descent() || parentStyle->lineHeight() != childStyle->lineHeight() 132 if (!childFlowBox->descendantsHaveSameLineHeightAndBaseline() 133 || !parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics()) 134 || parentStyle->lineHeight() != childStyle->lineHeight() 132 135 || (parentStyle->verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle->verticalAlign() != BASELINE 133 136 || childStyle->hasBorder() || childStyle->hasPadding() || childStyle->hasTextCombine()) … … 733 736 } 734 737 735 inline void InlineFlowBox::addTextBoxVisualOverflow( constInlineTextBox* textBox, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, IntRect& logicalVisualOverflow)738 inline void InlineFlowBox::addTextBoxVisualOverflow(InlineTextBox* textBox, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, IntRect& logicalVisualOverflow) 736 739 { 737 740 if (textBox->knownToHaveNoOverflow()) 738 741 return; 739 742 740 RenderStyle* style = renderer()->style(m_firstLine);743 RenderStyle* style = textBox->renderer()->style(m_firstLine); 741 744 742 745 GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(textBox); … … 789 792 logicalVisualOverflow = IntRect(logicalLeftVisualOverflow, logicalTopVisualOverflow, 790 793 logicalRightVisualOverflow - logicalLeftVisualOverflow, logicalBottomVisualOverflow - logicalTopVisualOverflow); 794 795 textBox->setLogicalOverflowRect(logicalVisualOverflow); 791 796 } 792 797 … … 836 841 if (rt->isBR()) 837 842 continue; 838 addTextBoxVisualOverflow(text, textBoxDataMap, logicalVisualOverflow); 843 IntRect textBoxOverflow(enclosingIntRect(text->logicalFrameRect())); 844 addTextBoxVisualOverflow(text, textBoxDataMap, textBoxOverflow); 845 logicalVisualOverflow.unite(textBoxOverflow); 839 846 } else if (curr->renderer()->isRenderInline()) { 840 847 InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr); -
trunk/Source/WebCore/rendering/InlineFlowBox.h
r82611 r83075 273 273 private: 274 274 void addBoxShadowVisualOverflow(IntRect& logicalVisualOverflow); 275 void addTextBoxVisualOverflow( constInlineTextBox*, GlyphOverflowAndFallbackFontsMap&, IntRect& logicalVisualOverflow);275 void addTextBoxVisualOverflow(InlineTextBox*, GlyphOverflowAndFallbackFontsMap&, IntRect& logicalVisualOverflow); 276 276 void addReplacedChildOverflow(const InlineBox*, IntRect& logicalLayoutOverflow, IntRect& logicalVisualOverflow); 277 277 -
trunk/Source/WebCore/rendering/InlineTextBox.cpp
r82611 r83075 49 49 namespace WebCore { 50 50 51 typedef WTF::HashMap<const InlineTextBox*, IntRect> InlineTextBoxOverflowMap; 52 static InlineTextBoxOverflowMap* gTextBoxesWithOverflow; 53 54 void InlineTextBox::destroy(RenderArena* arena) 55 { 56 if (!m_knownToHaveNoOverflow && gTextBoxesWithOverflow) 57 gTextBoxesWithOverflow->remove(this); 58 InlineBox::destroy(arena); 59 } 60 61 IntRect InlineTextBox::logicalOverflowRect() const 62 { 63 if (m_knownToHaveNoOverflow || !gTextBoxesWithOverflow) 64 return enclosingIntRect(logicalFrameRect()); 65 return gTextBoxesWithOverflow->get(this); 66 } 67 68 void InlineTextBox::setLogicalOverflowRect(const IntRect& rect) 69 { 70 ASSERT(!m_knownToHaveNoOverflow); 71 if (!gTextBoxesWithOverflow) 72 gTextBoxesWithOverflow = new InlineTextBoxOverflowMap; 73 gTextBoxesWithOverflow->add(this, rect); 74 } 75 51 76 int InlineTextBox::baselinePosition(FontBaseline baselineType) const 52 77 { 53 78 if (!isText() || !parent()) 54 79 return 0; 55 return parent()->baselinePosition(baselineType); 80 if (parent()->renderer() == renderer()->parent()) 81 return parent()->baselinePosition(baselineType); 82 return toRenderBoxModelObject(renderer()->parent())->baselinePosition(baselineType, m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine); 56 83 } 57 84 58 85 int InlineTextBox::lineHeight() const 59 86 { 60 if (!isText() || ! parent())87 if (!isText() || !renderer()->parent()) 61 88 return 0; 62 89 if (m_renderer->isBR()) 63 90 return toRenderBR(m_renderer)->lineHeight(m_firstLine); 64 return parent()->lineHeight(); 91 if (parent()->renderer() == renderer()->parent()) 92 return parent()->lineHeight(); 93 return toRenderBoxModelObject(renderer()->parent())->lineHeight(m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine); 65 94 } 66 95 … … 436 465 } 437 466 438 void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty, int lineTop, int lineBottom)467 void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty, int /*lineTop*/, int /*lineBottom*/) 439 468 { 440 469 if (isLineBreak() || !paintInfo.shouldPaintWithinRoot(renderer()) || renderer()->style()->visibility() != VISIBLE || … … 444 473 ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines); 445 474 446 int logicalLeftOverflow = 0; 447 int logicalRightOverflow = 0; 448 if (!knownToHaveNoOverflow()) { 449 // FIXME: Technically we're potentially incorporating other visual overflow that had nothing to do with us. 450 // Would it be simpler to just check our own shadow and stroke overflow by hand here? 451 IntRect parentVisualOverflow = parent()->logicalVisualOverflowRect(lineTop, lineBottom); 452 logicalLeftOverflow = parent()->logicalLeft() - parentVisualOverflow.x(); 453 logicalRightOverflow = parentVisualOverflow.maxX() - parent()->logicalRight(); 454 } 455 int logicalStart = logicalLeft() - logicalLeftOverflow + (isHorizontal() ? tx : ty); 456 int logicalExtent = logicalWidth() + logicalLeftOverflow + logicalRightOverflow; 475 int logicalLeftSide = logicalLeftVisualOverflow(); 476 int logicalRightSide = logicalRightVisualOverflow(); 477 int logicalStart = logicalLeftSide + (isHorizontal() ? tx : ty); 478 int logicalExtent = logicalRightSide - logicalLeftSide; 457 479 458 480 int paintEnd = isHorizontal() ? paintInfo.rect.maxX() : paintInfo.rect.maxY(); -
trunk/Source/WebCore/rendering/InlineTextBox.h
r82611 r83075 52 52 } 53 53 54 virtual void destroy(RenderArena*); 55 54 56 InlineTextBox* prevTextBox() const { return m_prevTextBox; } 55 57 InlineTextBox* nextTextBox() const { return m_nextTextBox; } … … 81 83 bool getEmphasisMarkPosition(RenderStyle*, TextEmphasisPosition&) const; 82 84 85 IntRect logicalOverflowRect() const; 86 void setLogicalOverflowRect(const IntRect&); 87 int logicalTopVisualOverflow() const { return logicalOverflowRect().y(); } 88 int logicalBottomVisualOverflow() const { return logicalOverflowRect().maxY(); } 89 int logicalLeftVisualOverflow() const { return logicalOverflowRect().x(); } 90 int logicalRightVisualOverflow() const { return logicalOverflowRect().maxX(); } 91 83 92 private: 84 93 int selectionTop(); -
trunk/Source/WebCore/rendering/RenderBlock.cpp
r83042 r83075 5327 5327 while (RenderObject* child = firstLetter->firstChild()) { 5328 5328 if (child->isText()) 5329 toRenderText(child)-> dirtyLineBoxes(true);5329 toRenderText(child)->removeAndDestroyTextBoxes(); 5330 5330 firstLetter->removeChild(child); 5331 5331 newFirstLetter->addChild(child, 0); -
trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp
r83066 r83075 214 214 ASSERT(obj->isRenderInline() || obj == this); 215 215 216 RenderInline* inlineFlow = (obj != this) ? toRenderInline(obj) : 0; 217 216 218 // Get the last box we made for this render object. 217 parentBox = obj->isRenderInline() ? toRenderInline(obj)->lastLineBox() : toRenderBlock(obj)->lastLineBox();219 parentBox = inlineFlow ? inlineFlow->lastLineBox() : toRenderBlock(obj)->lastLineBox(); 218 220 219 221 // If this box or its ancestor is constructed then it is from a previous line, and we need … … 223 225 // the same line (this can happen with very fancy language mixtures). 224 226 bool constructedNewBox = false; 225 if (!parentBox || parentIsConstructedOrHaveNext(parentBox)) { 227 bool allowedToConstructNewBox = !hasDefaultLineBoxContain || !inlineFlow || inlineFlow->alwaysCreateLineBoxes(); 228 bool canUseExistingParentBox = parentBox && !parentIsConstructedOrHaveNext(parentBox); 229 if (allowedToConstructNewBox && !canUseExistingParentBox) { 226 230 // We need to make a new box for this render object. Once 227 231 // made, we need to place it at the end of the current line. … … 236 240 } 237 241 238 if (!result) 239 result = parentBox; 240 241 // If we have hit the block itself, then |box| represents the root 242 // inline box for the line, and it doesn't have to be appended to any parent 243 // inline. 244 if (childBox) 245 parentBox->addToLine(childBox); 246 247 if (!constructedNewBox || obj == this) 248 break; 249 250 childBox = parentBox; 242 if (constructedNewBox || canUseExistingParentBox) { 243 if (!result) 244 result = parentBox; 245 246 // If we have hit the block itself, then |box| represents the root 247 // inline box for the line, and it doesn't have to be appended to any parent 248 // inline. 249 if (childBox) 250 parentBox->addToLine(childBox); 251 252 if (!constructedNewBox || obj == this) 253 break; 254 255 childBox = parentBox; 256 } 251 257 252 258 // If we've exceeded our line depth, then jump straight to the root and skip all the remaining … … 761 767 } 762 768 } else if (o->isText() || (o->isRenderInline() && !endOfInline)) { 769 if (!o->isText()) 770 toRenderInline(o)->updateAlwaysCreateLineBoxes(); 763 771 if (fullLayout || o->selfNeedsLayout()) 764 772 dirtyLineBoxesForRenderer(o, fullLayout); -
trunk/Source/WebCore/rendering/RenderInline.cpp
r82611 r83075 28 28 #include "GraphicsContext.h" 29 29 #include "HitTestResult.h" 30 #include "InlineTextBox.h" 30 31 #include "Page.h" 31 32 #include "RenderArena.h" … … 48 49 : RenderBoxModelObject(node) 49 50 , m_lineHeight(-1) 51 , m_alwaysCreateLineBoxes(false) 50 52 { 51 53 setChildrenInline(true); … … 145 147 m_lineHeight = -1; 146 148 149 if (!m_alwaysCreateLineBoxes) { 150 bool alwaysCreateLineBoxes = hasSelfPaintingLayer() || hasBoxDecorations() || style()->hasPadding() || style()->hasMargin() || style()->hasOutline(); 151 if (oldStyle && alwaysCreateLineBoxes) { 152 dirtyLineBoxes(false); 153 setNeedsLayout(true); 154 } 155 m_alwaysCreateLineBoxes = alwaysCreateLineBoxes; 156 } 157 147 158 // Update pseudos for :before and :after now. 148 159 if (!isAnonymous() && document()->usesBeforeAfterRules()) { 149 160 children()->updateBeforeAfterContent(this, BEFORE); 150 161 children()->updateBeforeAfterContent(this, AFTER); 162 } 163 } 164 165 void RenderInline::updateAlwaysCreateLineBoxes() 166 { 167 // Once we have been tainted once, just assume it will happen again. This way effects like hover highlighting that change the 168 // background color will only cause a layout on the first rollover. 169 if (m_alwaysCreateLineBoxes) 170 return; 171 172 RenderStyle* parentStyle = parent()->style(); 173 RenderInline* parentRenderInline = parent()->isRenderInline() ? toRenderInline(parent()) : 0; 174 bool checkFonts = document()->inNoQuirksMode(); 175 bool alwaysCreateLineBoxes = (parentRenderInline && parentRenderInline->alwaysCreateLineBoxes()) 176 || (parentRenderInline && parentStyle->verticalAlign() != BASELINE) 177 || style()->verticalAlign() != BASELINE 178 || style()->textEmphasisMark() != TextEmphasisMarkNone 179 || (checkFonts && (!parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(style()->font().fontMetrics()) 180 || parentStyle->lineHeight() != style()->lineHeight())); 181 182 if (!alwaysCreateLineBoxes && checkFonts && document()->usesFirstLineRules()) { 183 // Have to check the first line style as well. 184 parentStyle = parent()->style(true); 185 RenderStyle* childStyle = style(true); 186 alwaysCreateLineBoxes = !parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics()) 187 || parentStyle->font().fontMetrics().lineGap() != childStyle->font().fontMetrics().lineGap() 188 || childStyle->verticalAlign() != BASELINE 189 || parentStyle->lineHeight() != childStyle->lineHeight(); 190 } 191 192 if (alwaysCreateLineBoxes) { 193 dirtyLineBoxes(false); 194 m_alwaysCreateLineBoxes = true; 151 195 } 152 196 } … … 425 469 void RenderInline::absoluteRects(Vector<IntRect>& rects, int tx, int ty) 426 470 { 427 if (InlineFlowBox* curr = firstLineBox()) { 471 if (!alwaysCreateLineBoxes()) 472 culledInlineAbsoluteRects(this, rects, IntSize(tx, ty)); 473 else if (InlineFlowBox* curr = firstLineBox()) { 428 474 for (; curr; curr = curr->nextLineBox()) 429 rects.append( IntRect(tx + curr->x(), ty + curr->y(), curr->logicalWidth(), curr->logicalHeight()));475 rects.append(enclosingIntRect(FloatRect(tx + curr->x(), ty + curr->y(), curr->width(), curr->height()))); 430 476 } else 431 477 rects.append(IntRect(tx, ty, 0, 0)); … … 442 488 } 443 489 490 void RenderInline::culledInlineAbsoluteRects(const RenderInline* container, Vector<IntRect>& rects, const IntSize& offset) 491 { 492 bool isHorizontal = style()->isHorizontalWritingMode(); 493 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { 494 if (curr->isFloatingOrPositioned()) 495 continue; 496 497 // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block 498 // direction (aligned to the root box's baseline). 499 if (curr->isBox()) { 500 RenderBox* currBox = toRenderBox(curr); 501 if (currBox->inlineBoxWrapper()) { 502 RootInlineBox* rootBox = currBox->inlineBoxWrapper()->root(); 503 int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent()); 504 int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height(); 505 FloatRect result; 506 if (isHorizontal) 507 result = FloatRect(offset.width() + currBox->inlineBoxWrapper()->x() - currBox->marginLeft(), offset.height() + logicalTop, currBox->width() + currBox->marginLeft() + currBox->marginRight(), logicalHeight); 508 else 509 result = FloatRect(offset.width() + logicalTop, offset.height() + currBox->inlineBoxWrapper()->y() - currBox->marginTop(), logicalHeight, currBox->height() + currBox->marginTop() + currBox->marginBottom()); 510 rects.append(enclosingIntRect(result)); 511 } 512 } else if (curr->isRenderInline()) { 513 // If the child doesn't need line boxes either, then we can recur. 514 RenderInline* currInline = toRenderInline(curr); 515 if (!currInline->alwaysCreateLineBoxes()) 516 currInline->culledInlineAbsoluteRects(container, rects, offset); 517 else { 518 for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox()) { 519 RootInlineBox* rootBox = childLine->root(); 520 int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent()); 521 int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height(); 522 FloatRect result; 523 if (isHorizontal) 524 result = FloatRect(offset.width() + childLine->x() - childLine->marginLogicalLeft(), 525 offset.height() + logicalTop, 526 childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight(), 527 logicalHeight); 528 else 529 result = FloatRect(offset.width() + logicalTop, 530 offset.height() + childLine->y() - childLine->marginLogicalLeft(), 531 logicalHeight, 532 childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight()); 533 rects.append(enclosingIntRect(result)); 534 } 535 } 536 } else if (curr->isText()) { 537 RenderText* currText = toRenderText(curr); 538 for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox()) { 539 RootInlineBox* rootBox = childText->root(); 540 int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent()); 541 int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height(); 542 FloatRect result; 543 if (isHorizontal) 544 result = FloatRect(offset.width() + childText->x(), offset.height() + logicalTop, childText->logicalWidth(), logicalHeight); 545 else 546 result = FloatRect(offset.width() + logicalTop, offset.height() + childText->y(), logicalHeight, childText->logicalWidth()); 547 rects.append(enclosingIntRect(result)); 548 } 549 } 550 } 551 } 552 444 553 void RenderInline::absoluteQuads(Vector<FloatQuad>& quads) 445 554 { 446 if (InlineFlowBox* curr = firstLineBox()) { 555 if (!alwaysCreateLineBoxes()) 556 culledInlineAbsoluteQuads(this, quads); 557 else if (InlineFlowBox* curr = firstLineBox()) { 447 558 for (; curr; curr = curr->nextLineBox()) { 448 FloatRect localRect(curr->x(), curr->y(), curr-> logicalWidth(), curr->logicalHeight());559 FloatRect localRect(curr->x(), curr->y(), curr->width(), curr->height()); 449 560 quads.append(localToAbsoluteQuad(localRect)); 450 561 } … … 456 567 } 457 568 569 void RenderInline::culledInlineAbsoluteQuads(const RenderInline* container, Vector<FloatQuad>& quads) 570 { 571 bool isHorizontal = style()->isHorizontalWritingMode(); 572 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { 573 if (curr->isFloatingOrPositioned()) 574 continue; 575 576 // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block 577 // direction (aligned to the root box's baseline). 578 if (curr->isBox()) { 579 RenderBox* currBox = toRenderBox(curr); 580 if (currBox->inlineBoxWrapper()) { 581 RootInlineBox* rootBox = currBox->inlineBoxWrapper()->root(); 582 int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent()); 583 int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height(); 584 FloatRect result; 585 if (isHorizontal) 586 result = FloatRect(currBox->inlineBoxWrapper()->x() - currBox->marginLeft(), logicalTop, currBox->width() + currBox->marginLeft() + currBox->marginRight(), logicalHeight); 587 else 588 result = FloatRect(logicalTop, currBox->inlineBoxWrapper()->y() - currBox->marginTop(), logicalHeight, currBox->height() + currBox->marginTop() + currBox->marginBottom()); 589 quads.append(localToAbsoluteQuad(result)); 590 } 591 } else if (curr->isRenderInline()) { 592 // If the child doesn't need line boxes either, then we can recur. 593 RenderInline* currInline = toRenderInline(curr); 594 if (!currInline->alwaysCreateLineBoxes()) 595 currInline->culledInlineAbsoluteQuads(container, quads); 596 else { 597 for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox()) { 598 RootInlineBox* rootBox = childLine->root(); 599 int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent()); 600 int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height(); 601 FloatRect result; 602 if (isHorizontal) 603 result = FloatRect(childLine->x() - childLine->marginLogicalLeft(), 604 logicalTop, 605 childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight(), 606 logicalHeight); 607 else 608 result = FloatRect(logicalTop, 609 childLine->y() - childLine->marginLogicalLeft(), 610 logicalHeight, 611 childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight()); 612 quads.append(localToAbsoluteQuad(result)); 613 } 614 } 615 } else if (curr->isText()) { 616 RenderText* currText = toRenderText(curr); 617 for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox()) { 618 RootInlineBox* rootBox = childText->root(); 619 int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent()); 620 int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height(); 621 FloatRect result; 622 if (isHorizontal) 623 result = FloatRect(childText->x(), logicalTop, childText->logicalWidth(), logicalHeight); 624 else 625 result = FloatRect(logicalTop, childText->y(), logicalHeight, childText->logicalWidth()); 626 quads.append(localToAbsoluteQuad(result)); 627 } 628 } 629 } 630 } 631 458 632 int RenderInline::offsetLeft() const 459 633 { 460 634 int x = RenderBoxModelObject::offsetLeft(); 461 if ( firstLineBox())462 x += first LineBox()->x();635 if (InlineBox* firstBox = firstLineBoxIncludingCulling()) 636 x += firstBox->x(); 463 637 return x; 464 638 } … … 467 641 { 468 642 int y = RenderBoxModelObject::offsetTop(); 469 if ( firstLineBox())470 y += first LineBox()->y();643 if (InlineBox* firstBox = firstLineBoxIncludingCulling()) 644 y += firstBox->y(); 471 645 return y; 472 646 } … … 566 740 IntRect RenderInline::linesBoundingBox() const 567 741 { 742 if (!alwaysCreateLineBoxes()) { 743 ASSERT(!firstLineBox()); 744 return enclosingIntRect(culledInlineBoundingBox(this)); 745 } 746 568 747 IntRect result; 569 748 … … 595 774 } 596 775 776 FloatRect RenderInline::culledInlineBoundingBox(const RenderInline* container) const 777 { 778 FloatRect result; 779 bool isHorizontal = style()->isHorizontalWritingMode(); 780 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { 781 if (curr->isFloatingOrPositioned()) 782 continue; 783 784 // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block 785 // direction (aligned to the root box's baseline). 786 if (curr->isBox()) { 787 RenderBox* currBox = toRenderBox(curr); 788 if (currBox->inlineBoxWrapper()) { 789 RootInlineBox* rootBox = currBox->inlineBoxWrapper()->root(); 790 int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent()); 791 int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height(); 792 if (isHorizontal) 793 result.uniteIfNonZero(FloatRect(currBox->inlineBoxWrapper()->x() - currBox->marginLeft(), logicalTop, currBox->width() + currBox->marginLeft() + currBox->marginRight(), logicalHeight)); 794 else 795 result.uniteIfNonZero(FloatRect(logicalTop, currBox->inlineBoxWrapper()->y() - currBox->marginTop(), logicalHeight, currBox->height() + currBox->marginTop() + currBox->marginBottom())); 796 } 797 } else if (curr->isRenderInline()) { 798 // If the child doesn't need line boxes either, then we can recur. 799 RenderInline* currInline = toRenderInline(curr); 800 if (!currInline->alwaysCreateLineBoxes()) 801 result.uniteIfNonZero(currInline->culledInlineBoundingBox(container)); 802 else { 803 for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox()) { 804 RootInlineBox* rootBox = childLine->root(); 805 int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent()); 806 int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height(); 807 if (isHorizontal) 808 result.uniteIfNonZero(FloatRect(childLine->x() - childLine->marginLogicalLeft(), 809 logicalTop, 810 childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight(), 811 logicalHeight)); 812 else 813 result.uniteIfNonZero(FloatRect(logicalTop, 814 childLine->y() - childLine->marginLogicalLeft(), 815 logicalHeight, 816 childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight())); 817 818 } 819 } 820 } else if (curr->isText()) { 821 RenderText* currText = toRenderText(curr); 822 for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox()) { 823 RootInlineBox* rootBox = childText->root(); 824 int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent()); 825 int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height(); 826 if (isHorizontal) 827 result.uniteIfNonZero(FloatRect(childText->x(), logicalTop, childText->logicalWidth(), logicalHeight)); 828 else 829 result.uniteIfNonZero(FloatRect(logicalTop, childText->y(), logicalHeight, childText->logicalWidth())); 830 } 831 } 832 } 833 return enclosingIntRect(result); 834 } 835 836 InlineBox* RenderInline::culledInlineFirstLineBox() const 837 { 838 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { 839 if (curr->isFloatingOrPositioned()) 840 continue; 841 842 // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block 843 // direction (aligned to the root box's baseline). 844 if (curr->isBox()) { 845 RenderBox* currBox = toRenderBox(curr); 846 if (currBox->inlineBoxWrapper()) 847 return currBox->inlineBoxWrapper(); 848 } else if (curr->isRenderInline()) { 849 RenderInline* currInline = toRenderInline(curr); 850 InlineBox* result = currInline->firstLineBoxIncludingCulling(); 851 if (result) 852 return result; 853 } else if (curr->isText()) { 854 RenderText* currText = toRenderText(curr); 855 if (currText->firstTextBox()) 856 return currText->firstTextBox(); 857 } 858 } 859 return 0; 860 } 861 862 InlineBox* RenderInline::culledInlineLastLineBox() const 863 { 864 for (RenderObject* curr = lastChild(); curr; curr = curr->previousSibling()) { 865 if (curr->isFloatingOrPositioned()) 866 continue; 867 868 // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block 869 // direction (aligned to the root box's baseline). 870 if (curr->isBox()) { 871 RenderBox* currBox = toRenderBox(curr); 872 if (currBox->inlineBoxWrapper()) 873 return currBox->inlineBoxWrapper(); 874 } else if (curr->isRenderInline()) { 875 RenderInline* currInline = toRenderInline(curr); 876 InlineBox* result = currInline->lastLineBoxIncludingCulling(); 877 if (result) 878 return result; 879 } else if (curr->isText()) { 880 RenderText* currText = toRenderText(curr); 881 if (currText->lastTextBox()) 882 return currText->lastTextBox(); 883 } 884 } 885 return 0; 886 } 887 888 IntRect RenderInline::culledInlineVisualOverflowBoundingBox() const 889 { 890 IntRect result(culledInlineBoundingBox(this)); 891 bool isHorizontal = style()->isHorizontalWritingMode(); 892 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { 893 if (curr->isFloatingOrPositioned()) 894 continue; 895 896 // For overflow we just have to propagate by hand and recompute it all. 897 if (curr->isBox()) { 898 RenderBox* currBox = toRenderBox(curr); 899 if (!currBox->hasSelfPaintingLayer() && currBox->inlineBoxWrapper()) { 900 IntRect logicalRect = currBox->logicalVisualOverflowRectForPropagation(style()); 901 if (isHorizontal) { 902 logicalRect.move(currBox->x(), currBox->y()); 903 result.uniteIfNonZero(logicalRect); 904 } else { 905 logicalRect.move(currBox->y(), currBox->x()); 906 result.uniteIfNonZero(logicalRect.transposedRect()); 907 } 908 } 909 } else if (curr->isRenderInline()) { 910 // If the child doesn't need line boxes either, then we can recur. 911 RenderInline* currInline = toRenderInline(curr); 912 if (!currInline->alwaysCreateLineBoxes()) 913 result.uniteIfNonZero(currInline->culledInlineVisualOverflowBoundingBox()); 914 else if (!currInline->hasSelfPaintingLayer()) 915 result.uniteIfNonZero(currInline->linesVisualOverflowBoundingBox()); 916 } else if (curr->isText()) { 917 // FIXME; Overflow from text boxes is lost. We will need to cache this information in 918 // InlineTextBoxes. 919 RenderText* currText = toRenderText(curr); 920 result.uniteIfNonZero(currText->linesVisualOverflowBoundingBox()); 921 } 922 } 923 return result; 924 } 925 597 926 IntRect RenderInline::linesVisualOverflowBoundingBox() const 598 927 { 928 if (!alwaysCreateLineBoxes()) 929 return culledInlineVisualOverflowBoundingBox(); 930 599 931 if (!firstLineBox() || !lastLineBox()) 600 932 return IntRect(); 601 933 602 934 // Return the width of the minimal left side and the maximal right side. 603 float logicalLeftSide = numeric_limits<int>::max();604 float logicalRightSide = numeric_limits<int>::min();935 int logicalLeftSide = numeric_limits<int>::max(); 936 int logicalRightSide = numeric_limits<int>::min(); 605 937 for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { 606 logicalLeftSide = min(logicalLeftSide, static_cast<float>(curr->logicalLeftVisualOverflow()));607 logicalRightSide = max(logicalRightSide, static_cast<float>(curr->logicalRightVisualOverflow()));938 logicalLeftSide = min(logicalLeftSide, curr->logicalLeftVisualOverflow()); 939 logicalRightSide = max(logicalRightSide, curr->logicalRightVisualOverflow()); 608 940 } 609 941 … … 611 943 RootInlineBox* lastRootBox = lastLineBox()->root(); 612 944 613 float logicalLeft = firstLineBox()->logicalLeftVisualOverflow(); 614 float logicalTop = firstLineBox()->logicalTopVisualOverflow(firstRootBox->lineTop()); 615 float logicalWidth = logicalRightSide - logicalLeftSide; 616 float logicalHeight = lastLineBox()->logicalBottomVisualOverflow(lastRootBox->lineBottom()) - logicalTop; 617 618 IntRect rect = enclosingIntRect(FloatRect(logicalLeft, logicalTop, logicalWidth, logicalHeight)); 945 int logicalTop = firstLineBox()->logicalTopVisualOverflow(firstRootBox->lineTop()); 946 int logicalWidth = logicalRightSide - logicalLeftSide; 947 int logicalHeight = lastLineBox()->logicalBottomVisualOverflow(lastRootBox->lineBottom()) - logicalTop; 948 949 IntRect rect(logicalLeftSide, logicalTop, logicalWidth, logicalHeight); 619 950 if (!style()->isHorizontalWritingMode()) 620 951 rect = rect.transposedRect(); … … 627 958 ASSERT(!view() || !view()->layoutStateEnabled() || isRunIn()); 628 959 629 if (!firstLineBox () && !continuation())960 if (!firstLineBoxIncludingCulling() && !continuation()) 630 961 return IntRect(); 631 962 … … 895 1226 void RenderInline::dirtyLineBoxes(bool fullLayout) 896 1227 { 897 if (fullLayout) 1228 if (fullLayout) { 898 1229 m_lineBoxes.deleteLineBoxes(renderArena()); 899 else 1230 return; 1231 } 1232 1233 if (!alwaysCreateLineBoxes()) { 1234 // We have to grovel into our children in order to dirty the appropriate lines. 1235 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { 1236 if (curr->isFloatingOrPositioned()) 1237 continue; 1238 if (curr->isBox() && !curr->needsLayout()) { 1239 RenderBox* currBox = toRenderBox(curr); 1240 if (currBox->inlineBoxWrapper()) 1241 currBox->inlineBoxWrapper()->root()->markDirty(); 1242 } else if (!curr->selfNeedsLayout()) { 1243 if (curr->isRenderInline()) { 1244 RenderInline* currInline = toRenderInline(curr); 1245 for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox()) 1246 childLine->root()->markDirty(); 1247 } else if (curr->isText()) { 1248 RenderText* currText = toRenderText(curr); 1249 for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox()) 1250 childText->root()->markDirty(); 1251 } 1252 } 1253 } 1254 } else 900 1255 m_lineBoxes.dirtyLineBoxes(); 901 1256 } … … 908 1263 InlineFlowBox* RenderInline::createAndAppendInlineFlowBox() 909 1264 { 1265 setAlwaysCreateLineBoxes(); 910 1266 InlineFlowBox* flowBox = createInlineFlowBox(); 911 1267 m_lineBoxes.appendLineBox(flowBox); … … 984 1340 void RenderInline::addFocusRingRects(Vector<IntRect>& rects, int tx, int ty) 985 1341 { 986 for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) { 987 RootInlineBox* root = curr->root(); 988 int top = max(root->lineTop(), curr->logicalTop()); 989 int bottom = min(root->lineBottom(), curr->logicalBottom()); 990 IntRect rect(tx + curr->x(), ty + top, curr->logicalWidth(), bottom - top); 991 if (!rect.isEmpty()) 992 rects.append(rect); 1342 if (!alwaysCreateLineBoxes()) 1343 culledInlineAbsoluteRects(this, rects, IntSize(tx, ty)); 1344 else { 1345 for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) 1346 rects.append(enclosingIntRect(FloatRect(tx + curr->x(), ty + curr->y(), curr->width(), curr->height()))); 993 1347 } 994 1348 … … 1001 1355 else if (curr->isBox()) 1002 1356 pos.move(toRenderBox(curr)->x(), toRenderBox(curr)->y()); 1003 curr->addFocusRingRects(rects, pos.x(), pos.y());1357 curr->addFocusRingRects(rects, pos.x(), pos.y()); 1004 1358 } 1005 1359 } -
trunk/Source/WebCore/rendering/RenderInline.h
r81684 r83075 24 24 #define RenderInline_h 25 25 26 #include "InlineFlowBox.h" 26 27 #include "RenderBoxModelObject.h" 27 28 #include "RenderLineBoxList.h" … … 65 66 InlineFlowBox* firstLineBox() const { return m_lineBoxes.firstLineBox(); } 66 67 InlineFlowBox* lastLineBox() const { return m_lineBoxes.lastLineBox(); } 68 InlineBox* firstLineBoxIncludingCulling() const { return alwaysCreateLineBoxes() ? firstLineBox() : culledInlineFirstLineBox(); } 69 InlineBox* lastLineBoxIncludingCulling() const { return alwaysCreateLineBoxes() ? lastLineBox() : culledInlineLastLineBox(); } 67 70 68 71 virtual RenderBoxModelObject* virtualContinuation() const { return continuation(); } … … 79 82 using RenderBoxModelObject::setContinuation; 80 83 84 bool alwaysCreateLineBoxes() const { return m_alwaysCreateLineBoxes; } 85 void setAlwaysCreateLineBoxes() { m_alwaysCreateLineBoxes = true; } 86 void updateAlwaysCreateLineBoxes(); 87 81 88 protected: 82 89 virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle); … … 91 98 92 99 virtual bool isRenderInline() const { return true; } 100 101 FloatRect culledInlineBoundingBox(const RenderInline* container) const; 102 IntRect culledInlineVisualOverflowBoundingBox() const; 103 InlineBox* culledInlineFirstLineBox() const; 104 InlineBox* culledInlineLastLineBox() const; 105 void culledInlineAbsoluteRects(const RenderInline* container, Vector<IntRect>&, const IntSize&); 106 void culledInlineAbsoluteQuads(const RenderInline* container, Vector<FloatQuad>&); 93 107 94 108 void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild); … … 155 169 RenderLineBoxList m_lineBoxes; // All of the line boxes created for this inline flow. For example, <i>Hello<br>world.</i> will have two <i> line boxes. 156 170 157 mutable int m_lineHeight; 171 mutable int m_lineHeight : 31; 172 bool m_alwaysCreateLineBoxes : 1; 158 173 }; 159 174 -
trunk/Source/WebCore/rendering/RenderLineBoxList.cpp
r82611 r83075 318 318 return; 319 319 320 RenderInline* inlineContainer = container->isRenderInline() ? toRenderInline(container) : 0; 321 InlineBox* firstBox = inlineContainer ? inlineContainer->firstLineBoxIncludingCulling() : firstLineBox(); 322 320 323 // If we have no first line box, then just bail early. 321 if (!first LineBox()) {324 if (!firstBox) { 322 325 // For an empty inline, go ahead and propagate the check up to our parent, unless the parent 323 326 // is already dirty. … … 345 348 box = textBox->root(); 346 349 } else if (curr->isRenderInline()) { 347 Inline FlowBox* flowBox = toRenderInline(curr)->lastLineBox();348 if ( flowBox)349 box = flowBox->root();350 InlineBox* lastSiblingBox = toRenderInline(curr)->lastLineBoxIncludingCulling(); 351 if (lastSiblingBox) 352 box = lastSiblingBox->root(); 350 353 } 351 354 … … 354 357 } 355 358 if (!box) 356 box = first LineBox()->root();359 box = firstBox->root(); 357 360 358 361 // If we found a line box, then dirty it. -
trunk/Source/WebCore/rendering/RenderText.cpp
r82105 r83075 178 178 } 179 179 180 void RenderText:: destroy()180 void RenderText::removeAndDestroyTextBoxes() 181 181 { 182 182 if (!documentBeingDestroyed()) { … … 193 193 } 194 194 deleteTextBoxes(); 195 } 196 197 void RenderText::destroy() 198 { 199 removeAndDestroyTextBoxes(); 195 200 RenderObject::destroy(); 196 201 } … … 269 274 { 270 275 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) 271 rects.append( IntRect(tx + box->x(), ty + box->y(), box->logicalWidth(), box->logicalHeight()));276 rects.append(enclosingIntRect(FloatRect(tx + box->x(), ty + box->y(), box->width(), box->height()))); 272 277 } 273 278 … … 1301 1306 } 1302 1307 1308 IntRect RenderText::linesVisualOverflowBoundingBox() const 1309 { 1310 if (!firstTextBox()) 1311 return IntRect(); 1312 1313 // Return the width of the minimal left side and the maximal right side. 1314 int logicalLeftSide = numeric_limits<int>::max(); 1315 int logicalRightSide = numeric_limits<int>::min(); 1316 for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) { 1317 logicalLeftSide = min(logicalLeftSide, curr->logicalLeftVisualOverflow()); 1318 logicalRightSide = max(logicalRightSide, curr->logicalRightVisualOverflow()); 1319 } 1320 1321 int logicalTop = firstTextBox()->logicalTopVisualOverflow(); 1322 int logicalWidth = logicalRightSide - logicalLeftSide; 1323 int logicalHeight = lastTextBox()->logicalBottomVisualOverflow() - logicalTop; 1324 1325 IntRect rect(logicalLeftSide, logicalTop, logicalWidth, logicalHeight); 1326 if (!style()->isHorizontalWritingMode()) 1327 rect = rect.transposedRect(); 1328 return rect; 1329 } 1330 1303 1331 IntRect RenderText::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) 1304 1332 { -
trunk/Source/WebCore/rendering/RenderText.h
r81992 r83075 86 86 87 87 virtual IntRect linesBoundingBox() const; 88 IntRect linesVisualOverflowBoundingBox() const; 88 89 89 90 FloatPoint firstRunOrigin() const; … … 127 128 128 129 bool knownToHaveNoOverflowAndNoFallbackFonts() const { return m_knownToHaveNoOverflowAndNoFallbackFonts; } 130 131 void removeAndDestroyTextBoxes(); 129 132 130 133 protected: -
trunk/Source/WebCore/rendering/svg/RenderSVGInline.cpp
r75325 r83075 34 34 : RenderInline(n) 35 35 { 36 setAlwaysCreateLineBoxes(); 36 37 } 37 38 -
trunk/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp
r82611 r83075 104 104 characterLayout.layoutInlineTextBox(textBox); 105 105 } else { 106 ASSERT(child->isInlineFlowBox());107 108 106 // Skip generated content. 109 107 Node* node = child->renderer()->node(); 110 108 if (!node) 111 109 continue; 110 111 ASSERT(child->isInlineFlowBox()); 112 112 113 113 SVGInlineFlowBox* flowBox = static_cast<SVGInlineFlowBox*>(child); … … 147 147 textBox->setLogicalHeight(boxRect.height()); 148 148 } else { 149 ASSERT(child->isInlineFlowBox());150 151 149 // Skip generated content. 152 150 if (!child->renderer()->node()) 153 151 continue; 152 153 ASSERT(child->isInlineFlowBox()); 154 154 155 155 SVGInlineFlowBox* flowBox = static_cast<SVGInlineFlowBox*>(child);
Note: See TracChangeset
for help on using the changeset viewer.