17242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved. 27242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// Use of this source code is governed by a BSD-style license that can be 37242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// found in the LICENSE file. 47242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 57242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "config.h" 67242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/page/PrintContext.h" 77242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 87242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/dom/Document.h" 97242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/html/HTMLElement.h" 107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/testing/DummyPageHolder.h" 117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "platform/graphics/GraphicsContext.h" 127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "platform/testing/SkiaForCoreTesting.h" 137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "platform/text/TextStream.h" 147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include <gtest/gtest.h> 157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccinamespace blink { 177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciconst int kPageWidth = 800; 197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciconst int kPageHeight = 600; 207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass MockPrintContext : public PrintContext { 227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccipublic: 237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci MockPrintContext(LocalFrame* frame) : PrintContext(frame) { } 247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void outputLinkAndLinkedDestinations(GraphicsContext& context, Node* node, const IntRect& pageRect) 267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { 277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci PrintContext::outputLinkAndLinkedDestinations(context, node, pageRect); 287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}; 307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass MockCanvas : public SkCanvas { 327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccipublic: 337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci enum OperationType { 347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci DrawRect, 357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci DrawPoint 367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci }; 377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci struct Operation { 397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci OperationType type; 407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci SkRect rect; 417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci }; 427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci MockCanvas() : SkCanvas(kPageWidth, kPageHeight) { } 447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 457242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci virtual void drawRect(const SkRect& rect, const SkPaint& paint) OVERRIDE 467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { 477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ASSERT_TRUE(paint.getAnnotation()); 487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci Operation operation = { DrawRect, rect }; 497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_recordedOperations.append(operation); 507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci virtual void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) OVERRIDE 537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { 547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ASSERT_EQ(1u, count); // Only called from drawPoint(). 557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ASSERT_TRUE(paint.getAnnotation()); 567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci Operation operation = { DrawPoint, SkRect::MakeXYWH(pts[0].x(), pts[0].y(), 0, 0) }; 577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci m_recordedOperations.append(operation); 587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci const Vector<Operation>& recordedOperations() const { return m_recordedOperations; } 617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciprivate: 637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci Vector<Operation> m_recordedOperations; 647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}; 657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass PrintContextTest : public testing::Test { 677242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciprotected: 687242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci PrintContextTest() 697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci : m_pageHolder(DummyPageHolder::create(IntSize(kPageWidth, kPageHeight))) 707242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci , m_printContext(adoptPtrWillBeNoop(new MockPrintContext(document().frame()))) { } 717242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci Document& document() const { return m_pageHolder->document(); } 737242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci MockPrintContext& printContext() { return *m_printContext.get(); } 747242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void setBodyInnerHTML(String bodyContent) 767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { 777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci document().body()->setInnerHTML(bodyContent, ASSERT_NO_EXCEPTION); 787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci void printSinglePage(SkCanvas& canvas) 817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { 827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci IntRect pageRect(0, 0, kPageWidth, kPageHeight); 837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci GraphicsContext context(&canvas); 847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci printContext().begin(kPageWidth, kPageHeight); 857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci printContext().outputLinkAndLinkedDestinations(context, &document(), pageRect); 867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci printContext().end(); 877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 887242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 897242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci static String htmlForLink(int x, int y, int width, int height, const char* url) 907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { 917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci TextStream ts; 927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ts << "<a style='position: absolute; left: " << x << "px; top: " << y << "px; width: " << width << "px; height: " << height 937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci << "px' href='" << url << "'>" << url << "</a>"; 947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return ts.release(); 957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci static String htmlForAnchor(int x, int y, const char* name) 987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci { 997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci TextStream ts; 1007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ts << "<a name='" << name << "' style='position: absolute; left: " << x << "px; top: " << y << "px'>" << name << "</a>"; 1017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci return ts.release(); 1027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci } 1037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciprivate: 1057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci OwnPtr<DummyPageHolder> m_pageHolder; 1067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci OwnPtrWillBePersistent<MockPrintContext> m_printContext; 1077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}; 1087242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#define EXPECT_SKRECT_EQ(expectedX, expectedY, expectedWidth, expectedHeight, actualRect) \ 1107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci EXPECT_EQ(expectedX, actualRect.x()); \ 1117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci EXPECT_EQ(expectedY, actualRect.y()); \ 1127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci EXPECT_EQ(expectedWidth, actualRect.width()); \ 1137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci EXPECT_EQ(expectedHeight, actualRect.height()); 1147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciTEST_F(PrintContextTest, LinkTarget) 1167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{ 1177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci MockCanvas canvas; 1187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci setBodyInnerHTML(htmlForLink(50, 60, 70, 80, "http://www.google.com") 1197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci + htmlForLink(150, 160, 170, 180, "http://www.google.com#fragment")); 1207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci printSinglePage(canvas); 1217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci const Vector<MockCanvas::Operation>& operations = canvas.recordedOperations(); 1237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ASSERT_EQ(2u, operations.size()); 1247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // The items in the result can be in any sequence. 1267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci size_t firstIndex = operations[0].rect.x() == 50 ? 0 : 1; 1277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci EXPECT_EQ(MockCanvas::DrawRect, operations[firstIndex].type); 1287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci EXPECT_SKRECT_EQ(50, 60, 70, 80, operations[firstIndex].rect); 1297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // We should also check if the annotation is correct but Skia doesn't export 1307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci // SkAnnotation API. 1317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci size_t secondIndex = firstIndex == 0 ? 1 : 0; 1337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci EXPECT_EQ(MockCanvas::DrawRect, operations[secondIndex].type); 1347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci EXPECT_SKRECT_EQ(150, 160, 170, 180, operations[secondIndex].rect); 1357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci} 1367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciTEST_F(PrintContextTest, LinkedTarget) 1387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{ 1397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci MockCanvas canvas; 1407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci document().setBaseURLOverride(KURL(ParsedURLString, "http://a.com/")); 1417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci setBodyInnerHTML(htmlForLink(50, 60, 70, 80, "#fragment") // Generates a Link_Named_Dest_Key annotation 1427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci + htmlForLink(150, 160, 170, 180, "#not-found") // Generates no annotation 1437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci + htmlForAnchor(250, 260, "fragment") // Generates a Define_Named_Dest_Key annotation 1447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci + htmlForAnchor(350, 360, "fragment-not-used")); // Generates no annotation 1457242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci printSinglePage(canvas); 1467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci const Vector<MockCanvas::Operation>& operations = canvas.recordedOperations(); 1487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci ASSERT_EQ(2u, operations.size()); 1497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci size_t firstIndex = operations[0].rect.x() == 50 ? 0 : 1; 1517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci EXPECT_EQ(MockCanvas::DrawRect, operations[firstIndex].type); 1527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci EXPECT_SKRECT_EQ(50, 60, 70, 80, operations[firstIndex].rect); 1537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci size_t secondIndex = firstIndex == 0 ? 1 : 0; 1557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci EXPECT_EQ(MockCanvas::DrawPoint, operations[secondIndex].type); 1567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci EXPECT_SKRECT_EQ(250, 260, 0, 0, operations[secondIndex].rect); 1577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci} 1587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci 1597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci} // namespace blink 160