Changeset 135750 in webkit


Ignore:
Timestamp:
Nov 26, 2012 12:00:49 PM (11 years ago)
Author:
commit-queue@webkit.org
Message:

[CSS Regions] Add Region info for RootLineBoxes and pack the pagination data
https://bugs.webkit.org/show_bug.cgi?id=101332

Patch by Andrei Bucur <abucur@adobe.com> on 2012-11-26
Reviewed by David Hyatt.

Source/WebCore:

Currently the pagination information for lines is spread between the RootInlineBox and InlineFlowBox classes, consuming memory even though
the boxes were not the result of an pagination layout. To overcome this, a new struct (LineFragmentationData) is created that wraps all the data,
including two new members, the containing Region for the line and a boolean that states if the line was laid out in a Region or not.
The flag is necessary because the sanitize function on LineFragmentationData resets the containing Region to 0 if the Region was removed from
chain (so a value of 0 for the containing Region means two things). The sanitize function should prevent access to an invalid address.
The containing Region is used to detect if a line changed the Region where it resides. This will be helpful especially when implementing region
styling for layout properties (e.g. the font-size property https://bugs.webkit.org/show_bug.cgi?id=95559 ).
A line can change the region when it is shifted inside the containing block or if the entire block moves. This means it's better to delegate
the task of updating the containing Region to the block.

Tests: fast/regions/line-containing-region-crash.html

  • rendering/InlineFlowBox.cpp:

(SameSizeAsInlineFlowBox):

  • rendering/InlineFlowBox.h:

(WebCore::InlineFlowBox::InlineFlowBox):
(InlineFlowBox):

  • rendering/RenderBlock.cpp:

(WebCore::RenderBlock::lineWidthForPaginatedLineChanged):

  • rendering/RenderBlockLineLayout.cpp:

(WebCore::RenderBlock::layoutRunsAndFloatsInRange):
(WebCore::RenderBlock::linkToEndLineIfNeeded):
(WebCore::RenderBlock::determineStartPosition):

  • rendering/RootInlineBox.cpp:

(WebCore::RootInlineBox::RootInlineBox):
(WebCore::RootInlineBox::setContainingRegion):
(WebCore):
(WebCore::RootInlineBox::LineFragmentationData::sanitize): This is an O(1) function that checks if the containig Region is still valid pointer.

  • rendering/RootInlineBox.h:

(WebCore):
(WebCore::RootInlineBox::paginationStrut):
(WebCore::RootInlineBox::setPaginationStrut):
(WebCore::RootInlineBox::isFirstAfterPageBreak):
(WebCore::RootInlineBox::setIsFirstAfterPageBreak):
(WebCore::RootInlineBox::paginatedLineWidth):
(WebCore::RootInlineBox::setPaginatedLineWidth):
(RootInlineBox):
(WebCore::RootInlineBox::containingRegion):
(WebCore::RootInlineBox::hasContainingRegion): Use this to determine if the line has a region or not.
(WebCore::RootInlineBox::ensureLineFragmentationData):
(LineFragmentationData):
(WebCore::RootInlineBox::LineFragmentationData::LineFragmentationData):

LayoutTests:

The test checks if there is a crash when doing a line layout if:

  • the flow has no region
  • the flow has a region but the lines have no containing region
  • the flow has no region but the lines have a containing region
  • fast/regions/line-containing-region-crash-expected.txt: Added.
  • fast/regions/line-containing-region-crash.html: Added.
Location:
trunk
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r135749 r135750  
     12012-11-26  Andrei Bucur  <abucur@adobe.com>
     2
     3        [CSS Regions] Add Region info for RootLineBoxes and pack the pagination data
     4        https://bugs.webkit.org/show_bug.cgi?id=101332
     5
     6        Reviewed by David Hyatt.
     7
     8        The test checks if there is a crash when doing a line layout if:
     9        - the flow has no region
     10        - the flow has a region but the lines have no containing region
     11        - the flow has no region but the lines have a containing region
     12
     13        * fast/regions/line-containing-region-crash-expected.txt: Added.
     14        * fast/regions/line-containing-region-crash.html: Added.
     15
    1162012-11-26  Michelangelo De Simone  <michelangelo@webkit.org>
    217
  • trunk/Source/WebCore/ChangeLog

    r135749 r135750  
     12012-11-26  Andrei Bucur  <abucur@adobe.com>
     2
     3        [CSS Regions] Add Region info for RootLineBoxes and pack the pagination data
     4        https://bugs.webkit.org/show_bug.cgi?id=101332
     5
     6        Reviewed by David Hyatt.
     7
     8        Currently the pagination information for lines is spread between the RootInlineBox and InlineFlowBox classes, consuming memory even though
     9        the boxes were not the result of an pagination layout. To overcome this, a new struct (LineFragmentationData) is created that wraps all the data,
     10        including two new members, the containing Region for the line and a boolean that states if the line was laid out in a Region or not.
     11        The flag is necessary because the sanitize function on LineFragmentationData resets the containing Region to 0 if the Region was removed from
     12        chain (so a value of 0 for the containing Region means two things). The sanitize function should prevent access to an invalid address.
     13        The containing Region is used to detect if a line changed the Region where it resides. This will be helpful especially when implementing region
     14        styling for layout properties (e.g. the font-size property https://bugs.webkit.org/show_bug.cgi?id=95559 ).
     15        A line can change the region when it is shifted inside the containing block or if the entire block moves. This means it's better to delegate
     16        the task of updating the containing Region to the block.
     17
     18        Tests: fast/regions/line-containing-region-crash.html
     19
     20        * rendering/InlineFlowBox.cpp:
     21        (SameSizeAsInlineFlowBox):
     22        * rendering/InlineFlowBox.h:
     23        (WebCore::InlineFlowBox::InlineFlowBox):
     24        (InlineFlowBox):
     25        * rendering/RenderBlock.cpp:
     26        (WebCore::RenderBlock::lineWidthForPaginatedLineChanged):
     27        * rendering/RenderBlockLineLayout.cpp:
     28        (WebCore::RenderBlock::layoutRunsAndFloatsInRange):
     29        (WebCore::RenderBlock::linkToEndLineIfNeeded):
     30        (WebCore::RenderBlock::determineStartPosition):
     31        * rendering/RootInlineBox.cpp:
     32        (WebCore::RootInlineBox::RootInlineBox):
     33        (WebCore::RootInlineBox::setContainingRegion):
     34        (WebCore):
     35        (WebCore::RootInlineBox::LineFragmentationData::sanitize): This is an O(1) function that checks if the containig Region is still valid pointer.
     36        * rendering/RootInlineBox.h:
     37        (WebCore):
     38        (WebCore::RootInlineBox::paginationStrut):
     39        (WebCore::RootInlineBox::setPaginationStrut):
     40        (WebCore::RootInlineBox::isFirstAfterPageBreak):
     41        (WebCore::RootInlineBox::setIsFirstAfterPageBreak):
     42        (WebCore::RootInlineBox::paginatedLineWidth):
     43        (WebCore::RootInlineBox::setPaginatedLineWidth):
     44        (RootInlineBox):
     45        (WebCore::RootInlineBox::containingRegion):
     46        (WebCore::RootInlineBox::hasContainingRegion): Use this to determine if the line has a region or not.
     47        (WebCore::RootInlineBox::ensureLineFragmentationData):
     48        (LineFragmentationData):
     49        (WebCore::RootInlineBox::LineFragmentationData::LineFragmentationData):
     50
     51
    1522012-11-26  Michelangelo De Simone  <michelangelo@webkit.org>
    253
  • trunk/Source/WebCore/rendering/InlineFlowBox.cpp

    r134505 r135750  
    4949struct SameSizeAsInlineFlowBox : public InlineBox {
    5050    void* pointers[5];
    51     uint32_t bitfields : 24;
     51    uint32_t bitfields : 23;
    5252};
    5353
  • trunk/Source/WebCore/rendering/InlineFlowBox.h

    r134505 r135750  
    5353        , m_hasAnnotationsBefore(false)
    5454        , m_hasAnnotationsAfter(false)
    55         , m_isFirstAfterPageBreak(false)
    5655#ifndef NDEBUG
    5756        , m_hasBadChildList(false)
     
    326325    unsigned m_hasAnnotationsBefore : 1;
    327326    unsigned m_hasAnnotationsAfter : 1;
    328     unsigned m_isFirstAfterPageBreak : 1;
    329327
    330328    unsigned m_lineBreakBidiStatusEor : 5; // WTF::Unicode::Direction
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r135670 r135750  
    72467246        return false;
    72477247
    7248     return rootBox->paginatedLineWidth() != availableLogicalWidthForContent(rootBox->lineTopWithLeading() + lineDelta);
     7248    RenderRegion* currentRegion = regionAtBlockOffset(rootBox->lineTopWithLeading() + lineDelta);
     7249    // Just bail if we still don't have a region.
     7250    if (!rootBox->hasContainingRegion() && !currentRegion)
     7251        return false;
     7252    // Just bail if the region didn't change.
     7253    if (rootBox->hasContainingRegion() && rootBox->containingRegion() == currentRegion)
     7254        return false;
     7255    return rootBox->paginatedLineWidth() != availableLogicalWidthForContent(currentRegion, offsetFromLogicalTopOfFirstPage());
    72497256}
    72507257
  • trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp

    r135684 r135750  
    15091509                        setLogicalHeight(lineBox->lineBottomWithLeading());
    15101510                    }
     1511
     1512                    if (inRenderFlowThread())
     1513                        lineBox->setContainingRegion(regionAtBlockOffset(lineBox->lineTopWithLeading()));
    15111514                }
    15121515            }
     
    15631566                    line->adjustBlockDirectionPosition(delta);
    15641567                }
     1568                if (inRenderFlowThread())
     1569                    line->setContainingRegion(regionAtBlockOffset(line->lineTopWithLeading()));
    15651570                if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) {
    15661571                    Vector<RenderBox*>::iterator end = cleanLineFloats->end();
     
    16001605            LayoutRect logicalVisualOverflow(0, blockLogicalHeight, 1, bottomVisualOverflow - blockLogicalHeight);
    16011606            trailingFloatsLineBox->setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow, trailingFloatsLineBox->lineTop(), trailingFloatsLineBox->lineBottom());
     1607            if (inRenderFlowThread())
     1608                trailingFloatsLineBox->setContainingRegion(regionAtBlockOffset(trailingFloatsLineBox->lineTopWithLeading()));
    16021609        }
    16031610
     
    17941801                    curr->adjustBlockDirectionPosition(paginationDelta);
    17951802                }
     1803                if (inRenderFlowThread())
     1804                    curr->setContainingRegion(regionAtBlockOffset(curr->lineTopWithLeading()));
    17961805            }
    17971806
  • trunk/Source/WebCore/rendering/RootInlineBox.cpp

    r134505 r135750  
    3434#include "RenderArena.h"
    3535#include "RenderBlock.h"
     36#include "RenderFlowThread.h"
    3637#include "RenderView.h"
    3738#include "VerticalPositionCache.h"
     
    5354    , m_lineTopWithLeading(0)
    5455    , m_lineBottomWithLeading(0)
    55     , m_paginationStrut(0)
    56     , m_paginatedLineWidth(0)
    5756{
    5857    setIsHorizontal(block->isHorizontalWritingMode());
     
    250249        prev->markDirty();
    251250    }
     251}
     252
     253void RootInlineBox::setContainingRegion(RenderRegion* region)
     254{
     255    ASSERT(!isDirty());
     256    ASSERT(block()->inRenderFlowThread());
     257    LineFragmentationData* fragmentationData  = ensureLineFragmentationData();
     258    fragmentationData->m_containingRegion = region;
     259    fragmentationData->m_hasContainingRegion = !!region;
     260}
     261
     262RootInlineBox::LineFragmentationData* RootInlineBox::LineFragmentationData::sanitize(const RenderBlock* block)
     263{
     264    ASSERT(block->inRenderFlowThread());
     265    if (!m_containingRegion)
     266        return this;
     267
     268    RenderFlowThread* flowThread = block->enclosingRenderFlowThread();
     269    const RenderRegionList& regionList = flowThread->renderRegionList();
     270    // For pointer types the hash function is |safeToCompareToEmptyOrDeleted|. There shouldn't be any problems if m_containingRegion was deleted.
     271    if (!regionList.contains(m_containingRegion))
     272        m_containingRegion = 0;
     273
     274    return this;
    252275}
    253276
  • trunk/Source/WebCore/rendering/RootInlineBox.h

    r134505 r135750  
    2929class EllipsisBox;
    3030class HitTestResult;
     31class RenderRegion;
    3132
    3233struct BidiStatus;
     
    5455    LayoutUnit lineBottomWithLeading() const { return m_lineBottomWithLeading; }
    5556   
    56     LayoutUnit paginationStrut() const { return m_paginationStrut; }
    57     void setPaginationStrut(LayoutUnit s) { m_paginationStrut = s; }
    58 
    59     bool isFirstAfterPageBreak() const { return m_isFirstAfterPageBreak; }
    60     void setIsFirstAfterPageBreak(bool isFirstAfterPageBreak) { m_isFirstAfterPageBreak = isFirstAfterPageBreak; }
    61 
    62     LayoutUnit paginatedLineWidth() const { return m_paginatedLineWidth; }
    63     void setPaginatedLineWidth(LayoutUnit width) { m_paginatedLineWidth = width; }
     57    LayoutUnit paginationStrut() const { return m_fragmentationData ? m_fragmentationData->m_paginationStrut : LayoutUnit(0); }
     58    void setPaginationStrut(LayoutUnit strut) { ensureLineFragmentationData()->m_paginationStrut = strut; }
     59
     60    bool isFirstAfterPageBreak() const { return m_fragmentationData ? m_fragmentationData->m_isFirstAfterPageBreak : false; }
     61    void setIsFirstAfterPageBreak(bool isFirstAfterPageBreak) { ensureLineFragmentationData()->m_isFirstAfterPageBreak = isFirstAfterPageBreak; }
     62
     63    LayoutUnit paginatedLineWidth() const { return m_fragmentationData ? m_fragmentationData->m_paginatedLineWidth : LayoutUnit(0); }
     64    void setPaginatedLineWidth(LayoutUnit width) { ensureLineFragmentationData()->m_paginatedLineWidth = width; }
     65
     66    RenderRegion* containingRegion() const { return m_fragmentationData ? m_fragmentationData->sanitize(block())->m_containingRegion : 0; }
     67    bool hasContainingRegion() const { return m_fragmentationData ? m_fragmentationData->m_hasContainingRegion : false; }
     68    void setContainingRegion(RenderRegion*);
    6469
    6570    LayoutUnit selectionTop() const;
     
    194199    LayoutUnit beforeAnnotationsAdjustment() const;
    195200
     201    struct LineFragmentationData;
     202    LineFragmentationData* ensureLineFragmentationData()
     203    {
     204        if (!m_fragmentationData)
     205            m_fragmentationData = adoptPtr(new LineFragmentationData());
     206
     207        return m_fragmentationData.get();
     208    }
     209
    196210    // This folds into the padding at the end of InlineFlowBox on 64-bit.
    197211    unsigned m_lineBreakPos;
     
    208222    LayoutUnit m_lineBottomWithLeading;
    209223
    210     LayoutUnit m_paginationStrut;
    211     LayoutUnit m_paginatedLineWidth;
     224    struct LineFragmentationData {
     225        WTF_MAKE_NONCOPYABLE(LineFragmentationData); WTF_MAKE_FAST_ALLOCATED;
     226    public:
     227        LineFragmentationData()
     228            : m_containingRegion(0)
     229            , m_paginationStrut(0)
     230            , m_paginatedLineWidth(0)
     231            , m_isFirstAfterPageBreak(false)
     232            , m_hasContainingRegion(false)
     233        {
     234
     235        }
     236
     237        LineFragmentationData* sanitize(const RenderBlock*);
     238
     239        // It should not be assumed the |containingRegion| is always valid.
     240        // It can also be 0 if the flow has no region chain or an invalid pointer if the region is no longer in the chain.
     241        // Use |sanitize| to filter an invalid region.
     242        RenderRegion* m_containingRegion;
     243        LayoutUnit m_paginationStrut;
     244        LayoutUnit m_paginatedLineWidth;
     245        unsigned m_isFirstAfterPageBreak : 1;
     246        unsigned m_hasContainingRegion : 1; // We need to keep this to differentiate between the case of a void region and an invalid region.
     247    };
     248
     249    OwnPtr<LineFragmentationData> m_fragmentationData;
    212250
    213251    // Floats hanging off the line are pushed into this vector during layout. It is only
Note: See TracChangeset for help on using the changeset viewer.