blob: 638f6708343ec6c8b24dcb5d35cde124cbfc5452 [file] [log] [blame]
mtklein748ca3b2015-01-15 10:56:12 -08001#include "DMSrcSink.h"
2#include "SamplePipeControllers.h"
3#include "SkCommonFlags.h"
scroggof24f2242015-03-03 08:59:20 -08004#include "SkCodec.h"
mtklein748ca3b2015-01-15 10:56:12 -08005#include "SkDocument.h"
joshualitt5f5a8d72015-02-25 14:09:45 -08006#include "SkError.h"
mtklein748ca3b2015-01-15 10:56:12 -08007#include "SkMultiPictureDraw.h"
mtkleinad66f9b2015-02-13 15:11:10 -08008#include "SkNullCanvas.h"
mtklein748ca3b2015-01-15 10:56:12 -08009#include "SkOSFile.h"
mtkleinffa901a2015-03-16 10:38:07 -070010#include "SkPictureData.h"
mtklein748ca3b2015-01-15 10:56:12 -080011#include "SkPictureRecorder.h"
12#include "SkRandom.h"
fmalita2aafe6f2015-02-06 12:51:10 -080013#include "SkSVGCanvas.h"
scroggoa1193e42015-01-21 12:09:53 -080014#include "SkStream.h"
fmalita2aafe6f2015-02-06 12:51:10 -080015#include "SkXMLWriter.h"
mtklein748ca3b2015-01-15 10:56:12 -080016
17namespace DM {
18
mtklein748ca3b2015-01-15 10:56:12 -080019GMSrc::GMSrc(skiagm::GMRegistry::Factory factory) : fFactory(factory) {}
20
21Error GMSrc::draw(SkCanvas* canvas) const {
22 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
23 canvas->concat(gm->getInitialTransform());
24 gm->draw(canvas);
25 return "";
26}
27
28SkISize GMSrc::size() const {
29 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
30 return gm->getISize();
31}
32
33Name GMSrc::name() const {
34 SkAutoTDelete<skiagm::GM> gm(fFactory(NULL));
35 return gm->getName();
36}
37
38/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
39
scroggo9b77ddd2015-03-19 06:03:39 -070040CodecSrc::CodecSrc(Path path) : fPath(path) {}
mtklein748ca3b2015-01-15 10:56:12 -080041
scroggo9b77ddd2015-03-19 06:03:39 -070042Error CodecSrc::draw(SkCanvas* canvas) const {
43 SkImageInfo canvasInfo;
44 if (NULL == canvas->peekPixels(&canvasInfo, NULL)) {
45 // TODO: Once we implement GPU paths (e.g. JPEG YUV), we should use a deferred decode to
46 // let the GPU handle it.
47 return Error::Nonfatal("No need to test decoding to non-raster backend.");
48 }
49
mtklein75d98fd2015-01-18 07:05:01 -080050 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
mtklein748ca3b2015-01-15 10:56:12 -080051 if (!encoded) {
52 return SkStringPrintf("Couldn't read %s.", fPath.c_str());
53 }
scroggo9b77ddd2015-03-19 06:03:39 -070054
55 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
56 if (!codec) {
57 return SkStringPrintf("Couldn't decode %s.", fPath.c_str());
58 }
59
reed3ef71e32015-03-19 08:31:14 -070060 SkImageInfo decodeInfo = codec->getInfo().makeColorType(canvasInfo.colorType());
scroggo9b77ddd2015-03-19 06:03:39 -070061 if (decodeInfo.alphaType() == kUnpremul_SkAlphaType) {
62 // FIXME: Currently we cannot draw unpremultiplied sources.
63 decodeInfo = decodeInfo.makeAlphaType(kPremul_SkAlphaType);
64 }
65
66 SkBitmap bitmap;
67 if (!bitmap.tryAllocPixels(decodeInfo)) {
68 return SkStringPrintf("Image(%s) is too large (%d x %d)\n", fPath.c_str(),
69 decodeInfo.width(), decodeInfo.height());
70 }
71
72 SkAutoLockPixels alp(bitmap);
73 switch (codec->getPixels(decodeInfo, bitmap.getPixels(), bitmap.rowBytes())) {
74 case SkImageGenerator::kSuccess:
75 // We consider incomplete to be valid, since we should still decode what is
76 // available.
77 case SkImageGenerator::kIncompleteInput:
78 canvas->drawBitmap(bitmap, 0, 0);
79 return "";
80 case SkImageGenerator::kInvalidConversion:
81 return Error::Nonfatal("Incompatible colortype conversion");
82 default:
83 // Everything else is considered a failure.
84 return SkStringPrintf("Couldn't getPixels %s.", fPath.c_str());
85 }
86}
87
88SkISize CodecSrc::size() const {
89 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
90 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
reed3ef71e32015-03-19 08:31:14 -070091 return codec->getInfo().dimensions();
scroggo9b77ddd2015-03-19 06:03:39 -070092}
93
94Name CodecSrc::name() const {
95 return SkOSPath::Basename(fPath.c_str());
96}
97
98/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
99
100ImageSrc::ImageSrc(Path path, int divisor) : fPath(path), fDivisor(divisor) {}
101
102Error ImageSrc::draw(SkCanvas* canvas) const {
103 SkImageInfo canvasInfo;
104 if (NULL == canvas->peekPixels(&canvasInfo, NULL)) {
105 // TODO: Instead, use lazy decoding to allow the GPU to handle cases like YUV.
106 return Error::Nonfatal("No need to test decoding to non-raster backend.");
107 }
108
109 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
110 if (!encoded) {
111 return SkStringPrintf("Couldn't read %s.", fPath.c_str());
112 }
113 const SkColorType dstColorType = canvasInfo.colorType();
mtkleinedc93bc2015-01-30 13:22:23 -0800114 if (fDivisor == 0) {
mtklein748ca3b2015-01-15 10:56:12 -0800115 // Decode the full image.
116 SkBitmap bitmap;
scroggo9b77ddd2015-03-19 06:03:39 -0700117 if (!SkImageDecoder::DecodeMemory(encoded->data(), encoded->size(), &bitmap,
118 dstColorType, SkImageDecoder::kDecodePixels_Mode)) {
119 return SkStringPrintf("Couldn't decode %s.", fPath.c_str());
120 }
121 if (kRGB_565_SkColorType == dstColorType && !bitmap.isOpaque()) {
122 // Do not draw a bitmap with alpha to a destination without alpha.
123 return Error::Nonfatal("Uninteresting to decode image with alpha into 565.");
mtklein748ca3b2015-01-15 10:56:12 -0800124 }
mtklein75d98fd2015-01-18 07:05:01 -0800125 encoded.reset((SkData*)NULL); // Might as well drop this when we're done with it.
mtklein748ca3b2015-01-15 10:56:12 -0800126 canvas->drawBitmap(bitmap, 0,0);
127 return "";
128 }
mtkleinedc93bc2015-01-30 13:22:23 -0800129 // Decode subsets. This is a little involved.
scroggoa1193e42015-01-21 12:09:53 -0800130 SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(encoded));
131 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream.get()));
mtklein748ca3b2015-01-15 10:56:12 -0800132 if (!decoder) {
133 return SkStringPrintf("Can't find a good decoder for %s.", fPath.c_str());
134 }
scroggoa1193e42015-01-21 12:09:53 -0800135 stream->rewind();
mtklein748ca3b2015-01-15 10:56:12 -0800136 int w,h;
scroggoa1193e42015-01-21 12:09:53 -0800137 if (!decoder->buildTileIndex(stream.detach(), &w, &h) || w*h == 1) {
mtklein4089ef72015-03-05 08:40:28 -0800138 return Error::Nonfatal("Subset decoding not supported.");
mtklein748ca3b2015-01-15 10:56:12 -0800139 }
mtkleinedc93bc2015-01-30 13:22:23 -0800140
141 // Divide the image into subsets that cover the entire image.
142 if (fDivisor > w || fDivisor > h) {
143 return SkStringPrintf("divisor %d is too big for %s with dimensions (%d x %d)",
144 fDivisor, fPath.c_str(), w, h);
145 }
146 const int subsetWidth = w / fDivisor,
147 subsetHeight = h / fDivisor;
148 for (int y = 0; y < h; y += subsetHeight) {
149 for (int x = 0; x < w; x += subsetWidth) {
150 SkBitmap subset;
151 SkIRect rect = SkIRect::MakeXYWH(x, y, subsetWidth, subsetHeight);
152 if (!decoder->decodeSubset(&subset, rect, dstColorType)) {
153 return SkStringPrintf("Could not decode subset (%d, %d, %d, %d).",
154 x, y, x+subsetWidth, y+subsetHeight);
155 }
scroggo56e25dd2015-03-05 11:46:40 -0800156 if (kRGB_565_SkColorType == dstColorType && !subset.isOpaque()) {
157 // Do not draw a bitmap with alpha to a destination without alpha.
158 // This is not an error, but there is nothing interesting to show.
159
160 // This should only happen on the first iteration through the loop.
161 SkASSERT(0 == x && 0 == y);
162
163 return Error::Nonfatal("Uninteresting to decode image with alpha into 565.");
164 }
mtkleinedc93bc2015-01-30 13:22:23 -0800165 canvas->drawBitmap(subset, SkIntToScalar(x), SkIntToScalar(y));
mtklein748ca3b2015-01-15 10:56:12 -0800166 }
mtklein748ca3b2015-01-15 10:56:12 -0800167 }
168 return "";
169}
170
171SkISize ImageSrc::size() const {
mtklein75d98fd2015-01-18 07:05:01 -0800172 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(fPath.c_str()));
scroggo9b77ddd2015-03-19 06:03:39 -0700173 SkBitmap bitmap;
174 if (!encoded || !SkImageDecoder::DecodeMemory(encoded->data(),
175 encoded->size(),
176 &bitmap,
177 kUnknown_SkColorType,
178 SkImageDecoder::kDecodeBounds_Mode)) {
179 return SkISize::Make(0,0);
mtklein748ca3b2015-01-15 10:56:12 -0800180 }
scroggo9b77ddd2015-03-19 06:03:39 -0700181 return bitmap.dimensions();
mtklein748ca3b2015-01-15 10:56:12 -0800182}
183
mtklein9264a952015-01-20 10:11:53 -0800184Name ImageSrc::name() const {
mtkleinedc93bc2015-01-30 13:22:23 -0800185 return SkOSPath::Basename(fPath.c_str());
mtklein9264a952015-01-20 10:11:53 -0800186}
mtklein748ca3b2015-01-15 10:56:12 -0800187
188/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
189
mtkleinf4ba3212015-01-28 15:32:24 -0800190static const SkRect kSKPViewport = {0,0, 1000,1000};
191
mtklein8d17a132015-01-30 11:42:31 -0800192SKPSrc::SKPSrc(Path path) : fPath(path) {}
mtklein748ca3b2015-01-15 10:56:12 -0800193
194Error SKPSrc::draw(SkCanvas* canvas) const {
scroggoa1193e42015-01-21 12:09:53 -0800195 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str()));
mtklein75d98fd2015-01-18 07:05:01 -0800196 if (!stream) {
mtklein748ca3b2015-01-15 10:56:12 -0800197 return SkStringPrintf("Couldn't read %s.", fPath.c_str());
198 }
halcanary44906c62015-02-23 10:43:48 -0800199 SkAutoTUnref<SkPicture> pic(SkPicture::CreateFromStream(stream));
mtklein75d98fd2015-01-18 07:05:01 -0800200 if (!pic) {
201 return SkStringPrintf("Couldn't decode %s as a picture.", fPath.c_str());
202 }
203 stream.reset((SkStream*)NULL); // Might as well drop this when we're done with it.
mtkleinf4ba3212015-01-28 15:32:24 -0800204 canvas->clipRect(kSKPViewport);
mtklein748ca3b2015-01-15 10:56:12 -0800205 canvas->drawPicture(pic);
206 return "";
207}
208
209SkISize SKPSrc::size() const {
mtkleinffa901a2015-03-16 10:38:07 -0700210 SkAutoTDelete<SkStream> stream(SkStream::NewFromFile(fPath.c_str()));
211 if (!stream) {
212 return SkISize::Make(0,0);
213 }
214 SkPictInfo info;
215 if (!SkPicture::InternalOnly_StreamIsSKP(stream, &info)) {
216 return SkISize::Make(0,0);
217 }
218 SkRect viewport = kSKPViewport;
219 if (!viewport.intersect(info.fCullRect)) {
220 return SkISize::Make(0,0);
221 }
222 return viewport.roundOut().size();
mtklein748ca3b2015-01-15 10:56:12 -0800223}
224
225Name SKPSrc::name() const { return SkOSPath::Basename(fPath.c_str()); }
226
227/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
228
mtkleinad66f9b2015-02-13 15:11:10 -0800229Error NullSink::draw(const Src& src, SkBitmap*, SkWStream*, SkString*) const {
230 SkAutoTDelete<SkCanvas> canvas(SkCreateNullCanvas());
231 return src.draw(canvas);
232}
233
234/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
235
mtkleinb9eb4ac2015-02-02 18:26:03 -0800236DEFINE_bool(gpuStats, false, "Append GPU stats to the log for each GPU task?");
237
mtklein82d28432015-01-15 12:46:02 -0800238GPUSink::GPUSink(GrContextFactory::GLContextType ct,
239 GrGLStandard api,
240 int samples,
241 bool dfText,
242 bool threaded)
mtklein748ca3b2015-01-15 10:56:12 -0800243 : fContextType(ct)
244 , fGpuAPI(api)
245 , fSampleCount(samples)
mtklein82d28432015-01-15 12:46:02 -0800246 , fUseDFText(dfText)
247 , fThreaded(threaded) {}
mtklein748ca3b2015-01-15 10:56:12 -0800248
249int GPUSink::enclave() const {
mtklein55e88b22015-01-21 15:50:13 -0800250 return fThreaded ? kAnyThread_Enclave : kGPU_Enclave;
mtklein748ca3b2015-01-15 10:56:12 -0800251}
252
joshualitt5f5a8d72015-02-25 14:09:45 -0800253void PreAbandonGpuContextErrorHandler(SkError, void*) {}
254
mtkleinb9eb4ac2015-02-02 18:26:03 -0800255Error GPUSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString* log) const {
mtklein55e88b22015-01-21 15:50:13 -0800256 GrContextFactory factory;
mtkleinf4ba3212015-01-28 15:32:24 -0800257 const SkISize size = src.size();
mtklein748ca3b2015-01-15 10:56:12 -0800258 const SkImageInfo info =
259 SkImageInfo::Make(size.width(), size.height(), kN32_SkColorType, kPremul_SkAlphaType);
260 SkAutoTUnref<SkSurface> surface(
mtklein55e88b22015-01-21 15:50:13 -0800261 NewGpuSurface(&factory, fContextType, fGpuAPI, info, fSampleCount, fUseDFText));
mtklein748ca3b2015-01-15 10:56:12 -0800262 if (!surface) {
263 return "Could not create a surface.";
264 }
joshualitt5f5a8d72015-02-25 14:09:45 -0800265 if (FLAGS_preAbandonGpuContext) {
266 SkSetErrorCallback(&PreAbandonGpuContextErrorHandler, NULL);
267 factory.abandonContexts();
268 }
mtklein748ca3b2015-01-15 10:56:12 -0800269 SkCanvas* canvas = surface->getCanvas();
270 Error err = src.draw(canvas);
271 if (!err.isEmpty()) {
272 return err;
273 }
274 canvas->flush();
mtkleinb9eb4ac2015-02-02 18:26:03 -0800275 if (FLAGS_gpuStats) {
276 canvas->getGrContext()->dumpCacheStats(log);
277 canvas->getGrContext()->dumpGpuStats(log);
278 }
mtklein748ca3b2015-01-15 10:56:12 -0800279 dst->allocPixels(info);
joshualitt5f5a8d72015-02-25 14:09:45 -0800280 canvas->readPixels(dst, 0, 0);
mtklein55e88b22015-01-21 15:50:13 -0800281 if (FLAGS_abandonGpuContext) {
282 factory.abandonContexts();
283 }
mtklein748ca3b2015-01-15 10:56:12 -0800284 return "";
285}
286
287/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
288
halcanary47ef4d52015-03-03 09:13:09 -0800289static Error draw_skdocument(const Src& src, SkDocument* doc, SkWStream* dst) {
290 // Print the given DM:Src to a document, breaking on 8.5x11 pages.
291 SkASSERT(doc);
halcanaryfd4a9932015-01-28 11:45:58 -0800292 int width = src.size().width(),
293 height = src.size().height();
294
295 const int kLetterWidth = 612, // 8.5 * 72
296 kLetterHeight = 792; // 11 * 72
297 const SkRect letter = SkRect::MakeWH(SkIntToScalar(kLetterWidth),
298 SkIntToScalar(kLetterHeight));
299
300 int xPages = ((width - 1) / kLetterWidth) + 1;
301 int yPages = ((height - 1) / kLetterHeight) + 1;
302
303 for (int y = 0; y < yPages; ++y) {
304 for (int x = 0; x < xPages; ++x) {
305 int w = SkTMin(kLetterWidth, width - (x * kLetterWidth));
306 int h = SkTMin(kLetterHeight, height - (y * kLetterHeight));
307 SkCanvas* canvas =
308 doc->beginPage(SkIntToScalar(w), SkIntToScalar(h));
309 canvas->clipRect(letter);
310 canvas->translate(-letter.width() * x, -letter.height() * y);
311 Error err = src.draw(canvas);
312 if (!err.isEmpty()) {
313 return err;
314 }
315 doc->endPage();
316 }
mtklein748ca3b2015-01-15 10:56:12 -0800317 }
mtklein748ca3b2015-01-15 10:56:12 -0800318 doc->close();
halcanaryfd4a9932015-01-28 11:45:58 -0800319 dst->flush();
mtklein748ca3b2015-01-15 10:56:12 -0800320 return "";
321}
322
halcanary47ef4d52015-03-03 09:13:09 -0800323PDFSink::PDFSink() {}
324
325Error PDFSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
326 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(dst));
327 if (!doc) {
328 return "SkDocument::CreatePDF() returned NULL";
329 }
330 return draw_skdocument(src, doc.get(), dst);
331}
332
333/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
334
335XPSSink::XPSSink() {}
336
337Error XPSSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
338 SkAutoTUnref<SkDocument> doc(SkDocument::CreateXPS(dst));
339 if (!doc) {
340 return "SkDocument::CreateXPS() returned NULL";
341 }
342 return draw_skdocument(src, doc.get(), dst);
343}
mtklein748ca3b2015-01-15 10:56:12 -0800344/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
345
mtklein9c3f17d2015-01-28 11:35:18 -0800346SKPSink::SKPSink() {}
347
mtkleinb9eb4ac2015-02-02 18:26:03 -0800348Error SKPSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
mtklein9c3f17d2015-01-28 11:35:18 -0800349 SkSize size;
350 size = src.size();
351 SkPictureRecorder recorder;
352 Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
353 if (!err.isEmpty()) {
354 return err;
355 }
356 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
357 pic->serialize(dst);
358 return "";
359}
360
361/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
362
mtklein8a4527e2015-01-31 20:00:58 -0800363SVGSink::SVGSink() {}
364
mtkleinb9eb4ac2015-02-02 18:26:03 -0800365Error SVGSink::draw(const Src& src, SkBitmap*, SkWStream* dst, SkString*) const {
fmalita2aafe6f2015-02-06 12:51:10 -0800366 SkAutoTDelete<SkXMLWriter> xmlWriter(SkNEW_ARGS(SkXMLStreamWriter, (dst)));
367 SkAutoTUnref<SkCanvas> canvas(SkSVGCanvas::Create(
368 SkRect::MakeWH(SkIntToScalar(src.size().width()), SkIntToScalar(src.size().height())),
369 xmlWriter));
370 return src.draw(canvas);
mtklein8a4527e2015-01-31 20:00:58 -0800371}
372
373/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
374
mtklein748ca3b2015-01-15 10:56:12 -0800375RasterSink::RasterSink(SkColorType colorType) : fColorType(colorType) {}
376
mtkleinb9eb4ac2015-02-02 18:26:03 -0800377Error RasterSink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) const {
mtkleinf4ba3212015-01-28 15:32:24 -0800378 const SkISize size = src.size();
mtklein748ca3b2015-01-15 10:56:12 -0800379 // If there's an appropriate alpha type for this color type, use it, otherwise use premul.
380 SkAlphaType alphaType = kPremul_SkAlphaType;
381 (void)SkColorTypeValidateAlphaType(fColorType, alphaType, &alphaType);
382
383 dst->allocPixels(SkImageInfo::Make(size.width(), size.height(), fColorType, alphaType));
384 dst->eraseColor(SK_ColorTRANSPARENT);
385 SkCanvas canvas(*dst);
386 return src.draw(&canvas);
387}
388
389/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
390
mtkleind603b222015-02-17 11:13:33 -0800391static SkISize auto_compute_translate(SkMatrix* matrix, int srcW, int srcH) {
392 SkRect bounds = SkRect::MakeIWH(srcW, srcH);
393 matrix->mapRect(&bounds);
394 matrix->postTranslate(-bounds.x(), -bounds.y());
395 return SkISize::Make(SkScalarRoundToInt(bounds.width()), SkScalarRoundToInt(bounds.height()));
396}
397
mtklein748ca3b2015-01-15 10:56:12 -0800398ViaMatrix::ViaMatrix(SkMatrix matrix, Sink* sink) : fMatrix(matrix), fSink(sink) {}
399
mtkleinb9eb4ac2015-02-02 18:26:03 -0800400Error ViaMatrix::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
mtklein748ca3b2015-01-15 10:56:12 -0800401 // We turn our arguments into a Src, then draw that Src into our Sink to fill bitmap or stream.
402 struct ProxySrc : public Src {
mtkleind603b222015-02-17 11:13:33 -0800403 const Src& fSrc;
404 SkMatrix fMatrix;
405 SkISize fSize;
406
407 ProxySrc(const Src& src, SkMatrix matrix) : fSrc(src), fMatrix(matrix) {
408 fSize = auto_compute_translate(&fMatrix, src.size().width(), src.size().height());
409 }
mtklein748ca3b2015-01-15 10:56:12 -0800410
411 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
412 canvas->concat(fMatrix);
413 return fSrc.draw(canvas);
414 }
mtkleind603b222015-02-17 11:13:33 -0800415 SkISize size() const SK_OVERRIDE { return fSize; }
mtklein748ca3b2015-01-15 10:56:12 -0800416 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
417 } proxy(src, fMatrix);
mtkleinb9eb4ac2015-02-02 18:26:03 -0800418 return fSink->draw(proxy, bitmap, stream, log);
mtklein748ca3b2015-01-15 10:56:12 -0800419}
420
mtkleind603b222015-02-17 11:13:33 -0800421// Undoes any flip or 90 degree rotate without changing the scale of the bitmap.
422// This should be pixel-preserving.
423ViaUpright::ViaUpright(SkMatrix matrix, Sink* sink) : fMatrix(matrix), fSink(sink) {}
424
425Error ViaUpright::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
426 Error err = fSink->draw(src, bitmap, stream, log);
427 if (!err.isEmpty()) {
428 return err;
429 }
430
431 SkMatrix inverse;
432 if (!fMatrix.rectStaysRect() || !fMatrix.invert(&inverse)) {
433 return "Cannot upright --matrix.";
434 }
435 SkMatrix upright = SkMatrix::I();
436 upright.setScaleX(SkScalarSignAsScalar(inverse.getScaleX()));
437 upright.setScaleY(SkScalarSignAsScalar(inverse.getScaleY()));
438 upright.setSkewX(SkScalarSignAsScalar(inverse.getSkewX()));
439 upright.setSkewY(SkScalarSignAsScalar(inverse.getSkewY()));
440
441 SkBitmap uprighted;
442 SkISize size = auto_compute_translate(&upright, bitmap->width(), bitmap->height());
443 uprighted.allocPixels(bitmap->info().makeWH(size.width(), size.height()));
444
445 SkCanvas canvas(uprighted);
446 canvas.concat(upright);
447 SkPaint paint;
448 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
449 canvas.drawBitmap(*bitmap, 0, 0, &paint);
450
451 *bitmap = uprighted;
452 bitmap->lockPixels();
453 return "";
454}
455
mtklein748ca3b2015-01-15 10:56:12 -0800456/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
457
mtklein7edca212015-01-21 13:18:51 -0800458ViaPipe::ViaPipe(Sink* sink) : fSink(sink) {}
mtklein748ca3b2015-01-15 10:56:12 -0800459
mtkleinb9eb4ac2015-02-02 18:26:03 -0800460Error ViaPipe::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
mtklein7edca212015-01-21 13:18:51 -0800461 // We turn ourselves into another Src that draws our argument into bitmap/stream via pipe.
mtklein748ca3b2015-01-15 10:56:12 -0800462 struct ProxySrc : public Src {
463 const Src& fSrc;
mtklein7edca212015-01-21 13:18:51 -0800464 ProxySrc(const Src& src) : fSrc(src) {}
mtklein748ca3b2015-01-15 10:56:12 -0800465
466 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
467 SkISize size = this->size();
mtklein748ca3b2015-01-15 10:56:12 -0800468 PipeController controller(canvas, &SkImageDecoder::DecodeMemory);
469 SkGPipeWriter pipe;
mtklein7edca212015-01-21 13:18:51 -0800470 const uint32_t kFlags = 0; // We mirror SkDeferredCanvas, which doesn't use any flags.
471 return fSrc.draw(pipe.startRecording(&controller, kFlags, size.width(), size.height()));
mtklein748ca3b2015-01-15 10:56:12 -0800472 }
473 SkISize size() const SK_OVERRIDE { return fSrc.size(); }
474 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
mtklein7edca212015-01-21 13:18:51 -0800475 } proxy(src);
mtkleinb9eb4ac2015-02-02 18:26:03 -0800476 return fSink->draw(proxy, bitmap, stream, log);
mtklein748ca3b2015-01-15 10:56:12 -0800477}
478
479/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
480
481ViaSerialization::ViaSerialization(Sink* sink) : fSink(sink) {}
482
mtkleinb9eb4ac2015-02-02 18:26:03 -0800483Error ViaSerialization::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log)
484 const {
mtklein748ca3b2015-01-15 10:56:12 -0800485 // Record our Src into a picture.
486 SkSize size;
487 size = src.size();
488 SkPictureRecorder recorder;
489 Error err = src.draw(recorder.beginRecording(size.width(), size.height()));
490 if (!err.isEmpty()) {
491 return err;
492 }
493 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
494
495 // Serialize it and then deserialize it.
496 SkDynamicMemoryWStream wStream;
497 pic->serialize(&wStream);
scroggoa1193e42015-01-21 12:09:53 -0800498 SkAutoTDelete<SkStream> rStream(wStream.detachAsStream());
halcanary44906c62015-02-23 10:43:48 -0800499 SkAutoTUnref<SkPicture> deserialized(SkPicture::CreateFromStream(rStream));
mtklein748ca3b2015-01-15 10:56:12 -0800500
501 // Turn that deserialized picture into a Src, draw it into our Sink to fill bitmap or stream.
502 struct ProxySrc : public Src {
503 const SkPicture* fPic;
504 const SkISize fSize;
505 ProxySrc(const SkPicture* pic, SkISize size) : fPic(pic), fSize(size) {}
506
507 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
508 canvas->drawPicture(fPic);
509 return "";
510 }
511 SkISize size() const SK_OVERRIDE { return fSize; }
512 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
513 } proxy(deserialized, src.size());
mtkleinb9eb4ac2015-02-02 18:26:03 -0800514 return fSink->draw(proxy, bitmap, stream, log);
mtklein748ca3b2015-01-15 10:56:12 -0800515}
516
517/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
518
519ViaTiles::ViaTiles(int w, int h, SkBBHFactory* factory, Sink* sink)
520 : fW(w)
521 , fH(h)
522 , fFactory(factory)
523 , fSink(sink) {}
524
mtkleinb9eb4ac2015-02-02 18:26:03 -0800525Error ViaTiles::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
mtklein748ca3b2015-01-15 10:56:12 -0800526 // Record our Src into a picture.
527 SkSize size;
528 size = src.size();
529 SkPictureRecorder recorder;
530 Error err = src.draw(recorder.beginRecording(size.width(), size.height(), fFactory.get()));
531 if (!err.isEmpty()) {
532 return err;
533 }
534 SkAutoTUnref<SkPicture> pic(recorder.endRecording());
535
536 // Turn that picture into a Src that draws into our Sink via tiles + MPD.
537 struct ProxySrc : public Src {
538 const int fW, fH;
539 const SkPicture* fPic;
540 const SkISize fSize;
541 ProxySrc(int w, int h, const SkPicture* pic, SkISize size)
542 : fW(w), fH(h), fPic(pic), fSize(size) {}
543
544 Error draw(SkCanvas* canvas) const SK_OVERRIDE {
545 const int xTiles = (fSize.width() + fW - 1) / fW,
546 yTiles = (fSize.height() + fH - 1) / fH;
547 SkMultiPictureDraw mpd(xTiles*yTiles);
548 SkTDArray<SkSurface*> surfaces;
549 surfaces.setReserve(xTiles*yTiles);
550
551 SkImageInfo info = canvas->imageInfo().makeWH(fW, fH);
552 for (int j = 0; j < yTiles; j++) {
553 for (int i = 0; i < xTiles; i++) {
554 // This lets our ultimate Sink determine the best kind of surface.
555 // E.g., if it's a GpuSink, the surfaces and images are textures.
556 SkSurface* s = canvas->newSurface(info);
557 if (!s) {
558 s = SkSurface::NewRaster(info); // Some canvases can't create surfaces.
559 }
560 surfaces.push(s);
561 SkCanvas* c = s->getCanvas();
562 c->translate(SkIntToScalar(-i * fW),
563 SkIntToScalar(-j * fH)); // Line up the canvas with this tile.
564 mpd.add(c, fPic);
565 }
566 }
567 mpd.draw();
568 for (int j = 0; j < yTiles; j++) {
569 for (int i = 0; i < xTiles; i++) {
570 SkAutoTUnref<SkImage> image(surfaces[i+xTiles*j]->newImageSnapshot());
571 canvas->drawImage(image, SkIntToScalar(i*fW), SkIntToScalar(j*fH));
572 }
573 }
574 surfaces.unrefAll();
575 return "";
576 }
577 SkISize size() const SK_OVERRIDE { return fSize; }
578 Name name() const SK_OVERRIDE { sk_throw(); return ""; } // No one should be calling this.
579 } proxy(fW, fH, pic, src.size());
mtkleinb9eb4ac2015-02-02 18:26:03 -0800580 return fSink->draw(proxy, bitmap, stream, log);
mtklein748ca3b2015-01-15 10:56:12 -0800581}
582
583} // namespace DM