SkMultiPictureDocument.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * Copyright 2016 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #include "src/utils/SkMultiPictureDocument.h"
  8. #include "include/core/SkPicture.h"
  9. #include "include/core/SkPictureRecorder.h"
  10. #include "include/core/SkSerialProcs.h"
  11. #include "include/core/SkStream.h"
  12. #include "include/private/SkTArray.h"
  13. #include "include/private/SkTo.h"
  14. #include "include/utils/SkNWayCanvas.h"
  15. #include "src/utils/SkMultiPictureDocumentPriv.h"
  16. #include <limits.h>
  17. /*
  18. File format:
  19. BEGINNING_OF_FILE:
  20. kMagic
  21. uint32_t version_number (==2)
  22. uint32_t page_count
  23. {
  24. float sizeX
  25. float sizeY
  26. } * page_count
  27. skp file
  28. */
  29. namespace {
  30. // The unique file signature for this file type.
  31. static constexpr char kMagic[] = "Skia Multi-Picture Doc\n\n";
  32. static constexpr char kEndPage[] = "SkMultiPictureEndPage";
  33. const uint32_t kVersion = 2;
  34. static SkSize join(const SkTArray<SkSize>& sizes) {
  35. SkSize joined = {0, 0};
  36. for (SkSize s : sizes) {
  37. joined = SkSize{SkTMax(joined.width(), s.width()), SkTMax(joined.height(), s.height())};
  38. }
  39. return joined;
  40. }
  41. struct MultiPictureDocument final : public SkDocument {
  42. const SkSerialProcs fProcs;
  43. SkPictureRecorder fPictureRecorder;
  44. SkSize fCurrentPageSize;
  45. SkTArray<sk_sp<SkPicture>> fPages;
  46. SkTArray<SkSize> fSizes;
  47. MultiPictureDocument(SkWStream* s, const SkSerialProcs* procs)
  48. : SkDocument(s)
  49. , fProcs(procs ? *procs : SkSerialProcs())
  50. {}
  51. ~MultiPictureDocument() override { this->close(); }
  52. SkCanvas* onBeginPage(SkScalar w, SkScalar h) override {
  53. fCurrentPageSize.set(w, h);
  54. return fPictureRecorder.beginRecording(w, h);
  55. }
  56. void onEndPage() override {
  57. fSizes.push_back(fCurrentPageSize);
  58. fPages.push_back(fPictureRecorder.finishRecordingAsPicture());
  59. }
  60. void onClose(SkWStream* wStream) override {
  61. SkASSERT(wStream);
  62. SkASSERT(wStream->bytesWritten() == 0);
  63. wStream->writeText(kMagic);
  64. wStream->write32(kVersion);
  65. wStream->write32(SkToU32(fPages.count()));
  66. for (SkSize s : fSizes) {
  67. wStream->write(&s, sizeof(s));
  68. }
  69. SkSize bigsize = join(fSizes);
  70. SkCanvas* c = fPictureRecorder.beginRecording(SkRect::MakeSize(bigsize));
  71. for (const sk_sp<SkPicture>& page : fPages) {
  72. c->drawPicture(page);
  73. // Annotations must include some data.
  74. c->drawAnnotation(SkRect::MakeEmpty(), kEndPage, SkData::MakeWithCString("X"));
  75. }
  76. sk_sp<SkPicture> p = fPictureRecorder.finishRecordingAsPicture();
  77. p->serialize(wStream, &fProcs);
  78. fPages.reset();
  79. fSizes.reset();
  80. return;
  81. }
  82. void onAbort() override {
  83. fPages.reset();
  84. fSizes.reset();
  85. }
  86. };
  87. }
  88. sk_sp<SkDocument> SkMakeMultiPictureDocument(SkWStream* wStream, const SkSerialProcs* procs) {
  89. return sk_make_sp<MultiPictureDocument>(wStream, procs);
  90. }
  91. ////////////////////////////////////////////////////////////////////////////////
  92. int SkMultiPictureDocumentReadPageCount(SkStreamSeekable* stream) {
  93. if (!stream) {
  94. return 0;
  95. }
  96. stream->seek(0);
  97. const size_t size = sizeof(kMagic) - 1;
  98. char buffer[size];
  99. if (size != stream->read(buffer, size) || 0 != memcmp(kMagic, buffer, size)) {
  100. stream = nullptr;
  101. return 0;
  102. }
  103. uint32_t versionNumber;
  104. if (!stream->readU32(&versionNumber) || versionNumber != kVersion) {
  105. return 0;
  106. }
  107. uint32_t pageCount;
  108. if (!stream->readU32(&pageCount) || pageCount > INT_MAX) {
  109. return 0;
  110. }
  111. // leave stream position right here.
  112. return SkTo<int>(pageCount);
  113. }
  114. bool SkMultiPictureDocumentReadPageSizes(SkStreamSeekable* stream,
  115. SkDocumentPage* dstArray,
  116. int dstArrayCount) {
  117. if (!dstArray || dstArrayCount < 1) {
  118. return false;
  119. }
  120. int pageCount = SkMultiPictureDocumentReadPageCount(stream);
  121. if (pageCount < 1 || pageCount != dstArrayCount) {
  122. return false;
  123. }
  124. for (int i = 0; i < pageCount; ++i) {
  125. SkSize& s = dstArray[i].fSize;
  126. if (sizeof(s) != stream->read(&s, sizeof(s))) {
  127. return false;
  128. }
  129. }
  130. // leave stream position right here.
  131. return true;
  132. }
  133. namespace {
  134. struct PagerCanvas : public SkNWayCanvas {
  135. SkPictureRecorder fRecorder;
  136. SkDocumentPage* fDst;
  137. int fCount;
  138. int fIndex = 0;
  139. PagerCanvas(SkISize wh, SkDocumentPage* dst, int count)
  140. : SkNWayCanvas(wh.width(), wh.height()), fDst(dst), fCount(count) {
  141. this->nextCanvas();
  142. }
  143. void nextCanvas() {
  144. if (fIndex < fCount) {
  145. SkRect bounds = SkRect::MakeSize(fDst[fIndex].fSize);
  146. this->addCanvas(fRecorder.beginRecording(bounds));
  147. }
  148. }
  149. void onDrawAnnotation(const SkRect& r, const char* key, SkData* d) override {
  150. if (0 == strcmp(key, kEndPage)) {
  151. this->removeAll();
  152. if (fIndex < fCount) {
  153. fDst[fIndex].fPicture = fRecorder.finishRecordingAsPicture();
  154. ++fIndex;
  155. }
  156. this->nextCanvas();
  157. } else {
  158. this->SkNWayCanvas::onDrawAnnotation(r, key, d);
  159. }
  160. }
  161. };
  162. } // namespace
  163. bool SkMultiPictureDocumentRead(SkStreamSeekable* stream,
  164. SkDocumentPage* dstArray,
  165. int dstArrayCount,
  166. const SkDeserialProcs* procs) {
  167. if (!SkMultiPictureDocumentReadPageSizes(stream, dstArray, dstArrayCount)) {
  168. return false;
  169. }
  170. SkSize joined = {0.0f, 0.0f};
  171. for (int i = 0; i < dstArrayCount; ++i) {
  172. joined = SkSize{SkTMax(joined.width(), dstArray[i].fSize.width()),
  173. SkTMax(joined.height(), dstArray[i].fSize.height())};
  174. }
  175. auto picture = SkPicture::MakeFromStream(stream, procs);
  176. PagerCanvas canvas(joined.toCeil(), dstArray, dstArrayCount);
  177. // Must call playback(), not drawPicture() to reach
  178. // PagerCanvas::onDrawAnnotation().
  179. picture->playback(&canvas);
  180. if (canvas.fIndex != dstArrayCount) {
  181. SkDEBUGF("Malformed SkMultiPictureDocument: canvas.fIndex=%d dstArrayCount=%d\n",
  182. canvas.fIndex, dstArrayCount);
  183. }
  184. return true;
  185. }