| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/layout/LayoutTableSection.h" | 5 #include "core/layout/LayoutTableSection.h" |
| 6 | 6 |
| 7 #include "core/layout/LayoutTableCell.h" | 7 #include "core/layout/LayoutTableCell.h" |
| 8 #include "core/layout/LayoutTestHelper.h" | 8 #include "core/layout/LayoutTestHelper.h" |
| 9 | 9 |
| 10 namespace blink { | 10 namespace blink { |
| 11 | 11 |
| 12 namespace { | 12 namespace { |
| 13 | 13 |
| 14 using LayoutTableSectionTest = RenderingTest; | 14 class LayoutTableSectionTest : public RenderingTest { |
| 15 protected: |
| 16 LayoutTableSection* GetSectionByElementId(const char* id) { |
| 17 return ToLayoutTableSection(GetLayoutObjectByElementId(id)); |
| 18 } |
| 19 }; |
| 15 | 20 |
| 16 TEST_F(LayoutTableSectionTest, | 21 TEST_F(LayoutTableSectionTest, |
| 17 BackgroundIsKnownToBeOpaqueWithLayerAndCollapsedBorder) { | 22 BackgroundIsKnownToBeOpaqueWithLayerAndCollapsedBorder) { |
| 18 SetBodyInnerHTML( | 23 SetBodyInnerHTML( |
| 19 "<table style='border-collapse: collapse'>" | 24 "<table style='border-collapse: collapse'>" |
| 20 " <thead id='section' style='will-change: transform;" | 25 " <thead id='section' style='will-change: transform;" |
| 21 " background-color: blue'>" | 26 " background-color: blue'>" |
| 22 " <tr><td>Cell</td></tr>" | 27 " <tr><td>Cell</td></tr>" |
| 23 " </thead>" | 28 " </thead>" |
| 24 "</table>"); | 29 "</table>"); |
| 25 | 30 |
| 26 LayoutTableSection* section = | 31 auto* section = GetSectionByElementId("section"); |
| 27 ToLayoutTableSection(GetLayoutObjectByElementId("section")); | |
| 28 EXPECT_TRUE(section); | 32 EXPECT_TRUE(section); |
| 29 EXPECT_FALSE( | 33 EXPECT_FALSE( |
| 30 section->BackgroundIsKnownToBeOpaqueInRect(LayoutRect(0, 0, 1, 1))); | 34 section->BackgroundIsKnownToBeOpaqueInRect(LayoutRect(0, 0, 1, 1))); |
| 31 } | 35 } |
| 32 | 36 |
| 33 TEST_F(LayoutTableSectionTest, BackgroundIsKnownToBeOpaqueWithBorderSpacing) { | 37 TEST_F(LayoutTableSectionTest, BackgroundIsKnownToBeOpaqueWithBorderSpacing) { |
| 34 SetBodyInnerHTML( | 38 SetBodyInnerHTML( |
| 35 "<table style='border-spacing: 10px'>" | 39 "<table style='border-spacing: 10px'>" |
| 36 " <thead id='section' style='background-color: blue'>" | 40 " <thead id='section' style='background-color: blue'>" |
| 37 " <tr><td>Cell</td></tr>" | 41 " <tr><td>Cell</td></tr>" |
| 38 " </thead>" | 42 " </thead>" |
| 39 "</table>"); | 43 "</table>"); |
| 40 | 44 |
| 41 LayoutTableSection* section = | 45 auto* section = GetSectionByElementId("section"); |
| 42 ToLayoutTableSection(GetLayoutObjectByElementId("section")); | |
| 43 EXPECT_TRUE(section); | 46 EXPECT_TRUE(section); |
| 44 EXPECT_FALSE( | 47 EXPECT_FALSE( |
| 45 section->BackgroundIsKnownToBeOpaqueInRect(LayoutRect(0, 0, 1, 1))); | 48 section->BackgroundIsKnownToBeOpaqueInRect(LayoutRect(0, 0, 1, 1))); |
| 46 } | 49 } |
| 47 | 50 |
| 48 TEST_F(LayoutTableSectionTest, BackgroundIsKnownToBeOpaqueWithEmptyCell) { | 51 TEST_F(LayoutTableSectionTest, BackgroundIsKnownToBeOpaqueWithEmptyCell) { |
| 49 SetBodyInnerHTML( | 52 SetBodyInnerHTML( |
| 50 "<table style='border-spacing: 10px'>" | 53 "<table style='border-spacing: 10px'>" |
| 51 " <thead id='section' style='background-color: blue'>" | 54 " <thead id='section' style='background-color: blue'>" |
| 52 " <tr><td>Cell</td></tr>" | 55 " <tr><td>Cell</td></tr>" |
| 53 " <tr><td>Cell</td><td>Cell</td></tr>" | 56 " <tr><td>Cell</td><td>Cell</td></tr>" |
| 54 " </thead>" | 57 " </thead>" |
| 55 "</table>"); | 58 "</table>"); |
| 56 | 59 |
| 57 LayoutTableSection* section = | 60 auto* section = GetSectionByElementId("section"); |
| 58 ToLayoutTableSection(GetLayoutObjectByElementId("section")); | |
| 59 EXPECT_TRUE(section); | 61 EXPECT_TRUE(section); |
| 60 EXPECT_FALSE( | 62 EXPECT_FALSE( |
| 61 section->BackgroundIsKnownToBeOpaqueInRect(LayoutRect(0, 0, 1, 1))); | 63 section->BackgroundIsKnownToBeOpaqueInRect(LayoutRect(0, 0, 1, 1))); |
| 62 } | 64 } |
| 63 | 65 |
| 64 TEST_F(LayoutTableSectionTest, EmptySectionDirtiedRows) { | 66 TEST_F(LayoutTableSectionTest, EmptySectionDirtiedRows) { |
| 65 SetBodyInnerHTML( | 67 SetBodyInnerHTML( |
| 66 "<table style='border: 100px solid red'>" | 68 "<table style='border: 100px solid red'>" |
| 67 " <thead id='section'></thead>" | 69 " <thead id='section'></thead>" |
| 68 "</table>"); | 70 "</table>"); |
| 69 | 71 |
| 70 LayoutTableSection* section = | 72 auto* section = GetSectionByElementId("section"); |
| 71 ToLayoutTableSection(GetLayoutObjectByElementId("section")); | |
| 72 EXPECT_TRUE(section); | 73 EXPECT_TRUE(section); |
| 73 CellSpan cell_span = section->DirtiedRows(LayoutRect(50, 50, 100, 100)); | 74 CellSpan cell_span = section->DirtiedRows(LayoutRect(50, 50, 100, 100)); |
| 74 EXPECT_EQ(0u, cell_span.Start()); | 75 EXPECT_EQ(0u, cell_span.Start()); |
| 75 EXPECT_EQ(0u, cell_span.end()); | 76 EXPECT_EQ(0u, cell_span.end()); |
| 76 } | 77 } |
| 77 | 78 |
| 78 TEST_F(LayoutTableSectionTest, EmptySectionDirtiedEffectiveColumns) { | 79 TEST_F(LayoutTableSectionTest, EmptySectionDirtiedEffectiveColumns) { |
| 79 SetBodyInnerHTML( | 80 SetBodyInnerHTML( |
| 80 "<table style='border: 100px solid red'>" | 81 "<table style='border: 100px solid red'>" |
| 81 " <thead id='section'></thead>" | 82 " <thead id='section'></thead>" |
| 82 "</table>"); | 83 "</table>"); |
| 83 | 84 |
| 84 LayoutTableSection* section = | 85 auto* section = GetSectionByElementId("section"); |
| 85 ToLayoutTableSection(GetLayoutObjectByElementId("section")); | |
| 86 EXPECT_TRUE(section); | 86 EXPECT_TRUE(section); |
| 87 CellSpan cell_span = | 87 CellSpan cell_span = |
| 88 section->DirtiedEffectiveColumns(LayoutRect(50, 50, 100, 100)); | 88 section->DirtiedEffectiveColumns(LayoutRect(50, 50, 100, 100)); |
| 89 // The table has at least 1 column even if there is no cell. | 89 // The table has at least 1 column even if there is no cell. |
| 90 EXPECT_EQ(1u, section->Table()->NumEffectiveColumns()); | 90 EXPECT_EQ(1u, section->Table()->NumEffectiveColumns()); |
| 91 EXPECT_EQ(1u, cell_span.Start()); | 91 EXPECT_EQ(1u, cell_span.Start()); |
| 92 EXPECT_EQ(1u, cell_span.end()); | 92 EXPECT_EQ(1u, cell_span.end()); |
| 93 } | 93 } |
| 94 | 94 |
| 95 TEST_F(LayoutTableSectionTest, PrimaryCellAtAndOriginatingCellAt) { | 95 TEST_F(LayoutTableSectionTest, PrimaryCellAtAndOriginatingCellAt) { |
| 96 SetBodyInnerHTML( | 96 SetBodyInnerHTML( |
| 97 "<table>" | 97 "<table>" |
| 98 " <tbody id='section'>" | 98 " <tbody id='section'>" |
| 99 " <tr>" | 99 " <tr>" |
| 100 " <td id='cell00'></td>" | 100 " <td id='cell00'></td>" |
| 101 " <td id='cell01' rowspan='2'></td>" | 101 " <td id='cell01' rowspan='2'></td>" |
| 102 " </tr>" | 102 " </tr>" |
| 103 " <tr>" | 103 " <tr>" |
| 104 " <td id='cell10' colspan='2'></td>" | 104 " <td id='cell10' colspan='2'></td>" |
| 105 " </tr>" | 105 " </tr>" |
| 106 " </tbody>" | 106 " </tbody>" |
| 107 "</table>"); | 107 "</table>"); |
| 108 | 108 |
| 109 // x,yO: A cell originates from this grid slot. | 109 // x,yO: A cell originates from this grid slot. |
| 110 // x,yS: A cell originating from x,y spans into this slot. | 110 // x,yS: A cell originating from x,y spans into this slot. |
| 111 // 0 1 | 111 // 0 1 |
| 112 // 0 0,0(O) 0,1(O) | 112 // 0 0,0(O) 0,1(O) |
| 113 // 1 1,0(O) 1,0/0,1(S) | 113 // 1 1,0(O) 1,0/0,1(S) |
| 114 auto* section = ToLayoutTableSection(GetLayoutObjectByElementId("section")); | 114 auto* section = GetSectionByElementId("section"); |
| 115 auto* cell00 = GetLayoutObjectByElementId("cell00"); | 115 auto* cell00 = GetLayoutObjectByElementId("cell00"); |
| 116 auto* cell01 = GetLayoutObjectByElementId("cell01"); | 116 auto* cell01 = GetLayoutObjectByElementId("cell01"); |
| 117 auto* cell10 = GetLayoutObjectByElementId("cell10"); | 117 auto* cell10 = GetLayoutObjectByElementId("cell10"); |
| 118 | 118 |
| 119 EXPECT_EQ(cell00, section->PrimaryCellAt(0, 0)); | 119 EXPECT_EQ(cell00, section->PrimaryCellAt(0, 0)); |
| 120 EXPECT_EQ(cell01, section->PrimaryCellAt(0, 1)); | 120 EXPECT_EQ(cell01, section->PrimaryCellAt(0, 1)); |
| 121 EXPECT_EQ(cell10, section->PrimaryCellAt(1, 0)); | 121 EXPECT_EQ(cell10, section->PrimaryCellAt(1, 0)); |
| 122 EXPECT_EQ(cell10, section->PrimaryCellAt(1, 1)); | 122 EXPECT_EQ(cell10, section->PrimaryCellAt(1, 1)); |
| 123 EXPECT_EQ(cell00, section->OriginatingCellAt(0, 0)); | 123 EXPECT_EQ(cell00, section->OriginatingCellAt(0, 0)); |
| 124 EXPECT_EQ(cell01, section->OriginatingCellAt(0, 1)); | 124 EXPECT_EQ(cell01, section->OriginatingCellAt(0, 1)); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 147 " </tr>" | 147 " </tr>" |
| 148 " </tbody>" | 148 " </tbody>" |
| 149 "</table>"); | 149 "</table>"); |
| 150 | 150 |
| 151 // x,yO: A cell originates from this grid slot. | 151 // x,yO: A cell originates from this grid slot. |
| 152 // x,yS: A cell originating from x,y spans into this slot. | 152 // x,yS: A cell originating from x,y spans into this slot. |
| 153 // 0 1 2 | 153 // 0 1 2 |
| 154 // 0 0,0(O) 0,1(O) 0,2(O) | 154 // 0 0,0(O) 0,1(O) 0,2(O) |
| 155 // 1 1,0(O) 1,0/0,1(S) 0,2(S) | 155 // 1 1,0(O) 1,0/0,1(S) 0,2(S) |
| 156 // 2 2,0(O) 2,0(S) 2,0(S) | 156 // 2 2,0(O) 2,0(S) 2,0(S) |
| 157 auto* section = ToLayoutTableSection(GetLayoutObjectByElementId("section")); | 157 auto* section = GetSectionByElementId("section"); |
| 158 | 158 |
| 159 // Cell 0,0 only. | 159 // Cell 0,0 only. |
| 160 auto span = section->DirtiedRows(LayoutRect(5, 5, 90, 90)); | 160 auto span = section->DirtiedRows(LayoutRect(5, 5, 90, 90)); |
| 161 EXPECT_EQ(0u, span.Start()); | 161 EXPECT_EQ(0u, span.Start()); |
| 162 EXPECT_EQ(1u, span.end()); | 162 EXPECT_EQ(1u, span.end()); |
| 163 span = section->DirtiedEffectiveColumns(LayoutRect(5, 5, 90, 90)); | 163 span = section->DirtiedEffectiveColumns(LayoutRect(5, 5, 90, 90)); |
| 164 EXPECT_EQ(0u, span.Start()); | 164 EXPECT_EQ(0u, span.Start()); |
| 165 EXPECT_EQ(1u, span.end()); | 165 EXPECT_EQ(1u, span.end()); |
| 166 | 166 |
| 167 // Rect intersects the first row and all originating primary cells. | 167 // Rect intersects the first row and all originating primary cells. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 // Rect intersects (1,2) and (2,2). Dirtied rows and dirtied columns cover all | 204 // Rect intersects (1,2) and (2,2). Dirtied rows and dirtied columns cover all |
| 205 // rows and columns. | 205 // rows and columns. |
| 206 span = section->DirtiedRows(LayoutRect(205, 105, 90, 190)); | 206 span = section->DirtiedRows(LayoutRect(205, 105, 90, 190)); |
| 207 EXPECT_EQ(0u, span.Start()); | 207 EXPECT_EQ(0u, span.Start()); |
| 208 EXPECT_EQ(3u, span.end()); | 208 EXPECT_EQ(3u, span.end()); |
| 209 span = section->DirtiedEffectiveColumns(LayoutRect(205, 105, 90, 190)); | 209 span = section->DirtiedEffectiveColumns(LayoutRect(205, 105, 90, 190)); |
| 210 EXPECT_EQ(0u, span.Start()); | 210 EXPECT_EQ(0u, span.Start()); |
| 211 EXPECT_EQ(3u, span.end()); | 211 EXPECT_EQ(3u, span.end()); |
| 212 } | 212 } |
| 213 | 213 |
| 214 TEST_F(LayoutTableSectionTest, VisualOverflowWithCollapsedBorders) { |
| 215 SetBodyInnerHTML( |
| 216 "<style>" |
| 217 " table { border-collapse: collapse }" |
| 218 " td { border: 0px solid blue; padding: 0 }" |
| 219 " div { width: 100px; height: 100px }" |
| 220 "</style>" |
| 221 "<table>" |
| 222 " <tbody id='section'>" |
| 223 " <tr>" |
| 224 " <td style='border-bottom-width: 10px;" |
| 225 " outline: 3px solid blue'><div></div></td>" |
| 226 " <td style='border-width: 3px 15px'><div></div></td>" |
| 227 " </tr>" |
| 228 " <tr style='outline: 8px solid green'><td><div></div></td></tr>" |
| 229 " </tbody>" |
| 230 "</table>"); |
| 231 |
| 232 auto* section = GetSectionByElementId("section"); |
| 233 |
| 234 // The section's self visual overflow covers the collapsed borders. |
| 235 LayoutRect expected_self_visual_overflow = section->BorderBoxRect(); |
| 236 expected_self_visual_overflow.ExpandEdges(LayoutUnit(1), LayoutUnit(8), |
| 237 LayoutUnit(0), LayoutUnit(0)); |
| 238 EXPECT_EQ(expected_self_visual_overflow, section->SelfVisualOverflowRect()); |
| 239 |
| 240 // The section's visual overflow covers self visual overflow and visual |
| 241 // overflows rows. |
| 242 LayoutRect expected_visual_overflow = section->BorderBoxRect(); |
| 243 expected_visual_overflow.ExpandEdges(LayoutUnit(3), LayoutUnit(8), |
| 244 LayoutUnit(8), LayoutUnit(8)); |
| 245 EXPECT_EQ(expected_visual_overflow, section->VisualOverflowRect()); |
| 246 } |
| 247 |
| 214 } // anonymous namespace | 248 } // anonymous namespace |
| 215 | 249 |
| 216 } // namespace blink | 250 } // namespace blink |
| OLD | NEW |