blob: 85c18abf48d3eddfd23fa96754970c6b156ee296 [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "pdf/pdfium/pdfium_print.h"
#include <memory>
#include <optional>
#include "base/files/file_path.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "pdf/pdfium/pdfium_engine.h"
#include "pdf/pdfium/pdfium_engine_exports.h"
#include "pdf/pdfium/pdfium_test_base.h"
#include "pdf/test/test_client.h"
#include "pdf/test/test_helpers.h"
#include "printing/pdf_render_settings.h"
#include "printing/units.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/public/web/web_print_params.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size_f.h"
#include "ui/gfx/geometry/skia_conversions.h"
namespace chrome_pdf {
using PDFiumPrintTest = PDFiumTestBase;
using ::testing::ElementsAre;
namespace {
// blink::WebPrintParams takes values in CSS pixels, not points.
constexpr gfx::SizeF kUSLetterSize = {816, 1056};
constexpr gfx::RectF kUSLetterRect = {{0, 0}, kUSLetterSize};
constexpr gfx::RectF kPrintableAreaRect = {{24, 24}, {768, 977.33333}};
using ExpectedDimensions = std::vector<gfx::SizeF>;
std::string GenerateRendererSpecificFileName(const std::string& file_name,
bool use_skia_renderer) {
return base::StringPrintf("%s%s.png", file_name.c_str(),
use_skia_renderer ? "_skia" : "");
}
base::FilePath GetReferenceFilePath(base::StringPiece test_filename) {
return base::FilePath(FILE_PATH_LITERAL("pdfium_print"))
.AppendASCII(test_filename);
}
blink::WebPrintParams GetDefaultPrintParams() {
blink::WebPrintParams params;
params.default_page_description.size = kUSLetterSize;
params.printable_area_in_css_pixels = kUSLetterRect;
params.print_scaling_option = printing::mojom::PrintScalingOption::kNone;
return params;
}
void CheckPdfDimensions(const std::vector<uint8_t>& pdf_data,
const ExpectedDimensions& expected_dimensions) {
PDFiumEngineExports exports;
int page_count;
ASSERT_TRUE(exports.GetPDFDocInfo(pdf_data, &page_count, nullptr));
ASSERT_GT(page_count, 0);
ASSERT_EQ(expected_dimensions.size(), static_cast<size_t>(page_count));
for (int i = 0; i < page_count; ++i) {
std::optional<gfx::SizeF> page_size =
exports.GetPDFPageSizeByIndex(pdf_data, i);
ASSERT_TRUE(page_size.has_value());
EXPECT_EQ(expected_dimensions[i], page_size.value());
}
}
void CheckPdfRendering(const std::vector<uint8_t>& pdf_data,
int page_number,
const gfx::SizeF& size_in_points,
base::StringPiece expected_png_filename) {
int width_in_pixels =
printing::ConvertUnit(size_in_points.width(), printing::kPointsPerInch,
printing::kDefaultPdfDpi);
int height_in_pixels =
printing::ConvertUnit(size_in_points.height(), printing::kPointsPerInch,
printing::kDefaultPdfDpi);
const gfx::Rect page_rect(width_in_pixels, height_in_pixels);
SkBitmap page_bitmap;
page_bitmap.allocPixels(
SkImageInfo::Make(gfx::SizeToSkISize(page_rect.size()),
kBGRA_8888_SkColorType, kPremul_SkAlphaType));
PDFEngineExports::RenderingSettings settings(
gfx::Size(printing::kDefaultPdfDpi, printing::kDefaultPdfDpi), page_rect,
/*fit_to_bounds=*/true,
/*stretch_to_bounds=*/false,
/*keep_aspect_ratio=*/true,
/*center_in_bounds=*/true,
/*autorotate=*/false, /*use_color=*/true, /*render_for_printing=*/true);
PDFiumEngineExports exports;
ASSERT_TRUE(exports.RenderPDFPageToBitmap(pdf_data, page_number, settings,
page_bitmap.getPixels()));
EXPECT_TRUE(MatchesPngFile(page_bitmap.asImage().get(),
GetReferenceFilePath(expected_png_filename)));
}
} // namespace
TEST_P(PDFiumPrintTest, Basic) {
TestClient client;
std::unique_ptr<PDFiumEngine> engine =
InitializeEngine(&client, FILE_PATH_LITERAL("hello_world2.pdf"));
ASSERT_TRUE(engine);
PDFiumPrint print(engine.get());
blink::WebPrintParams print_params = GetDefaultPrintParams();
blink::WebPrintParams print_params_raster = print_params;
print_params_raster.rasterize_pdf = true;
{
// Print 2 pages.
const ExpectedDimensions kExpectedDimensions = {{612.0, 792.0},
{612.0, 792.0}};
const std::vector<int> pages = {0, 1};
std::vector<uint8_t> pdf_data = print.PrintPagesAsPdf(pages, print_params);
CheckPdfDimensions(pdf_data, kExpectedDimensions);
pdf_data = print.PrintPagesAsPdf(pages, print_params_raster);
CheckPdfDimensions(pdf_data, kExpectedDimensions);
}
{
// Print 1 page.
const ExpectedDimensions kExpectedDimensions = {{612.0, 792.0}};
const std::vector<int> pages = {0};
std::vector<uint8_t> pdf_data = print.PrintPagesAsPdf(pages, print_params);
CheckPdfDimensions(pdf_data, kExpectedDimensions);
pdf_data = print.PrintPagesAsPdf(pages, print_params_raster);
CheckPdfDimensions(pdf_data, kExpectedDimensions);
}
{
// Print the other page.
const ExpectedDimensions kExpectedDimensions = {{612.0, 792.0}};
const std::vector<int> pages = {1};
std::vector<uint8_t> pdf_data = print.PrintPagesAsPdf(pages, print_params);
CheckPdfDimensions(pdf_data, kExpectedDimensions);
pdf_data = print.PrintPagesAsPdf(pages, print_params_raster);
CheckPdfDimensions(pdf_data, kExpectedDimensions);
}
}
TEST_P(PDFiumPrintTest, AlterScalingDefault) {
TestClient client;
std::unique_ptr<PDFiumEngine> engine =
InitializeEngine(&client, FILE_PATH_LITERAL("rectangles.pdf"));
ASSERT_TRUE(engine);
PDFiumPrint print(engine.get());
const ExpectedDimensions kExpectedDimensions = {{612.0, 792.0}};
const std::vector<int> pages = {0};
blink::WebPrintParams print_params = GetDefaultPrintParams();
print_params.printable_area_in_css_pixels = kPrintableAreaRect;
std::vector<uint8_t> pdf_data = print.PrintPagesAsPdf(pages, print_params);
CheckPdfDimensions(pdf_data, kExpectedDimensions);
CheckPdfRendering(
pdf_data, 0, kExpectedDimensions[0],
GenerateRendererSpecificFileName("alter_scaling_default",
/*use_skia_renderer=*/GetParam()));
print_params.rasterize_pdf = true;
pdf_data = print.PrintPagesAsPdf(pages, print_params);
CheckPdfDimensions(pdf_data, kExpectedDimensions);
CheckPdfRendering(
pdf_data, 0, kExpectedDimensions[0],
GenerateRendererSpecificFileName("alter_scaling_default_raster",
/*use_skia_renderer=*/GetParam()));
}
TEST_P(PDFiumPrintTest, AlterScalingFitPaper) {
TestClient client;
std::unique_ptr<PDFiumEngine> engine =
InitializeEngine(&client, FILE_PATH_LITERAL("rectangles.pdf"));
ASSERT_TRUE(engine);
PDFiumPrint print(engine.get());
const ExpectedDimensions kExpectedDimensions = {{612.0, 792.0}};
const std::vector<int> pages = {0};
blink::WebPrintParams print_params = GetDefaultPrintParams();
print_params.printable_area_in_css_pixels = kPrintableAreaRect;
print_params.print_scaling_option =
printing::mojom::PrintScalingOption::kFitToPaper;
std::vector<uint8_t> pdf_data = print.PrintPagesAsPdf(pages, print_params);
CheckPdfDimensions(pdf_data, kExpectedDimensions);
CheckPdfRendering(
pdf_data, 0, kExpectedDimensions[0],
GenerateRendererSpecificFileName("alter_scaling_fit-paper",
/*use_skia_renderer=*/GetParam()));
print_params.rasterize_pdf = true;
pdf_data = print.PrintPagesAsPdf(pages, print_params);
CheckPdfDimensions(pdf_data, kExpectedDimensions);
CheckPdfRendering(
pdf_data, 0, kExpectedDimensions[0],
GenerateRendererSpecificFileName("alter_scaling_fit-paper_raster",
/*use_skia_renderer=*/GetParam()));
}
TEST_P(PDFiumPrintTest, AlterScalingFitPrintable) {
TestClient client;
std::unique_ptr<PDFiumEngine> engine =
InitializeEngine(&client, FILE_PATH_LITERAL("rectangles.pdf"));
ASSERT_TRUE(engine);
PDFiumPrint print(engine.get());
const ExpectedDimensions kExpectedDimensions = {{612.0, 792.0}};
const std::vector<int> pages = {0};
blink::WebPrintParams print_params = GetDefaultPrintParams();
print_params.printable_area_in_css_pixels = kPrintableAreaRect;
print_params.print_scaling_option =
printing::mojom::PrintScalingOption::kFitToPrintableArea;
std::vector<uint8_t> pdf_data = print.PrintPagesAsPdf(pages, print_params);
CheckPdfDimensions(pdf_data, kExpectedDimensions);
CheckPdfRendering(
pdf_data, 0, kExpectedDimensions[0],
GenerateRendererSpecificFileName("alter_scaling_fit-printable",
/*use_skia_renderer=*/GetParam()));
print_params.rasterize_pdf = true;
pdf_data = print.PrintPagesAsPdf(pages, print_params);
CheckPdfDimensions(pdf_data, kExpectedDimensions);
CheckPdfRendering(
pdf_data, 0, kExpectedDimensions[0],
GenerateRendererSpecificFileName("alter_scaling_fit-printable_raster",
/*use_skia_renderer=*/GetParam()));
}
INSTANTIATE_TEST_SUITE_P(All, PDFiumPrintTest, testing::Bool());
} // namespace chrome_pdf