blob: 398c6eb5dfc77953b84451034d958b85f69c4a16 [file] [log] [blame]
fmalita1dedc3d2015-08-04 13:53:14 -07001/*
2 * Copyright 2015 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
8#include "SkImageGenerator.h"
fmalita1dedc3d2015-08-04 13:53:14 -07009#include "SkCanvas.h"
10#include "SkMatrix.h"
11#include "SkPaint.h"
12#include "SkPicture.h"
reed8f343722015-08-13 13:32:39 -070013#include "SkSurface.h"
bungemand3ebb482015-08-05 13:57:49 -070014#include "SkTLazy.h"
fmalita1dedc3d2015-08-04 13:53:14 -070015
16class SkPictureImageGenerator : SkImageGenerator {
17public:
18 static SkImageGenerator* Create(const SkISize&, const SkPicture*, const SkMatrix*,
19 const SkPaint*);
20
21protected:
22 bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[],
23 int* ctableCount) override;
reed7850eb22015-12-02 14:19:47 -080024 bool onComputeScaledDimensions(SkScalar scale, SupportedSizes*) override;
25 bool onGenerateScaledPixels(const SkISize&, const SkIPoint&, const SkPixmap&) override;
26
reed8f343722015-08-13 13:32:39 -070027#if SK_SUPPORT_GPU
bsalomon5f5527f2015-10-15 12:14:55 -070028 GrTexture* onGenerateTexture(GrContext*, const SkIRect*) override;
reed8f343722015-08-13 13:32:39 -070029#endif
fmalita1dedc3d2015-08-04 13:53:14 -070030
31private:
32 SkPictureImageGenerator(const SkISize&, const SkPicture*, const SkMatrix*, const SkPaint*);
33
34 SkAutoTUnref<const SkPicture> fPicture;
35 SkMatrix fMatrix;
36 SkTLazy<SkPaint> fPaint;
37
38 typedef SkImageGenerator INHERITED;
39};
40
41SkImageGenerator* SkPictureImageGenerator::Create(const SkISize& size, const SkPicture* picture,
42 const SkMatrix* matrix, const SkPaint* paint) {
43 if (!picture || size.isEmpty()) {
44 return nullptr;
45 }
46
halcanary385fe4d2015-08-26 13:07:48 -070047 return new SkPictureImageGenerator(size, picture, matrix, paint);
fmalita1dedc3d2015-08-04 13:53:14 -070048}
49
50SkPictureImageGenerator::SkPictureImageGenerator(const SkISize& size, const SkPicture* picture,
51 const SkMatrix* matrix, const SkPaint* paint)
52 : INHERITED(SkImageInfo::MakeN32Premul(size))
53 , fPicture(SkRef(picture)) {
54
55 if (matrix) {
56 fMatrix = *matrix;
57 } else {
58 fMatrix.reset();
59 }
60
61 if (paint) {
62 fPaint.set(*paint);
63 }
64}
65
66bool SkPictureImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
67 SkPMColor ctable[], int* ctableCount) {
68 if (info != getInfo() || ctable || ctableCount) {
69 return false;
70 }
71
72 SkBitmap bitmap;
73 if (!bitmap.installPixels(info, pixels, rowBytes)) {
74 return false;
75 }
76
77 bitmap.eraseColor(SK_ColorTRANSPARENT);
78 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
79 canvas.drawPicture(fPicture, &fMatrix, fPaint.getMaybeNull());
80
81 return true;
82}
83
reed7850eb22015-12-02 14:19:47 -080084bool SkPictureImageGenerator::onComputeScaledDimensions(SkScalar scale,
85 SupportedSizes* sizes) {
86 SkASSERT(scale > 0 && scale <= 1);
87 const int w = this->getInfo().width();
88 const int h = this->getInfo().height();
89 const int sw = SkScalarRoundToInt(scale * w);
90 const int sh = SkScalarRoundToInt(scale * h);
91 if (sw > 0 && sh > 0) {
92 sizes->fSizes[0].set(sw, sh);
93 sizes->fSizes[1].set(sw, sh);
94 return true;
95 }
96 return false;
97}
98
99bool SkPictureImageGenerator::onGenerateScaledPixels(const SkISize& scaledSize,
100 const SkIPoint& scaledOrigin,
101 const SkPixmap& scaledPixels) {
102 int w = scaledSize.width();
103 int h = scaledSize.height();
104
105 const SkScalar scaleX = SkIntToScalar(w) / this->getInfo().width();
106 const SkScalar scaleY = SkIntToScalar(h) / this->getInfo().height();
107 SkMatrix matrix = SkMatrix::MakeScale(scaleX, scaleY);
108 matrix.postTranslate(-SkIntToScalar(scaledOrigin.x()), -SkIntToScalar(scaledOrigin.y()));
109
110 SkBitmap bitmap;
halcanarye36ec872015-12-09 11:36:59 -0800111 if (!bitmap.installPixels(scaledPixels)) {
reed7850eb22015-12-02 14:19:47 -0800112 return false;
113 }
114
115 bitmap.eraseColor(SK_ColorTRANSPARENT);
116 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
117 matrix.preConcat(fMatrix);
118 canvas.drawPicture(fPicture, &matrix, fPaint.getMaybeNull());
119 return true;
120}
121
122///////////////////////////////////////////////////////////////////////////////////////////////////
123
fmalita1dedc3d2015-08-04 13:53:14 -0700124SkImageGenerator* SkImageGenerator::NewFromPicture(const SkISize& size, const SkPicture* picture,
125 const SkMatrix* matrix, const SkPaint* paint) {
126 return SkPictureImageGenerator::Create(size, picture, matrix, paint);
127}
reed8f343722015-08-13 13:32:39 -0700128
129///////////////////////////////////////////////////////////////////////////////////////////////////
130
131#if SK_SUPPORT_GPU
132#include "GrTexture.h"
133
bsalomon5f5527f2015-10-15 12:14:55 -0700134GrTexture* SkPictureImageGenerator::onGenerateTexture(GrContext* ctx, const SkIRect* subset) {
reed935d6cf2015-08-18 11:16:09 -0700135 const SkImageInfo& info = this->getInfo();
136 SkImageInfo surfaceInfo = subset ? info.makeWH(subset->width(), subset->height()) : info;
137
reed8f343722015-08-13 13:32:39 -0700138 //
139 // TODO: respect the usage, by possibly creating a different (pow2) surface
140 //
141 SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(ctx,
142 SkSurface::kYes_Budgeted,
reed935d6cf2015-08-18 11:16:09 -0700143 surfaceInfo));
reed8f343722015-08-13 13:32:39 -0700144 if (!surface.get()) {
145 return nullptr;
146 }
reed935d6cf2015-08-18 11:16:09 -0700147
148 SkMatrix matrix = fMatrix;
149 if (subset) {
150 matrix.postTranslate(-subset->x(), -subset->y());
151 }
reed8f343722015-08-13 13:32:39 -0700152 surface->getCanvas()->clear(0); // does NewRenderTarget promise to do this for us?
reed935d6cf2015-08-18 11:16:09 -0700153 surface->getCanvas()->drawPicture(fPicture, &matrix, fPaint.getMaybeNull());
reed8f343722015-08-13 13:32:39 -0700154 SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
155 if (!image.get()) {
156 return nullptr;
157 }
158 return SkSafeRef(image->getTexture());
159}
160#endif