Changeset 54784 in webkit


Ignore:
Timestamp:
Feb 15, 2010 11:48:38 AM (14 years ago)
Author:
mitz@apple.com
Message:

<rdar://problem/7647300> Incorrect client rects for blocks the span multiple columns and their descendants
https://bugs.webkit.org/show_bug.cgi?id=34923

Reviewed by Simon Fraser.

WebCore:

Test: fast/multicol/client-rects.html

In column layout, a different transform applies to different points in
the block and its descendants, depending on their y coordinate within the
block. offsetFromContainer() used to return the offset that applied to
the origin. With this change, it returns the offset that applies to a
given reference point. When mapping a quad from local to absolute
coordinates, the top left of the quad’s bounding box is used as that
reference point.

  • editing/SelectionController.cpp:

(WebCore::SelectionController::layout): Pass the caret’s origin as the
reference point to offsetFromContainer().

  • rendering/RenderBlock.cpp:

(WebCore::RenderBlock::adjustForColumns): Adds the offset between the
given point and its image under the column paint-time transform to the
given offset. Used by offsetFromContainer() where it had previously used
adjustRectForColumns(), which takes a rect and operates less efficiently.

  • rendering/RenderBlock.h:
  • rendering/RenderBox.cpp:

(WebCore::RenderBox::mapLocalToContainer): Pass the transformed point as
the reference point to offsetFromContainer().
(WebCore::RenderBox::mapAbsoluteToLocalPoint): Pass a point to
offsetFromContainer().
(WebCore::RenderBox::offsetFromContainer): Use adjustForColumns() instead
of adjustRectForColumns(), and use the reference point to get the right
adjustment for the point of interest, instead of the origin, in case this
box spans multiple columns.

  • rendering/RenderBox.h:
  • rendering/RenderInline.cpp:

(WebCore::RenderInline::offsetFromContainer): Ditto. Actually apply the
column offset to the computation, which previously this function didn’t
do.
(WebCore::RenderInline::mapLocalToContainer): Pass the transformed point
as the reference point to offsetFromContainer().
(WebCore::RenderInline::mapAbsoluteToLocalPoint): Pass a point to
offsetFromContainer().

  • rendering/RenderInline.h:
  • rendering/RenderObject.cpp:

(WebCore::RenderObject::mapLocalToContainer): Apply column adjustment,
based on the reference point, to the transform if needed.
(WebCore::RenderObject::localToContainerQuad): Initialize the
TransformState with the top left corner of the quad’s bounding box. It
is later used as the reference point when deciding on which column to
base the calculations.
(WebCore::RenderObject::offsetFromContainer): Adjust for columns.
(WebCore::RenderObject::offsetFromAncestorContainer): Pass the origin
as the reference point to offsetFromContainer().

  • rendering/RenderObject.h:

(WebCore::RenderObject::adjustForColumns): Added.

  • rendering/RenderTableCell.cpp:

(WebCore::RenderTableCell::offsetFromContainer): Pass the reference
point through.

  • rendering/RenderTableCell.h:
  • rendering/RenderText.cpp:

(WebCore::RenderText::absoluteRectsForRange): Map (the origin of) each
rect to absolute coordinates individually.

  • rendering/RenderThemeMac.mm:

(WebCore::RenderThemeMac::convertToPaintingRect): Pass a point to
offsetFromContainer().

LayoutTests:

  • fast/multicol/client-rects-expected.checksum: Added.
  • fast/multicol/client-rects-expected.png: Added.
  • fast/multicol/client-rects-expected.txt: Added.
  • fast/multicol/client-rects.html: Added.
Location:
trunk
Files:
4 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r54783 r54784  
     12010-02-15  Dan Bernstein  <mitz@apple.com>
     2
     3        Reviewed by Simon Fraser.
     4
     5        <rdar://problem/7647300> Incorrect client rects for blocks the span multiple columns and their descendants
     6        https://bugs.webkit.org/show_bug.cgi?id=34923
     7
     8        * fast/multicol/client-rects-expected.checksum: Added.
     9        * fast/multicol/client-rects-expected.png: Added.
     10        * fast/multicol/client-rects-expected.txt: Added.
     11        * fast/multicol/client-rects.html: Added.
     12
    1132010-02-12  Alexey Proskuryakov  <ap@apple.com>
    214
  • trunk/WebCore/ChangeLog

    r54783 r54784  
     12010-02-15  Dan Bernstein  <mitz@apple.com>
     2
     3        Reviewed by Simon Fraser.
     4
     5        <rdar://problem/7647300> Incorrect client rects for blocks the span multiple columns and their descendants
     6        https://bugs.webkit.org/show_bug.cgi?id=34923
     7
     8        Test: fast/multicol/client-rects.html
     9
     10        In column layout, a different transform applies to different points in
     11        the block and its descendants, depending on their y coordinate within the
     12        block. offsetFromContainer() used to return the offset that applied to
     13        the origin. With this change, it returns the offset that applies to a
     14        given reference point. When mapping a quad from local to absolute
     15        coordinates, the top left of the quad’s bounding box is used as that
     16        reference point.
     17
     18        * editing/SelectionController.cpp:
     19        (WebCore::SelectionController::layout): Pass the caret’s origin as the
     20        reference point to offsetFromContainer().
     21        * rendering/RenderBlock.cpp:
     22        (WebCore::RenderBlock::adjustForColumns): Adds the offset between the
     23        given point and its image under the column paint-time transform to the
     24        given offset. Used by offsetFromContainer() where it had previously used
     25        adjustRectForColumns(), which takes a rect and operates less efficiently.
     26        * rendering/RenderBlock.h:
     27        * rendering/RenderBox.cpp:
     28        (WebCore::RenderBox::mapLocalToContainer): Pass the transformed point as
     29        the reference point to offsetFromContainer().
     30        (WebCore::RenderBox::mapAbsoluteToLocalPoint): Pass a point to
     31        offsetFromContainer().
     32        (WebCore::RenderBox::offsetFromContainer): Use adjustForColumns() instead
     33        of adjustRectForColumns(), and use the reference point to get the right
     34        adjustment for the point of interest, instead of the origin, in case this
     35        box spans multiple columns.
     36        * rendering/RenderBox.h:
     37        * rendering/RenderInline.cpp:
     38        (WebCore::RenderInline::offsetFromContainer): Ditto. Actually apply the
     39        column offset to the computation, which previously this function didn’t
     40        do.
     41        (WebCore::RenderInline::mapLocalToContainer): Pass the transformed point
     42        as the reference point to offsetFromContainer().
     43        (WebCore::RenderInline::mapAbsoluteToLocalPoint): Pass a point to
     44        offsetFromContainer().
     45        * rendering/RenderInline.h:
     46        * rendering/RenderObject.cpp:
     47        (WebCore::RenderObject::mapLocalToContainer): Apply column adjustment,
     48        based on the reference point, to the transform if needed.
     49        (WebCore::RenderObject::localToContainerQuad): Initialize the
     50        TransformState with the top left corner of the quad’s bounding box. It
     51        is later used as the reference point when deciding on which column to
     52        base the calculations.
     53        (WebCore::RenderObject::offsetFromContainer): Adjust for columns.
     54        (WebCore::RenderObject::offsetFromAncestorContainer): Pass the origin
     55        as the reference point to offsetFromContainer().
     56        * rendering/RenderObject.h:
     57        (WebCore::RenderObject::adjustForColumns): Added.
     58        * rendering/RenderTableCell.cpp:
     59        (WebCore::RenderTableCell::offsetFromContainer): Pass the reference
     60        point through.
     61        * rendering/RenderTableCell.h:
     62        * rendering/RenderText.cpp:
     63        (WebCore::RenderText::absoluteRectsForRange): Map (the origin of) each
     64        rect to absolute coordinates individually.
     65        * rendering/RenderThemeMac.mm:
     66        (WebCore::RenderThemeMac::convertToPaintingRect): Pass a point to
     67        offsetFromContainer().
     68
    1692010-02-12  Alexey Proskuryakov  <ap@apple.com>
    270
  • trunk/WebCore/editing/SelectionController.cpp

    r53218 r54784  
    841841
    842842            // Compute an offset between the renderer and the caretPainter
    843             IntSize offsetFromPainter;
    844843            bool unrooted = false;
    845844            while (renderer != caretPainter) {
     
    849848                    break;
    850849                }
    851                 offsetFromPainter += renderer->offsetFromContainer(containerObject);
     850                localRect.move(renderer->offsetFromContainer(containerObject, localRect.location()));
    852851                renderer = containerObject;
    853852            }
    854853           
    855             if (!unrooted) {
    856                 // Move the caret rect to the coords of the painter
    857                 localRect.move(offsetFromPainter);
     854            if (!unrooted)
    858855                m_caretRect = localRect;
    859             }
    860856           
    861857            m_absCaretBoundsDirty = true;
  • trunk/WebCore/rendering/RenderBlock.cpp

    r53577 r54784  
    38733873
    38743874    r = result;
     3875}
     3876
     3877void RenderBlock::adjustForColumns(IntSize& offset, const IntPoint& point) const
     3878{
     3879    if (!hasColumns())
     3880        return;
     3881
     3882    // FIXME: This is incorrect for right-to-left columns.
     3883
     3884    Vector<IntRect>& columnRects = *this->columnRects();
     3885
     3886    int gapWidth = columnGap();
     3887    int xOffset = 0;
     3888    int yOffset = 0;
     3889    size_t columnCount = columnRects.size();
     3890    for (size_t i = 0; i < columnCount; ++i) {
     3891        IntRect columnRect = columnRects[i];
     3892        if (point.y() < columnRect.bottom() + yOffset) {
     3893            offset.expand(xOffset, -yOffset);
     3894            return;
     3895        }
     3896
     3897        xOffset += columnRect.width() + gapWidth;
     3898        yOffset += columnRect.height();
     3899    }
    38753900}
    38763901
  • trunk/WebCore/rendering/RenderBlock.h

    r54665 r54784  
    129129
    130130    void adjustRectForColumns(IntRect&) const;
     131    virtual void adjustForColumns(IntSize&, const IntPoint&) const;
    131132
    132133    void addContinuationWithOutline(RenderInline*);
  • trunk/WebCore/rendering/RenderBox.cpp

    r54503 r54784  
    975975        fixed |= isFixedPos;
    976976   
    977     IntSize containerOffset = offsetFromContainer(o);
     977    IntSize containerOffset = offsetFromContainer(o, roundedIntPoint(transformState.mappedPoint()));
    978978
    979979    bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D());
     
    10161016    o->mapAbsoluteToLocalPoint(fixed, useTransforms, transformState);
    10171017
    1018     IntSize containerOffset = offsetFromContainer(o);
     1018    IntSize containerOffset = offsetFromContainer(o, IntPoint());
    10191019
    10201020    bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D());
     
    10271027}
    10281028
    1029 IntSize RenderBox::offsetFromContainer(RenderObject* o) const
     1029IntSize RenderBox::offsetFromContainer(RenderObject* o, const IntPoint& point) const
    10301030{
    10311031    ASSERT(o == container());
     
    10361036
    10371037    if (!isInline() || isReplaced()) {
    1038         RenderBlock* cb;
    1039         if (o->isBlockFlow() && style()->position() != AbsolutePosition && style()->position() != FixedPosition
    1040                 && (cb = toRenderBlock(o))->hasColumns()) {
    1041             IntRect rect(x(), y(), 1, 1);
    1042             cb->adjustRectForColumns(rect);
    1043             offset.expand(rect.x(), rect.y());
    1044         } else
    1045             offset.expand(x(), y());
     1038        if (style()->position() != AbsolutePosition && style()->position() != FixedPosition)
     1039            o->adjustForColumns(offset, IntPoint(point.x() + x(), point.y() + y()));
     1040        offset.expand(x(), y());
    10461041    }
    10471042
  • trunk/WebCore/rendering/RenderBox.h

    r54503 r54784  
    174174    virtual void setOverrideSize(int);
    175175
    176     virtual IntSize offsetFromContainer(RenderObject*) const;
     176    virtual IntSize offsetFromContainer(RenderObject*, const IntPoint&) const;
    177177   
    178178    int calcBorderBoxWidth(int width) const;
  • trunk/WebCore/rendering/RenderInline.cpp

    r52632 r54784  
    711711}
    712712
    713 IntSize RenderInline::offsetFromContainer(RenderObject* container) const
     713IntSize RenderInline::offsetFromContainer(RenderObject* container, const IntPoint& point) const
    714714{
    715715    ASSERT(container == this->container());
     
    719719        offset += relativePositionOffset();
    720720
    721     if (!isInline() || isReplaced()) {
    722         RenderBlock* cb;
    723         if (container->isBlockFlow() && (cb = toRenderBlock(container))->hasColumns()) {
    724             IntRect rect(0, 0, 1, 1);
    725             cb->adjustRectForColumns(rect);
    726         }
    727     }
     721    container->adjustForColumns(offset, point);
    728722
    729723    if (container->hasOverflowClip())
     
    754748        return;
    755749
    756     IntSize containerOffset = offsetFromContainer(o);
     750    IntSize containerOffset = offsetFromContainer(o, roundedIntPoint(transformState.mappedPoint()));
    757751
    758752    bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D());
     
    786780    o->mapAbsoluteToLocalPoint(fixed, useTransforms, transformState);
    787781
    788     IntSize containerOffset = offsetFromContainer(o);
     782    IntSize containerOffset = offsetFromContainer(o, IntPoint());
    789783
    790784    bool preserve3D = useTransforms && (o->style()->preserves3D() || style()->preserves3D());
  • trunk/WebCore/rendering/RenderInline.h

    r52632 r54784  
    4545    virtual void absoluteQuads(Vector<FloatQuad>&);
    4646
    47     virtual IntSize offsetFromContainer(RenderObject*) const;
     47    virtual IntSize offsetFromContainer(RenderObject*, const IntPoint&) const;
    4848
    4949    IntRect linesBoundingBox() const;
  • trunk/WebCore/rendering/RenderObject.cpp

    r54649 r54784  
    17631763        return;
    17641764
     1765    IntSize columnOffset;
     1766    o->adjustForColumns(columnOffset, roundedIntPoint(transformState.mappedPoint()));
     1767    if (!columnOffset.isZero())
     1768        transformState.move(columnOffset);
     1769
    17651770    if (o->hasOverflowClip())
    17661771        transformState.move(-toRenderBox(o)->layer()->scrolledContentOffset());
     
    18191824FloatQuad RenderObject::localToContainerQuad(const FloatQuad& localQuad, RenderBoxModelObject* repaintContainer, bool fixed) const
    18201825{
    1821     TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint(), &localQuad);
     1826    TransformState transformState(TransformState::ApplyTransformDirection, localQuad.boundingBox().location(), &localQuad);
    18221827    mapLocalToContainer(repaintContainer, fixed, true, transformState);
    18231828    transformState.flatten();
     
    18261831}
    18271832
    1828 IntSize RenderObject::offsetFromContainer(RenderObject* o) const
     1833IntSize RenderObject::offsetFromContainer(RenderObject* o, const IntPoint& point) const
    18291834{
    18301835    ASSERT(o == container());
    18311836
    18321837    IntSize offset;
     1838
     1839    o->adjustForColumns(offset, point);
     1840
    18331841    if (o->hasOverflowClip())
    18341842        offset -= toRenderBox(o)->layer()->scrolledContentOffset();
     
    18401848{
    18411849    IntSize offset;
     1850    IntPoint referencePoint;
    18421851    const RenderObject* currContainer = this;
    18431852    do {
     
    18471856            break;
    18481857        ASSERT(!currContainer->hasTransform());
    1849         offset += currContainer->offsetFromContainer(nextContainer);
     1858        IntSize currentOffset = currContainer->offsetFromContainer(nextContainer, referencePoint);
     1859        offset += currentOffset;
     1860        referencePoint.move(currentOffset);
    18501861        currContainer = nextContainer;
    18511862    } while (currContainer != container);
  • trunk/WebCore/rendering/RenderObject.h

    r54649 r54784  
    563563    FloatQuad localToContainerQuad(const FloatQuad&, RenderBoxModelObject* repaintContainer, bool fixed = false) const;
    564564
    565     // Return the offset from the container() renderer (excluding transforms)
    566     virtual IntSize offsetFromContainer(RenderObject*) const;
     565    // Return the offset from the container() renderer (excluding transforms). In multi-column layout,
     566    // different offsets apply at different points, so return the offset that applies to the given point.
     567    virtual IntSize offsetFromContainer(RenderObject*, const IntPoint&) const;
    567568    // Return the offset from an object up the container() chain. Asserts that none of the intermediate objects have transforms.
    568569    IntSize offsetFromAncestorContainer(RenderObject*) const;
     
    642643    // that rect in the coordinate space of repaintContainer.
    643644    virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false);
     645
     646    // If multiple-column layout results in applying an offset to the given point, add the same
     647    // offset to the given size.
     648    virtual void adjustForColumns(IntSize&, const IntPoint&) const { }
    644649
    645650    virtual unsigned int length() const { return 1; }
  • trunk/WebCore/rendering/RenderTableCell.cpp

    r54615 r54784  
    155155}
    156156
    157 IntSize RenderTableCell::offsetFromContainer(RenderObject* o) const
     157IntSize RenderTableCell::offsetFromContainer(RenderObject* o, const IntPoint& point) const
    158158{
    159159    ASSERT(o == container());
    160160
    161     IntSize offset = RenderBlock::offsetFromContainer(o);
     161    IntSize offset = RenderBlock::offsetFromContainer(o, point);
    162162    if (parent())
    163163        offset.expand(-parentBox()->x(), -parentBox()->y());
  • trunk/WebCore/rendering/RenderTableCell.h

    r52683 r54784  
    120120    virtual void paintMask(PaintInfo&, int tx, int ty);
    121121
    122     virtual IntSize offsetFromContainer(RenderObject*) const;
     122    virtual IntSize offsetFromContainer(RenderObject*, const IntPoint&) const;
    123123    virtual IntRect clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer);
    124124    virtual void computeRectForRepaint(RenderBoxModelObject* repaintContainer, IntRect&, bool fixed = false);
  • trunk/WebCore/rendering/RenderText.cpp

    r54117 r54784  
    231231    end = min(end, static_cast<unsigned>(INT_MAX));
    232232   
    233     FloatPoint absPos = localToAbsolute(FloatPoint());
    234 
    235233    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
    236234        // Note: box->end() returns the index of the last character, not the index past it
    237235        if (start <= box->start() && box->end() < end) {
    238             IntRect r = IntRect(absPos.x() + box->x(), absPos.y() + box->y(), box->width(), box->height());
     236            IntRect r = IntRect(box->x(), box->y(), box->width(), box->height());
    239237            if (useSelectionHeight) {
    240                 IntRect selectionRect = box->selectionRect(absPos.x(), absPos.y(), start, end);
     238                IntRect selectionRect = box->selectionRect(0, 0, start, end);
    241239                r.setHeight(selectionRect.height());
    242240                r.setY(selectionRect.y());
    243241            }
     242            FloatPoint origin = localToAbsolute(r.location());
     243            r.setX(origin.x());
     244            r.setY(origin.y());
    244245            rects.append(r);
    245246        } else {
    246247            unsigned realEnd = min(box->end() + 1, end);
    247             IntRect r = box->selectionRect(absPos.x(), absPos.y(), start, realEnd);
     248            IntRect r = box->selectionRect(0, 0, start, realEnd);
    248249            if (!r.isEmpty()) {
    249250                if (!useSelectionHeight) {
    250251                    // change the height and y position because selectionRect uses selection-specific values
    251252                    r.setHeight(box->height());
    252                     r.setY(absPos.y() + box->y());
     253                    r.setY(box->y());
    253254                }
     255                FloatPoint origin = localToAbsolute(r.location());
     256                localToAbsolute(origin);
     257                r.setX(origin.x());
     258                r.setY(origin.y());
    254259                rects.append(r);
    255260            }
  • trunk/WebCore/rendering/RenderThemeMac.mm

    r52094 r54784  
    521521    while (renderer && renderer != inputRenderer) {
    522522        RenderObject* containingRenderer = renderer->container();
    523         offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer);
     523        offsetFromInputRenderer -= renderer->offsetFromContainer(containingRenderer, IntPoint());
    524524        renderer = containingRenderer;
    525525    }
Note: See TracChangeset for help on using the changeset viewer.