diff --git a/third_party/blink/renderer/core/page/print_context_test.cc b/third_party/blink/renderer/core/page/print_context_test.cc index 36df50f346eefe..c72c51872602f5 100644 --- a/third_party/blink/renderer/core/page/print_context_test.cc +++ b/third_party/blink/renderer/core/page/print_context_test.cc @@ -130,14 +130,17 @@ class PrintContextTest : public PaintTestConfigurations, public RenderingTest { GetDocument().body()->setInnerHTML(body_content); } - void PrintSinglePage(SkCanvas& canvas) { - gfx::Rect page_rect(0, 0, kPageWidth, kPageHeight); + gfx::Rect PrintSinglePage(SkCanvas& canvas, int page_number = 0) { GetDocument().SetPrinting(Document::kBeforePrinting); Event* event = MakeGarbageCollected(); GetPrintContext().GetFrame()->DomWindow()->DispatchEvent(*event); - GetPrintContext().BeginPrintMode(page_rect.width(), page_rect.height()); + GetPrintContext().BeginPrintMode(kPageWidth, kPageHeight); GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint( DocumentUpdateReason::kTest); + + GetPrintContext().ComputePageRects(gfx::SizeF(kPageWidth, kPageHeight)); + gfx::Rect page_rect = GetPrintContext().PageRect(page_number); + auto* builder = MakeGarbageCollected(); GraphicsContext& context = builder->Context(); context.SetPrinting(true); @@ -151,6 +154,7 @@ class PrintContextTest : public PaintTestConfigurations, public RenderingTest { } builder->EndRecording()->Playback(&canvas); GetPrintContext().EndPrintMode(); + return page_rect; } static String AbsoluteBlockHtmlForLink(int x, @@ -466,6 +470,57 @@ TEST_P(PrintContextTest, LinkTargetBoundingBox) { EXPECT_SKRECT_EQ(50, 60, 200, 100, operations[0].rect); } +TEST_P(PrintContextTest, LinkInFragmentedContainer) { + SetBodyInnerHTML(R"HTML( + +
+
+ link 1
+ + link 2
+ link 3
+
+ )HTML"); + + MockPageContextCanvas first_page_canvas; + gfx::Rect page_rect = PrintSinglePage(first_page_canvas, 0); + Vector operations = + first_page_canvas.RecordedOperations(); + + // TODO(crbug.com/1392701): Should be 1. + ASSERT_EQ(operations.size(), 3u); + + const auto& page1_link1 = operations[0]; + EXPECT_EQ(page1_link1.type, MockPageContextCanvas::kDrawRect); + EXPECT_GE(page1_link1.rect.y(), page_rect.height() - 90); + EXPECT_LE(page1_link1.rect.bottom(), page_rect.height() - 40); + + MockPageContextCanvas second_page_canvas; + page_rect = PrintSinglePage(second_page_canvas, 1); + operations = second_page_canvas.RecordedOperations(); + + // TODO(crbug.com/1392701): Should be 2. + ASSERT_EQ(operations.size(), 3u); + // TODO(crbug.com/1392701): Should be operations[0] + const auto& page2_link1 = operations[1]; + // TODO(crbug.com/1392701): Should be operations[1] + const auto& page2_link2 = operations[2]; + + EXPECT_EQ(page2_link1.type, MockPageContextCanvas::kDrawRect); + EXPECT_GE(page2_link1.rect.y(), page_rect.y()); + EXPECT_LE(page2_link1.rect.bottom(), page_rect.y() + 50); + EXPECT_EQ(page2_link2.type, MockPageContextCanvas::kDrawRect); + EXPECT_GE(page2_link2.rect.y(), page_rect.y() + 50); + EXPECT_LE(page2_link2.rect.bottom(), page_rect.y() + 100); +} + // Here are a few tests to check that shrink to fit doesn't mess up page count. TEST_P(PrintContextTest, ScaledVerticalRL1) { diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc index 5b7cb08913f0ac..c22267b1c6a8f0 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc @@ -821,8 +821,20 @@ void NGBoxFragmentPainter::PaintLineBoxes(const PaintInfo& paint_info, if (child_paint_info.phase == PaintPhase::kForeground && child_paint_info.ShouldAddUrlMetadata()) { + // TODO(crbug.com/1392701): Avoid walking the LayoutObject tree (which is + // what AddURLRectsForInlineChildrenRecursively() does). We should walk the + // fragment tree instead (if we can figure out how to deal with culled + // inlines - or get rid of them). Walking the LayoutObject tree means that + // we'll visit every link in the container for each fragment generated, + // leading to duplicate entries. This is only fine as long as the absolute + // offsets is the same every time a given link is visited. Otherwise links + // might end up as unclickable in the resulting PDF. So make sure that the + // paint offset relative to the first fragment generated by this + // container. This matches legacy engine behavior. + PhysicalOffset paint_offset_for_first_fragment = + paint_offset - OffsetInStitchedFragments(box_fragment_); AddURLRectsForInlineChildrenRecursively(*layout_object, child_paint_info, - paint_offset); + paint_offset_for_first_fragment); } // If we have no lines then we have no work to do.