Changeset 280017 in webkit


Ignore:
Timestamp:
Jul 16, 2021 10:42:32 PM (12 months ago)
Author:
Simon Fraser
Message:

getBoundingClientRect() returns the incorrect rectangle on elements whose parent element is set -webkit-column-count
https://bugs.webkit.org/show_bug.cgi?id=99959
rdar://80106111

Reviewed by Alan Bujtas.
Source/WebCore:

getBoundingClientRect() and getClientRects() for elements inside multicol had a quick
and dirty implementation that just mapped the element center point into a column. This
resulted in odd, negative top/left in some cases.

Fix by correctly generating multiple rects for elements that span columns, following
the repaint code path that already knew how to do this correctly.

The entry point is RenderFragmentContainer::absoluteQuadsForBox() which now has a
real implementation. For each fragment that the box covers, it calls fragmentRectsForFlowContentRect()
which generates one or more rects; RenderMultiColumnSet overrides this to
compute rects for multicol.

We have to take care not to eliminate empty rects, since the API does return these.

Tested by existing tests.

  • dom/Element.cpp:

(WebCore::Element::absoluteEventBounds):

  • rendering/RenderBlock.cpp:

(WebCore::RenderBlock::absoluteQuadsIgnoringContinuation const):

  • rendering/RenderBox.cpp:

(WebCore::RenderBox::absoluteQuads const):

  • rendering/RenderFragmentContainer.cpp:

(WebCore::RenderFragmentContainer::fragmentedFlowContentRectangle):
(WebCore::RenderFragmentContainer::fragmentRectsForFlowContentRect):

  • rendering/RenderFragmentContainer.h:

(WebCore::RenderFragmentContainer::absoluteQuadsForBoxInFragment): Deleted.

  • rendering/RenderFragmentedFlow.cpp:

(WebCore::RenderFragmentedFlow::absoluteQuadsForBox const):

  • rendering/RenderFragmentedFlow.h:
  • rendering/RenderMultiColumnFlow.h:
  • rendering/RenderMultiColumnSet.cpp:

(WebCore::RenderMultiColumnSet::firstAndLastColumnsFromOffsets const):
(WebCore::RenderMultiColumnSet::repaintFragmentedFlowContent):
(WebCore::RenderMultiColumnSet::fragmentRectsForFlowContentRect):
(WebCore::RenderMultiColumnSet::collectLayerFragments):

  • rendering/RenderMultiColumnSet.h:

LayoutTests:

These tests have all progressed.

  • fast/multicol/client-rects-spanners-complex.html:
  • fast/multicol/client-rects-spanners.html:
  • fast/multicol/client-rects.html:
  • fast/multicol/newmulticol/client-rects.html:
  • imported/blink/fast/multicol/client-rects-rtl-expected.html:
  • imported/blink/fast/multicol/client-rects-rtl.html: This test appeared to be hand-coded to the incorrect old behavior.
  • platform/ios/fast/multicol/client-rects-expected.txt:
  • platform/ios/fast/multicol/client-rects-spanners-complex-expected.txt:
  • platform/ios/fast/multicol/client-rects-spanners-expected.txt:
  • platform/ios/fast/multicol/newmulticol/client-rects-expected.txt:
  • platform/mac/fast/multicol/client-rects-expected.txt:
  • platform/mac/fast/multicol/client-rects-spanners-complex-expected.txt:
  • platform/mac/fast/multicol/client-rects-spanners-expected.txt:
  • platform/mac/fast/multicol/newmulticol/client-rects-expected.txt:
Location:
trunk
Files:
26 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r280012 r280017  
     12021-07-16  Simon Fraser  <simon.fraser@apple.com>
     2
     3        getBoundingClientRect() returns the incorrect rectangle on elements whose parent element is set -webkit-column-count
     4        https://bugs.webkit.org/show_bug.cgi?id=99959
     5        rdar://80106111
     6
     7        Reviewed by Alan Bujtas.
     8
     9        These tests have all progressed.
     10
     11        * fast/multicol/client-rects-spanners-complex.html:
     12        * fast/multicol/client-rects-spanners.html:
     13        * fast/multicol/client-rects.html:
     14        * fast/multicol/newmulticol/client-rects.html:
     15        * imported/blink/fast/multicol/client-rects-rtl-expected.html:
     16        * imported/blink/fast/multicol/client-rects-rtl.html: This test appeared to be hand-coded to the incorrect old behavior.
     17        * platform/ios/fast/multicol/client-rects-expected.txt:
     18        * platform/ios/fast/multicol/client-rects-spanners-complex-expected.txt:
     19        * platform/ios/fast/multicol/client-rects-spanners-expected.txt:
     20        * platform/ios/fast/multicol/newmulticol/client-rects-expected.txt:
     21        * platform/mac/fast/multicol/client-rects-expected.txt:
     22        * platform/mac/fast/multicol/client-rects-spanners-complex-expected.txt:
     23        * platform/mac/fast/multicol/client-rects-spanners-expected.txt:
     24        * platform/mac/fast/multicol/newmulticol/client-rects-expected.txt:
     25
    1262021-07-16  Eric Hutchison  <ehutchison@apple.com>
    227
  • trunk/LayoutTests/fast/multicol/client-rects-spanners-complex.html

    r168985 r280017  
    176176    var block = document.getElementById("t4");
    177177    range.selectNode(block);
    178     placeMarkersForRange(range, 1);
     178    placeMarkersForRange(range, 2);
    179179
    180180    var slider = document.getElementById("t5");
     
    207207    var block = document.getElementById("t11");
    208208    range.selectNode(block);
    209     placeMarkersForRange(range, 1);
     209    placeMarkersForRange(range, 2);
    210210
    211211    var slider = document.getElementById("t12");
     
    238238    var block = document.getElementById("t18");
    239239    range.selectNode(block);
    240     placeMarkersForRange(range, 1);
     240    placeMarkersForRange(range, 2);
    241241
    242242    var slider = document.getElementById("t19");
  • trunk/LayoutTests/fast/multicol/client-rects-spanners.html

    r168985 r280017  
    174174    var block = document.getElementById("t4");
    175175    range.selectNode(block);
    176     placeMarkersForRange(range, 1);
     176    placeMarkersForRange(range, 2);
    177177
    178178    var slider = document.getElementById("t5");
     
    205205    var block = document.getElementById("t11");
    206206    range.selectNode(block);
    207     placeMarkersForRange(range, 1);
     207    placeMarkersForRange(range, 2);
    208208
    209209    var slider = document.getElementById("t12");
     
    236236    var block = document.getElementById("t18");
    237237    range.selectNode(block);
    238     placeMarkersForRange(range, 1);
     238    placeMarkersForRange(range, 2);
    239239
    240240    var slider = document.getElementById("t19");
  • trunk/LayoutTests/fast/multicol/client-rects.html

    r165991 r280017  
    170170    var block = document.getElementById("t4");
    171171    range.selectNode(block);
    172     placeMarkersForRange(range, 1);
     172    placeMarkersForRange(range, 2);
    173173
    174174    var slider = document.getElementById("t5");
     
    201201    var block = document.getElementById("t11");
    202202    range.selectNode(block);
    203     placeMarkersForRange(range, 1);
     203    placeMarkersForRange(range, 2);
    204204
    205205    var slider = document.getElementById("t12");
     
    232232    var block = document.getElementById("t18");
    233233    range.selectNode(block);
    234     placeMarkersForRange(range, 1);
     234    placeMarkersForRange(range, 2);
    235235
    236236    var slider = document.getElementById("t19");
  • trunk/LayoutTests/fast/multicol/newmulticol/client-rects.html

    r168985 r280017  
    173173    var block = document.getElementById("t4");
    174174    range.selectNode(block);
    175     placeMarkersForRange(range, 1);
     175    placeMarkersForRange(range, 2);
    176176
    177177    var slider = document.getElementById("t5");
     
    204204    var block = document.getElementById("t11");
    205205    range.selectNode(block);
    206     placeMarkersForRange(range, 1);
     206    placeMarkersForRange(range, 2);
    207207
    208208    var slider = document.getElementById("t12");
     
    235235    var block = document.getElementById("t18");
    236236    range.selectNode(block);
    237     placeMarkersForRange(range, 1);
     237    placeMarkersForRange(range, 2);
    238238
    239239    var slider = document.getElementById("t19");
  • trunk/LayoutTests/imported/blink/fast/multicol/client-rects-rtl-expected.html

    r190629 r280017  
    3535        margin-top: 40px;
    3636        height: 10px;
    37         border: none;
     37    }
     38    .special > .first span:last-child {
     39        height: 10px;
    3840    }
    3941    .special > .second span:first-child {
    40         border-bottom: none;
    41         height: 10px;
    42         margin-top: -10px;
    43         background-color: white;
    44     }
    45     .special > .second span:last-child {
    46         border-top: none;
    4742        height: 15px;
    4843    }
     
    7873    <div class="column second"><span></span></div>
    7974</div>
    80 <p>
    81     Except here, where the blue border should be around the bigger slice of the blue square, on the left.
    82 </p>
    8375<div class="columns special">
    8476    <div class="column first"><span></span></div>
    85     <div class="column second"><span></span><span></span></div>
     77    <div class="column second"><span></span></div>
    8678</div>
  • trunk/LayoutTests/imported/blink/fast/multicol/client-rects-rtl.html

    r190629 r280017  
    7070</div>
    7171
    72 <p>
    73     Except here, where the blue border should be around the bigger slice of the blue square, on the left.
    74 </p>
    75 
    7672<div class="columns">
    7773    <div id="t7" style=" margin-top: 40px; width: 25px; height: 25px; background-color: lightblue;"></div>
     
    118114    var block = document.getElementById("t4");
    119115    range.selectNode(block);
    120     placeMarkersForRange(range, 1);
     116    placeMarkersForRange(range, 2);
    121117
    122118    var slider = document.getElementById("t5");
  • trunk/LayoutTests/platform/ios/fast/multicol/client-rects-expected.txt

    r273154 r280017  
    310310layer at (669,92) size 25x25
    311311  RenderBlock (positioned) {DIV} at (668,92) size 26x25 [border: (3px solid #0000FF80)]
    312 layer at (69,210) size 25x25
    313   RenderBlock (positioned) {DIV} at (68,210) size 26x25 [border: (3px solid #0000FF80)]
     312layer at (16,260) size 25x10
     313  RenderBlock (positioned) {DIV} at (16,260) size 25x10 [border: (3px solid #0000FF80)]
     314layer at (69,220) size 25x15
     315  RenderBlock (positioned) {DIV} at (68,220) size 26x15 [border: (3px solid #0000FF80)]
    314316layer at (171,180) size 25x25
    315317  RenderBlock (positioned) {DIV} at (171,180) size 25x25 [border: (3px solid #0000FF80)]
     
    338340layer at (596,233) size 25x25
    339341  RenderBlock (positioned) {DIV} at (596,232) size 25x26 [border: (3px solid #0000FF80)]
    340 layer at (676,233) size 25x25
    341   RenderBlock (positioned) {DIV} at (676,232) size 25x26 [border: (3px solid #0000FF80)]
     342layer at (726,180) size 10x25
     343  RenderBlock (positioned) {DIV} at (726,180) size 10x25 [border: (3px solid #0000FF80)]
     344layer at (686,233) size 15x25
     345  RenderBlock (positioned) {DIV} at (686,232) size 15x26 [border: (3px solid #0000FF80)]
    342346layer at (26,301) size 25x25
    343347  RenderBlock (positioned) {DIV} at (26,301) size 25x25 [border: (3px solid #0000FF80)]
     
    366370layer at (501,354) size 25x25
    367371  RenderBlock (positioned) {DIV} at (501,353) size 25x26 [border: (3px solid #0000FF80)]
    368 layer at (601,354) size 25x25
    369   RenderBlock (positioned) {DIV} at (601,353) size 25x26 [border: (3px solid #0000FF80)]
     372layer at (566,301) size 10x25
     373  RenderBlock (positioned) {DIV} at (566,301) size 10x25 [border: (3px solid #0000FF80)]
     374layer at (601,354) size 15x25
     375  RenderBlock (positioned) {DIV} at (601,353) size 15x26 [border: (3px solid #0000FF80)]
  • trunk/LayoutTests/platform/ios/fast/multicol/client-rects-spanners-complex-expected.txt

    r273154 r280017  
    399399layer at (669,127) size 25x25
    400400  RenderBlock (positioned) {DIV} at (668,127) size 26x25 [border: (3px solid #0000FF80)]
    401 layer at (16,293) size 25x25
    402   RenderBlock (positioned) {DIV} at (16,293) size 25x25 [border: (3px solid #0000FF80)]
     401layer at (16,293) size 25x15
     402  RenderBlock (positioned) {DIV} at (16,293) size 25x15 [border: (3px solid #0000FF80)]
     403layer at (69,253) size 25x10
     404  RenderBlock (positioned) {DIV} at (68,253) size 26x10 [border: (3px solid #0000FF80)]
    403405layer at (206,218) size 25x25
    404406  RenderBlock (positioned) {DIV} at (206,218) size 25x25 [border: (3px solid #0000FF80)]
     
    423425layer at (596,271) size 25x25
    424426  RenderBlock (positioned) {DIV} at (596,270) size 25x26 [border: (3px solid #0000FF80)]
    425 layer at (698,273) size 25x25
    426   RenderBlock (positioned) {DIV} at (698,272) size 25x26 [border: (3px solid #0000FF80)]
     427layer at (753,220) size 6x25
     428  RenderBlock (positioned) {DIV} at (753,220) size 6x25 [border: (3px solid #0000FF80)]
     429layer at (701,273) size 22x25
     430  RenderBlock (positioned) {DIV} at (701,272) size 22x26 [border: (3px solid #0000FF80)]
    427431layer at (61,392) size 25x25
    428432  RenderBlock (positioned) {DIV} at (61,391) size 25x26 [border: (3px solid #0000FF80)]
    429 layer at (231,339) size 25x25
    430   RenderBlock (positioned) {DIV} at (231,339) size 25x25 [border: (3px solid #0000FF80)]
     433layer at (231,339) size 15x25
     434  RenderBlock (positioned) {DIV} at (231,339) size 15x25 [border: (3px solid #0000FF80)]
     435layer at (191,392) size 10x25
     436  RenderBlock (positioned) {DIV} at (191,391) size 10x26 [border: (3px solid #0000FF80)]
    431437layer at (291,339) size 25x25
    432438  RenderBlock (positioned) {DIV} at (291,339) size 25x25 [border: (3px solid #0000FF80)]
     
    451457layer at (681,392) size 25x25
    452458  RenderBlock (positioned) {DIV} at (681,391) size 25x26 [border: (3px solid #0000FF80)]
    453 layer at (59,515) size 25x25
    454   RenderBlock (positioned) {DIV} at (59,514) size 25x26 [border: (3px solid #0000FF80)]
     459layer at (26,462) size 6x25
     460  RenderBlock (positioned) {DIV} at (26,462) size 6x25 [border: (3px solid #0000FF80)]
     461layer at (59,515) size 22x25
     462  RenderBlock (positioned) {DIV} at (59,514) size 22x26 [border: (3px solid #0000FF80)]
    455463layer at (186,513) size 25x25
    456464  RenderBlock (positioned) {DIV} at (186,512) size 25x26 [border: (3px solid #0000FF80)]
    457 layer at (276,460) size 25x25
    458   RenderBlock (positioned) {DIV} at (276,460) size 25x25 [border: (3px solid #0000FF80)]
     465layer at (286,460) size 15x25
     466  RenderBlock (positioned) {DIV} at (286,460) size 15x25 [border: (3px solid #0000FF80)]
     467layer at (331,513) size 10x25
     468  RenderBlock (positioned) {DIV} at (331,512) size 10x26 [border: (3px solid #0000FF80)]
  • trunk/LayoutTests/platform/ios/fast/multicol/client-rects-spanners-expected.txt

    r273154 r280017  
    359359layer at (669,102) size 25x25
    360360  RenderBlock (positioned) {DIV} at (668,102) size 26x25 [border: (3px solid #0000FF80)]
    361 layer at (69,210) size 25x25
    362   RenderBlock (positioned) {DIV} at (68,210) size 26x25 [border: (3px solid #0000FF80)]
     361layer at (16,260) size 25x10
     362  RenderBlock (positioned) {DIV} at (16,260) size 25x10 [border: (3px solid #0000FF80)]
     363layer at (69,220) size 25x15
     364  RenderBlock (positioned) {DIV} at (68,220) size 26x15 [border: (3px solid #0000FF80)]
    363365layer at (181,180) size 25x25
    364366  RenderBlock (positioned) {DIV} at (181,180) size 25x25 [border: (3px solid #0000FF80)]
     
    387389layer at (656,233) size 25x25
    388390  RenderBlock (positioned) {DIV} at (656,232) size 25x26 [border: (3px solid #0000FF80)]
    389 layer at (26,354) size 25x25
    390   RenderBlock (positioned) {DIV} at (26,353) size 25x26 [border: (3px solid #0000FF80)]
     391layer at (76,301) size 10x25
     392  RenderBlock (positioned) {DIV} at (76,301) size 10x25 [border: (3px solid #0000FF80)]
     393layer at (36,354) size 15x25
     394  RenderBlock (positioned) {DIV} at (36,353) size 15x26 [border: (3px solid #0000FF80)]
    391395layer at (126,301) size 25x25
    392396  RenderBlock (positioned) {DIV} at (126,301) size 25x25 [border: (3px solid #0000FF80)]
     
    415419layer at (651,354) size 25x25
    416420  RenderBlock (positioned) {DIV} at (651,353) size 25x26 [border: (3px solid #0000FF80)]
    417 layer at (61,475) size 25x25
    418   RenderBlock (positioned) {DIV} at (61,474) size 25x26 [border: (3px solid #0000FF80)]
     421layer at (26,422) size 10x25
     422  RenderBlock (positioned) {DIV} at (26,422) size 10x25 [border: (3px solid #0000FF80)]
     423layer at (61,475) size 15x25
     424  RenderBlock (positioned) {DIV} at (61,474) size 15x26 [border: (3px solid #0000FF80)]
  • trunk/LayoutTests/platform/ios/fast/multicol/newmulticol/client-rects-expected.txt

    r273154 r280017  
    310310layer at (669,92) size 25x25
    311311  RenderBlock (positioned) {DIV} at (668,92) size 26x25 [border: (3px solid #0000FF80)]
    312 layer at (69,210) size 25x25
    313   RenderBlock (positioned) {DIV} at (68,210) size 26x25 [border: (3px solid #0000FF80)]
     312layer at (16,260) size 25x10
     313  RenderBlock (positioned) {DIV} at (16,260) size 25x10 [border: (3px solid #0000FF80)]
     314layer at (69,220) size 25x15
     315  RenderBlock (positioned) {DIV} at (68,220) size 26x15 [border: (3px solid #0000FF80)]
    314316layer at (171,180) size 25x25
    315317  RenderBlock (positioned) {DIV} at (171,180) size 25x25 [border: (3px solid #0000FF80)]
     
    338340layer at (596,233) size 25x25
    339341  RenderBlock (positioned) {DIV} at (596,232) size 25x26 [border: (3px solid #0000FF80)]
    340 layer at (676,233) size 25x25
    341   RenderBlock (positioned) {DIV} at (676,232) size 25x26 [border: (3px solid #0000FF80)]
     342layer at (726,180) size 10x25
     343  RenderBlock (positioned) {DIV} at (726,180) size 10x25 [border: (3px solid #0000FF80)]
     344layer at (686,233) size 15x25
     345  RenderBlock (positioned) {DIV} at (686,232) size 15x26 [border: (3px solid #0000FF80)]
    342346layer at (26,301) size 25x25
    343347  RenderBlock (positioned) {DIV} at (26,301) size 25x25 [border: (3px solid #0000FF80)]
     
    366370layer at (501,354) size 25x25
    367371  RenderBlock (positioned) {DIV} at (501,353) size 25x26 [border: (3px solid #0000FF80)]
    368 layer at (601,354) size 25x25
    369   RenderBlock (positioned) {DIV} at (601,353) size 25x26 [border: (3px solid #0000FF80)]
     372layer at (566,301) size 10x25
     373  RenderBlock (positioned) {DIV} at (566,301) size 10x25 [border: (3px solid #0000FF80)]
     374layer at (601,354) size 15x25
     375  RenderBlock (positioned) {DIV} at (601,353) size 15x26 [border: (3px solid #0000FF80)]
  • trunk/LayoutTests/platform/mac/fast/multicol/client-rects-expected.txt

    r252598 r280017  
    310310layer at (669,91) size 25x25
    311311  RenderBlock (positioned) {DIV} at (668,91) size 26x25 [border: (3px solid #0000FF80)]
    312 layer at (69,208) size 25x25
    313   RenderBlock (positioned) {DIV} at (68,208) size 26x25 [border: (3px solid #0000FF80)]
     312layer at (16,258) size 25x10
     313  RenderBlock (positioned) {DIV} at (16,258) size 25x10 [border: (3px solid #0000FF80)]
     314layer at (69,218) size 25x15
     315  RenderBlock (positioned) {DIV} at (68,218) size 26x15 [border: (3px solid #0000FF80)]
    314316layer at (171,178) size 25x25
    315317  RenderBlock (positioned) {DIV} at (171,178) size 25x25 [border: (3px solid #0000FF80)]
     
    338340layer at (596,231) size 25x25
    339341  RenderBlock (positioned) {DIV} at (596,230) size 25x26 [border: (3px solid #0000FF80)]
    340 layer at (676,231) size 25x25
    341   RenderBlock (positioned) {DIV} at (676,230) size 25x26 [border: (3px solid #0000FF80)]
     342layer at (726,178) size 10x25
     343  RenderBlock (positioned) {DIV} at (726,178) size 10x25 [border: (3px solid #0000FF80)]
     344layer at (686,231) size 15x25
     345  RenderBlock (positioned) {DIV} at (686,230) size 15x26 [border: (3px solid #0000FF80)]
    342346layer at (26,298) size 25x25
    343347  RenderBlock (positioned) {DIV} at (26,298) size 25x25 [border: (3px solid #0000FF80)]
     
    366370layer at (501,351) size 25x25
    367371  RenderBlock (positioned) {DIV} at (501,350) size 25x26 [border: (3px solid #0000FF80)]
    368 layer at (601,351) size 25x25
    369   RenderBlock (positioned) {DIV} at (601,350) size 25x26 [border: (3px solid #0000FF80)]
     372layer at (566,298) size 10x25
     373  RenderBlock (positioned) {DIV} at (566,298) size 10x25 [border: (3px solid #0000FF80)]
     374layer at (601,351) size 15x25
     375  RenderBlock (positioned) {DIV} at (601,350) size 15x26 [border: (3px solid #0000FF80)]
  • trunk/LayoutTests/platform/mac/fast/multicol/client-rects-spanners-complex-expected.txt

    r252598 r280017  
    399399layer at (669,126) size 25x25
    400400  RenderBlock (positioned) {DIV} at (668,126) size 26x25 [border: (3px solid #0000FF80)]
    401 layer at (16,292) size 25x25
    402   RenderBlock (positioned) {DIV} at (16,292) size 25x25 [border: (3px solid #0000FF80)]
     401layer at (16,292) size 25x15
     402  RenderBlock (positioned) {DIV} at (16,292) size 25x15 [border: (3px solid #0000FF80)]
     403layer at (69,252) size 25x10
     404  RenderBlock (positioned) {DIV} at (68,252) size 26x10 [border: (3px solid #0000FF80)]
    403405layer at (206,217) size 25x25
    404406  RenderBlock (positioned) {DIV} at (206,217) size 25x25 [border: (3px solid #0000FF80)]
     
    427429layer at (61,390) size 25x25
    428430  RenderBlock (positioned) {DIV} at (61,389) size 25x26 [border: (3px solid #0000FF80)]
    429 layer at (231,337) size 25x25
    430   RenderBlock (positioned) {DIV} at (231,337) size 25x25 [border: (3px solid #0000FF80)]
     431layer at (231,337) size 15x25
     432  RenderBlock (positioned) {DIV} at (231,337) size 15x25 [border: (3px solid #0000FF80)]
     433layer at (191,390) size 10x25
     434  RenderBlock (positioned) {DIV} at (191,389) size 10x26 [border: (3px solid #0000FF80)]
    431435layer at (291,337) size 25x25
    432436  RenderBlock (positioned) {DIV} at (291,337) size 25x25 [border: (3px solid #0000FF80)]
     
    455459layer at (186,510) size 25x25
    456460  RenderBlock (positioned) {DIV} at (186,509) size 25x26 [border: (3px solid #0000FF80)]
    457 layer at (276,457) size 25x25
    458   RenderBlock (positioned) {DIV} at (276,457) size 25x25 [border: (3px solid #0000FF80)]
     461layer at (286,457) size 15x25
     462  RenderBlock (positioned) {DIV} at (286,457) size 15x25 [border: (3px solid #0000FF80)]
     463layer at (331,510) size 10x25
     464  RenderBlock (positioned) {DIV} at (331,509) size 10x26 [border: (3px solid #0000FF80)]
  • trunk/LayoutTests/platform/mac/fast/multicol/client-rects-spanners-expected.txt

    r252598 r280017  
    359359layer at (669,101) size 25x25
    360360  RenderBlock (positioned) {DIV} at (668,101) size 26x25 [border: (3px solid #0000FF80)]
    361 layer at (69,208) size 25x25
    362   RenderBlock (positioned) {DIV} at (68,208) size 26x25 [border: (3px solid #0000FF80)]
     361layer at (16,258) size 25x10
     362  RenderBlock (positioned) {DIV} at (16,258) size 25x10 [border: (3px solid #0000FF80)]
     363layer at (69,218) size 25x15
     364  RenderBlock (positioned) {DIV} at (68,218) size 26x15 [border: (3px solid #0000FF80)]
    363365layer at (181,178) size 25x25
    364366  RenderBlock (positioned) {DIV} at (181,178) size 25x25 [border: (3px solid #0000FF80)]
     
    387389layer at (656,231) size 25x25
    388390  RenderBlock (positioned) {DIV} at (656,230) size 25x26 [border: (3px solid #0000FF80)]
    389 layer at (26,351) size 25x25
    390   RenderBlock (positioned) {DIV} at (26,350) size 25x26 [border: (3px solid #0000FF80)]
     391layer at (76,298) size 10x25
     392  RenderBlock (positioned) {DIV} at (76,298) size 10x25 [border: (3px solid #0000FF80)]
     393layer at (36,351) size 15x25
     394  RenderBlock (positioned) {DIV} at (36,350) size 15x26 [border: (3px solid #0000FF80)]
    391395layer at (126,298) size 25x25
    392396  RenderBlock (positioned) {DIV} at (126,298) size 25x25 [border: (3px solid #0000FF80)]
     
    415419layer at (651,351) size 25x25
    416420  RenderBlock (positioned) {DIV} at (651,350) size 25x26 [border: (3px solid #0000FF80)]
    417 layer at (61,471) size 25x25
    418   RenderBlock (positioned) {DIV} at (61,470) size 25x26 [border: (3px solid #0000FF80)]
     421layer at (26,418) size 10x25
     422  RenderBlock (positioned) {DIV} at (26,418) size 10x25 [border: (3px solid #0000FF80)]
     423layer at (61,471) size 15x25
     424  RenderBlock (positioned) {DIV} at (61,470) size 15x26 [border: (3px solid #0000FF80)]
  • trunk/LayoutTests/platform/mac/fast/multicol/newmulticol/client-rects-expected.txt

    r252598 r280017  
    310310layer at (669,91) size 25x25
    311311  RenderBlock (positioned) {DIV} at (668,91) size 26x25 [border: (3px solid #0000FF80)]
    312 layer at (69,208) size 25x25
    313   RenderBlock (positioned) {DIV} at (68,208) size 26x25 [border: (3px solid #0000FF80)]
     312layer at (16,258) size 25x10
     313  RenderBlock (positioned) {DIV} at (16,258) size 25x10 [border: (3px solid #0000FF80)]
     314layer at (69,218) size 25x15
     315  RenderBlock (positioned) {DIV} at (68,218) size 26x15 [border: (3px solid #0000FF80)]
    314316layer at (171,178) size 25x25
    315317  RenderBlock (positioned) {DIV} at (171,178) size 25x25 [border: (3px solid #0000FF80)]
     
    338340layer at (596,231) size 25x25
    339341  RenderBlock (positioned) {DIV} at (596,230) size 25x26 [border: (3px solid #0000FF80)]
    340 layer at (676,231) size 25x25
    341   RenderBlock (positioned) {DIV} at (676,230) size 25x26 [border: (3px solid #0000FF80)]
     342layer at (726,178) size 10x25
     343  RenderBlock (positioned) {DIV} at (726,178) size 10x25 [border: (3px solid #0000FF80)]
     344layer at (686,231) size 15x25
     345  RenderBlock (positioned) {DIV} at (686,230) size 15x26 [border: (3px solid #0000FF80)]
    342346layer at (26,298) size 25x25
    343347  RenderBlock (positioned) {DIV} at (26,298) size 25x25 [border: (3px solid #0000FF80)]
     
    366370layer at (501,351) size 25x25
    367371  RenderBlock (positioned) {DIV} at (501,350) size 25x26 [border: (3px solid #0000FF80)]
    368 layer at (601,351) size 25x25
    369   RenderBlock (positioned) {DIV} at (601,350) size 25x26 [border: (3px solid #0000FF80)]
     372layer at (566,298) size 10x25
     373  RenderBlock (positioned) {DIV} at (566,298) size 10x25 [border: (3px solid #0000FF80)]
     374layer at (601,351) size 15x25
     375  RenderBlock (positioned) {DIV} at (601,350) size 15x26 [border: (3px solid #0000FF80)]
  • trunk/Source/WebCore/ChangeLog

    r280016 r280017  
     12021-07-16  Simon Fraser  <simon.fraser@apple.com>
     2
     3        getBoundingClientRect() returns the incorrect rectangle on elements whose parent element is set -webkit-column-count
     4        https://bugs.webkit.org/show_bug.cgi?id=99959
     5        rdar://80106111
     6
     7        Reviewed by Alan Bujtas.
     8       
     9        getBoundingClientRect() and getClientRects() for elements inside multicol had a quick
     10        and dirty implementation that just mapped the element center point into a column. This
     11        resulted in odd, negative top/left in some cases.
     12
     13        Fix by correctly generating multiple rects for elements that span columns, following
     14        the repaint code path that already knew how to do this correctly.
     15       
     16        The entry point is RenderFragmentContainer::absoluteQuadsForBox() which now has a
     17        real implementation. For each fragment that the box covers, it calls fragmentRectsForFlowContentRect()
     18        which generates one or more rects; RenderMultiColumnSet overrides this to
     19        compute rects for multicol.
     20
     21        We have to take care not to eliminate empty rects, since the API does return these.
     22
     23        Tested by existing tests.
     24
     25        * dom/Element.cpp:
     26        (WebCore::Element::absoluteEventBounds):
     27        * rendering/RenderBlock.cpp:
     28        (WebCore::RenderBlock::absoluteQuadsIgnoringContinuation const):
     29        * rendering/RenderBox.cpp:
     30        (WebCore::RenderBox::absoluteQuads const):
     31        * rendering/RenderFragmentContainer.cpp:
     32        (WebCore::RenderFragmentContainer::fragmentedFlowContentRectangle):
     33        (WebCore::RenderFragmentContainer::fragmentRectsForFlowContentRect):
     34        * rendering/RenderFragmentContainer.h:
     35        (WebCore::RenderFragmentContainer::absoluteQuadsForBoxInFragment): Deleted.
     36        * rendering/RenderFragmentedFlow.cpp:
     37        (WebCore::RenderFragmentedFlow::absoluteQuadsForBox const):
     38        * rendering/RenderFragmentedFlow.h:
     39        * rendering/RenderMultiColumnFlow.h:
     40        * rendering/RenderMultiColumnSet.cpp:
     41        (WebCore::RenderMultiColumnSet::firstAndLastColumnsFromOffsets const):
     42        (WebCore::RenderMultiColumnSet::repaintFragmentedFlowContent):
     43        (WebCore::RenderMultiColumnSet::fragmentRectsForFlowContentRect):
     44        (WebCore::RenderMultiColumnSet::collectLayerFragments):
     45        * rendering/RenderMultiColumnSet.h:
     46
    1472021-07-16  Kate Cheney  <katherine_cheney@apple.com>
    248
  • trunk/Source/WebCore/dom/Element.cpp

    r279988 r280017  
    15291529                bool wasFixed = false;
    15301530                Vector<FloatQuad> quads;
    1531                 FloatRect localRect(0, 0, box.width(), box.height());
    1532                 if (fragmentedFlow->absoluteQuadsForBox(quads, &wasFixed, &box, localRect.y(), localRect.maxY())) {
     1531                if (fragmentedFlow->absoluteQuadsForBox(quads, &wasFixed, &box)) {
    15331532                    result = LayoutRect(unitedBoundingBoxes(quads));
    15341533                    computedBounds = true;
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r279918 r280017  
    27972797    // https://bugs.webkit.org/show_bug.cgi?id=46781
    27982798    auto* fragmentedFlow = enclosingFragmentedFlow();
    2799     if (!fragmentedFlow || !fragmentedFlow->absoluteQuadsForBox(quads, wasFixed, this, logicalRect.y(), logicalRect.maxY()))
     2799    if (!fragmentedFlow || !fragmentedFlow->absoluteQuadsForBox(quads, wasFixed, this))
    28002800        quads.append(localToAbsoluteQuad(logicalRect, UseTransforms, wasFixed));
    28012801}
  • trunk/Source/WebCore/rendering/RenderBox.cpp

    r279918 r280017  
    633633void RenderBox::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
    634634{
    635     FloatRect localRect(0, 0, width(), height());
    636 
    637635    RenderFragmentedFlow* fragmentedFlow = enclosingFragmentedFlow();
    638     if (fragmentedFlow && fragmentedFlow->absoluteQuadsForBox(quads, wasFixed, this, localRect.y(), localRect.maxY()))
     636    if (fragmentedFlow && fragmentedFlow->absoluteQuadsForBox(quads, wasFixed, this))
    639637        return;
    640638
     639    auto localRect = FloatRect { 0, 0, width(), height() };
    641640    quads.append(localToAbsoluteQuad(localRect, UseTransforms, wasFixed));
    642641}
  • trunk/Source/WebCore/rendering/RenderFragmentContainer.cpp

    r279958 r280017  
    259259}
    260260
     261LayoutRect RenderFragmentContainer::fragmentedFlowContentRectangle(const LayoutRect& rect, const LayoutRect& fragmentedFlowPortionRect, const LayoutPoint& fragmentLocation, const LayoutRect* fragmentedFlowPortionClipRect)
     262{
     263    auto clippedRect = rect;
     264
     265    if (fragmentedFlowPortionClipRect) {
     266        LayoutRect flippedFragmentedFlowPortionClipRect(*fragmentedFlowPortionClipRect);
     267        fragmentedFlow()->flipForWritingMode(flippedFragmentedFlowPortionClipRect);
     268        clippedRect.edgeInclusiveIntersect(flippedFragmentedFlowPortionClipRect); // edgeInclusiveIntersect to avoid rects with zero height or width becoming zero-sized.
     269    }
     270
     271    LayoutRect flippedFragmentedFlowPortionRect(fragmentedFlowPortionRect);
     272    fragmentedFlow()->flipForWritingMode(flippedFragmentedFlowPortionRect);
     273
     274    // Put the fragment rect into the fragment's physical coordinate space.
     275    clippedRect.setLocation(fragmentLocation + (clippedRect.location() - flippedFragmentedFlowPortionRect.location()));
     276
     277    // Now switch to the fragment's writing mode coordinate space and let it repaint itself.
     278    flipForWritingMode(clippedRect);
     279   
     280    return clippedRect;
     281}
     282
     283Vector<LayoutRect> RenderFragmentContainer::fragmentRectsForFlowContentRect(const LayoutRect& contentRect)
     284{
     285    auto portionRect = fragmentedFlowPortionRect();
     286    auto fragmentLocation = contentBoxRect().location();
     287   
     288    auto fragmentRect = contentRect;
     289   
     290    auto flippedFragmentedFlowPortionRect = portionRect;
     291    fragmentedFlow()->flipForWritingMode(flippedFragmentedFlowPortionRect);
     292    fragmentRect.setLocation(fragmentLocation + (fragmentRect.location() - flippedFragmentedFlowPortionRect.location()));
     293
     294    flipForWritingMode(fragmentRect);
     295
     296    return { fragmentRect };
     297}
     298
    261299void RenderFragmentContainer::installFragmentedFlow()
    262300{
     
    382420}
    383421
     422// FIXME: Unused.
    384423void RenderFragmentContainer::adjustFragmentBoundsFromFragmentedFlowPortionRect(LayoutRect& fragmentBounds) const
    385424{
  • trunk/Source/WebCore/rendering/RenderFragmentContainer.h

    r279958 r280017  
    120120    VisiblePosition positionForPoint(const LayoutPoint&, const RenderFragmentContainer*) override;
    121121
    122     virtual void absoluteQuadsForBoxInFragment(Vector<FloatQuad>&, bool*, const RenderBox*, float, float) { }
     122    virtual Vector<LayoutRect> fragmentRectsForFlowContentRect(const LayoutRect&);
    123123
    124124protected:
     
    138138    LayoutRect overflowRectForFragmentedFlowPortion(const LayoutRect& fragmentedFlowPortionRect, bool isFirstPortion, bool isLastPortion, OverflowType);
    139139    void repaintFragmentedFlowContentRectangle(const LayoutRect& repaintRect, const LayoutRect& fragmentedFlowPortionRect, const LayoutPoint& fragmentLocation, const LayoutRect* fragmentedFlowPortionClipRect = 0);
     140
     141    LayoutRect fragmentedFlowContentRectangle(const LayoutRect&, const LayoutRect& fragmentedFlowPortionRect, const LayoutPoint& fragmentLocation, const LayoutRect* fragmentedFlowPortionClipRect = 0);
    140142
    141143    void computeOverflowFromFragmentedFlow();
  • trunk/Source/WebCore/rendering/RenderFragmentedFlow.cpp

    r279918 r280017  
    217217    for (auto& fragment : m_fragmentList)
    218218        fragment->repaintFragmentedFlowContent(repaintRect);
     219}
     220
     221bool RenderFragmentedFlow::absoluteQuadsForBox(Vector<FloatQuad>& quads, bool* wasFixed, const RenderBox* box) const
     222{
     223    if (!hasValidFragmentInfo())
     224        return false;
     225
     226    auto boxRect = FloatRect { { }, box->size() };
     227    auto boxRectInFlowCoordinates = LayoutRect { box->localToContainerQuad(boxRect, this).boundingBox() };
     228
     229    RenderFragmentContainer* startFragment = nullptr;
     230    RenderFragmentContainer* endFragment = nullptr;
     231    if (!computedFragmentRangeForBox(box, startFragment, endFragment))
     232        return false;
     233
     234    for (auto it = m_fragmentList.find(startFragment), end = m_fragmentList.end(); it != end; ++it) {
     235        auto* fragment = *it;
     236        auto rectsInFragment = fragment->fragmentRectsForFlowContentRect(boxRectInFlowCoordinates);
     237        for (auto rect : rectsInFragment) {
     238            auto absoluteQuad = fragment->localToAbsoluteQuad(FloatRect(rect), UseTransforms, wasFixed);
     239            quads.append(absoluteQuad);
     240        }
     241
     242        if (fragment == endFragment)
     243            break;
     244    }
     245
     246    return true;
    219247}
    220248
  • trunk/Source/WebCore/rendering/RenderFragmentedFlow.h

    r278354 r280017  
    163163    bool fragmentInRange(const RenderFragmentContainer* targetFragment, const RenderFragmentContainer* startFragment, const RenderFragmentContainer* endFragment) const;
    164164
    165     virtual bool absoluteQuadsForBox(Vector<FloatQuad>&, bool*, const RenderBox*, float, float) const { return false; }
     165    bool absoluteQuadsForBox(Vector<FloatQuad>&, bool*, const RenderBox*) const;
    166166
    167167    void layout() override;
  • trunk/Source/WebCore/rendering/RenderMultiColumnFlow.h

    r279958 r280017  
    7575    bool progressionIsReversed() const { return m_progressionIsReversed; }
    7676    void setProgressionIsReversed(bool reversed) { m_progressionIsReversed = reversed; }
    77    
    78     RenderFragmentContainer* mapFromFlowToFragment(TransformState&) const override;
    79    
     77
     78    RenderFragmentContainer* mapFromFlowToFragment(TransformState&) const final;
     79
    8080    // This method takes a logical offset and returns a physical translation that can be applied to map
    8181    // a physical point (corresponding to the logical offset) into the fragment's physical coordinate space.
  • trunk/Source/WebCore/rendering/RenderMultiColumnSet.cpp

    r279958 r280017  
    523523}
    524524
     525std::pair<unsigned, unsigned> RenderMultiColumnSet::firstAndLastColumnsFromOffsets(LayoutUnit topOffset, LayoutUnit bottomOffset) const
     526{
     527    auto portionRect = fragmentedFlowPortionRect();
     528
     529    // Handle the offset being out of range.
     530    auto fragmentedFlowLogicalTop = isHorizontalWritingMode() ? portionRect.y() : portionRect.x();
     531    auto fragmentedFlowLogicalBottom = isHorizontalWritingMode() ? portionRect.maxY() : portionRect.maxX();
     532
     533    auto computeColumnIndex = [&](LayoutUnit offset, bool isBottom) -> unsigned {
     534        if (offset < fragmentedFlowLogicalTop)
     535            return 0;
     536
     537        if (offset >= fragmentedFlowLogicalBottom)
     538            return columnCount() - 1;
     539
     540        // Sometimes computedColumnHeight() is 0 here: see https://bugs.webkit.org/show_bug.cgi?id=132884
     541        auto columnHeight = computedColumnHeight();
     542        if (!columnHeight)
     543            return 0;
     544
     545        auto columnIndex = static_cast<float>(offset - fragmentedFlowLogicalTop) / columnHeight;
     546        if (isBottom && WTF::isIntegral(columnIndex) && columnIndex > 0)
     547            columnIndex -= 1;
     548
     549        return static_cast<unsigned>(columnIndex);
     550    };
     551
     552    return { computeColumnIndex(topOffset, false), computeColumnIndex(bottomOffset, true) };
     553}
     554
    525555LayoutRect RenderMultiColumnSet::fragmentedFlowPortionRectAt(unsigned index) const
    526556{
     
    678708    LayoutUnit repaintLogicalBottom = (isHorizontalWritingMode() ? fragmentedFlowRepaintRect.maxY() : fragmentedFlowRepaintRect.maxX()) - 1;
    679709   
     710    // FIXME: this should use firstAndLastColumnsFromOffsets.
    680711    unsigned startColumn = columnIndexAtOffset(repaintLogicalTop);
    681712    unsigned endColumn = columnIndexAtOffset(repaintLogicalBottom);
     
    696727        repaintFragmentedFlowContentRectangle(repaintRect, fragmentedFlowPortion, colRect.location(), &fragmentedFlowOverflowPortion);
    697728    }
     729}
     730
     731Vector<LayoutRect> RenderMultiColumnSet::fragmentRectsForFlowContentRect(const LayoutRect& rect)
     732{
     733    auto fragmentedFlowRect = rect;
     734    fragmentedFlow()->flipForWritingMode(fragmentedFlowRect);
     735
     736    auto logicalTop = isHorizontalWritingMode() ? fragmentedFlowRect.y() : fragmentedFlowRect.x();
     737    auto logicalBottom = isHorizontalWritingMode() ? fragmentedFlowRect.maxY() : fragmentedFlowRect.maxX();
     738
     739    auto startAndEndColumns = firstAndLastColumnsFromOffsets(logicalTop, logicalBottom);
     740
     741    Vector<LayoutRect> perColumnRects;
     742   
     743    LayoutUnit colGap = columnGap();
     744    unsigned colCount = columnCount();
     745    for (unsigned i = startAndEndColumns.first; i <= startAndEndColumns.second; i++) {
     746        auto colRect = columnRectAt(i);
     747        flipForWritingMode(colRect);
     748       
     749        auto fragmentedFlowPortion = fragmentedFlowPortionRectAt(i);
     750        auto fragmentedFlowOverflowPortion = fragmentedFlowPortionOverflowRect(fragmentedFlowPortion, i, colCount, colGap);
     751
     752        auto rectInColumn = fragmentedFlowContentRectangle(rect, fragmentedFlowPortion, colRect.location(), &fragmentedFlowOverflowPortion);
     753        flipForWritingMode(rectInColumn);
     754        perColumnRects.append(rectInColumn);
     755    }
     756
     757    return perColumnRects;
    698758}
    699759
     
    757817    // Figure out the start and end columns and only check within that range so that we don't walk the
    758818    // entire column set.
     819    // FIXME: this should use firstAndLastColumnsFromOffsets.
    759820    unsigned startColumn = columnIndexAtOffset(layerLogicalTop);
    760821    unsigned endColumn = columnIndexAtOffset(layerLogicalBottom);
  • trunk/Source/WebCore/rendering/RenderMultiColumnSet.h

    r279958 r280017  
    166166    void adjustFragmentBoundsFromFragmentedFlowPortionRect(LayoutRect& fragmentBounds) const override;
    167167
     168    Vector<LayoutRect> fragmentRectsForFlowContentRect(const LayoutRect&) final;
     169
    168170    VisiblePosition positionForPoint(const LayoutPoint&, const RenderFragmentContainer*) override;
    169171
     
    185187    };
    186188    unsigned columnIndexAtOffset(LayoutUnit, ColumnIndexCalculationMode = ClampToExistingColumns) const;
     189
     190    std::pair<unsigned, unsigned> firstAndLastColumnsFromOffsets(LayoutUnit topOffset, LayoutUnit bottomOffset) const;
    187191
    188192    void setAndConstrainColumnHeight(LayoutUnit);
Note: See TracChangeset for help on using the changeset viewer.