Changeset 128416 in webkit


Ignore:
Timestamp:
Sep 13, 2012 12:51:00 AM (12 years ago)
Author:
commit-queue@webkit.org
Message:

[CSSRegions][CSSOM] Implement Element.getRegionFlowRanges
https://bugs.webkit.org/show_bug.cgi?id=78493

Patch by Raul Hudea <rhudea@adobe.com> on 2012-09-13
Reviewed by David Hyatt.

Source/WebCore:

Implement the getRegionFlowRanges function from the CSS Regions spec. It is implemented by iterating over
the content nodes and figuring out which nodes have boundingBox intersecting the region box and figuring out
the start and end positions.

Tests: fast/regions/get-region-flow-ranges-absolute-pos.html

fast/regions/get-region-flow-ranges-content-nodes.html
fast/regions/get-region-flow-ranges-display-none.html
fast/regions/get-region-flow-ranges-empty-regions.html
fast/regions/get-region-flow-ranges-fixed-pos.html
fast/regions/get-region-flow-ranges-horiz-bt.html
fast/regions/get-region-flow-ranges-inline-only.html
fast/regions/get-region-flow-ranges-text-vert-lr.html
fast/regions/get-region-flow-ranges-text.html
fast/regions/get-region-flow-ranges-vert-lr.html
fast/regions/get-region-flow-ranges-vert-rl.html
fast/regions/get-region-flow-ranges-writing-modes-rl-rb-lr.html
fast/regions/get-region-flow-ranges-writing-modes-tb-rl-lr.html
fast/regions/get-region-flow-ranges.html

  • dom/Element.cpp:

(WebCore::Element::webkitGetRegionFlowRanges):
(WebCore):

  • dom/Element.h:
  • dom/Element.idl: added the webkitGetRegionFlowRanges method
  • rendering/RenderBlock.cpp:

(WebCore::RenderBlock::computeStartPositionDeltaForChildAvoidingFloats): Use the logicalTopOfFlowThreadContentRect instead of offsetFromLogicalTopOfFirstPage (renamed)
(WebCore::RenderBlock::hasNextPage): Use the logicalTopOfFlowThreadContentRect instead of offsetFromLogicalTopOfFirstPage (renamed)
(WebCore::RenderBlock::offsetFromLogicalTopOfFirstPage): Added a slower path which works without LayoutState
(WebCore::RenderBlock::clampToStartAndEndRegions): Use the logicalTopOfFlowThreadContentRect instead of offsetFromLogicalTopOfFirstPage (renamed)

  • rendering/RenderBox.cpp:

(WebCore::RenderBox::shrinkLogicalWidthToAvoidFloats): Use the logicalTopOfFlowThreadContentRect instead of offsetFromLogicalTopOfFirstPage (renamed)
(WebCore::RenderBox::containingBlockAvailableLineWidthInRegion): Use the logicalTopOfFlowThreadContentRect instead of offsetFromLogicalTopOfFirstPage (renamed)
(WebCore::computeInlineStaticDistance): Use the logicalTopOfFlowThreadContentRect instead of offsetFromLogicalTopOfFirstPage (renamed)

  • rendering/RenderNamedFlowThread.cpp:

(WebCore::isContainedInNodes):
(WebCore):
(WebCore::boxIntersectsRegion):
(WebCore::RenderNamedFlowThread::getRanges): returns a vector of Ranges that contains Node that are part of a region

  • rendering/RenderNamedFlowThread.h:

(RenderNamedFlowThread):

  • rendering/RenderRegion.cpp:

(WebCore::RenderRegion::logicalTopOfFlowThreadContentRect): Returns the logical top of a rectangle inside the flow thread content
(WebCore):
(WebCore::RenderRegion::logicalBottomOfFlowThreadContentRect): Returns the logical bottom of a rectangle inside the flow thread content
(WebCore::RenderRegion::getRanges): proxy the getRanges call to its named flow thread

  • rendering/RenderRegion.h:

(RenderRegion):
(WebCore::RenderRegion::logicalTopForFlowThreadContent): Renamed from offsetFromLogicalTopOfFirstPage
(WebCore::RenderRegion::logicalBottomForFlowThreadContent): Returns the logical bottom of the FlowThreadContent rect

LayoutTests:

Add tests for getRegionFlowRanges call.

  • fast/regions/get-region-flow-ranges-absolute-pos-expected.txt: Added.
  • fast/regions/get-region-flow-ranges-absolute-pos.html: Added.
  • fast/regions/get-region-flow-ranges-content-nodes-expected.txt: Added.
  • fast/regions/get-region-flow-ranges-content-nodes.html: Added.
  • fast/regions/get-region-flow-ranges-display-none-expected.txt: Added.
  • fast/regions/get-region-flow-ranges-display-none.html: Added.
  • fast/regions/get-region-flow-ranges-empty-regions-expected.txt: Added.
  • fast/regions/get-region-flow-ranges-empty-regions.html: Added.
  • fast/regions/get-region-flow-ranges-expected.txt: Added.
  • fast/regions/get-region-flow-ranges-fixed-pos-expected.txt: Added.
  • fast/regions/get-region-flow-ranges-fixed-pos.html: Added.
  • fast/regions/get-region-flow-ranges-horiz-bt-expected.txt: Added.
  • fast/regions/get-region-flow-ranges-horiz-bt.html: Added.
  • fast/regions/get-region-flow-ranges-inline-only-expected.txt: Added.
  • fast/regions/get-region-flow-ranges-inline-only.html: Added.
  • fast/regions/get-region-flow-ranges-text-expected.txt: Added.
  • fast/regions/get-region-flow-ranges-text-vert-lr-expected.txt: Added.
  • fast/regions/get-region-flow-ranges-text-vert-lr.html: Added.
  • fast/regions/get-region-flow-ranges-text.html: Added.
  • fast/regions/get-region-flow-ranges-vert-lr-expected.txt: Added.
  • fast/regions/get-region-flow-ranges-vert-lr.html: Added.
  • fast/regions/get-region-flow-ranges-vert-rl-expected.txt: Added.
  • fast/regions/get-region-flow-ranges-vert-rl.html: Added.
  • fast/regions/get-region-flow-ranges-writing-modes-rl-rb-lr-expected.txt: Added.
  • fast/regions/get-region-flow-ranges-writing-modes-rl-rb-lr.html: Added.
  • fast/regions/get-region-flow-ranges-writing-modes-tb-rl-lr-expected.txt: Added.
  • fast/regions/get-region-flow-ranges-writing-modes-tb-rl-lr.html: Added.
  • fast/regions/get-region-flow-ranges.html: Added.
  • fast/regions/resources/helper.js:

(getName):
(getRangeAt):
(compareArrays):

Location:
trunk
Files:
28 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r128414 r128416  
     12012-09-13  Raul Hudea  <rhudea@adobe.com>
     2
     3        [CSSRegions][CSSOM] Implement Element.getRegionFlowRanges
     4        https://bugs.webkit.org/show_bug.cgi?id=78493
     5
     6        Reviewed by David Hyatt.
     7
     8        Add tests for getRegionFlowRanges call.
     9
     10        * fast/regions/get-region-flow-ranges-absolute-pos-expected.txt: Added.
     11        * fast/regions/get-region-flow-ranges-absolute-pos.html: Added.
     12        * fast/regions/get-region-flow-ranges-content-nodes-expected.txt: Added.
     13        * fast/regions/get-region-flow-ranges-content-nodes.html: Added.
     14        * fast/regions/get-region-flow-ranges-display-none-expected.txt: Added.
     15        * fast/regions/get-region-flow-ranges-display-none.html: Added.
     16        * fast/regions/get-region-flow-ranges-empty-regions-expected.txt: Added.
     17        * fast/regions/get-region-flow-ranges-empty-regions.html: Added.
     18        * fast/regions/get-region-flow-ranges-expected.txt: Added.
     19        * fast/regions/get-region-flow-ranges-fixed-pos-expected.txt: Added.
     20        * fast/regions/get-region-flow-ranges-fixed-pos.html: Added.
     21        * fast/regions/get-region-flow-ranges-horiz-bt-expected.txt: Added.
     22        * fast/regions/get-region-flow-ranges-horiz-bt.html: Added.
     23        * fast/regions/get-region-flow-ranges-inline-only-expected.txt: Added.
     24        * fast/regions/get-region-flow-ranges-inline-only.html: Added.
     25        * fast/regions/get-region-flow-ranges-text-expected.txt: Added.
     26        * fast/regions/get-region-flow-ranges-text-vert-lr-expected.txt: Added.
     27        * fast/regions/get-region-flow-ranges-text-vert-lr.html: Added.
     28        * fast/regions/get-region-flow-ranges-text.html: Added.
     29        * fast/regions/get-region-flow-ranges-vert-lr-expected.txt: Added.
     30        * fast/regions/get-region-flow-ranges-vert-lr.html: Added.
     31        * fast/regions/get-region-flow-ranges-vert-rl-expected.txt: Added.
     32        * fast/regions/get-region-flow-ranges-vert-rl.html: Added.
     33        * fast/regions/get-region-flow-ranges-writing-modes-rl-rb-lr-expected.txt: Added.
     34        * fast/regions/get-region-flow-ranges-writing-modes-rl-rb-lr.html: Added.
     35        * fast/regions/get-region-flow-ranges-writing-modes-tb-rl-lr-expected.txt: Added.
     36        * fast/regions/get-region-flow-ranges-writing-modes-tb-rl-lr.html: Added.
     37        * fast/regions/get-region-flow-ranges.html: Added.
     38        * fast/regions/resources/helper.js:
     39        (getName):
     40        (getRangeAt):
     41        (compareArrays):
     42
    1432012-09-13  Zan Dobersek  <zandobersek@gmail.com>
    244
  • trunk/LayoutTests/fast/regions/resources/helper.js

    r108103 r128416  
    161161    expression ? logPassMessage("") : logFailMessage(failMessage);
    162162}
     163
     164// used by getRegionFlowRanges tests
     165function getName(node) {
     166  if (!node) return "undefined";
     167  if (node.nodeType == 3) // Text node
     168    return "#text";
     169  // all the others should have an id
     170  return node.id;
     171}
     172
     173function getRangeAt(arrRange, index) {
     174  if (index < arrRange.length)
     175    return [getName(arrRange[index].startContainer), arrRange[index].startOffset, getName(arrRange[index].endContainer), arrRange[index].endOffset];
     176  return null;
     177}
     178
     179function compareArrays(current, expected) {
     180    try {
     181        if (current == null) {
     182            testFailed("Null object. Expected [" + expected.toString() + "] was null");
     183            return;
     184        }
     185        if (current.length !== expected.length) {
     186            testFailed("Array length differs. Expected [" + expected.toString() + "] was [" + current.toString() + "]");
     187            return;
     188        }
     189        for (var i = 0; i < current.length; i++)
     190            if (current[i] !== expected[i]) {
     191                testFailed("Expected ["  + expected.toString() + "]. Was [" + current.toString() + "]");
     192                return;
     193            }
     194    } catch (ex) {
     195        testFailed(current + " threw exception " + ex);
     196    }
     197    testPassed("Array ["  + expected.toString() + "] is equal to [" + current.toString() + "]");
     198}
  • trunk/Source/WebCore/ChangeLog

    r128411 r128416  
     12012-09-13  Raul Hudea  <rhudea@adobe.com>
     2
     3        [CSSRegions][CSSOM] Implement Element.getRegionFlowRanges
     4        https://bugs.webkit.org/show_bug.cgi?id=78493
     5
     6        Reviewed by David Hyatt.
     7
     8        Implement the getRegionFlowRanges function from the CSS Regions spec. It is implemented by iterating over
     9        the content nodes and figuring out which nodes have boundingBox intersecting the region box and figuring out
     10        the start and end positions.
     11
     12        Tests: fast/regions/get-region-flow-ranges-absolute-pos.html
     13               fast/regions/get-region-flow-ranges-content-nodes.html
     14               fast/regions/get-region-flow-ranges-display-none.html
     15               fast/regions/get-region-flow-ranges-empty-regions.html
     16               fast/regions/get-region-flow-ranges-fixed-pos.html
     17               fast/regions/get-region-flow-ranges-horiz-bt.html
     18               fast/regions/get-region-flow-ranges-inline-only.html
     19               fast/regions/get-region-flow-ranges-text-vert-lr.html
     20               fast/regions/get-region-flow-ranges-text.html
     21               fast/regions/get-region-flow-ranges-vert-lr.html
     22               fast/regions/get-region-flow-ranges-vert-rl.html
     23               fast/regions/get-region-flow-ranges-writing-modes-rl-rb-lr.html
     24               fast/regions/get-region-flow-ranges-writing-modes-tb-rl-lr.html
     25               fast/regions/get-region-flow-ranges.html
     26
     27        * dom/Element.cpp:
     28        (WebCore::Element::webkitGetRegionFlowRanges):
     29        (WebCore):
     30        * dom/Element.h:
     31        * dom/Element.idl: added the webkitGetRegionFlowRanges method
     32        * rendering/RenderBlock.cpp:
     33        (WebCore::RenderBlock::computeStartPositionDeltaForChildAvoidingFloats): Use the logicalTopOfFlowThreadContentRect instead of offsetFromLogicalTopOfFirstPage (renamed)
     34        (WebCore::RenderBlock::hasNextPage): Use the logicalTopOfFlowThreadContentRect instead of offsetFromLogicalTopOfFirstPage (renamed)
     35        (WebCore::RenderBlock::offsetFromLogicalTopOfFirstPage): Added a slower path which works without LayoutState
     36        (WebCore::RenderBlock::clampToStartAndEndRegions): Use the logicalTopOfFlowThreadContentRect instead of offsetFromLogicalTopOfFirstPage (renamed)
     37        * rendering/RenderBox.cpp:
     38        (WebCore::RenderBox::shrinkLogicalWidthToAvoidFloats): Use the logicalTopOfFlowThreadContentRect instead of offsetFromLogicalTopOfFirstPage (renamed)
     39        (WebCore::RenderBox::containingBlockAvailableLineWidthInRegion): Use the logicalTopOfFlowThreadContentRect instead of offsetFromLogicalTopOfFirstPage (renamed)
     40        (WebCore::computeInlineStaticDistance): Use the logicalTopOfFlowThreadContentRect instead of offsetFromLogicalTopOfFirstPage (renamed)
     41        * rendering/RenderNamedFlowThread.cpp:
     42        (WebCore::isContainedInNodes):
     43        (WebCore):
     44        (WebCore::boxIntersectsRegion):
     45        (WebCore::RenderNamedFlowThread::getRanges): returns a vector of Ranges that contains Node that are part of a region
     46        * rendering/RenderNamedFlowThread.h:
     47        (RenderNamedFlowThread):
     48        * rendering/RenderRegion.cpp:
     49        (WebCore::RenderRegion::logicalTopOfFlowThreadContentRect): Returns the logical top of a rectangle inside the flow thread content
     50        (WebCore):
     51        (WebCore::RenderRegion::logicalBottomOfFlowThreadContentRect): Returns the logical bottom of a rectangle inside the flow thread content
     52        (WebCore::RenderRegion::getRanges): proxy the getRanges call to its named flow thread
     53        * rendering/RenderRegion.h:
     54        (RenderRegion):
     55        (WebCore::RenderRegion::logicalTopForFlowThreadContent): Renamed from offsetFromLogicalTopOfFirstPage
     56        (WebCore::RenderRegion::logicalBottomForFlowThreadContent): Returns the logical bottom of the FlowThreadContent rect
     57
    1582012-09-13  Adam Barth  <abarth@webkit.org>
    259
  • trunk/Source/WebCore/dom/Element.cpp

    r128363 r128416  
    20632063}
    20642064
     2065#if ENABLE(CSS_REGIONS)
     2066
     2067Vector<RefPtr<Range> > Element::webkitGetRegionFlowRanges() const
     2068{
     2069    document()->updateLayoutIgnorePendingStylesheets();
     2070
     2071    Vector<RefPtr<Range> > rangeObjects;
     2072    if (document()->cssRegionsEnabled() && renderer() && renderer()->isRenderRegion()) {
     2073        RenderRegion* region = toRenderRegion(renderer());
     2074        if (region->isValid())
     2075            region->getRanges(rangeObjects);
     2076    }
     2077
     2078    return rangeObjects;
     2079}
     2080
     2081#endif
     2082
    20652083#ifndef NDEBUG
    20662084bool Element::fastAttributeLookupAllowed(const QualifiedName& name) const
  • trunk/Source/WebCore/dom/Element.h

    r127811 r128416  
    428428    RenderRegion* renderRegion() const;
    429429    const AtomicString& webkitRegionOverset() const;
     430#if ENABLE(CSS_REGIONS)
     431    Vector<RefPtr<Range> > webkitGetRegionFlowRanges() const;
     432#endif
    430433
    431434    bool hasID() const;
  • trunk/Source/WebCore/dom/Element.idl

    r126245 r128416  
    145145        // CSS Regions API
    146146        readonly attribute DOMString webkitRegionOverset;
     147        [Conditional=CSS_REGIONS] sequence<Range> webkitGetRegionFlowRanges();
    147148
    148149#if !defined(LANGUAGE_OBJECTIVE_C) || !LANGUAGE_OBJECTIVE_C
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r128201 r128416  
    22332233    LayoutUnit blockOffset = logicalTopForChild(child);
    22342234    if (region)
    2235         blockOffset = max(blockOffset, blockOffset + (region->offsetFromLogicalTopOfFirstPage() - offsetFromLogicalTopOfFirstPage));
     2235        blockOffset = max(blockOffset, blockOffset + (region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage));
    22362236
    22372237    LayoutUnit startOff = startOffsetForLine(blockOffset, false, region, offsetFromLogicalTopOfFirstPage, logicalHeightForChild(child));
     
    68976897    if (region->isLastRegion())
    68986898        return region->isRenderRegionSet() || region->style()->regionOverflow() == BreakRegionOverflow
    6899             || (pageBoundaryRule == IncludePageBoundary && pageOffset == region->offsetFromLogicalTopOfFirstPage());
     6899            || (pageBoundaryRule == IncludePageBoundary && pageOffset == region->logicalTopForFlowThreadContent());
    69006900    return true;
    69016901}
     
    71887188LayoutUnit RenderBlock::offsetFromLogicalTopOfFirstPage() const
    71897189{
    7190     // FIXME: This function needs to work without layout state. It's fine to use the layout state as a cache
    7191     // for speed, but we need a slow implementation that will walk up the containing block chain and figure
    7192     // out our offset from the top of the page.
    71937190    LayoutState* layoutState = view()->layoutState();
    7194     if (!layoutState || !layoutState->isPaginated())
    7195         return 0;
    7196 
    7197     // FIXME: Sanity check that the renderer in the layout state is ours, since otherwise the computation will be off.
    7198     // Right now this assert gets hit inside computeLogicalHeight for percentage margins, since they're computed using
    7199     // widths which can vary in each region. Until we patch that, we can't have this assert.
    7200     // ASSERT(layoutState->m_renderer == this);
    7201 
    7202     LayoutSize offsetDelta = layoutState->m_layoutOffset - layoutState->m_pageOffset;
    7203     return isHorizontalWritingMode() ? offsetDelta.height() : offsetDelta.width();
     7191    if (layoutState && !layoutState->isPaginated())
     7192        return ZERO_LAYOUT_UNIT;
     7193    if (layoutState) {
     7194        // FIXME: Sanity check that the renderer in the layout state is ours, since otherwise the computation will be off.
     7195        // Right now this assert gets hit inside computeLogicalHeight for percentage margins, since they're computed using
     7196        // widths which can vary in each region. Until we patch that, we can't have this assert.
     7197        // ASSERT(layoutState->m_renderer == this);
     7198
     7199        LayoutSize offsetDelta = layoutState->m_layoutOffset - layoutState->m_pageOffset;
     7200        return isHorizontalWritingMode() ? offsetDelta.height() : offsetDelta.width();
     7201    }
     7202    // FIXME: Right now, this assert is hit outside layout, from logicalLeftSelectionOffset in selectionGapRectsForRepaint (called from FrameSelection::selectAll).
     7203    // ASSERT(inRenderFlowThread());
     7204
     7205    // FIXME: This is a slower path that doesn't use layout state and relies on getting your logical top inside the enclosing flow thread. It doesn't
     7206    // work with columns or pages currently, but it should once they have been switched over to using flow threads.
     7207    if (!inRenderFlowThread())
     7208        return ZERO_LAYOUT_UNIT;
     7209
     7210    const RenderBlock* currentBlock = this;
     7211    LayoutRect blockRect(0, 0, width(), height());
     7212
     7213    while (currentBlock && !currentBlock->isRenderFlowThread()) {
     7214        RenderBlock* containerBlock = currentBlock->containingBlock();
     7215        ASSERT(containerBlock);
     7216        if (!containerBlock)
     7217            return ZERO_LAYOUT_UNIT;
     7218        LayoutPoint currentBlockLocation = currentBlock->location();
     7219
     7220        if (containerBlock->style()->writingMode() != currentBlock->style()->writingMode()) {
     7221            // We have to put the block rect in container coordinates
     7222            // and we have to take into account both the container and current block flipping modes
     7223            if (containerBlock->style()->isFlippedBlocksWritingMode()) {
     7224                if (containerBlock->isHorizontalWritingMode())
     7225                    blockRect.setY(currentBlock->height() - blockRect.maxY());
     7226                else
     7227                    blockRect.setX(currentBlock->width() - blockRect.maxX());
     7228            }
     7229            currentBlock->flipForWritingMode(blockRect);
     7230        }
     7231        blockRect.moveBy(currentBlockLocation);
     7232        currentBlock = containerBlock;
     7233    };
     7234    return currentBlock->isHorizontalWritingMode() ? blockRect.y() : blockRect.x();
    72047235}
    72057236
     
    72497280    enclosingRenderFlowThread()->getRegionRangeForBox(this, startRegion, endRegion);
    72507281   
    7251     if (startRegion && region->offsetFromLogicalTopOfFirstPage() < startRegion->offsetFromLogicalTopOfFirstPage())
     7282    if (startRegion && region->logicalTopForFlowThreadContent() < startRegion->logicalTopForFlowThreadContent())
    72527283        return startRegion;
    7253     if (endRegion && region->offsetFromLogicalTopOfFirstPage() > endRegion->offsetFromLogicalTopOfFirstPage())
     7284    if (endRegion && region->logicalTopForFlowThreadContent() > endRegion->logicalTopForFlowThreadContent())
    72547285        return endRegion;
    72557286   
  • trunk/Source/WebCore/rendering/RenderBox.cpp

    r128375 r128416  
    11581158    LayoutUnit adjustedPageOffsetForContainingBlock = offsetFromLogicalTopOfFirstPage - logicalTop();
    11591159    if (region) {
    1160         LayoutUnit offsetFromLogicalTopOfRegion = region ? region->offsetFromLogicalTopOfFirstPage() - offsetFromLogicalTopOfFirstPage : ZERO_LAYOUT_UNIT;
     1160        LayoutUnit offsetFromLogicalTopOfRegion = region ? region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage : ZERO_LAYOUT_UNIT;
    11611161        logicalTopPosition = max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion);
    11621162        containingBlockRegion = cb->clampToStartAndEndRegions(region);
     
    12201220    LayoutUnit adjustedPageOffsetForContainingBlock = offsetFromLogicalTopOfFirstPage - logicalTop();
    12211221    if (region) {
    1222         LayoutUnit offsetFromLogicalTopOfRegion = region ? region->offsetFromLogicalTopOfFirstPage() - offsetFromLogicalTopOfFirstPage : ZERO_LAYOUT_UNIT;
     1222        LayoutUnit offsetFromLogicalTopOfRegion = region ? region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage : ZERO_LAYOUT_UNIT;
    12231223        logicalTopPosition = max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion);
    12241224        containingBlockRegion = cb->clampToStartAndEndRegions(region);
     
    25042504                    const RenderBlock* cb = toRenderBlock(curr);
    25052505                    region = cb->clampToStartAndEndRegions(region);
    2506                     RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(region, region->offsetFromLogicalTopOfFirstPage());
     2506                    RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(region, region->logicalTopForFlowThreadContent());
    25072507                    if (boxInfo)
    25082508                        staticPosition += boxInfo->logicalLeft();
     
    25232523                     const RenderBlock* cb = toRenderBlock(curr);
    25242524                     region = cb->clampToStartAndEndRegions(region);
    2525                      RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(region, region->offsetFromLogicalTopOfFirstPage());
     2525                     RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(region, region->logicalTopForFlowThreadContent());
    25262526                     if (boxInfo) {
    25272527                        if (curr != containerBlock)
  • trunk/Source/WebCore/rendering/RenderNamedFlowThread.cpp

    r128293 r128416  
    2828
    2929#include "FlowThreadController.h"
     30#include "InlineTextBox.h"
    3031#include "InspectorInstrumentation.h"
     32#include "Position.h"
     33#include "RenderInline.h"
    3134#include "RenderRegion.h"
     35#include "RenderText.h"
    3236#include "RenderView.h"
     37#include "Text.h"
    3338#include "WebKitNamedFlow.h"
    3439
     
    396401}
    397402
    398 }
     403static bool isContainedInNodes(Vector<Node*> others, Node* node)
     404{
     405    for (size_t i = 0; i < others.size(); i++) {
     406        Node* other = others.at(i);
     407        if (other->contains(node))
     408            return true;
     409    }
     410    return false;
     411}
     412
     413static bool boxIntersectsRegion(LayoutUnit logicalTopForBox, LayoutUnit logicalBottomForBox, LayoutUnit logicalTopForRegion, LayoutUnit logicalBottomForRegion)
     414{
     415    bool regionIsEmpty = logicalBottomForRegion != MAX_LAYOUT_UNIT && logicalTopForRegion != MIN_LAYOUT_UNIT
     416                         && (logicalBottomForRegion - logicalTopForRegion) <= 0;
     417    return  (logicalBottomForBox - logicalTopForBox) > 0
     418            && !regionIsEmpty
     419            && logicalTopForBox < logicalBottomForRegion && logicalTopForRegion < logicalBottomForBox;
     420}
     421
     422void RenderNamedFlowThread::getRanges(Vector<RefPtr<Range> >& rangeObjects, const RenderRegion* region) const
     423{
     424    LayoutUnit logicalTopForRegion;
     425    LayoutUnit logicalBottomForRegion;
     426
     427    // extend the first region top to contain everything up to its logical height
     428    if (region->isFirstRegion())
     429        logicalTopForRegion = MIN_LAYOUT_UNIT;
     430    else
     431        logicalTopForRegion =  region->logicalTopForFlowThreadContent();
     432
     433    // extend the last region to contain everything above its y()
     434    if (region->isLastRegion())
     435        logicalBottomForRegion = MAX_LAYOUT_UNIT;
     436    else
     437        logicalBottomForRegion = region->logicalBottomForFlowThreadContent();
     438
     439    Vector<Node*> nodes;
     440    // eliminate the contentNodes that are descendants of other contentNodes
     441    for (NamedFlowContentNodes::const_iterator it = contentNodes().begin(); it != contentNodes().end(); ++it) {
     442        Node* node = *it;
     443        if (!isContainedInNodes(nodes, node))
     444            nodes.append(node);
     445    }
     446
     447    for (size_t i = 0; i < nodes.size(); i++) {
     448        Node* contentNode = nodes.at(i);
     449        if (!contentNode->renderer())
     450            continue;
     451
     452        ExceptionCode ignoredException;
     453        RefPtr<Range> range = Range::create(contentNode->document());
     454        bool foundStartPosition = false;
     455        bool startsAboveRegion = true;
     456        bool endsBelowRegion = true;
     457        bool skipOverOutsideNodes = false;
     458        Node* lastEndNode = 0;
     459
     460        for (Node* node = contentNode; node; node = node->traverseNextNode(contentNode)) {
     461            RenderObject* renderer = node->renderer();
     462            if (!renderer)
     463                continue;
     464
     465            LayoutRect boundingBox;
     466            if (renderer->isRenderInline())
     467                boundingBox = toRenderInline(renderer)->linesBoundingBox();
     468            else if (renderer->isText())
     469                boundingBox = toRenderText(renderer)->linesBoundingBox();
     470            else {
     471                boundingBox =  toRenderBox(renderer)->frameRect();
     472                if (toRenderBox(renderer)->isRelPositioned())
     473                    boundingBox.move(toRenderBox(renderer)->relativePositionLogicalOffset());
     474            }
     475
     476            LayoutUnit offsetTop = renderer->containingBlock()->offsetFromLogicalTopOfFirstPage();
     477            const LayoutPoint logicalOffsetFromTop(isHorizontalWritingMode() ? ZERO_LAYOUT_UNIT :  offsetTop,
     478                isHorizontalWritingMode() ? offsetTop : ZERO_LAYOUT_UNIT);
     479
     480            boundingBox.moveBy(logicalOffsetFromTop);
     481
     482            LayoutUnit logicalTopForRenderer = region->logicalTopOfFlowThreadContentRect(boundingBox);
     483            LayoutUnit logicalBottomForRenderer = region->logicalBottomOfFlowThreadContentRect(boundingBox);
     484
     485            // if the bounding box of the current element doesn't intersect the region box
     486            // close the current range only if the start element began inside the region,
     487            // otherwise just move the start position after this node and keep skipping them until we found a proper start position.
     488            if (!boxIntersectsRegion(logicalTopForRenderer, logicalBottomForRenderer, logicalTopForRegion, logicalBottomForRegion)) {
     489                if (foundStartPosition) {
     490                    if (!startsAboveRegion) {
     491                        if (range->intersectsNode(node, ignoredException))
     492                            range->setEndBefore(node, ignoredException);
     493                        rangeObjects.append(range->cloneRange(ignoredException));
     494                        range = Range::create(contentNode->document());
     495                        startsAboveRegion = true;
     496                    } else
     497                        skipOverOutsideNodes = true;
     498                }
     499                if (skipOverOutsideNodes)
     500                    range->setStartAfter(node, ignoredException);
     501                foundStartPosition = false;
     502                continue;
     503            }
     504
     505            // start position
     506            if (logicalTopForRenderer < logicalTopForRegion && startsAboveRegion) {
     507                if (renderer->isText()) { // Text crosses region top
     508                    // for Text elements, just find the last textbox that is contained inside the region and use its start() offset as start position
     509                    RenderText* textRenderer = toRenderText(renderer);
     510                    for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
     511                        if (offsetTop + box->logicalBottom() < logicalTopForRegion)
     512                            continue;
     513                        range->setStart(Position(toText(node), box->start()));
     514                        startsAboveRegion = false;
     515                        break;
     516                    }
     517                } else { // node crosses region top
     518                    // for all elements, except Text, just set the start position to be before their children
     519                    startsAboveRegion = true;
     520                    range->setStart(Position(node, Position::PositionIsBeforeChildren));
     521                }
     522            } else { // node starts inside region
     523                // for elements that start inside the region, set the start position to be before them. If we found one, we will just skip the others until
     524                // the range is closed.
     525                if (startsAboveRegion) {
     526                    startsAboveRegion = false;
     527                    range->setStartBefore(node, ignoredException);
     528                }
     529            }
     530            skipOverOutsideNodes  = false;
     531            foundStartPosition = true;
     532
     533            // end position
     534            if (logicalBottomForRegion < logicalBottomForRenderer && (endsBelowRegion || (!endsBelowRegion && !node->isDescendantOf(lastEndNode)))) {
     535                // for Text elements, just find just find the last textbox that is contained inside the region and use its start()+len() offset as end position
     536                if (renderer->isText()) { // Text crosses region bottom
     537                    RenderText* textRenderer = toRenderText(renderer);
     538                    InlineTextBox* lastBox = 0;
     539                    for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
     540                        if ((offsetTop + box->logicalTop()) < logicalBottomForRegion) {
     541                            lastBox = box;
     542                            continue;
     543                        }
     544                        ASSERT(lastBox);
     545                        if (lastBox)
     546                            range->setEnd(Position(toText(node), lastBox->start() + lastBox->len()));
     547                        break;
     548                    }
     549                    endsBelowRegion = false;
     550                    lastEndNode = node;
     551                } else { // node crosses region bottom
     552                    // for all elements, except Text, just set the start position to be after their children
     553                    range->setEnd(Position(node, Position::PositionIsAfterChildren));
     554                    endsBelowRegion = true;
     555                    lastEndNode = node;
     556                }
     557            } else { // node ends inside region
     558                // for elements that ends inside the region, set the end position to be after them
     559                // allow this end position to be changed only by other elements that are not descendants of the current end node
     560                if (endsBelowRegion || (!endsBelowRegion && !node->isDescendantOf(lastEndNode))) {
     561                    range->setEndAfter(node, ignoredException);
     562                    endsBelowRegion = false;
     563                    lastEndNode = node;
     564                }
     565            }
     566        }
     567        if (foundStartPosition || skipOverOutsideNodes)
     568            rangeObjects.append(range);
     569    }
     570}
     571
     572}
  • trunk/Source/WebCore/rendering/RenderNamedFlowThread.h

    r127472 r128416  
    7171    bool hasContentNode(Node* contentNode) const { ASSERT(contentNode); return m_contentNodes.contains(contentNode); }
    7272    bool isMarkedForDestruction() const;
     73    void getRanges(Vector<RefPtr<Range> >&, const RenderRegion*) const;
    7374
    7475protected:
  • trunk/Source/WebCore/rendering/RenderRegion.cpp

    r128155 r128416  
    3636#include "IntRect.h"
    3737#include "PaintInfo.h"
     38#include "Range.h"
    3839#include "RenderBoxRegionInfo.h"
    3940#include "RenderNamedFlowThread.h"
     
    329330}
    330331
    331 LayoutUnit RenderRegion::offsetFromLogicalTopOfFirstPage() const
    332 {
    333     if (!m_isValid || !m_flowThread)
    334         return 0;
    335     if (m_flowThread->isHorizontalWritingMode())
    336         return flowThreadPortionRect().y();
    337     return flowThreadPortionRect().x();
     332LayoutUnit RenderRegion::logicalTopOfFlowThreadContentRect(const LayoutRect& rect) const
     333{
     334    if (!m_isValid || !flowThread())
     335        return ZERO_LAYOUT_UNIT;
     336    return flowThread()->isHorizontalWritingMode() ? rect.y() : rect.x();
     337}
     338
     339LayoutUnit RenderRegion::logicalBottomOfFlowThreadContentRect(const LayoutRect& rect) const
     340{
     341    if (!m_isValid || !flowThread())
     342        return ZERO_LAYOUT_UNIT;
     343    return flowThread()->isHorizontalWritingMode() ? rect.maxY() : rect.maxX();
    338344}
    339345
     
    537543}
    538544
     545void RenderRegion::getRanges(Vector<RefPtr<Range> >& rangeObjects) const
     546{
     547    RenderNamedFlowThread* namedFlow = view()->flowThreadController()->ensureRenderFlowThreadWithName(style()->regionThread());
     548    namedFlow->getRanges(rangeObjects, this);
     549}
     550
    539551} // namespace WebCore
  • trunk/Source/WebCore/rendering/RenderRegion.h

    r128155 r128416  
    7979    void deleteAllRenderBoxRegionInfo();
    8080
    81     LayoutUnit offsetFromLogicalTopOfFirstPage() const;
    82 
    8381    bool isFirstRegion() const;
    8482    bool isLastRegion() const;
     
    105103    virtual LayoutUnit maxPreferredLogicalWidth() const OVERRIDE;
    106104   
     105    LayoutUnit logicalTopOfFlowThreadContentRect(const LayoutRect&) const;
     106    LayoutUnit logicalBottomOfFlowThreadContentRect(const LayoutRect&) const;
     107    LayoutUnit logicalTopForFlowThreadContent() const { return logicalTopOfFlowThreadContentRect(flowThreadPortionRect()); };
     108    LayoutUnit logicalBottomForFlowThreadContent() const { return logicalBottomOfFlowThreadContentRect(flowThreadPortionRect()); };
     109
     110    void getRanges(Vector<RefPtr<Range> >&) const;
     111
    107112    // This method represents the logical height of the entire flow thread portion used by the region or set.
    108113    // For RenderRegions it matches logicalPaginationHeight(), but for sets it is the height of all the pages
Note: See TracChangeset for help on using the changeset viewer.