blob: 0de1685f8b1eaea452302f63c79364c1eaf5ab87 [file]
// Copyright 2021 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/test/test_helpers.h"
#include <string_view>
#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/test/task_environment.h"
#include "base/test/test_switches.h"
#include "build/build_config.h"
#include "cc/test/pixel_comparator.h"
#include "cc/test/pixel_test_utils.h"
#include "pdf/pdfium/pdfium_engine_exports.h"
#include "printing/units.h"
#include "testing/gtest/include/gtest/gtest.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/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkColorType.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 "third_party/skia/include/core/SkSurface.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/skia_conversions.h"
#if BUILDFLAG(IS_WIN)
#include "base/strings/utf_string_conversions.h"
#endif
namespace chrome_pdf {
namespace {
base::test::TaskEnvironment* g_task_environment = nullptr;
testing::AssertionResult MatchesPngFileImpl(
const SkImage& actual_image,
const base::FilePath& expected_png_file,
const cc::PixelComparator& comparitor) {
SkBitmap actual_bitmap;
if (!actual_image.asLegacyBitmap(&actual_bitmap)) {
return testing::AssertionFailure() << "Reference: " << expected_png_file;
}
const base::FilePath expected_path = GetTestDataFilePath(expected_png_file);
if (cc::MatchesPNGFile(actual_bitmap, expected_path, comparitor)) {
return testing::AssertionSuccess();
}
auto* cmd = base::CommandLine::ForCurrentProcess();
if (!cmd->HasSwitch(switches::kRebaselinePixelTests)) {
return testing::AssertionFailure() << "Reference: " << expected_png_file;
}
if (cc::WritePNGFile(actual_bitmap, expected_path, true)) {
return testing::AssertionSuccess();
}
return testing::AssertionFailure() << "Rebase: " << expected_png_file;
}
SkBitmap RenderPdfToSkBitmap(base::span<const uint8_t> pdf_data,
int page_index,
const gfx::Size& size_in_points) {
const gfx::Rect page_rect(size_in_points);
SkBitmap page_bitmap;
page_bitmap.allocPixels(
SkImageInfo::Make(gfx::SizeToSkISize(page_rect.size()),
kBGRA_8888_SkColorType, kPremul_SkAlphaType));
PDFiumEngineExports::RenderingSettings settings(
gfx::Size(printing::kPointsPerInch, printing::kPointsPerInch), page_rect,
/*fit_to_bounds=*/false,
/*stretch_to_bounds=*/false,
/*keep_aspect_ratio=*/true,
/*center_in_bounds=*/false,
/*autorotate=*/false, /*use_color=*/true, /*render_for_printing=*/false);
PDFiumEngineExports exports;
if (!exports.RenderPDFPageToBitmap(pdf_data, page_index, settings,
page_bitmap.getPixels())) {
ADD_FAILURE();
}
return page_bitmap;
}
} // namespace
base::FilePath GetTestDataFilePath(const base::FilePath& path) {
return base::PathService::CheckedGet(base::DIR_SRC_TEST_DATA_ROOT)
.Append(FILE_PATH_LITERAL("pdf"))
.Append(FILE_PATH_LITERAL("test"))
.Append(FILE_PATH_LITERAL("data"))
.Append(path);
}
base::FilePath::StringType GetTestDataPathWithPlatformSuffix(
std::string_view filename) {
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
#if BUILDFLAG(IS_WIN)
base::FilePath path(base::UTF8ToWide(filename));
static constexpr std::wstring_view kSuffix = L"_win";
#else
base::FilePath path(filename);
static constexpr std::string_view kSuffix = "_mac";
#endif // BUILDFLAG(IS_WIN)
return path.InsertBeforeExtension(kSuffix).value();
#else
return base::FilePath(filename).value();
#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
}
base::FilePath GetReferenceFilePath(
base::FilePath::StringViewType sub_directory,
std::string_view test_filename,
bool use_platform_suffix) {
if (use_platform_suffix) {
return base::FilePath(sub_directory)
.Append(GetTestDataPathWithPlatformSuffix(test_filename));
}
return base::FilePath(sub_directory).AppendASCII(test_filename);
}
testing::AssertionResult MatchesPngFile(
const SkImage& actual_image,
const base::FilePath& expected_png_file) {
return MatchesPngFileImpl(actual_image, expected_png_file,
cc::ExactPixelComparator());
}
testing::AssertionResult FuzzyMatchesPngFile(
const SkImage& actual_image,
const base::FilePath& expected_png_file) {
// Effectively a "FuzzyPixelOffByTwoComparator".
cc::FuzzyPixelComparator comparator;
comparator.SetErrorPixelsPercentageLimit(100.0f);
comparator.SetAbsErrorLimit(2);
return MatchesPngFileImpl(actual_image, expected_png_file, comparator);
}
bool IsBitmapBlank(const SkBitmap& bitmap) {
for (int i = 0; i < bitmap.width(); ++i) {
for (int j = 0; j < bitmap.height(); ++j) {
if (bitmap.getColor(i, j) != SK_ColorWHITE) {
return false;
}
}
}
return true;
}
bool IsImageBlank(const SkImage& image) {
SkBitmap bitmap;
if (!image.asLegacyBitmap(&bitmap)) {
ADD_FAILURE();
return false;
}
return IsBitmapBlank(bitmap);
}
void CheckPdfRendering(base::span<const uint8_t> pdf_data,
int page_index,
const gfx::Size& size_in_points,
const base::FilePath& expected_png_file) {
SkBitmap page_bitmap =
RenderPdfToSkBitmap(pdf_data, page_index, size_in_points);
EXPECT_TRUE(MatchesPngFile(*page_bitmap.asImage(), expected_png_file));
}
void CheckFuzzyPdfRendering(base::span<const uint8_t> pdf_data,
int page_index,
const gfx::Size& size_in_points,
const base::FilePath& expected_png_file) {
SkBitmap page_bitmap =
RenderPdfToSkBitmap(pdf_data, page_index, size_in_points);
EXPECT_TRUE(FuzzyMatchesPngFile(*page_bitmap.asImage(), expected_png_file));
}
sk_sp<SkSurface> CreateSkiaSurfaceForTesting(const gfx::Size& size,
SkColor color) {
auto surface = SkSurfaces::Raster(
SkImageInfo::MakeN32Premul(size.width(), size.height()));
surface->getCanvas()->clear(color);
return surface;
}
sk_sp<SkImage> CreateSkiaImageForTesting(const gfx::Size& size, SkColor color) {
return CreateSkiaSurfaceForTesting(size, color)->makeImageSnapshot();
}
static v8::Isolate* g_isolate = nullptr;
v8::Isolate* GetBlinkIsolate() {
return g_isolate;
}
void SetBlinkIsolate(v8::Isolate* isolate) {
g_isolate = isolate;
}
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 SetPdfTestTaskEnvironment(base::test::TaskEnvironment* task_environment) {
g_task_environment = task_environment;
}
base::test::TaskEnvironment& GetPdfTestTaskEnvironment() {
CHECK(g_task_environment);
return *g_task_environment;
}
} // namespace chrome_pdf