Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(348)

Unified Diff: printing/pdf_metafile_skia.cc

Issue 694213002: Remove calls to deprecated SkPDFDevice and SkPDFDocuemnt. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comments from Vitaly Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: printing/pdf_metafile_skia.cc
diff --git a/printing/pdf_metafile_skia.cc b/printing/pdf_metafile_skia.cc
index 36a42d9d135cc875e803c8f01a3c2b5b048d5e8c..30b39a244ef8ec41ee2092a42e0c7119f20092e8 100644
--- a/printing/pdf_metafile_skia.cc
+++ b/printing/pdf_metafile_skia.cc
@@ -9,15 +9,17 @@
#include "base/metrics/histogram.h"
#include "base/numerics/safe_conversions.h"
#include "base/posix/eintr_wrapper.h"
+#include "skia/ext/platform_canvas.h"
#include "skia/ext/refptr.h"
-#include "skia/ext/vector_platform_device_skia.h"
-#include "third_party/skia/include/core/SkData.h"
+#include "skia/ext/vector_canvas.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkDocument.h"
+#include "third_party/skia/include/core/SkPictureRecorder.h"
+#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkScalar.h"
+#include "third_party/skia/include/core/SkSize.h"
#include "third_party/skia/include/core/SkStream.h"
-#include "third_party/skia/include/core/SkTypeface.h"
-#include "third_party/skia/include/pdf/SkPDFDevice.h"
-#include "third_party/skia/include/pdf/SkPDFDocument.h"
#include "ui/gfx/point.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
@@ -30,115 +32,208 @@
#include "base/file_descriptor_posix.h"
#endif
+class SkBaseDevice;
+
+namespace {
+// This struct represents all the data we need to draw and redraw this
+// page into a SkDocument.
+struct Page {
+ Page(const SkSize& page_size, const SkRect& content_area);
+ SkSize page_size_;
+ SkRect content_area_;
+ skia::RefPtr<SkPicture> content_;
+};
+
+Page::Page(const SkSize& page_size, const SkRect& content_area)
+ : page_size_(page_size), content_area_(content_area), content_(/*NULL*/) {}
+
+SkSize ToSkSize(const gfx::Size& size) {
+ return SkSize::Make(SkIntToScalar(size.width()),
+ SkIntToScalar(size.height()));
+}
+
+SkRect ToSkRect(const gfx::Rect& rect) {
+ return SkRect::MakeLTRB(SkIntToScalar(rect.x()),
+ SkIntToScalar(rect.y()),
+ SkIntToScalar(rect.right()),
+ SkIntToScalar(rect.bottom()));
+}
+
+gfx::Rect ToGfxRect(const SkRect& rect) {
+ return gfx::Rect(SkScalarTruncToInt(rect.x()),
+ SkScalarTruncToInt(rect.y()),
+ SkScalarTruncToInt(rect.width()),
+ SkScalarTruncToInt(rect.height()));
+}
+
+bool WriteAssetToBuffer(SkStreamAsset* asset, void* buffer, size_t size) {
+ DCHECK(asset);
+ DCHECK(asset->getPosition() == 0);
+ size_t length = asset->getLength();
+ if (length > size)
+ return false;
+ bool success = (length == asset->read(buffer, length));
+ (void)asset->rewind();
+ return success;
+}
+
+} // namespace
+
namespace printing {
struct PdfMetafileSkiaData {
- skia::RefPtr<SkPDFDevice> current_page_;
- SkPDFDocument pdf_doc_;
- SkDynamicMemoryWStream pdf_stream_;
+ scoped_ptr<SkPictureRecorder> recorder_; // Current recording
+
+ std::vector<Page> pages_;
+ skia::RefPtr<SkStreamAsset> pdf_data_;
Vitaly Buka (NO REVIEWS) 2014/11/04 19:23:55 I guess order shouldbe be: 1. Methods 2. Members
hal.canary 2014/11/16 21:29:28 Acknowledged.
+
+ // True when the current page is outstanding (and still writable).
+ bool PageOutstanding() const;
+
+ // True if InitFromData() or FinishDocument has been called.
+ bool HasData() const;
+
+ size_t PageCount() const;
+
+ // Return a const pointer to the page, or NULL on error.
+ // The page must be finished (via FinishPage()).
+ // The pointer is only valid while pages_ is unmodified.
+ const Page* GetPage(size_t page_number) const;
+
#if defined(OS_MACOSX)
PdfMetafileCg pdf_cg_;
#endif
};
+bool PdfMetafileSkiaData::PageOutstanding() const {
+ return recorder_.get() != NULL;
+}
+
+bool PdfMetafileSkiaData::HasData() const { return (pdf_data_.get() != NULL); }
+
+size_t PdfMetafileSkiaData::PageCount() const { return pages_.size(); }
+
+const Page* PdfMetafileSkiaData::GetPage(size_t page_number) const {
+ if (page_number >= PageCount())
+ return NULL;
+
+ // Last page and page not finished recording
+ if ((page_number == PageCount() - 1) && this->PageOutstanding())
+ return NULL;
+ DCHECK(pages_[page_number].content_.get());
+ return &(pages_[page_number]);
+}
+
PdfMetafileSkia::~PdfMetafileSkia() {}
bool PdfMetafileSkia::Init() {
return true;
}
+
+// TODO(halcanary): Create a Metafile class that only stores data.
+// Metafile::InitFromData is orthogonal to what the rest of
+// PdfMetafileSkia does.
bool PdfMetafileSkia::InitFromData(const void* src_buffer,
uint32 src_buffer_size) {
- return data_->pdf_stream_.write(src_buffer, src_buffer_size);
+ if (data_->HasData())
+ data_->pdf_data_.clear(); // free up RAM first.
+ SkDynamicMemoryWStream dynamic_memory;
+ if (!dynamic_memory.write(src_buffer, src_buffer_size))
+ return false;
+ data_->pdf_data_ = skia::AdoptRef(dynamic_memory.detachAsStream());
+ return true;
+}
+
+skia::RefPtr<skia::VectorCanvas> PdfMetafileSkia::GetVectorCanvasForNewPage(
+ const gfx::Size& page_size, const gfx::Rect& content_area,
+ const float& scale_factor) {
+ return this->StartPage(page_size, content_area, scale_factor)
+ ? skia::SharePtr(data_->recorder_->getRecordingCanvas())
+ : skia::RefPtr<skia::VectorCanvas>(/*NULL*/);
}
SkBaseDevice* PdfMetafileSkia::StartPageForVectorCanvas(
const gfx::Size& page_size, const gfx::Rect& content_area,
const float& scale_factor) {
- DCHECK(!page_outstanding_);
- page_outstanding_ = true;
-
- // Adjust for the margins and apply the scale factor.
- SkMatrix transform;
- transform.setTranslate(SkIntToScalar(content_area.x()),
- SkIntToScalar(content_area.y()));
- transform.preScale(SkFloatToScalar(scale_factor),
- SkFloatToScalar(scale_factor));
-
- SkISize pdf_page_size = SkISize::Make(page_size.width(), page_size.height());
- SkISize pdf_content_size =
- SkISize::Make(content_area.width(), content_area.height());
- skia::RefPtr<SkPDFDevice> pdf_device =
- skia::AdoptRef(new skia::VectorPlatformDeviceSkia(
- pdf_page_size, pdf_content_size, transform));
- data_->current_page_ = pdf_device;
- return pdf_device.get();
+ NOTREACHED(); // Skia has deprecated the use of SkPDFDevice.
+ return NULL;
}
+
bool PdfMetafileSkia::StartPage(const gfx::Size& page_size,
const gfx::Rect& content_area,
const float& scale_factor) {
- NOTREACHED();
- return false;
+ if (data_->PageOutstanding())
+ this->FinishPage();
+
+ data_->recorder_.reset(SkNEW(SkPictureRecorder));
+ SkSize sk_page_size = ToSkSize(page_size);
+ data_->pages_.push_back(Page(sk_page_size, ToSkRect(content_area)));
+
+ SkCanvas* recordingCanvas = data_->recorder_->beginRecording(
+ sk_page_size.width(), sk_page_size.height(), NULL, 0);
+ // recordingCanvas is owned by the data_->recorder_. No ref() necessary.
+ if (!recordingCanvas)
+ return false;
+ recordingCanvas->scale(scale_factor, scale_factor);
+ return true;
}
bool PdfMetafileSkia::FinishPage() {
- DCHECK(data_->current_page_.get());
-
- data_->pdf_doc_.appendPage(data_->current_page_.get());
- page_outstanding_ = false;
+ if (!data_->PageOutstanding())
+ return false;
+ DCHECK(!(data_->pages_.back().content_.get()));
+ data_->pages_.back().content_ =
+ skia::AdoptRef(data_->recorder_->endRecording());
+ data_->recorder_.reset();
return true;
}
bool PdfMetafileSkia::FinishDocument() {
- // Don't do anything if we've already set the data in InitFromData.
- if (data_->pdf_stream_.getOffset())
- return true;
-
- if (page_outstanding_)
- FinishPage();
-
- data_->current_page_.clear();
-
- int font_counts[SkAdvancedTypefaceMetrics::kOther_Font + 2];
- data_->pdf_doc_.getCountOfFontTypes(font_counts);
- for (int type = 0;
- type <= SkAdvancedTypefaceMetrics::kOther_Font + 1;
- type++) {
- for (int count = 0; count < font_counts[type]; count++) {
- UMA_HISTOGRAM_ENUMERATION(
- "PrintPreview.FontType", type,
- SkAdvancedTypefaceMetrics::kOther_Font + 2);
- }
+ // If we've already set the data in InitFromData, overwrite it.
+ if (data_->HasData())
+ data_->pdf_data_.clear(); // Free up RAM first.
+
+ if (data_->PageOutstanding())
+ this->FinishPage();
+
+ SkDynamicMemoryWStream pdf_stream;
+ skia::RefPtr<SkDocument> pdf_doc =
+ skia::AdoptRef(SkDocument::CreatePDF(&pdf_stream));
+ for (const auto& page : data_->pages_) {
+ SkCanvas* canvas =
+ pdf_doc->beginPage(page.page_size_.width(), page.page_size_.height(),
+ &(page.content_area_));
Vitaly Buka (NO REVIEWS) 2014/11/04 19:23:55 just &page.content_area_
hal.canary 2014/11/16 21:29:28 Done.
+ canvas->drawPicture(page.content_.get());
+ pdf_doc->endPage();
}
+ if (!pdf_doc->close())
+ return false;
- return data_->pdf_doc_.emitPDF(&data_->pdf_stream_);
+ data_->pdf_data_ = skia::AdoptRef(pdf_stream.detachAsStream());
+ return true;
}
uint32 PdfMetafileSkia::GetDataSize() const {
- return base::checked_cast<uint32>(data_->pdf_stream_.getOffset());
+ if (!data_->pdf_data_)
+ return 0;
+ return base::checked_cast<uint32>(data_->pdf_data_->getLength());
}
bool PdfMetafileSkia::GetData(void* dst_buffer,
uint32 dst_buffer_size) const {
- if (dst_buffer_size < GetDataSize())
+ if (!data_->pdf_data_)
return false;
-
- SkAutoDataUnref data(data_->pdf_stream_.copyToData());
- memcpy(dst_buffer, data->bytes(), dst_buffer_size);
- return true;
+ return WriteAssetToBuffer(data_->pdf_data_.get(), dst_buffer,
+ base::checked_cast<size_t>(dst_buffer_size));
}
gfx::Rect PdfMetafileSkia::GetPageBounds(unsigned int page_number) const {
- // TODO(vandebo) add a method to get the page size for a given page to
- // SkPDFDocument.
- NOTIMPLEMENTED();
- return gfx::Rect();
+ return ToGfxRect(data_->pages_[page_number].content_area_);
}
unsigned int PdfMetafileSkia::GetPageCount() const {
- // TODO(vandebo) add a method to get the number of pages to SkPDFDocument.
- NOTIMPLEMENTED();
- return 0;
+ return base::checked_cast<int>(data_->PageCount());
}
gfx::NativeDrawingContext PdfMetafileSkia::context() const {
@@ -170,28 +265,53 @@ bool PdfMetafileSkia::RenderPage(unsigned int page_number,
CGContextRef context,
const CGRect rect,
const MacRenderPageParams& params) const {
- DCHECK_GT(data_->pdf_stream_.getOffset(), 0U);
+ DCHECK_GT(GetDataSize(), 0U);
if (data_->pdf_cg_.GetDataSize() == 0) {
- SkAutoDataUnref data(data_->pdf_stream_.copyToData());
- data_->pdf_cg_.InitFromData(data->bytes(), data->size());
+ if (GetDataSize() == 0)
+ return false;
+ size_t length = data_->pdf_data_->getLength();
+ scoped_ptr<uint8_t[]> buffer(new uint8_t[length]);
Vitaly Buka (NO REVIEWS) 2014/11/04 19:23:55 just std::vector<uint8_t> buffer(length)?
hal.canary 2014/11/16 21:29:28 Done.
+ (void)WriteAssetToBuffer(data_->pdf_data_.get(), buffer.get(), length);
+ data_->pdf_cg_.InitFromData(buffer.get(),
+ base::checked_cast<uint32>(length));
}
return data_->pdf_cg_.RenderPage(page_number, context, rect, params);
}
#endif
+bool PdfMetafileSkia::SaveTo(base::File* file) const {
+ DCHECK(file);
+ if (GetDataSize() == 0U)
+ return false;
+ DCHECK(data_->pdf_data_.get());
+ SkStreamAsset* asset = data_->pdf_data_.get();
+ DCHECK_EQ(asset->getPosition(), 0U);
+
+ char buffer[4096];
Vitaly Buka (NO REVIEWS) 2014/11/04 19:23:55 maybe std::vector for 1Mb?
hal.canary 2014/11/16 21:29:28 Done.
+ do {
+ size_t read_size = asset->read(buffer, sizeof(buffer));
Vitaly Buka (NO REVIEWS) 2014/11/04 19:23:55 read_size == 0 ?
hal.canary 2014/11/16 21:29:28 Done.
+ DCHECK_GE(sizeof(buffer), read_size);
+ if (!file->WriteAtCurrentPos(buffer, base::checked_cast<int>(read_size))) {
+ (void)asset->rewind();
+ return false;
+ }
+ } while (!asset->isAtEnd());
+
+ (void)asset->rewind();
+ return true;
+}
+
#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
+
bool PdfMetafileSkia::SaveToFD(const base::FileDescriptor& fd) const {
- DCHECK_GT(data_->pdf_stream_.getOffset(), 0U);
+ DCHECK_GT(GetDataSize(), 0U);
if (fd.fd < 0) {
DLOG(ERROR) << "Invalid file descriptor!";
return false;
}
base::File file(fd.fd);
- SkAutoDataUnref data(data_->pdf_stream_.copyToData());
- bool result =
- file.WriteAtCurrentPos(reinterpret_cast<const char*>(data->data()),
- GetDataSize()) == static_cast<int>(GetDataSize());
+ bool result = this->SaveTo(&file);
DLOG_IF(ERROR, !result) << "Failed to save file with fd " << fd.fd;
if (!fd.auto_close)
@@ -200,30 +320,30 @@ bool PdfMetafileSkia::SaveToFD(const base::FileDescriptor& fd) const {
}
#endif
-PdfMetafileSkia::PdfMetafileSkia()
- : data_(new PdfMetafileSkiaData),
- page_outstanding_(false) {
+PdfMetafileSkia::PdfMetafileSkia() : data_(new PdfMetafileSkiaData) {
+ DCHECK(!data_->PageOutstanding());
}
scoped_ptr<PdfMetafileSkia> PdfMetafileSkia::GetMetafileForCurrentPage() {
- scoped_ptr<PdfMetafileSkia> metafile;
- SkPDFDocument pdf_doc(SkPDFDocument::kDraftMode_Flags);
- if (!pdf_doc.appendPage(data_->current_page_.get()))
+ // If we only ever need the metafile for the last page, should we
+ // only keep a handle on one SkPicture?
+ DCHECK_NE(data_->PageCount(), 0U);
+ DCHECK(!data_->PageOutstanding());
+ scoped_ptr<PdfMetafileSkia> metafile(new PdfMetafileSkia);
+
+ if (data_->PageCount() == 0)
return metafile.Pass();
- SkDynamicMemoryWStream pdf_stream;
- if (!pdf_doc.emitPDF(&pdf_stream))
+ const Page* page = data_->GetPage(data_->PageCount() - 1);
+ if (!page)
return metafile.Pass();
- SkAutoDataUnref data_copy(pdf_stream.copyToData());
- if (data_copy->size() == 0)
- return scoped_ptr<PdfMetafileSkia>();
+ metafile->data_->pages_.push_back(*page); // Copy page data;
+ // Should increment refcnt on page->content_.
- metafile.reset(new PdfMetafileSkia);
- if (!metafile->InitFromData(data_copy->bytes(),
- base::checked_cast<uint32>(data_copy->size()))) {
+ if (!metafile->FinishDocument()) // Generate PDF.
metafile.reset();
- }
+
return metafile.Pass();
}
« printing/pdf_metafile_skia.h ('K') | « printing/pdf_metafile_skia.h ('k') | skia/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698