• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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"
9 #include "SkCanvas.h"
10 #include "SkMatrix.h"
11 #include "SkPaint.h"
12 #include "SkPicture.h"
13 #include "SkSurface.h"
14 #include "SkTLazy.h"
15 
16 class SkPictureImageGenerator : SkImageGenerator {
17 public:
18     static SkImageGenerator* Create(const SkISize&, const SkPicture*, const SkMatrix*,
19                                     const SkPaint*);
20 
21 protected:
22     bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[],
23                      int* ctableCount) override;
24     bool onComputeScaledDimensions(SkScalar scale, SupportedSizes*) override;
25     bool onGenerateScaledPixels(const SkISize&, const SkIPoint&, const SkPixmap&) override;
26 
27 #if SK_SUPPORT_GPU
28     GrTexture* onGenerateTexture(GrContext*, const SkIRect*) override;
29 #endif
30 
31 private:
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 
Create(const SkISize & size,const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)41 SkImageGenerator* 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 
47     return new SkPictureImageGenerator(size, picture, matrix, paint);
48 }
49 
SkPictureImageGenerator(const SkISize & size,const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)50 SkPictureImageGenerator::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 
onGetPixels(const SkImageInfo & info,void * pixels,size_t rowBytes,SkPMColor ctable[],int * ctableCount)66 bool 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 
onComputeScaledDimensions(SkScalar scale,SupportedSizes * sizes)84 bool 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 
onGenerateScaledPixels(const SkISize & scaledSize,const SkIPoint & scaledOrigin,const SkPixmap & scaledPixels)99 bool 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;
111     if (!bitmap.installPixels(scaledPixels)) {
112         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 
NewFromPicture(const SkISize & size,const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)124 SkImageGenerator* SkImageGenerator::NewFromPicture(const SkISize& size, const SkPicture* picture,
125                                                    const SkMatrix* matrix, const SkPaint* paint) {
126     return SkPictureImageGenerator::Create(size, picture, matrix, paint);
127 }
128 
129 ///////////////////////////////////////////////////////////////////////////////////////////////////
130 
131 #if SK_SUPPORT_GPU
132 #include "GrTexture.h"
133 
onGenerateTexture(GrContext * ctx,const SkIRect * subset)134 GrTexture* SkPictureImageGenerator::onGenerateTexture(GrContext* ctx, const SkIRect* subset) {
135     const SkImageInfo& info = this->getInfo();
136     SkImageInfo surfaceInfo = subset ? info.makeWH(subset->width(), subset->height()) : info;
137 
138     //
139     // TODO: respect the usage, by possibly creating a different (pow2) surface
140     //
141     SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(ctx, SkBudgeted::kYes,
142                                                                surfaceInfo));
143     if (!surface.get()) {
144         return nullptr;
145     }
146 
147     SkMatrix matrix = fMatrix;
148     if (subset) {
149         matrix.postTranslate(-subset->x(), -subset->y());
150     }
151     surface->getCanvas()->clear(0); // does NewRenderTarget promise to do this for us?
152     surface->getCanvas()->drawPicture(fPicture, &matrix, fPaint.getMaybeNull());
153     SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
154     if (!image.get()) {
155         return nullptr;
156     }
157     return SkSafeRef(image->getTexture());
158 }
159 #endif
160