| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "printing/pdf_metafile_skia.h" | 5 #include "printing/pdf_metafile_skia.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <utility> | 9 #include <utility> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/files/file.h" | 12 #include "base/files/file.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/time/time.h" | 14 #include "base/time/time.h" |
| 15 #include "printing/print_settings.h" | 15 #include "printing/print_settings.h" |
| 16 #include "skia/ext/skia_utils_base.h" |
| 16 #include "third_party/skia/include/core/SkDocument.h" | 17 #include "third_party/skia/include/core/SkDocument.h" |
| 18 #include "third_party/skia/include/core/SkImageDeserializer.h" |
| 17 #include "third_party/skia/include/core/SkPictureRecorder.h" | 19 #include "third_party/skia/include/core/SkPictureRecorder.h" |
| 18 #include "third_party/skia/include/core/SkStream.h" | 20 #include "third_party/skia/include/core/SkStream.h" |
| 21 //#include "third_party/skia/include/core/SkWriteBuffer.h" |
| 19 // Note that headers in third_party/skia/src are fragile. This is | 22 // Note that headers in third_party/skia/src are fragile. This is |
| 20 // an experimental, fragile, and diagnostic-only document type. | 23 // an experimental, fragile, and diagnostic-only document type. |
| 21 #include "third_party/skia/src/utils/SkMultiPictureDocument.h" | 24 #include "third_party/skia/src/utils/SkMultiPictureDocument.h" |
| 22 #include "ui/gfx/geometry/safe_integer_conversions.h" | 25 #include "ui/gfx/geometry/safe_integer_conversions.h" |
| 23 #include "ui/gfx/skia_util.h" | 26 #include "ui/gfx/skia_util.h" |
| 24 | 27 |
| 25 #if defined(OS_MACOSX) | 28 #if defined(OS_MACOSX) |
| 26 #include "printing/pdf_metafile_cg_mac.h" | 29 #include "printing/pdf_metafile_cg_mac.h" |
| 27 #endif | 30 #endif |
| 28 | 31 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 : SkString(agent.c_str(), agent.size()); | 73 : SkString(agent.c_str(), agent.size()); |
| 71 return SkDocument::MakePDF(wStream, SK_ScalarDefaultRasterDPI, metadata, | 74 return SkDocument::MakePDF(wStream, SK_ScalarDefaultRasterDPI, metadata, |
| 72 nullptr, false); | 75 nullptr, false); |
| 73 } | 76 } |
| 74 | 77 |
| 75 } // namespace | 78 } // namespace |
| 76 | 79 |
| 77 namespace printing { | 80 namespace printing { |
| 78 | 81 |
| 79 struct Page { | 82 struct Page { |
| 80 Page(SkSize s, sk_sp<SkPicture> c) : size_(s), content_(std::move(c)) {} | 83 Page(SkSize s, sk_sp<SkDrawable> c) : size_(s), content_(std::move(c)) {} |
| 81 Page(Page&& that) : size_(that.size_), content_(std::move(that.content_)) {} | 84 Page(Page&& that) : size_(that.size_), content_(std::move(that.content_)) {} |
| 82 Page(const Page&) = default; | 85 Page(const Page&) = default; |
| 83 Page& operator=(const Page&) = default; | 86 Page& operator=(const Page&) = default; |
| 84 Page& operator=(Page&& that) { | 87 Page& operator=(Page&& that) { |
| 85 size_ = that.size_; | 88 size_ = that.size_; |
| 86 content_ = std::move(that.content_); | 89 content_ = std::move(that.content_); |
| 87 return *this; | 90 return *this; |
| 88 } | 91 } |
| 89 SkSize size_; | 92 SkSize size_; |
| 90 sk_sp<SkPicture> content_; | 93 sk_sp<SkDrawable> content_; |
| 91 }; | 94 }; |
| 92 | 95 |
| 93 struct PdfMetafileSkiaData { | 96 struct PdfMetafileSkiaData { |
| 94 SkPictureRecorder recorder_; // Current recording | 97 SkPictureRecorder recorder_; // Current recording |
| 95 | 98 |
| 96 std::vector<Page> pages_; | 99 std::vector<Page> pages_; |
| 97 std::unique_ptr<SkStreamAsset> pdf_data_; | 100 std::unique_ptr<SkStreamAsset> pdf_data_; |
| 98 | 101 |
| 99 // The scale factor is used because Blink occasionally calls | 102 // The scale factor is used because Blink occasionally calls |
| 100 // SkCanvas::getTotalMatrix() even though the total matrix is not as | 103 // SkCanvas::getTotalMatrix() even though the total matrix is not as |
| (...skipping 16 matching lines...) Expand all Loading... |
| 117 // TODO(halcanary): Create a Metafile class that only stores data. | 120 // TODO(halcanary): Create a Metafile class that only stores data. |
| 118 // Metafile::InitFromData is orthogonal to what the rest of | 121 // Metafile::InitFromData is orthogonal to what the rest of |
| 119 // PdfMetafileSkia does. | 122 // PdfMetafileSkia does. |
| 120 bool PdfMetafileSkia::InitFromData(const void* src_buffer, | 123 bool PdfMetafileSkia::InitFromData(const void* src_buffer, |
| 121 size_t src_buffer_size) { | 124 size_t src_buffer_size) { |
| 122 data_->pdf_data_ = base::MakeUnique<SkMemoryStream>( | 125 data_->pdf_data_ = base::MakeUnique<SkMemoryStream>( |
| 123 src_buffer, src_buffer_size, true /* copy_data? */); | 126 src_buffer, src_buffer_size, true /* copy_data? */); |
| 124 return true; | 127 return true; |
| 125 } | 128 } |
| 126 | 129 |
| 130 bool PdfMetafileSkia::InitFromPageDataBuffer(const char* src_buffer, |
| 131 size_t src_buffer_size) { |
| 132 size_t pos = 0; |
| 133 while (pos < src_buffer_size) { |
| 134 size_t size = *((size_t*)(src_buffer + pos)); |
| 135 pos += sizeof(size_t); |
| 136 if (pos + size + 2 * sizeof(SkScalar) > src_buffer_size) { |
| 137 return false; |
| 138 } |
| 139 SkScalar width = *((SkScalar*)(src_buffer + pos)); |
| 140 pos += sizeof(SkScalar); |
| 141 SkScalar height = *((SkScalar*)(src_buffer + pos)); |
| 142 pos += sizeof(SkScalar); |
| 143 |
| 144 std::unique_ptr<SkDrawable> d = skia::ReadDrawable(src_buffer + pos, size); |
| 145 |
| 146 data_->pages_.emplace_back(SkSize::Make(width, height), |
| 147 sk_sp<SkDrawable>(d.release())); |
| 148 pos += size; |
| 149 } |
| 150 return true; |
| 151 } |
| 152 |
| 127 void PdfMetafileSkia::StartPage(const gfx::Size& page_size, | 153 void PdfMetafileSkia::StartPage(const gfx::Size& page_size, |
| 128 const gfx::Rect& content_area, | 154 const gfx::Rect& content_area, |
| 129 const float& scale_factor) { | 155 const float& scale_factor) { |
| 130 DCHECK_GT(page_size.width(), 0); | 156 DCHECK_GT(page_size.width(), 0); |
| 131 DCHECK_GT(page_size.height(), 0); | 157 DCHECK_GT(page_size.height(), 0); |
| 132 DCHECK_GT(scale_factor, 0.0f); | 158 DCHECK_GT(scale_factor, 0.0f); |
| 133 if (data_->recorder_.getRecordingCanvas()) | 159 if (data_->recorder_.getRecordingCanvas()) |
| 134 FinishPage(); | 160 FinishPage(); |
| 135 DCHECK(!data_->recorder_.getRecordingCanvas()); | 161 DCHECK(!data_->recorder_.getRecordingCanvas()); |
| 136 | 162 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 159 const gfx::Rect& content_area, | 185 const gfx::Rect& content_area, |
| 160 const float& scale_factor) { | 186 const float& scale_factor) { |
| 161 StartPage(page_size, content_area, scale_factor); | 187 StartPage(page_size, content_area, scale_factor); |
| 162 return data_->recorder_.getRecordingCanvas(); | 188 return data_->recorder_.getRecordingCanvas(); |
| 163 } | 189 } |
| 164 | 190 |
| 165 bool PdfMetafileSkia::FinishPage() { | 191 bool PdfMetafileSkia::FinishPage() { |
| 166 if (!data_->recorder_.getRecordingCanvas()) | 192 if (!data_->recorder_.getRecordingCanvas()) |
| 167 return false; | 193 return false; |
| 168 | 194 |
| 169 sk_sp<SkPicture> pic = data_->recorder_.finishRecordingAsPicture(); | 195 sk_sp<SkDrawable> pic = data_->recorder_.finishRecordingAsDrawable(); |
| 170 if (data_->scale_factor_ != 1.0f) { | 196 if (data_->scale_factor_ != 1.0f) { |
| 171 SkCanvas* canvas = data_->recorder_.beginRecording(data_->size_.width(), | 197 SkCanvas* canvas = data_->recorder_.beginRecording(data_->size_.width(), |
| 172 data_->size_.height()); | 198 data_->size_.height()); |
| 173 canvas->scale(data_->scale_factor_, data_->scale_factor_); | 199 canvas->scale(data_->scale_factor_, data_->scale_factor_); |
| 174 canvas->drawPicture(pic); | 200 canvas->drawDrawable(pic.get()); |
| 175 pic = data_->recorder_.finishRecordingAsPicture(); | 201 pic = data_->recorder_.finishRecordingAsDrawable(); |
| 176 } | 202 } |
| 177 data_->pages_.emplace_back(data_->size_, std::move(pic)); | 203 data_->pages_.emplace_back(data_->size_, pic); |
| 178 return true; | 204 return true; |
| 179 } | 205 } |
| 180 | 206 |
| 207 void PdfMetafileSkia::FinishAllPages() { |
| 208 // If we've already set the data in InitFromData, leave it be. |
| 209 if (data_->pdf_data_) { |
| 210 return; |
| 211 } |
| 212 |
| 213 if (data_->recorder_.getRecordingCanvas()) { |
| 214 FinishPage(); |
| 215 } |
| 216 } |
| 217 |
| 181 bool PdfMetafileSkia::FinishDocument() { | 218 bool PdfMetafileSkia::FinishDocument() { |
| 182 // If we've already set the data in InitFromData, leave it be. | 219 // If we've already set the data in InitFromData, leave it be. |
| 183 if (data_->pdf_data_) | 220 if (data_->pdf_data_) |
| 184 return false; | 221 return false; |
| 185 | 222 |
| 186 if (data_->recorder_.getRecordingCanvas()) | 223 if (data_->recorder_.getRecordingCanvas()) |
| 187 FinishPage(); | 224 FinishPage(); |
| 188 | 225 |
| 189 SkDynamicMemoryWStream stream; | 226 SkDynamicMemoryWStream stream; |
| 190 sk_sp<SkDocument> doc; | 227 sk_sp<SkDocument> doc; |
| 191 switch (data_->type_) { | 228 switch (data_->type_) { |
| 192 case PDF_SKIA_DOCUMENT_TYPE: | 229 case PDF_SKIA_DOCUMENT_TYPE: |
| 193 doc = MakePdfDocument(&stream); | 230 doc = MakePdfDocument(&stream); |
| 194 break; | 231 break; |
| 195 case MSKP_SKIA_DOCUMENT_TYPE: | 232 case MSKP_SKIA_DOCUMENT_TYPE: |
| 196 doc = SkMakeMultiPictureDocument(&stream); | 233 doc = SkMakeMultiPictureDocument(&stream); |
| 197 break; | 234 break; |
| 198 } | 235 } |
| 199 | 236 |
| 200 for (const Page& page : data_->pages_) { | 237 for (const Page& page : data_->pages_) { |
| 201 SkCanvas* canvas = doc->beginPage(page.size_.width(), page.size_.height()); | 238 SkCanvas* canvas = doc->beginPage(page.size_.width(), page.size_.height()); |
| 202 canvas->drawPicture(page.content_); | 239 canvas->drawDrawable(page.content_.get()); |
| 203 doc->endPage(); | 240 doc->endPage(); |
| 204 } | 241 } |
| 205 doc->close(); | 242 doc->close(); |
| 206 | 243 |
| 207 data_->pdf_data_.reset(stream.detachAsStream()); | 244 data_->pdf_data_.reset(stream.detachAsStream()); |
| 208 return true; | 245 return true; |
| 209 } | 246 } |
| 210 | 247 |
| 248 std::unique_ptr<char[]> PdfMetafileSkia::GetPageDataBuffer(size_t* size) const { |
| 249 struct PageInfo { |
| 250 PageInfo(SkScalar w, SkScalar h, std::vector<char> d) |
| 251 : width(w), height(h), data(std::move(d)) {} |
| 252 SkScalar width; |
| 253 SkScalar height; |
| 254 std::vector<char> data; |
| 255 }; |
| 256 std::vector<PageInfo> serialized_pages; |
| 257 size_t total_buf_size = 0; |
| 258 for (size_t i = 0; i < data_->pages_.size(); ++i) { |
| 259 // Flatten each page into buffer. |
| 260 std::vector<char> flattened = |
| 261 skia::WriteDrawable(data_->pages_[i].content_.get()); |
| 262 if (!flattened.size() || !flattened.data()) { |
| 263 continue; |
| 264 } |
| 265 total_buf_size += sizeof(size_t) + sizeof(SkScalar) * 2 + flattened.size(); |
| 266 serialized_pages.emplace_back(data_->pages_[i].size_.width(), |
| 267 data_->pages_[i].size_.height(), |
| 268 std::move(flattened)); |
| 269 } |
| 270 if (!total_buf_size) { |
| 271 *size = 0; |
| 272 return nullptr; |
| 273 } |
| 274 std::unique_ptr<char[]> buf(new char[total_buf_size]); |
| 275 char* buf_pos = buf.get(); |
| 276 for (size_t i = 0; i < serialized_pages.size(); ++i) { |
| 277 size_t size = serialized_pages[i].data.size(); |
| 278 memcpy(buf_pos, &size, sizeof(size_t)); |
| 279 buf_pos += sizeof(size_t); |
| 280 memcpy(buf_pos, &serialized_pages[i].width, sizeof(SkScalar)); |
| 281 buf_pos += sizeof(SkScalar); |
| 282 memcpy(buf_pos, &serialized_pages[i].height, sizeof(SkScalar)); |
| 283 buf_pos += sizeof(SkScalar); |
| 284 memcpy(buf_pos, serialized_pages[i].data.data(), size); |
| 285 buf_pos += size; |
| 286 } |
| 287 *size = total_buf_size; |
| 288 return buf; |
| 289 } |
| 290 |
| 291 void PdfMetafileSkia::GetSkp(SkWStream* stream) const { |
| 292 if (data_->pages_.size() >= 1) |
| 293 data_->pages_[0].content_->newPictureSnapshot()->serialize(stream); |
| 294 } |
| 295 |
| 296 void PdfMetafileSkia::ConvertPagesToPdf() { |
| 297 SkDynamicMemoryWStream stream; |
| 298 sk_sp<SkDocument> doc = MakePdfDocument(&stream); |
| 299 |
| 300 for (const Page& page : data_->pages_) { |
| 301 SkCanvas* canvas = doc->beginPage(page.size_.width(), page.size_.height()); |
| 302 canvas->drawPicture(page.content_->newPictureSnapshot()); |
| 303 doc->endPage(); |
| 304 } |
| 305 doc->close(); |
| 306 |
| 307 data_->pdf_data_.reset(stream.detachAsStream()); |
| 308 } |
| 309 |
| 211 uint32_t PdfMetafileSkia::GetDataSize() const { | 310 uint32_t PdfMetafileSkia::GetDataSize() const { |
| 212 if (!data_->pdf_data_) | 311 if (!data_->pdf_data_) |
| 213 return 0; | 312 return 0; |
| 214 return base::checked_cast<uint32_t>(data_->pdf_data_->getLength()); | 313 return base::checked_cast<uint32_t>(data_->pdf_data_->getLength()); |
| 215 } | 314 } |
| 216 | 315 |
| 217 bool PdfMetafileSkia::GetData(void* dst_buffer, | 316 bool PdfMetafileSkia::GetData(void* dst_buffer, |
| 218 uint32_t dst_buffer_size) const { | 317 uint32_t dst_buffer_size) const { |
| 219 if (!data_->pdf_data_) | 318 if (!data_->pdf_data_) |
| 220 return false; | 319 return false; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 std::unique_ptr<PdfMetafileSkia> metafile(new PdfMetafileSkia(type)); | 412 std::unique_ptr<PdfMetafileSkia> metafile(new PdfMetafileSkia(type)); |
| 314 | 413 |
| 315 if (data_->pages_.size() == 0) | 414 if (data_->pages_.size() == 0) |
| 316 return metafile; | 415 return metafile; |
| 317 | 416 |
| 318 if (data_->recorder_.getRecordingCanvas()) // page outstanding | 417 if (data_->recorder_.getRecordingCanvas()) // page outstanding |
| 319 return metafile; | 418 return metafile; |
| 320 | 419 |
| 321 metafile->data_->pages_.push_back(data_->pages_.back()); | 420 metafile->data_->pages_.push_back(data_->pages_.back()); |
| 322 | 421 |
| 323 if (!metafile->FinishDocument()) // Generate PDF. | 422 // if (!metafile->FinishDocument()) // Generate PDF. |
| 324 metafile.reset(); | 423 // metafile.reset(); |
| 325 | 424 |
| 326 return metafile; | 425 return metafile; |
| 327 } | 426 } |
| 328 | 427 |
| 329 } // namespace printing | 428 } // namespace printing |
| OLD | NEW |