blob: c27e466ddd83cdf8339537b69efa8bfd27af38d9 [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 "components/printing/service/pdf_compositor_impl.h"
#include <utility>
#include <vector>
#include "base/logging.h"
#include "base/memory/shared_memory.h"
#include "base/memory/shared_memory_handle.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "printing/common/pdf_metafile_utils.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkDocument.h"
#include "third_party/skia/src/utils/SkMultiPictureDocument.h"
namespace printing {
PdfCompositorImpl::PdfCompositorImpl(
const std::string& creator,
std::unique_ptr<service_manager::ServiceContextRef> service_ref)
: service_ref_(std::move(service_ref)), creator_(creator) {}
PdfCompositorImpl::~PdfCompositorImpl() = default;
void PdfCompositorImpl::CompositePdf(
mojo::ScopedSharedBufferHandle sk_handle,
mojom::PdfCompositor::CompositePdfCallback callback) {
DCHECK(sk_handle.is_valid());
base::SharedMemoryHandle memory_handle;
size_t memory_size = 0;
bool read_only_flag = false;
const MojoResult result = mojo::UnwrapSharedMemoryHandle(
std::move(sk_handle), &memory_handle, &memory_size, &read_only_flag);
DCHECK_EQ(MOJO_RESULT_OK, result);
DCHECK_GT(memory_size, 0u);
std::unique_ptr<base::SharedMemory> shm =
base::MakeUnique<base::SharedMemory>(memory_handle, true);
if (!shm->Map(memory_size)) {
DLOG(ERROR) << "CompositePdf: Shared memory map failed.";
std::move(callback).Run(mojo::ScopedSharedBufferHandle());
return;
}
SkMemoryStream stream(shm->memory(), memory_size);
int page_count = SkMultiPictureDocumentReadPageCount(&stream);
if (!page_count) {
DLOG(ERROR) << "CompositePdf: No page is read.";
std::move(callback).Run(mojo::ScopedSharedBufferHandle());
return;
}
std::vector<SkDocumentPage> pages(page_count);
if (!SkMultiPictureDocumentRead(&stream, pages.data(), page_count)) {
DLOG(ERROR) << "CompositePdf: Page reading failed.";
std::move(callback).Run(mojo::ScopedSharedBufferHandle());
return;
}
SkDynamicMemoryWStream wstream;
sk_sp<SkDocument> doc = MakePdfDocument(creator_, &wstream);
for (const auto& page : pages) {
SkCanvas* canvas = doc->beginPage(page.fSize.width(), page.fSize.height());
canvas->drawPicture(page.fPicture);
doc->endPage();
}
doc->close();
mojo::ScopedSharedBufferHandle buffer =
mojo::SharedBufferHandle::Create(wstream.bytesWritten());
DCHECK(buffer.is_valid());
mojo::ScopedSharedBufferMapping mapping = buffer->Map(wstream.bytesWritten());
DCHECK(mapping);
wstream.copyToAndReset(mapping.get());
std::move(callback).Run(std::move(buffer));
}
} // namespace printing