blob: 693ebb7b16593910b1032d3a06c26cc7a1fc1b9d [file] [log] [blame]
// Copyright 2017 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 "chrome/services/printing/pdf_to_pwg_raster_converter.h"
#include <limits>
#include <string>
#include <utility>
#include "chrome/utility/cloud_print/bitmap_image.h"
#include "chrome/utility/cloud_print/pwg_encoder.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "pdf/pdf.h"
#include "printing/pdf_render_settings.h"
namespace printing {
namespace {
bool RenderPdfPagesToPwgRaster(base::File pdf_file,
const PdfRenderSettings& settings,
const PwgRasterSettings& bitmap_settings,
base::File bitmap_file) {
base::File::Info info;
if (!pdf_file.GetInfo(&info) || info.size <= 0 ||
info.size > std::numeric_limits<int>::max())
return false;
int data_size = static_cast<int>(info.size);
std::string data(data_size, 0);
if (pdf_file.Read(0, &data[0], data_size) != data_size)
return false;
int total_page_count = 0;
if (!chrome_pdf::GetPDFDocInfo(data.data(), data_size, &total_page_count,
nullptr)) {
return false;
}
std::string pwg_header = cloud_print::PwgEncoder::GetDocumentHeader();
int bytes_written =
bitmap_file.WriteAtCurrentPos(pwg_header.data(), pwg_header.size());
if (bytes_written != static_cast<int>(pwg_header.size()))
return false;
cloud_print::BitmapImage image(settings.area.size(),
cloud_print::BitmapImage::BGRA);
for (int i = 0; i < total_page_count; ++i) {
int page_number = i;
if (bitmap_settings.reverse_page_order)
page_number = total_page_count - 1 - page_number;
if (!chrome_pdf::RenderPDFPageToBitmap(
data.data(), data_size, page_number, image.pixel_data(),
image.size().width(), image.size().height(), settings.dpi,
settings.autorotate)) {
return false;
}
cloud_print::PwgHeaderInfo header_info;
header_info.dpi = gfx::Size(settings.dpi, settings.dpi);
header_info.total_pages = total_page_count;
header_info.color_space = bitmap_settings.use_color
? cloud_print::PwgHeaderInfo::SRGB
: cloud_print::PwgHeaderInfo::SGRAY;
// Transform odd pages.
if (page_number % 2) {
switch (bitmap_settings.odd_page_transform) {
case TRANSFORM_NORMAL:
break;
case TRANSFORM_ROTATE_180:
header_info.flipx = true;
header_info.flipy = true;
break;
case TRANSFORM_FLIP_HORIZONTAL:
header_info.flipx = true;
break;
case TRANSFORM_FLIP_VERTICAL:
header_info.flipy = true;
break;
}
}
if (bitmap_settings.rotate_all_pages) {
header_info.flipx = !header_info.flipx;
header_info.flipy = !header_info.flipy;
}
std::string pwg_page =
cloud_print::PwgEncoder::EncodePage(image, header_info);
if (pwg_page.empty())
return false;
bytes_written =
bitmap_file.WriteAtCurrentPos(pwg_page.data(), pwg_page.size());
if (bytes_written != static_cast<int>(pwg_page.size()))
return false;
}
return true;
}
} // namespace
PdfToPwgRasterConverter::PdfToPwgRasterConverter(
std::unique_ptr<service_manager::ServiceContextRef> service_ref)
: service_ref_(std::move(service_ref)) {}
PdfToPwgRasterConverter::~PdfToPwgRasterConverter() {}
void PdfToPwgRasterConverter::Convert(
mojo::ScopedHandle pdf_file_in,
const PdfRenderSettings& pdf_settings,
const PwgRasterSettings& pwg_raster_settings,
mojo::ScopedHandle pwg_raster_file_out,
ConvertCallback callback) {
base::PlatformFile pdf_file;
if (mojo::UnwrapPlatformFile(std::move(pdf_file_in), &pdf_file) !=
MOJO_RESULT_OK) {
LOG(ERROR) << "Invalid PDF file passed to PdfToPwgRasterConverter.";
std::move(callback).Run(false);
return;
}
base::PlatformFile pwg_raster_file;
if (mojo::UnwrapPlatformFile(std::move(pwg_raster_file_out),
&pwg_raster_file) != MOJO_RESULT_OK) {
LOG(ERROR) << "Invalid PWGRaster file passed to PdfToPwgRasterConverter.";
std::move(callback).Run(false);
return;
}
bool result = RenderPdfPagesToPwgRaster(base::File(pdf_file), pdf_settings,
pwg_raster_settings,
base::File(pwg_raster_file));
std::move(callback).Run(result);
}
} // namespace printing