Changeset 20103 in webkit


Ignore:
Timestamp:
Mar 11, 2007 4:14:34 AM (17 years ago)
Author:
antti
Message:

Reviewed by Hyatt.

Optimize linebox memory consumption:

  • move all bitfields to baseclass compacting them
  • make InlineTextBox::m_truncation unsigned short and make it relative to m_start
  • remove extremely rarely used EllipsisBox pointer from RootInlineBox and instead use a global hashmap to store it if needed
  • use minimum required number of bits to store BidiStatus enum variables in RootInlineBox
  • move overflow variables in RootInlineBox to a separate struct that is instantiated only if any of the variables is set to a value that can't trivially be derived from box x, y, width and height


As a result line box objects shrink:

InlineBox: 44 -> 44 bytes
InlineTextBox: 68 -> 60 bytes
InlineFlowBox: 68 -> 64 bytes
RootInlineBox: 128 -> 88 bytes


The optimizations possiblity was noticed when debugging http://bugs.webkit.org/show_bug.cgi?id=12833
Bug 12833: REGRESSION: Selecting text in 6.6MB txt file is sluggish as of the Feb 19th nightly
<rdar://problem/5028159>


On that page the patch saves 11.5MB or some 21% of linebox memory consumption. It also
actually improves selection performance somewhat by improving memory locality.

  • rendering/InlineBox.h: (WebCore::InlineBox::InlineBox):
  • rendering/InlineFlowBox.h: (WebCore::InlineFlowBox::InlineFlowBox):
  • rendering/InlineTextBox.cpp: (WebCore::InlineTextBox::placeEllipsisBox): (WebCore::InlineTextBox::nodeAtPoint): (WebCore::InlineTextBox::paint): (WebCore::InlineTextBox::paintDecoration): (WebCore::InlineTextBox::paintSpellingOrGrammarMarker): (WebCore::InlineTextBox::paintMarkedTextUnderline):
  • rendering/InlineTextBox.h: (WebCore::InlineTextBox::InlineTextBox):
  • rendering/RootInlineBox.cpp: (WebCore::throw): (WebCore::RootInlineBox::Overflow::operator delete): (WebCore::RootInlineBox::Overflow::destroy): (WebCore::RootInlineBox::destroy): (WebCore::RootInlineBox::detachEllipsisBox): (WebCore::RootInlineBox::clearTruncation): (WebCore::RootInlineBox::placeEllipsis): (WebCore::RootInlineBox::paintEllipsisBox): (WebCore::RootInlineBox::addHighlightOverflow): (WebCore::RootInlineBox::nodeAtPoint): (WebCore::RootInlineBox::adjustPosition): (WebCore::RootInlineBox::selectionTop): (WebCore::RootInlineBox::setLineBreakInfo): (WebCore::RootInlineBox::ellipsisBox): (WebCore::RootInlineBox::setVerticalOverflowPositions): (WebCore::RootInlineBox::setHorizontalOverflowPositions): (WebCore::RootInlineBox::setVerticalSelectionPositions):
  • rendering/RootInlineBox.h: (WebCore::RootInlineBox::RootInlineBox): (WebCore::RootInlineBox::topOverflow): (WebCore::RootInlineBox::bottomOverflow): (WebCore::RootInlineBox::leftOverflow): (WebCore::RootInlineBox::rightOverflow): (WebCore::RootInlineBox::lineBreakBidiStatus): (WebCore::RootInlineBox::selectionBottom): (WebCore::RootInlineBox::Overflow::Overflow):
Location:
trunk/WebCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r20102 r20103  
     12007-03-11  Antti Koivisto  <antti@apple.com>
     2
     3        Reviewed by Hyatt.
     4
     5        Optimize linebox memory consumption:
     6        - move all bitfields to baseclass compacting them
     7        - make InlineTextBox::m_truncation unsigned short and make it relative to m_start
     8        - remove extremely rarely used EllipsisBox pointer from RootInlineBox and instead
     9          use a global hashmap to store it if needed
     10        - use minimum required number of bits to store BidiStatus enum variables in RootInlineBox
     11        - move overflow variables in RootInlineBox to a separate struct that is instantiated
     12          only if any of the variables is set to a value that can't trivially be derived from
     13          box x, y, width and height
     14         
     15        As a result line box objects shrink:
     16            InlineBox: 44 -> 44 bytes
     17            InlineTextBox: 68 -> 60 bytes
     18            InlineFlowBox: 68 -> 64 bytes
     19            RootInlineBox: 128 -> 88 bytes
     20           
     21        The optimizations possiblity was noticed when debugging http://bugs.webkit.org/show_bug.cgi?id=12833
     22        Bug 12833: REGRESSION: Selecting text in 6.6MB txt file is sluggish as of the Feb 19th nightly
     23        <rdar://problem/5028159>
     24       
     25        On that page the patch saves 11.5MB or some 21% of linebox memory consumption. It also
     26        actually improves selection performance somewhat by improving memory locality.
     27
     28        * rendering/InlineBox.h:
     29        (WebCore::InlineBox::InlineBox):
     30        * rendering/InlineFlowBox.h:
     31        (WebCore::InlineFlowBox::InlineFlowBox):
     32        * rendering/InlineTextBox.cpp:
     33        (WebCore::InlineTextBox::placeEllipsisBox):
     34        (WebCore::InlineTextBox::nodeAtPoint):
     35        (WebCore::InlineTextBox::paint):
     36        (WebCore::InlineTextBox::paintDecoration):
     37        (WebCore::InlineTextBox::paintSpellingOrGrammarMarker):
     38        (WebCore::InlineTextBox::paintMarkedTextUnderline):
     39        * rendering/InlineTextBox.h:
     40        (WebCore::InlineTextBox::InlineTextBox):
     41        * rendering/RootInlineBox.cpp:
     42        (WebCore::throw):
     43        (WebCore::RootInlineBox::Overflow::operator delete):
     44        (WebCore::RootInlineBox::Overflow::destroy):
     45        (WebCore::RootInlineBox::destroy):
     46        (WebCore::RootInlineBox::detachEllipsisBox):
     47        (WebCore::RootInlineBox::clearTruncation):
     48        (WebCore::RootInlineBox::placeEllipsis):
     49        (WebCore::RootInlineBox::paintEllipsisBox):
     50        (WebCore::RootInlineBox::addHighlightOverflow):
     51        (WebCore::RootInlineBox::nodeAtPoint):
     52        (WebCore::RootInlineBox::adjustPosition):
     53        (WebCore::RootInlineBox::selectionTop):
     54        (WebCore::RootInlineBox::setLineBreakInfo):
     55        (WebCore::RootInlineBox::ellipsisBox):
     56        (WebCore::RootInlineBox::setVerticalOverflowPositions):
     57        (WebCore::RootInlineBox::setHorizontalOverflowPositions):
     58        (WebCore::RootInlineBox::setVerticalSelectionPositions):
     59        * rendering/RootInlineBox.h:
     60        (WebCore::RootInlineBox::RootInlineBox):
     61        (WebCore::RootInlineBox::topOverflow):
     62        (WebCore::RootInlineBox::bottomOverflow):
     63        (WebCore::RootInlineBox::leftOverflow):
     64        (WebCore::RootInlineBox::rightOverflow):
     65        (WebCore::RootInlineBox::lineBreakBidiStatus):
     66        (WebCore::RootInlineBox::selectionBottom):
     67        (WebCore::RootInlineBox::Overflow::Overflow):
     68
    1692007-03-11  Alexey Proskuryakov  <ap@webkit.org>
    270
  • trunk/WebCore/rendering/InlineBox.h

    r18874 r20103  
    4444        , m_height(0)
    4545        , m_baseline(0)
     46        , m_next(0)
     47        , m_prev(0)
     48        , m_parent(0)
    4649        , m_firstLine(false)
    4750        , m_constructed(false)
    4851        , m_dirty(false)
    4952        , m_extracted(false)
    50         , m_next(0)
    51         , m_prev(0)
    52         , m_parent(0)
     53        , m_includeLeftEdge(false)
     54        , m_includeRightEdge(false)
     55        , m_hasTextChildren(false)
     56        , m_endsWithBreak(false)
     57        , m_hasSelectedChildren(false)
     58        , m_hasEllipsisBox(false)
     59        , m_reversed(false)
     60        , m_treatAsText(true)
     61        , m_toAdd(0)
    5362    {
    5463    }
     
    6271        , m_height(height)
    6372        , m_baseline(baseline)
     73        , m_next(next)
     74        , m_prev(prev)
     75        , m_parent(parent)
    6476        , m_firstLine(firstLine)
    6577        , m_constructed(constructed)
    6678        , m_dirty(dirty)
    6779        , m_extracted(extracted)
    68         , m_next(next)
    69         , m_prev(prev)
    70         , m_parent(parent)
     80        , m_includeLeftEdge(false)
     81        , m_includeRightEdge(false)
     82        , m_hasTextChildren(false)
     83        , m_endsWithBreak(false)
     84        , m_hasSelectedChildren(false)   
     85        , m_hasEllipsisBox(false)
     86        , m_reversed(false)
     87        , m_treatAsText(true)
     88        , m_toAdd(0)
    7189    {
    7290    }
     
    193211    int m_baseline;
    194212
     213    InlineBox* m_next; // The next element on the same line as us.
     214    InlineBox* m_prev; // The previous element on the same line as us.
     215   
     216    InlineFlowBox* m_parent; // The box that contains us.
     217   
     218    // Some of these bits are actually for subclasses and moved here to compact the structures.
     219    // for this class
    195220    bool m_firstLine : 1;
    196221    bool m_constructed : 1;
    197222    bool m_dirty : 1;
    198223    bool m_extracted : 1;
    199 
    200     InlineBox* m_next; // The next element on the same line as us.
    201     InlineBox* m_prev; // The previous element on the same line as us.
    202 
    203     InlineFlowBox* m_parent; // The box that contains us.
     224    // for InlineFlowBox
     225    bool m_includeLeftEdge : 1;
     226    bool m_includeRightEdge : 1;
     227    bool m_hasTextChildren : 1;
     228    // for RootInlineBox
     229    bool m_endsWithBreak : 1;  // Whether the line ends with a <br>.
     230    bool m_hasSelectedChildren : 1; // Whether we have any children selected (this bit will also be set if the <br> that terminates our line is selected).
     231    bool m_hasEllipsisBox : 1;
     232    // for InlineTextBox
     233    bool m_reversed : 1;
     234    bool m_dirOverride : 1;
     235    bool m_treatAsText : 1; // Whether or not to treat a <br> as text for the purposes of line height.
     236    int m_toAdd : 13; // for justified text
    204237};
    205238
  • trunk/WebCore/rendering/InlineFlowBox.h

    r18874 r20103  
    3939        , m_lastChild(0)
    4040        , m_maxHorizontalVisualOverflow(0)
    41         , m_includeLeftEdge(false)
    42         , m_includeRightEdge(false)
    43         , m_hasTextChildren(false)
    4441    {
    4542    }
     
    133130    InlineBox* m_lastChild;
    134131    int m_maxHorizontalVisualOverflow;
    135     bool m_includeLeftEdge : 1;
    136     bool m_includeRightEdge : 1;
    137     bool m_hasTextChildren : 1;
    138132};
    139133
  • trunk/WebCore/rendering/InlineTextBox.cpp

    r20067 r20103  
    187187           
    188188            // Set the truncation index on the text run.  The ellipsis needs to be placed just after the last visible character.
    189             m_truncation = offset + m_start;
     189            m_truncation = offset;
    190190            return m_x + static_cast<RenderText*>(m_object)->width(m_start, offset, textPos(), m_firstLine);
    191191        }
     
    415415        int endPoint = m_len;
    416416        if (m_truncation != cNoTruncation)
    417             endPoint = m_truncation - m_start;
     417            endPoint = m_truncation;
    418418        paintInfo.context->drawText(TextRun(textStr, m_start, endPoint), IntPoint(m_x + tx, m_y + ty + m_baseline), textStyle);
    419419    } else {
     
    577577   
    578578    int width = (m_truncation == cNoTruncation) ? m_width
    579         : static_cast<RenderText*>(m_object)->width(m_start, m_truncation - m_start, textPos(), m_firstLine);
     579        : static_cast<RenderText*>(m_object)->width(m_start, m_truncation, textPos(), m_firstLine);
    580580   
    581581    // Get the text decoration colors.
     
    624624    }
    625625    if (m_truncation != cNoTruncation) {
    626         paintEnd = min(paintEnd, (unsigned)m_truncation);
     626        paintEnd = min(paintEnd, (unsigned)m_start + m_truncation);
    627627        useWholeWidth = false;
    628628    }
     
    772772    }
    773773    if (m_truncation != cNoTruncation) {
    774         paintEnd = min(paintEnd, (unsigned)m_truncation);
     774        paintEnd = min(paintEnd, (unsigned)m_start + m_truncation);
    775775        useWholeWidth = false;
    776776    }
  • trunk/WebCore/rendering/InlineTextBox.h

    r19140 r20103  
    3232namespace WebCore {
    3333
    34 const int cNoTruncation = -1;
    35 const int cFullTruncation = -2;
     34const unsigned short cNoTruncation = USHRT_MAX;
     35const unsigned short cFullTruncation = USHRT_MAX - 1;
    3636
    3737class String;
     
    4848        , m_len(0)
    4949        , m_truncation(cNoTruncation)
    50         , m_reversed(false)
    51         , m_treatAsText(true)
    52         , m_toAdd(0)
    5350    {
    5451    }
     
    133130    unsigned short m_len;
    134131
    135     int m_truncation; // Where to truncate when text overflow is applied.  We use special constants to
     132    unsigned short m_truncation; // Where to truncate when text overflow is applied.  We use special constants to
    136133                      // denote no truncation (the whole run paints) and full truncation (nothing paints at all).
    137 
    138     bool m_reversed : 1;
    139     bool m_dirOverride : 1;
    140     bool m_treatAsText : 1; // Whether or not to treat a <br> as text for the purposes of line height.
    141     int m_toAdd : 13; // for justified text
    142134
    143135private:
  • trunk/WebCore/rendering/RootInlineBox.cpp

    r20067 r20103  
    2828#include "GraphicsContext.h"
    2929#include "HitTestResult.h"
     30#include "RenderArena.h"
    3031#include "RenderBlock.h"
    3132
     
    3334
    3435namespace WebCore {
     36   
     37typedef WTF::HashMap<const RootInlineBox*, EllipsisBox*> EllipsisBoxMap;
     38static EllipsisBoxMap* gEllipsisBoxMap = 0;
     39
     40void* RootInlineBox::Overflow::operator new(size_t sz, RenderArena* renderArena) throw()
     41{
     42    return renderArena->allocate(sz);
     43}
     44
     45void RootInlineBox::Overflow::operator delete(void* ptr, size_t sz)
     46{
     47    // Stash size where destroy can find it.
     48    *(size_t *)ptr = sz;
     49}
     50
     51void RootInlineBox::Overflow::destroy(RenderArena* renderArena)
     52{
     53    delete this;
     54    // Recover the size left there for us by operator delete and free the memory.
     55    renderArena->free(*(size_t *)this, this);
     56}
    3557
    3658void RootInlineBox::destroy(RenderArena* arena)
    3759{
     60    if (m_overflow)
     61        m_overflow->destroy(arena);
    3862    detachEllipsisBox(arena);
    3963    InlineFlowBox::destroy(arena);
     
    4266void RootInlineBox::detachEllipsisBox(RenderArena* arena)
    4367{
    44     if (m_ellipsisBox) {
    45         m_ellipsisBox->destroy(arena);
    46         m_ellipsisBox = 0;
     68    if (m_hasEllipsisBox) {
     69        EllipsisBoxMap::iterator it = gEllipsisBoxMap->find(this);
     70        it->second->destroy(arena);
     71        gEllipsisBoxMap->remove(it);
     72        m_hasEllipsisBox = false;
    4773    }
    4874}
     
    5076void RootInlineBox::clearTruncation()
    5177{
    52     if (m_ellipsisBox) {
     78    if (m_hasEllipsisBox) {
    5379        detachEllipsisBox(m_object->renderArena());
    5480        InlineFlowBox::clearTruncation();
     
    7298{
    7399    // Create an ellipsis box.
    74     m_ellipsisBox = new (m_object->renderArena()) EllipsisBox(m_object, ellipsisStr, this,
     100    EllipsisBox* ellipsisBox = new (m_object->renderArena()) EllipsisBox(m_object, ellipsisStr, this,
    75101                                                              ellipsisWidth - (markupBox ? markupBox->width() : 0),
    76102                                                              yPos(), height(), baseline(), !prevRootBox(),
    77103                                                              markupBox);
     104   
     105    if (!gEllipsisBoxMap)
     106        gEllipsisBoxMap = new EllipsisBoxMap();
     107    gEllipsisBoxMap->add(this, ellipsisBox);
     108    m_hasEllipsisBox = true;
    78109
    79110    if (ltr && (xPos() + width() + ellipsisWidth) <= blockEdge) {
    80         m_ellipsisBox->m_x = xPos() + width();
     111        ellipsisBox->m_x = xPos() + width();
    81112        return;
    82113    }
     
    86117    // truncated).
    87118    bool foundBox = false;
    88     m_ellipsisBox->m_x = placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox);
     119    ellipsisBox->m_x = placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox);
    89120}
    90121
     
    99130void RootInlineBox::paintEllipsisBox(RenderObject::PaintInfo& paintInfo, int tx, int ty) const
    100131{
    101     if (m_ellipsisBox && object()->shouldPaintWithinRoot(paintInfo) && object()->style()->visibility() == VISIBLE &&
     132    if (m_hasEllipsisBox && object()->shouldPaintWithinRoot(paintInfo) && object()->style()->visibility() == VISIBLE &&
    102133            paintInfo.phase == PaintPhaseForeground)
    103         m_ellipsisBox->paint(paintInfo, tx, ty);
     134        ellipsisBox()->paint(paintInfo, tx, ty);
    104135}
    105136
     
    110141    FloatRect rootRect(0, selectionTop(), width(), selectionHeight());
    111142    IntRect inflatedRect = enclosingIntRect(object()->document()->frame()->customHighlightLineRect(object()->style()->highlight(), rootRect, object()->node()));
    112     m_leftOverflow = min(m_leftOverflow, inflatedRect.x());
    113     m_rightOverflow = max(m_rightOverflow, inflatedRect.right());
    114     m_topOverflow = min(m_topOverflow, inflatedRect.y());
    115     m_bottomOverflow = max(m_bottomOverflow, inflatedRect.bottom());
     143    setVerticalOverflowPositions(min(leftOverflow(), inflatedRect.x()), max(rightOverflow(), inflatedRect.right()));
     144    setHorizontalOverflowPositions(min(topOverflow(), inflatedRect.y()), max(bottomOverflow(), inflatedRect.bottom()));
    116145}
    117146
     
    142171bool RootInlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty)
    143172{
    144     if (m_ellipsisBox && object()->style()->visibility() == VISIBLE) {
    145         if (m_ellipsisBox->nodeAtPoint(request, result, x, y, tx, ty)) {
     173    if (m_hasEllipsisBox && object()->style()->visibility() == VISIBLE) {
     174        if (ellipsisBox()->nodeAtPoint(request, result, x, y, tx, ty)) {
    146175            object()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
    147176            return true;
     
    154183{
    155184    InlineFlowBox::adjustPosition(dx, dy);
    156     m_topOverflow += dy;
    157     m_bottomOverflow += dy;
     185    if (m_overflow) {
     186        m_overflow->m_topOverflow += dy;
     187        m_overflow->m_bottomOverflow += dy;
     188        m_overflow->m_selectionTop += dy;
     189        m_overflow->m_selectionBottom += dy;
     190    }
    158191    m_blockHeight += dy;
    159     m_selectionTop += dy;
    160     m_selectionBottom += dy;
    161192}
    162193
     
    260291int RootInlineBox::selectionTop()
    261292{
     293    int selectionTop = m_overflow ? m_overflow->m_selectionTop : m_y;
    262294    if (!prevRootBox())
    263         return m_selectionTop;
     295        return selectionTop;
    264296
    265297    int prevBottom = prevRootBox()->selectionBottom();
    266     if (prevBottom < m_selectionTop && block()->containsFloats()) {
     298    if (prevBottom < selectionTop && block()->containsFloats()) {
    267299        // This line has actually been moved further down, probably from a large line-height, but possibly because the
    268300        // line was forced to clear floats.  If so, let's check the offsets, and only be willing to use the previous
     
    270302        int prevLeft = block()->leftOffset(prevBottom);
    271303        int prevRight = block()->rightOffset(prevBottom);
    272         int newLeft = block()->leftOffset(m_selectionTop);
    273         int newRight = block()->rightOffset(m_selectionTop);
     304        int newLeft = block()->leftOffset(selectionTop);
     305        int newRight = block()->rightOffset(selectionTop);
    274306        if (prevLeft > newLeft || prevRight < newRight)
    275             return m_selectionTop;
     307            return selectionTop;
    276308    }
    277309
     
    320352    m_lineBreakPos = breakPos;
    321353    m_lineBreakContext = context;
    322     if (status)
    323         m_lineBreakBidiStatus = *status;
     354    if (status) {
     355        m_lineBreakBidiStatusEor = status->eor;
     356        m_lineBreakBidiStatusLastStrong = status->lastStrong;
     357        m_lineBreakBidiStatusLast = status->last;
     358    }
     359}
     360
     361EllipsisBox* RootInlineBox::ellipsisBox() const
     362{
     363    if (!m_hasEllipsisBox)
     364        return false;
     365    return gEllipsisBoxMap->get(this);
     366}
     367
     368void RootInlineBox::setVerticalOverflowPositions(int top, int bottom)
     369{
     370    if (!m_overflow) {
     371        if (top == m_y && bottom == m_y + m_height)
     372            return;
     373        m_overflow = new (m_object->renderArena()) Overflow(this);
     374    }
     375    m_overflow->m_topOverflow = top;
     376    m_overflow->m_bottomOverflow = bottom;
     377}
     378
     379void RootInlineBox::setHorizontalOverflowPositions(int left, int right)
     380{
     381    if (!m_overflow) {
     382        if (left == m_x && right == m_x + m_width)
     383            return;
     384        m_overflow = new (m_object->renderArena()) Overflow(this);       
     385    }
     386    m_overflow->m_leftOverflow = left;
     387    m_overflow->m_rightOverflow = right;
     388}
     389
     390void RootInlineBox::setVerticalSelectionPositions(int top, int bottom)
     391{
     392    if (!m_overflow) {
     393        if (top == m_y && bottom == m_y + m_height)
     394            return;
     395        m_overflow = new (m_object->renderArena()) Overflow(this);
     396    }
     397    m_overflow->m_selectionTop = top;
     398    m_overflow->m_selectionBottom = bottom;
    324399}
    325400
  • trunk/WebCore/rendering/RootInlineBox.h

    r18758 r20103  
    3737    RootInlineBox(RenderObject* obj)
    3838        : InlineFlowBox(obj)
    39         , m_topOverflow(0)
    40         , m_bottomOverflow(0)
    41         , m_leftOverflow(0)
    42         , m_rightOverflow(0)
     39        , m_overflow(0)
    4340        , m_lineBreakObj(0)
    4441        , m_lineBreakPos(0)
    4542        , m_lineBreakContext(0)
    46         , m_blockHeight(0)
    47         , m_endsWithBreak(false)
    48         , m_hasSelectedChildren(false)
    49         , m_ellipsisBox(0)
    5043    {
    5144    }
     
    6154    virtual void adjustPosition(int dx, int dy);
    6255
    63     virtual int topOverflow() { return m_topOverflow; }
    64     virtual int bottomOverflow() { return m_bottomOverflow; }
    65     virtual int leftOverflow() { return m_leftOverflow; }
    66     virtual int rightOverflow() { return m_rightOverflow; }
     56    virtual int topOverflow() { return m_overflow ? m_overflow->m_topOverflow : m_y; }
     57    virtual int bottomOverflow() { return m_overflow ? m_overflow->m_bottomOverflow : m_y + m_height; }
     58    virtual int leftOverflow() { return m_overflow ? m_overflow->m_leftOverflow : m_x; }
     59    virtual int rightOverflow() { return m_overflow ? m_overflow->m_rightOverflow : m_x + m_width; }
    6760
    68     virtual void setVerticalOverflowPositions(int top, int bottom) { m_topOverflow = top; m_bottomOverflow = bottom; }
    69     void setHorizontalOverflowPositions(int left, int right) { m_leftOverflow = left; m_rightOverflow = right; }
     61    virtual void setVerticalOverflowPositions(int top, int bottom);
     62    void setHorizontalOverflowPositions(int left, int right);
    7063
    71     virtual void setVerticalSelectionPositions(int top, int bottom) { m_selectionTop = top; m_selectionBottom = bottom; }
     64    virtual void setVerticalSelectionPositions(int top, int bottom);
    7265
    7366    RenderObject* lineBreakObj() const { return m_lineBreakObj; }
    74     BidiStatus lineBreakBidiStatus() const { return m_lineBreakBidiStatus; }
     67    BidiStatus lineBreakBidiStatus() const {
     68        BidiStatus status;
     69        status.eor = m_lineBreakBidiStatusEor;
     70        status.lastStrong = m_lineBreakBidiStatusLastStrong;
     71        status.last = m_lineBreakBidiStatusLast;
     72        return status;
     73    }
    7574    BidiContext* lineBreakBidiContext() const { return m_lineBreakContext.get(); }
    7675    void setLineBreakInfo(RenderObject*, unsigned breakPos, BidiStatus*, BidiContext*);
     
    9190    virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox);
    9291
    93     EllipsisBox* ellipsisBox() const { return m_ellipsisBox; }
     92    EllipsisBox* ellipsisBox() const;
    9493
    9594    void paintEllipsisBox(RenderObject::PaintInfo&, int tx, int ty) const;
     
    119118
    120119    int selectionTop();
    121     int selectionBottom() { return m_selectionBottom; }
     120    int selectionBottom() { return m_overflow ? m_overflow->m_selectionBottom : m_y + m_height; }
    122121    int selectionHeight() { return max(0, selectionBottom() - selectionTop()); }
    123122
     
    128127    // that spills out above the height of our font (e.g, a tall image), or something that extends further
    129128    // below our line (e.g., a child whose font has a huge descent).
    130     int m_topOverflow;
    131     int m_bottomOverflow;
    132     int m_leftOverflow;
    133     int m_rightOverflow;
    134 
    135     int m_selectionTop;
    136     int m_selectionBottom;
     129       
     130    // Allocated only when some of these fields have non-default values
     131    struct Overflow {
     132        Overflow(RootInlineBox* box)
     133            : m_topOverflow(box->m_y)
     134            , m_bottomOverflow(box->m_y + box->m_height)
     135            , m_leftOverflow(box->m_x)
     136            , m_rightOverflow(box->m_x + box->m_width)
     137            , m_selectionTop(box->m_y)
     138            , m_selectionBottom(box->m_y + box->m_height)
     139            {
     140            }
     141        void destroy(RenderArena*);
     142        void* operator new(size_t, RenderArena*) throw();
     143        void operator delete(void*, size_t);
     144       
     145        int m_topOverflow;
     146        int m_bottomOverflow;
     147        int m_leftOverflow;
     148        int m_rightOverflow;
     149        int m_selectionTop;
     150        int m_selectionBottom;
     151    private:
     152        void* operator new(size_t) throw();
     153    };
     154   
     155    Overflow* m_overflow;
    137156
    138157    // Where this line ended.  The exact object and the position within that object are stored so that
     
    141160    unsigned m_lineBreakPos;
    142161
    143     BidiStatus m_lineBreakBidiStatus;
    144162    RefPtr<BidiContext> m_lineBreakContext;
    145163
     
    147165    int m_blockHeight;
    148166
    149     // Whether the line ends with a <br>.
    150     bool m_endsWithBreak : 1;
    151 
    152     // Whether we have any children selected (this bit will also be set if the <br> that terminates our
    153     // line is selected).
    154     bool m_hasSelectedChildren : 1;
    155 
    156     // An inline text box that represents our text truncation string.
    157     EllipsisBox* m_ellipsisBox;
     167    WTF::Unicode::Direction m_lineBreakBidiStatusEor : 5;
     168    WTF::Unicode::Direction m_lineBreakBidiStatusLastStrong : 5;
     169    WTF::Unicode::Direction m_lineBreakBidiStatusLast : 5;
    158170};
    159171
Note: See TracChangeset for help on using the changeset viewer.