123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- // Copyright (c) 2011 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "printing/pdf_metafile_cg_mac.h"
- #import <ApplicationServices/ApplicationServices.h>
- #include <stdint.h>
- #include <memory>
- #include <string>
- #include <vector>
- #include "base/files/file_util.h"
- #include "base/hash/sha1.h"
- #include "base/path_service.h"
- #include "printing/mojom/print.mojom.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "ui/gfx/codec/png_codec.h"
- #include "ui/gfx/geometry/rect.h"
- namespace printing {
- namespace {
- base::FilePath GetPdfTestData(const base::FilePath::StringType& filename) {
- base::FilePath root_path;
- if (!base::PathService::Get(base::DIR_SOURCE_ROOT, &root_path))
- return base::FilePath();
- return root_path.Append("pdf").Append("test").Append("data").Append(filename);
- }
- base::FilePath GetPrintingTestData(const base::FilePath::StringType& filename) {
- base::FilePath root_path;
- if (!base::PathService::Get(base::DIR_SOURCE_ROOT, &root_path))
- return base::FilePath();
- return root_path.Append("printing")
- .Append("test")
- .Append("data")
- .Append("pdf_cg")
- .Append(filename);
- }
- std::unique_ptr<PdfMetafileCg> GetPdfMetafile(
- const base::FilePath::StringType& pdf_filename) {
- // Get test data.
- base::FilePath pdf_file = GetPdfTestData(pdf_filename);
- if (pdf_file.empty())
- return nullptr;
- std::string pdf_data;
- if (!base::ReadFileToString(pdf_file, &pdf_data))
- return nullptr;
- // Initialize and check metafile.
- auto pdf_cg = std::make_unique<PdfMetafileCg>();
- if (!pdf_cg->InitFromData(base::as_bytes(base::make_span(pdf_data))))
- return nullptr;
- return pdf_cg;
- }
- void RenderedPdfSha1(const base::FilePath::StringType& pdf_filename,
- size_t page_number,
- const gfx::Rect& expected_page_bounds,
- const gfx::Size& dest_size,
- bool autorotate,
- bool fit_to_page,
- base::SHA1Digest* rendered_hash) {
- // Initialize and verify the metafile.
- std::unique_ptr<PdfMetafileCg> pdf_cg = GetPdfMetafile(pdf_filename);
- ASSERT_TRUE(pdf_cg);
- ASSERT_LE(page_number, pdf_cg->GetPageCount());
- const gfx::Rect bounds = pdf_cg->GetPageBounds(page_number);
- ASSERT_EQ(expected_page_bounds, bounds);
- // Set up rendering context.
- constexpr size_t kBitsPerComponent = 8;
- constexpr size_t kBytesPerPixel = 4;
- const size_t kStride = dest_size.width() * kBytesPerPixel;
- std::vector<uint8_t> rendered_bitmap(dest_size.height() * kStride);
- base::ScopedCFTypeRef<CGColorSpaceRef> color_space(
- CGColorSpaceCreateDeviceRGB());
- base::ScopedCFTypeRef<CGContextRef> context(CGBitmapContextCreate(
- rendered_bitmap.data(), dest_size.width(), dest_size.height(),
- kBitsPerComponent, kStride, color_space,
- uint32_t{kCGImageAlphaPremultipliedFirst} | kCGBitmapByteOrder32Little));
- // Render using metafile and calculate the output hash.
- ASSERT_TRUE(pdf_cg->RenderPage(page_number, context,
- gfx::Rect(dest_size).ToCGRect(), autorotate,
- fit_to_page));
- *rendered_hash = base::SHA1HashSpan(rendered_bitmap);
- }
- void ExpectedPngSha1(const base::FilePath::StringType& expected_png_filename,
- const gfx::Size& expected_png_size,
- base::SHA1Digest* expected_hash) {
- base::FilePath expected_png_file = GetPrintingTestData(expected_png_filename);
- ASSERT_FALSE(expected_png_file.empty());
- std::string expected_png_data;
- ASSERT_TRUE(base::ReadFileToString(expected_png_file, &expected_png_data));
- // Decode expected PNG and calculate the output hash.
- std::vector<uint8_t> expected_png_bitmap;
- int png_width;
- int png_height;
- ASSERT_TRUE(gfx::PNGCodec::Decode(
- reinterpret_cast<const uint8_t*>(expected_png_data.data()),
- expected_png_data.size(), gfx::PNGCodec::FORMAT_BGRA,
- &expected_png_bitmap, &png_width, &png_height));
- ASSERT_EQ(expected_png_size.width(), png_width);
- ASSERT_EQ(expected_png_size.height(), png_height);
- *expected_hash = base::SHA1HashSpan(expected_png_bitmap);
- }
- void TestRenderPageWithTransformParams(
- const base::FilePath::StringType& pdf_filename,
- size_t page_number,
- const gfx::Rect& expected_page_bounds,
- const base::FilePath::StringType& expected_png_filename,
- const gfx::Size& dest_size,
- bool autorotate,
- bool fit_to_page) {
- base::SHA1Digest rendered_hash;
- RenderedPdfSha1(pdf_filename, page_number, expected_page_bounds, dest_size,
- autorotate, fit_to_page, &rendered_hash);
- base::SHA1Digest expected_hash;
- ExpectedPngSha1(expected_png_filename, dest_size, &expected_hash);
- // Make sure the hashes match.
- EXPECT_EQ(expected_hash, rendered_hash);
- }
- void TestRenderPage(const base::FilePath::StringType& pdf_filename,
- size_t page_number,
- const gfx::Rect& expected_page_bounds,
- const base::FilePath::StringType& expected_png_filename,
- const gfx::Size& dest_size) {
- TestRenderPageWithTransformParams(
- pdf_filename, page_number, expected_page_bounds, expected_png_filename,
- dest_size, /*autorotate=*/true, /*fit_to_page=*/false);
- }
- } // namespace
- TEST(PdfMetafileCgTest, Pdf) {
- // Test in-renderer constructor.
- PdfMetafileCg pdf;
- EXPECT_TRUE(pdf.Init());
- EXPECT_TRUE(pdf.context());
- // Render page 1.
- constexpr gfx::Rect kRect1(10, 10, 520, 700);
- constexpr gfx::Size kSize1(540, 720);
- pdf.StartPage(kSize1, kRect1, 1.25, mojom::PageOrientation::kUpright);
- pdf.FinishPage();
- // Render page 2.
- constexpr gfx::Rect kRect2(10, 10, 520, 700);
- constexpr gfx::Size kSize2(720, 540);
- pdf.StartPage(kSize2, kRect2, 2.0, mojom::PageOrientation::kUpright);
- pdf.FinishPage();
- pdf.FinishDocument();
- // Check data size.
- const uint32_t size = pdf.GetDataSize();
- EXPECT_GT(size, 0U);
- // Get resulting data.
- std::vector<char> buffer(size, 0);
- pdf.GetData(&buffer.front(), size);
- // Test browser-side constructor.
- PdfMetafileCg pdf2;
- // TODO(thestig): Make `buffer` uint8_t and avoid the base::as_bytes() call.
- EXPECT_TRUE(pdf2.InitFromData(base::as_bytes(base::make_span(buffer))));
- // Get the first 4 characters from pdf2.
- std::vector<char> buffer2(4, 0);
- pdf2.GetData(&buffer2.front(), 4);
- // Test that the header begins with "%PDF".
- std::string header(&buffer2.front(), 4);
- EXPECT_EQ(0U, header.find("%PDF", 0));
- // Test that the PDF is correctly reconstructed.
- EXPECT_EQ(2U, pdf2.GetPageCount());
- gfx::Size page_size = pdf2.GetPageBounds(1).size();
- EXPECT_EQ(540, page_size.width());
- EXPECT_EQ(720, page_size.height());
- page_size = pdf2.GetPageBounds(2).size();
- EXPECT_EQ(720, page_size.width());
- EXPECT_EQ(540, page_size.height());
- }
- TEST(PdfMetafileCgTest, GetPageBounds) {
- // Get test data.
- base::FilePath pdf_file = GetPdfTestData("rectangles_multi_pages.pdf");
- ASSERT_FALSE(pdf_file.empty());
- std::string pdf_data;
- ASSERT_TRUE(base::ReadFileToString(pdf_file, &pdf_data));
- // Initialize and check metafile.
- PdfMetafileCg pdf_cg;
- ASSERT_TRUE(pdf_cg.InitFromData(base::as_bytes(base::make_span(pdf_data))));
- ASSERT_EQ(5u, pdf_cg.GetPageCount());
- // Since the input into GetPageBounds() is a 1-indexed page number, 0 and 6
- // are out of bounds.
- gfx::Rect bounds;
- for (size_t i : {0, 6}) {
- bounds = pdf_cg.GetPageBounds(i);
- EXPECT_EQ(0, bounds.x());
- EXPECT_EQ(0, bounds.y());
- EXPECT_EQ(0, bounds.width());
- EXPECT_EQ(0, bounds.height());
- }
- // Whereas 1-5 are in bounds.
- for (size_t i = 1; i < 6; ++i) {
- bounds = pdf_cg.GetPageBounds(i);
- EXPECT_EQ(0, bounds.x());
- EXPECT_EQ(0, bounds.y());
- EXPECT_EQ(200, bounds.width());
- EXPECT_EQ(250, bounds.height());
- }
- }
- TEST(PdfMetafileCgTest, RenderPortraitRectangles) {
- constexpr gfx::Rect kPageBounds(200, 300);
- constexpr gfx::Size kDestinationSize(200, 300);
- TestRenderPage("rectangles.pdf", /*page_number=*/1, kPageBounds,
- "render_portrait_rectangles_expected.0.png", kDestinationSize);
- }
- TEST(PdfMetafileCgTest, RenderAutorotatedPortraitRectangles) {
- constexpr gfx::Rect kPageBounds(200, 300);
- constexpr gfx::Size kDestinationSize(300, 200);
- TestRenderPage("rectangles.pdf", /*page_number=*/1, kPageBounds,
- "render_autorotated_portrait_rectangles_expected.0.png",
- kDestinationSize);
- }
- TEST(PdfMetafileCgTest, RenderLargePortraitRectangles) {
- constexpr gfx::Rect kPageBounds(200, 300);
- constexpr gfx::Size kDestinationSize(100, 120);
- TestRenderPage("rectangles.pdf", /*page_number=*/1, kPageBounds,
- "render_large_portrait_rectangles_expected.0.png",
- kDestinationSize);
- }
- TEST(PdfMetafileCgTest, RenderSmallPortraitRectangles) {
- constexpr gfx::Rect kPageBounds(200, 300);
- constexpr gfx::Size kDestinationSize(300, 450);
- TestRenderPage("rectangles.pdf", /*page_number=*/1, kPageBounds,
- "render_small_portrait_rectangles_expected.0.png",
- kDestinationSize);
- }
- TEST(PdfMetafileCgTest, RenderLandscapeRectangles) {
- constexpr gfx::Rect kPageBounds(800, 500);
- constexpr gfx::Size kDestinationSize(400, 600);
- TestRenderPage("landscape_rectangles.pdf", /*page_number=*/1, kPageBounds,
- "render_landscape_rectangles_expected.0.png",
- kDestinationSize);
- }
- TEST(PdfMetafileCgTest, RenderRotatedRectangles) {
- constexpr gfx::Rect kPageBounds(800, 500);
- constexpr gfx::Size kLandscapeDestinationSize(600, 400);
- constexpr gfx::Size kPortraitDestinationSize(400, 600);
- TestRenderPage("rotated_rectangles.pdf", /*page_number=*/1, kPageBounds,
- "render_rotated_rectangles_expected.0.png",
- kLandscapeDestinationSize);
- TestRenderPage("rotated_rectangles.pdf", /*page_number=*/2, kPageBounds,
- "render_rotated_rectangles_expected.1.png",
- kPortraitDestinationSize);
- TestRenderPage("rotated_rectangles.pdf", /*page_number=*/3, kPageBounds,
- "render_rotated_rectangles_expected.2.png",
- kLandscapeDestinationSize);
- TestRenderPage("rotated_rectangles.pdf", /*page_number=*/4, kPageBounds,
- "render_rotated_rectangles_expected.3.png",
- kPortraitDestinationSize);
- TestRenderPage("rotated_rectangles.pdf", /*page_number=*/1, kPageBounds,
- "render_autorotated_rotated_rectangles_expected.0.png",
- kPortraitDestinationSize);
- TestRenderPage("rotated_rectangles.pdf", /*page_number=*/2, kPageBounds,
- "render_autorotated_rotated_rectangles_expected.1.png",
- kLandscapeDestinationSize);
- TestRenderPage("rotated_rectangles.pdf", /*page_number=*/3, kPageBounds,
- "render_autorotated_rotated_rectangles_expected.2.png",
- kPortraitDestinationSize);
- TestRenderPage("rotated_rectangles.pdf", /*page_number=*/4, kPageBounds,
- "render_autorotated_rotated_rectangles_expected.3.png",
- kLandscapeDestinationSize);
- }
- TEST(PdfMetafileCgTest, RenderLargeLandscapeRectangles) {
- constexpr gfx::Rect kPageBounds(800, 500);
- constexpr gfx::Size kDestinationSize(200, 300);
- TestRenderPage("landscape_rectangles.pdf", /*page_number=*/1, kPageBounds,
- "render_large_landscape_rectangles_expected.0.png",
- kDestinationSize);
- }
- TEST(PdfMetafileCgTest, RenderSmallLandscapeRectangles) {
- constexpr gfx::Rect kPageBounds(800, 500);
- constexpr gfx::Size kDestinationSize(600, 900);
- TestRenderPage("landscape_rectangles.pdf", /*page_number=*/1, kPageBounds,
- "render_small_landscape_rectangles_expected.0.png",
- kDestinationSize);
- }
- TEST(PdfMetafileCgTest, RenderScaledLargeLandscapeRectangles) {
- constexpr gfx::Rect kPageBounds(800, 500);
- constexpr gfx::Size kDestinationSize(300, 450);
- TestRenderPageWithTransformParams(
- "landscape_rectangles.pdf", /*page_number=*/1, kPageBounds,
- "render_scaled_large_landscape_rectangles_expected.0.png",
- kDestinationSize,
- /*autorotate=*/true, /*fit_to_page=*/true);
- }
- TEST(PdfMetafileCgTest, RenderScaledSmallLandscapeRectangles) {
- constexpr gfx::Rect kPageBounds(800, 500);
- constexpr gfx::Size kDestinationSize(600, 900);
- TestRenderPageWithTransformParams(
- "landscape_rectangles.pdf", /*page_number=*/1, kPageBounds,
- "render_scaled_small_landscape_rectangles_expected.0.png",
- kDestinationSize,
- /*autorotate=*/true, /*fit_to_page=*/true);
- }
- } // namespace printing
|