Changeset 83075 in webkit


Ignore:
Timestamp:
Apr 6, 2011 11:20:52 AM (13 years ago)
Author:
hyatt@apple.com
Message:

https://bugs.webkit.org/show_bug.cgi?id=57916

Reviewed by Dan Bernstein.

Implement an optimization to the line box tree to cull out most of the intermediate
line boxes that can occur between the root line box and the leaves of the tree (images
and text).

Source/WebCore:

RenderInlines now have a boolean member, m_alwaysCreateLineBoxes,
that starts off as false. Only if it gets flipped to true will there be any line boxes
created for that RenderInline.

  • page/FocusController.cpp:

(WebCore::FocusController::advanceFocusDirectionally):
Adjust the ordering of updateLayout calls to make sure rects aren't queried unless layout
is up to date.

  • page/SpatialNavigation.cpp:

(WebCore::hasOffscreenRect):
(WebCore::nodeRectInAbsoluteCoordinates):
Add asserts in spatial navigation code to catch any future bad queries that might be made
for rectangles without layout being up to date.

  • platform/graphics/FloatRect.cpp:

(WebCore::FloatRect::uniteIfNonZero):

  • platform/graphics/FloatRect.h:
  • platform/graphics/IntRect.cpp:

(WebCore::IntRect::uniteIfNonZero):

  • platform/graphics/IntRect.h:

Add a new unite function that is useful for the render tree to FloatRect and IntRect. This
version allows rect unites to happen if either width or height is nonzero.

  • rendering/HitTestResult.cpp:

(WebCore::HitTestResult::addNodeToRectBasedTestResult):
Make sure rect-based hit testing properly adds in culled inline ancestors to the set of nodes
if content inside those inlines is hit.

  • rendering/InlineBox.h:

(WebCore::InlineBox::logicalFrameRect):
Fix a bug in this function for obtaining the logical frame rect of an inline box.

  • rendering/InlineFlowBox.cpp:

(WebCore::InlineFlowBox::addToLine):
addToLine now also checks line gap in the line box tree optimization checks.

(WebCore::InlineFlowBox::addTextBoxVisualOverflow):
(WebCore::InlineFlowBox::computeOverflow):

  • rendering/InlineFlowBox.h:

Rewritten to add the text box overflow to the text box itself.

  • rendering/InlineTextBox.cpp:

(WebCore::InlineTextBox::destroy):
Destroy has been changed to call a helper function to remove and destroy the line boxes that
is now called from one additional spot.

(WebCore::InlineTextBox::logicalOverflowRect):
(WebCore::InlineTextBox::setLogicalOverflowRect):
Text boxes now cache their own overflow in a global hash table.

(WebCore::InlineTextBox::baselinePosition):
(WebCore::InlineTextBox::lineHeight):
Changed to not assume that the parent line box's renderer is the RenderText's immediate
parent, since intermediate line boxes may have been culled.

(WebCore::InlineTextBox::paint):
Paint now properly checks only the text box overflow instead of the parent line box's overflow.

  • rendering/InlineTextBox.h:

(WebCore::InlineTextBox::logicalTopVisualOverflow):
(WebCore::InlineTextBox::logicalBottomVisualOverflow):
(WebCore::InlineTextBox::logicalLeftVisualOverflow):
(WebCore::InlineTextBox::logicalRightVisualOverflow):
New accessors to obtain overflow for inline text boxes.

  • rendering/RenderBlock.cpp:

(WebCore::RenderBlock::updateFirstLetter):
updateFirstLetter now removes text boxes from the line box tree before it destroys them, since those
text boxes may not have anything in between them and the block that contains the inline first letter
container.

  • rendering/RenderBlockLineLayout.cpp:

(WebCore::RenderBlock::createLineBoxes):
The culling optimization is done here. Only if the RenderInline says that boxes are allowed will they
be created.

(WebCore::RenderBlock::layoutInlineChildren):
The state of the RenderInline is updated here, in case it is discovered that line boxes are now needed.
This is done before any lines are built.

  • rendering/RenderInline.cpp:

(WebCore::RenderInline::RenderInline):
The new m_alwaysCreateLineBoxes flag has been added to the constructor.

(WebCore::RenderInline::styleDidChange):
An initial update of the m_alwaysCreateLineBoxes happens here for things that can be checked immediately
(like having a layer, borders, padding, margins or backgrounds). Some checks that depend on examining
the RenderInline's parent (including first line styles) happen later in layoutInlineChildren.

(WebCore::RenderInline::updateAlwaysCreateLineBoxes):
The function called by layoutInlineChildren to check parent and child style differences (e.g., font,
vertical alignment, line height, etc.).

(WebCore::RenderInline::absoluteRects):
(WebCore::RenderInline::culledInlineAbsoluteRects):
absoluteRects calls culledInlineAbsoluteRects when m_alwaysCreateLineBoxes is false.

(WebCore::RenderInline::absoluteQuads):
(WebCore::RenderInline::culledInlineAbsoluteQuads):
absoluteQuads calls culledInlineAbsoluteQuads when m_alwaysCreateLineBoxes is false.

(WebCore::RenderInline::offsetLeft):
(WebCore::RenderInline::offsetTop):
offsetLeft and offsetTop now check descendant renderers when m_alwaysCreateLineBoxes is false.

(WebCore::RenderInline::linesBoundingBox):
(WebCore::RenderInline::culledInlineBoundingBox):
lineBoundingBox calls culledInlineBoundingBox when m_alwaysCreateLineBoxes is false.

(WebCore::RenderInline::culledInlineFirstLineBox):
(WebCore::RenderInline::culledInlineLastLineBox):
Helpers that return the first and last line box descendants. Used by firstLineBoxIncludingCulling and
lastLineBoxIncludingCulling (which are in turn called by offsetLeft and offsetTop).

(WebCore::RenderInline::culledInlineVisualOverflowBoundingBox):
(WebCore::RenderInline::linesVisualOverflowBoundingBox):
linesVisualOverflowBoundingBox calls culledInlineVisualOverflowBoundingBox when m_alwaysCreateLineBoxes is false.

(WebCore::RenderInline::clippedOverflowRectForRepaint):
The initial bailout check is now done using firstLineBoxIncludingCulling instead of just firstLineBox.

(WebCore::RenderInline::dirtyLineBoxes):
dirtyLineBoxes now crawls into descendants to figure out which root lines to dirty when
m_alwaysCreateLineBoxes is false.

(WebCore::RenderInline::createAndAppendInlineFlowBox):
Clear the m_alwaysCreateLineBoxes if a box gets added anyway. This happens for leaf inline flows and also
when line-box-contain is set to an unusual value.

(WebCore::RenderInline::addFocusRingRects):
Used culledInlineAbsoluteRects in place of the line box walk when m_alwaysCreateLineBoxes is false.

  • rendering/RenderInline.h:

(WebCore::RenderInline::firstLineBoxIncludingCulling):
(WebCore::RenderInline::lastLineBoxIncludingCulling):
Helpers used in a few places (like offsetLeft and offsetTop), mostly in places where the existence of a box
is all that needs checking.

(WebCore::RenderInline::alwaysCreateLineBoxes):
(WebCore::RenderInline::setAlwaysCreateLineBoxes):
Functions for getting and setting the m_alwaysCreateLineBoxes flag.

  • rendering/RenderLineBoxList.cpp:

(WebCore::RenderLineBoxList::dirtyLinesFromChangedChild):
Modified to use firstLineBoxIncludingCulling and lastLineBoxIncludingCulling to ensure the right set of
lines get dirtied.

  • rendering/RenderText.cpp:

(WebCore::RenderText::removeAndDestroyTextBoxes):
New helper invoked by destroy and also from updateFirstLetter.

(WebCore::RenderText::destroy):
Changed to call removeAndDestroyTextBoxes.

(WebCore::RenderText::absoluteRects):
Fixed to be properly physical instead of logical.

(WebCore::RenderText::linesVisualOverflowBoundingBox):
New implementation for RenderText that gives the bounding box of the text boxes including overflow from
shadows, glyphs, text-stroke, etc. Used by RenderInline::culledInlineVisualOverflowBoundingBox.

  • rendering/RenderText.h:
  • rendering/svg/RenderSVGInline.cpp:

(WebCore::RenderSVGInline::RenderSVGInline):
RenderSVGInline always sets m_alwaysCreateLineBoxes to true so that SVG is unaffected by this optimization.

  • rendering/svg/SVGRootInlineBox.cpp:

(WebCore::SVGRootInlineBox::layoutCharactersInTextBoxes):
(WebCore::SVGRootInlineBox::layoutChildBoxes):
Move the isInlineFlowBox asserts to after the generated content skips, since the generated content boxes are
now InlineTextBoxes (the enclosing InlineFlowBoxes got culled).

LayoutTests:

RenderInlines now have a boolean member, m_alwaysCreateLineBoxes,
that starts off as false. Only if it gets flipped to true will there be any line boxes
created for that RenderInline.

  • platform/mac/fast/blockflow/text-orientation-basic-expected.txt:
  • platform/mac/fast/text/capitalize-empty-generated-string-expected.txt:
Location:
trunk
Files:
26 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r83074 r83075  
     12011-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
    1182011-04-06  MORITA Hajime  <morrita@google.com>
    219
  • trunk/LayoutTests/platform/mac/fast/blockflow/text-orientation-basic-expected.txt

    r80582 r83075  
    2727            RenderText {#text} at (44,1) size 40x254
    2828              text run at (44,1) width 254: "Hello world"
    29           RenderBR {BR} at (64,254) size 0x1
     29          RenderBR {BR} at (52,254) size 0x1
    3030          RenderInline {SPAN} at (0,0) size 36x199
    3131            RenderText {#text} at (94,1) size 36x199
     
    4545            RenderText {#text} at (44,1) size 40x255
    4646              text run at (44,1) width 255: "Hello world"
    47           RenderBR {BR} at (64,256) size 0x0
     47          RenderBR {BR} at (52,256) size 0x0
    4848          RenderInline {SPAN} at (0,0) size 36x198
    4949            RenderText {#text} at (94,1) size 36x198
  • trunk/LayoutTests/platform/mac/fast/text/capitalize-empty-generated-string-expected.txt

    r30635 r83075  
    2323            text run at (0,0) width 46: "Lorem "
    2424          RenderInline {SPAN} at (0,0) size 39x18
    25             RenderInline (generated) at (0,0) size 0x18
     25            RenderInline (generated) at (0,0) size 0x0
    2626              RenderText at (0,0) size 0x0
    2727            RenderText {#text} at (46,0) size 39x18
     
    3939            text run at (0,0) width 23: "Lor"
    4040          RenderInline {SPAN} at (0,0) size 62x18
    41             RenderInline (generated) at (0,0) size 0x18
     41            RenderInline (generated) at (0,0) size 0x0
    4242              RenderText at (0,0) size 0x0
    4343            RenderText {#text} at (23,0) size 62x18
  • trunk/Source/WebCore/ChangeLog

    r83070 r83075  
     12011-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
    11842011-04-05  Enrica Casucci  <enrica@apple.com>
    2185
  • trunk/Source/WebCore/page/FocusController.cpp

    r82525 r83075  
    598598    Node* container = focusedDocument;
    599599
     600    if (container->isDocumentNode())
     601        static_cast<Document*>(container)->updateLayoutIgnorePendingStylesheets();
     602       
    600603    // Figure out the starting rect.
    601604    IntRect startingRect;
     
    613616    bool consumed = false;
    614617    do {
    615         if (container->isDocumentNode())
    616             static_cast<Document*>(container)->updateLayoutIgnorePendingStylesheets();
    617618        consumed = advanceFocusDirectionallyInContainer(container, startingRect, direction, event);
    618619        startingRect = nodeRectInAbsoluteCoordinates(container, true /* ignore border */);
    619620        container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, container);
     621        if (container && container->isDocumentNode())
     622            static_cast<Document*>(container)->updateLayoutIgnorePendingStylesheets();
    620623    } while (!consumed && container);
    621624
  • trunk/Source/WebCore/page/SpatialNavigation.cpp

    r79021 r83075  
    301301        return true;
    302302
     303    ASSERT(!frameView->needsLayout());
     304
    303305    IntRect containerViewportRect = frameView->visibleContentRect();
    304306    // We want to select a node if it is currently off screen, but will be
     
    518520IntRect nodeRectInAbsoluteCoordinates(Node* node, bool ignoreBorder)
    519521{
    520     ASSERT(node && node->renderer());
     522    ASSERT(node && node->renderer() && !node->document()->view()->needsLayout());
    521523
    522524    if (node->isDocumentNode())
  • trunk/Source/WebCore/platform/graphics/FloatRect.cpp

    r77286 r83075  
    9898}
    9999
     100void 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
    100118void FloatRect::scale(float sx, float sy)
    101119{
  • trunk/Source/WebCore/platform/graphics/FloatRect.h

    r79578 r83075  
    113113    void intersect(const FloatRect&);
    114114    void unite(const FloatRect&);
     115    void uniteIfNonZero(const FloatRect&);
    115116
    116117    // Note, this doesn't match what IntRect::contains(IntPoint&) does; the int version
  • trunk/Source/WebCore/platform/graphics/FontMetrics.h

    r76445 r83075  
    9797    int lineSpacing() const { return lroundf(m_lineSpacing); }
    9898
     99    bool hasIdenticalAscentDescentAndLineGap(const FontMetrics& other) const
     100    {
     101        return ascent() == other.ascent() && descent() == other.descent() && lineGap() == other.lineGap();
     102    }
     103
    99104private:
    100105    friend class SimpleFontData;
  • trunk/Source/WebCore/platform/graphics/IntRect.cpp

    r77286 r83075  
    9797}
    9898
     99void 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
    99120void IntRect::scale(float s)
    100121{
  • trunk/Source/WebCore/platform/graphics/IntRect.h

    r79578 r83075  
    145145    void intersect(const IntRect&);
    146146    void unite(const IntRect&);
     147    void uniteIfNonZero(const IntRect&);
    147148
    148149    void inflateX(int dx)
  • trunk/Source/WebCore/rendering/HitTestResult.cpp

    r82340 r83075  
    3333#include "HTMLParserIdioms.h"
    3434#include "RenderImage.h"
     35#include "RenderInline.h"
    3536#include "Scrollbar.h"
    3637#include "SelectionController.h"
     
    545546    mutableRectBasedTestResult().add(node);
    546547
     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    }
    547562    return !rect.contains(rectForPoint(x, y));
    548563}
     
    562577    mutableRectBasedTestResult().add(node);
    563578
     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    }
    564593    return !rect.contains(rectForPoint(x, y));
    565594}
  • trunk/Source/WebCore/rendering/InlineBox.h

    r82611 r83075  
    264264    int logicalHeight() const;
    265265
    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()); }
    267267
    268268    virtual int baselinePosition(FontBaseline baselineType) const { return boxModelObject()->baselinePosition(baselineType, m_firstLine, isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine); }
  • trunk/Source/WebCore/rendering/InlineFlowBox.cpp

    r82611 r83075  
    9898    child->setIsHorizontal(isHorizontal());
    9999    if (child->isText()) {
    100         m_hasTextChildren = true;
     100        if (child->renderer()->parent() == renderer())
     101            m_hasTextChildren = true;
    101102        m_hasTextDescendants = true;
    102103    } else if (child->isInlineFlowBox()) {
     
    112113            shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
    113114        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()
    117118                    || (parentStyle->verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle->verticalAlign() != BASELINE)
    118119                    shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
    119             } else if (childStyle->hasTextCombine() || childStyle->textEmphasisMark() != TextEmphasisMarkNone)
     120            }
     121            if (childStyle->hasTextCombine() || childStyle->textEmphasisMark() != TextEmphasisMarkNone)
    120122                shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
    121123        } else {
     
    128130                InlineFlowBox* childFlowBox = static_cast<InlineFlowBox*>(child);
    129131                // 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()
    132135                    || (parentStyle->verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle->verticalAlign() != BASELINE
    133136                    || childStyle->hasBorder() || childStyle->hasPadding() || childStyle->hasTextCombine())
     
    733736}
    734737
    735 inline void InlineFlowBox::addTextBoxVisualOverflow(const InlineTextBox* textBox, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, IntRect& logicalVisualOverflow)
     738inline void InlineFlowBox::addTextBoxVisualOverflow(InlineTextBox* textBox, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, IntRect& logicalVisualOverflow)
    736739{
    737740    if (textBox->knownToHaveNoOverflow())
    738741        return;
    739742
    740     RenderStyle* style = renderer()->style(m_firstLine);
     743    RenderStyle* style = textBox->renderer()->style(m_firstLine);
    741744   
    742745    GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(textBox);
     
    789792    logicalVisualOverflow = IntRect(logicalLeftVisualOverflow, logicalTopVisualOverflow,
    790793                                    logicalRightVisualOverflow - logicalLeftVisualOverflow, logicalBottomVisualOverflow - logicalTopVisualOverflow);
     794                                   
     795    textBox->setLogicalOverflowRect(logicalVisualOverflow);
    791796}
    792797
     
    836841            if (rt->isBR())
    837842                continue;
    838             addTextBoxVisualOverflow(text, textBoxDataMap, logicalVisualOverflow);
     843            IntRect textBoxOverflow(enclosingIntRect(text->logicalFrameRect()));
     844            addTextBoxVisualOverflow(text, textBoxDataMap, textBoxOverflow);
     845            logicalVisualOverflow.unite(textBoxOverflow);
    839846        } else  if (curr->renderer()->isRenderInline()) {
    840847            InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr);
  • trunk/Source/WebCore/rendering/InlineFlowBox.h

    r82611 r83075  
    273273private:
    274274    void addBoxShadowVisualOverflow(IntRect& logicalVisualOverflow);
    275     void addTextBoxVisualOverflow(const InlineTextBox*, GlyphOverflowAndFallbackFontsMap&, IntRect& logicalVisualOverflow);
     275    void addTextBoxVisualOverflow(InlineTextBox*, GlyphOverflowAndFallbackFontsMap&, IntRect& logicalVisualOverflow);
    276276    void addReplacedChildOverflow(const InlineBox*, IntRect& logicalLayoutOverflow, IntRect& logicalVisualOverflow);
    277277
  • trunk/Source/WebCore/rendering/InlineTextBox.cpp

    r82611 r83075  
    4949namespace WebCore {
    5050
     51typedef WTF::HashMap<const InlineTextBox*, IntRect> InlineTextBoxOverflowMap;
     52static InlineTextBoxOverflowMap* gTextBoxesWithOverflow;
     53
     54void InlineTextBox::destroy(RenderArena* arena)
     55{
     56    if (!m_knownToHaveNoOverflow && gTextBoxesWithOverflow)
     57        gTextBoxesWithOverflow->remove(this);
     58    InlineBox::destroy(arena);
     59}
     60
     61IntRect InlineTextBox::logicalOverflowRect() const
     62{
     63    if (m_knownToHaveNoOverflow || !gTextBoxesWithOverflow)
     64        return enclosingIntRect(logicalFrameRect());
     65    return gTextBoxesWithOverflow->get(this);
     66}
     67
     68void InlineTextBox::setLogicalOverflowRect(const IntRect& rect)
     69{
     70    ASSERT(!m_knownToHaveNoOverflow);
     71    if (!gTextBoxesWithOverflow)
     72        gTextBoxesWithOverflow = new InlineTextBoxOverflowMap;
     73    gTextBoxesWithOverflow->add(this, rect);
     74}
     75
    5176int InlineTextBox::baselinePosition(FontBaseline baselineType) const
    5277{
    5378    if (!isText() || !parent())
    5479        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);
    5683}
    5784   
    5885int InlineTextBox::lineHeight() const
    5986{
    60     if (!isText() || !parent())
     87    if (!isText() || !renderer()->parent())
    6188        return 0;
    6289    if (m_renderer->isBR())
    6390        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);
    6594}
    6695
     
    436465}
    437466
    438 void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty, int lineTop, int lineBottom)
     467void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty, int /*lineTop*/, int /*lineBottom*/)
    439468{
    440469    if (isLineBreak() || !paintInfo.shouldPaintWithinRoot(renderer()) || renderer()->style()->visibility() != VISIBLE ||
     
    444473    ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines);
    445474
    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;
    457479   
    458480    int paintEnd = isHorizontal() ? paintInfo.rect.maxX() : paintInfo.rect.maxY();
  • trunk/Source/WebCore/rendering/InlineTextBox.h

    r82611 r83075  
    5252    }
    5353
     54    virtual void destroy(RenderArena*);
     55
    5456    InlineTextBox* prevTextBox() const { return m_prevTextBox; }
    5557    InlineTextBox* nextTextBox() const { return m_nextTextBox; }
     
    8183    bool getEmphasisMarkPosition(RenderStyle*, TextEmphasisPosition&) const;
    8284
     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   
    8392private:
    8493    int selectionTop();
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r83042 r83075  
    53275327            while (RenderObject* child = firstLetter->firstChild()) {
    53285328                if (child->isText())
    5329                     toRenderText(child)->dirtyLineBoxes(true);
     5329                    toRenderText(child)->removeAndDestroyTextBoxes();
    53305330                firstLetter->removeChild(child);
    53315331                newFirstLetter->addChild(child, 0);
  • trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp

    r83066 r83075  
    214214        ASSERT(obj->isRenderInline() || obj == this);
    215215       
     216        RenderInline* inlineFlow = (obj != this) ? toRenderInline(obj) : 0;
     217
    216218        // 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();
    218220
    219221        // If this box or its ancestor is constructed then it is from a previous line, and we need
     
    223225        // the same line (this can happen with very fancy language mixtures).
    224226        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) {
    226230            // We need to make a new box for this render object.  Once
    227231            // made, we need to place it at the end of the current line.
     
    236240        }
    237241
    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        }
    251257
    252258        // If we've exceeded our line depth, then jump straight to the root and skip all the remaining
     
    761767                }
    762768            } else if (o->isText() || (o->isRenderInline() && !endOfInline)) {
     769                if (!o->isText())
     770                    toRenderInline(o)->updateAlwaysCreateLineBoxes();
    763771                if (fullLayout || o->selfNeedsLayout())
    764772                    dirtyLineBoxesForRenderer(o, fullLayout);
  • trunk/Source/WebCore/rendering/RenderInline.cpp

    r82611 r83075  
    2828#include "GraphicsContext.h"
    2929#include "HitTestResult.h"
     30#include "InlineTextBox.h"
    3031#include "Page.h"
    3132#include "RenderArena.h"
     
    4849    : RenderBoxModelObject(node)
    4950    , m_lineHeight(-1)
     51    , m_alwaysCreateLineBoxes(false)
    5052{
    5153    setChildrenInline(true);
     
    145147    m_lineHeight = -1;
    146148
     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
    147158    // Update pseudos for :before and :after now.
    148159    if (!isAnonymous() && document()->usesBeforeAfterRules()) {
    149160        children()->updateBeforeAfterContent(this, BEFORE);
    150161        children()->updateBeforeAfterContent(this, AFTER);
     162    }
     163}
     164
     165void 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;
    151195    }
    152196}
     
    425469void RenderInline::absoluteRects(Vector<IntRect>& rects, int tx, int ty)
    426470{
    427     if (InlineFlowBox* curr = firstLineBox()) {
     471    if (!alwaysCreateLineBoxes())
     472        culledInlineAbsoluteRects(this, rects, IntSize(tx, ty));
     473    else if (InlineFlowBox* curr = firstLineBox()) {
    428474        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())));
    430476    } else
    431477        rects.append(IntRect(tx, ty, 0, 0));
     
    442488}
    443489
     490void 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
    444553void RenderInline::absoluteQuads(Vector<FloatQuad>& quads)
    445554{
    446     if (InlineFlowBox* curr = firstLineBox()) {
     555    if (!alwaysCreateLineBoxes())
     556        culledInlineAbsoluteQuads(this, quads);
     557    else if (InlineFlowBox* curr = firstLineBox()) {
    447558        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());
    449560            quads.append(localToAbsoluteQuad(localRect));
    450561        }
     
    456567}
    457568
     569void 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
    458632int RenderInline::offsetLeft() const
    459633{
    460634    int x = RenderBoxModelObject::offsetLeft();
    461     if (firstLineBox())
    462         x += firstLineBox()->x();
     635    if (InlineBox* firstBox = firstLineBoxIncludingCulling())
     636        x += firstBox->x();
    463637    return x;
    464638}
     
    467641{
    468642    int y = RenderBoxModelObject::offsetTop();
    469     if (firstLineBox())
    470         y += firstLineBox()->y();
     643    if (InlineBox* firstBox = firstLineBoxIncludingCulling())
     644        y += firstBox->y();
    471645    return y;
    472646}
     
    566740IntRect RenderInline::linesBoundingBox() const
    567741{
     742    if (!alwaysCreateLineBoxes()) {
     743        ASSERT(!firstLineBox());
     744        return enclosingIntRect(culledInlineBoundingBox(this));
     745    }
     746
    568747    IntRect result;
    569748   
     
    595774}
    596775
     776FloatRect 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
     836InlineBox* 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
     862InlineBox* 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
     888IntRect 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
    597926IntRect RenderInline::linesVisualOverflowBoundingBox() const
    598927{
     928    if (!alwaysCreateLineBoxes())
     929        return culledInlineVisualOverflowBoundingBox();
     930
    599931    if (!firstLineBox() || !lastLineBox())
    600932        return IntRect();
    601933
    602934    // 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();
    605937    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());
    608940    }
    609941
     
    611943    RootInlineBox* lastRootBox = lastLineBox()->root();
    612944   
    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);
    619950    if (!style()->isHorizontalWritingMode())
    620951        rect = rect.transposedRect();
     
    627958    ASSERT(!view() || !view()->layoutStateEnabled() || isRunIn());
    628959
    629     if (!firstLineBox() && !continuation())
     960    if (!firstLineBoxIncludingCulling() && !continuation())
    630961        return IntRect();
    631962
     
    8951226void RenderInline::dirtyLineBoxes(bool fullLayout)
    8961227{
    897     if (fullLayout)
     1228    if (fullLayout) {
    8981229        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
    9001255        m_lineBoxes.dirtyLineBoxes();
    9011256}
     
    9081263InlineFlowBox* RenderInline::createAndAppendInlineFlowBox()
    9091264{
     1265    setAlwaysCreateLineBoxes();
    9101266    InlineFlowBox* flowBox = createInlineFlowBox();
    9111267    m_lineBoxes.appendLineBox(flowBox);
     
    9841340void RenderInline::addFocusRingRects(Vector<IntRect>& rects, int tx, int ty)
    9851341{
    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())));
    9931347    }
    9941348
     
    10011355            else if (curr->isBox())
    10021356                pos.move(toRenderBox(curr)->x(), toRenderBox(curr)->y());
    1003            curr->addFocusRingRects(rects, pos.x(), pos.y());
     1357            curr->addFocusRingRects(rects, pos.x(), pos.y());
    10041358        }
    10051359    }
  • trunk/Source/WebCore/rendering/RenderInline.h

    r81684 r83075  
    2424#define RenderInline_h
    2525
     26#include "InlineFlowBox.h"
    2627#include "RenderBoxModelObject.h"
    2728#include "RenderLineBoxList.h"
     
    6566    InlineFlowBox* firstLineBox() const { return m_lineBoxes.firstLineBox(); }
    6667    InlineFlowBox* lastLineBox() const { return m_lineBoxes.lastLineBox(); }
     68    InlineBox* firstLineBoxIncludingCulling() const { return alwaysCreateLineBoxes() ? firstLineBox() : culledInlineFirstLineBox(); }
     69    InlineBox* lastLineBoxIncludingCulling() const { return alwaysCreateLineBoxes() ? lastLineBox() : culledInlineLastLineBox(); }
    6770
    6871    virtual RenderBoxModelObject* virtualContinuation() const { return continuation(); }
     
    7982    using RenderBoxModelObject::setContinuation;
    8083
     84    bool alwaysCreateLineBoxes() const { return m_alwaysCreateLineBoxes; }
     85    void setAlwaysCreateLineBoxes() { m_alwaysCreateLineBoxes = true; }
     86    void updateAlwaysCreateLineBoxes();
     87
    8188protected:
    8289    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
     
    9198
    9299    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>&);
    93107
    94108    void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild);
     
    155169    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.
    156170
    157     mutable int m_lineHeight;
     171    mutable int m_lineHeight : 31;
     172    bool m_alwaysCreateLineBoxes : 1;
    158173};
    159174
  • trunk/Source/WebCore/rendering/RenderLineBoxList.cpp

    r82611 r83075  
    318318        return;
    319319
     320    RenderInline* inlineContainer = container->isRenderInline() ? toRenderInline(container) : 0;
     321    InlineBox* firstBox = inlineContainer ? inlineContainer->firstLineBoxIncludingCulling() : firstLineBox();
     322
    320323    // If we have no first line box, then just bail early.
    321     if (!firstLineBox()) {
     324    if (!firstBox) {
    322325        // For an empty inline, go ahead and propagate the check up to our parent, unless the parent
    323326        // is already dirty.
     
    345348                box = textBox->root();
    346349        } else if (curr->isRenderInline()) {
    347             InlineFlowBox* flowBox = toRenderInline(curr)->lastLineBox();
    348             if (flowBox)
    349                 box = flowBox->root();
     350            InlineBox* lastSiblingBox = toRenderInline(curr)->lastLineBoxIncludingCulling();
     351            if (lastSiblingBox)
     352                box = lastSiblingBox->root();
    350353        }
    351354
     
    354357    }
    355358    if (!box)
    356         box = firstLineBox()->root();
     359        box = firstBox->root();
    357360
    358361    // If we found a line box, then dirty it.
  • trunk/Source/WebCore/rendering/RenderText.cpp

    r82105 r83075  
    178178}
    179179
    180 void RenderText::destroy()
     180void RenderText::removeAndDestroyTextBoxes()
    181181{
    182182    if (!documentBeingDestroyed()) {
     
    193193    }
    194194    deleteTextBoxes();
     195}
     196
     197void RenderText::destroy()
     198{
     199    removeAndDestroyTextBoxes();
    195200    RenderObject::destroy();
    196201}
     
    269274{
    270275    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())));
    272277}
    273278
     
    13011306}
    13021307
     1308IntRect 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
    13031331IntRect RenderText::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
    13041332{
  • trunk/Source/WebCore/rendering/RenderText.h

    r81992 r83075  
    8686
    8787    virtual IntRect linesBoundingBox() const;
     88    IntRect linesVisualOverflowBoundingBox() const;
    8889
    8990    FloatPoint firstRunOrigin() const;
     
    127128   
    128129    bool knownToHaveNoOverflowAndNoFallbackFonts() const { return m_knownToHaveNoOverflowAndNoFallbackFonts; }
     130
     131    void removeAndDestroyTextBoxes();
    129132
    130133protected:
  • trunk/Source/WebCore/rendering/svg/RenderSVGInline.cpp

    r75325 r83075  
    3434    : RenderInline(n)
    3535{
     36    setAlwaysCreateLineBoxes();
    3637}
    3738
  • trunk/Source/WebCore/rendering/svg/SVGRootInlineBox.cpp

    r82611 r83075  
    104104            characterLayout.layoutInlineTextBox(textBox);
    105105        } else {
    106             ASSERT(child->isInlineFlowBox());
    107 
    108106            // Skip generated content.
    109107            Node* node = child->renderer()->node();
    110108            if (!node)
    111109                continue;
     110
     111            ASSERT(child->isInlineFlowBox());
    112112
    113113            SVGInlineFlowBox* flowBox = static_cast<SVGInlineFlowBox*>(child);
     
    147147            textBox->setLogicalHeight(boxRect.height());
    148148        } else {
    149             ASSERT(child->isInlineFlowBox());
    150 
    151149            // Skip generated content.
    152150            if (!child->renderer()->node())
    153151                continue;
     152
     153            ASSERT(child->isInlineFlowBox());
    154154
    155155            SVGInlineFlowBox* flowBox = static_cast<SVGInlineFlowBox*>(child);
Note: See TracChangeset for help on using the changeset viewer.