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 "SkImage_Base.h"
9 #include "SkCanvas.h"
10 #include "SkMakeUnique.h"
11 #include "SkMatrix.h"
12 #include "SkPaint.h"
13 #include "SkPicture.h"
14 #include "SkPictureImageGenerator.h"
15 #include "SkSurface.h"
16
17 std::unique_ptr<SkImageGenerator>
Make(const SkISize & size,sk_sp<SkPicture> picture,const SkMatrix * matrix,const SkPaint * paint,SkImage::BitDepth bitDepth,sk_sp<SkColorSpace> colorSpace)18 SkPictureImageGenerator::Make(const SkISize& size, sk_sp<SkPicture> picture, const SkMatrix* matrix,
19 const SkPaint* paint, SkImage::BitDepth bitDepth,
20 sk_sp<SkColorSpace> colorSpace) {
21 if (!picture || size.isEmpty()) {
22 return nullptr;
23 }
24
25 if (SkImage::BitDepth::kF16 == bitDepth && (!colorSpace || !colorSpace->gammaIsLinear())) {
26 return nullptr;
27 }
28
29 if (colorSpace && (!colorSpace->gammaCloseToSRGB() && !colorSpace->gammaIsLinear())) {
30 return nullptr;
31 }
32
33 SkColorType colorType = kN32_SkColorType;
34 if (SkImage::BitDepth::kF16 == bitDepth) {
35 colorType = kRGBA_F16_SkColorType;
36 }
37
38 SkImageInfo info = SkImageInfo::Make(size.width(), size.height(), colorType,
39 kPremul_SkAlphaType, std::move(colorSpace));
40 return std::unique_ptr<SkImageGenerator>(
41 new SkPictureImageGenerator(info, std::move(picture), matrix, paint));
42 }
43
SkPictureImageGenerator(const SkImageInfo & info,sk_sp<SkPicture> picture,const SkMatrix * matrix,const SkPaint * paint)44 SkPictureImageGenerator::SkPictureImageGenerator(const SkImageInfo& info, sk_sp<SkPicture> picture,
45 const SkMatrix* matrix, const SkPaint* paint)
46 : INHERITED(info)
47 , fPicture(std::move(picture)) {
48
49 if (matrix) {
50 fMatrix = *matrix;
51 } else {
52 fMatrix.reset();
53 }
54
55 if (paint) {
56 fPaint.set(*paint);
57 }
58 }
59
onGetPixels(const SkImageInfo & info,void * pixels,size_t rowBytes,SkPMColor ctable[],int * ctableCount)60 bool SkPictureImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
61 SkPMColor ctable[], int* ctableCount) {
62 if (ctable || ctableCount) {
63 return false;
64 }
65
66 SkBitmap bitmap;
67 if (!bitmap.installPixels(info, pixels, rowBytes)) {
68 return false;
69 }
70
71 bitmap.eraseColor(SK_ColorTRANSPARENT);
72 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
73 canvas.drawPicture(fPicture.get(), &fMatrix, fPaint.getMaybeNull());
74
75 return true;
76 }
77
78 ///////////////////////////////////////////////////////////////////////////////////////////////////
79
80 std::unique_ptr<SkImageGenerator>
MakeFromPicture(const SkISize & size,sk_sp<SkPicture> picture,const SkMatrix * matrix,const SkPaint * paint,SkImage::BitDepth bitDepth,sk_sp<SkColorSpace> colorSpace)81 SkImageGenerator::MakeFromPicture(const SkISize& size, sk_sp<SkPicture> picture,
82 const SkMatrix* matrix, const SkPaint* paint,
83 SkImage::BitDepth bitDepth, sk_sp<SkColorSpace> colorSpace) {
84 // Check this here (rather than in SkPictureImageGenerator::Create) so SkPictureShader
85 // has a private entry point to create legacy picture backed images.
86 if (!colorSpace) {
87 return nullptr;
88 }
89
90 return SkPictureImageGenerator::Make(size, std::move(picture), matrix, paint, bitDepth,
91 std::move(colorSpace));
92 }
93
94 ///////////////////////////////////////////////////////////////////////////////////////////////////
95
96 #if SK_SUPPORT_GPU
onGenerateTexture(GrContext * ctx,const SkImageInfo & info,const SkIPoint & origin)97 sk_sp<GrTextureProxy> SkPictureImageGenerator::onGenerateTexture(GrContext* ctx,
98 const SkImageInfo& info,
99 const SkIPoint& origin) {
100 SkASSERT(ctx);
101
102 //
103 // TODO: respect the usage, by possibly creating a different (pow2) surface
104 //
105 sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kYes, info));
106 if (!surface) {
107 return nullptr;
108 }
109
110 SkMatrix matrix = fMatrix;
111 matrix.postTranslate(-origin.x(), -origin.y());
112 surface->getCanvas()->clear(0); // does NewRenderTarget promise to do this for us?
113 surface->getCanvas()->drawPicture(fPicture.get(), &matrix, fPaint.getMaybeNull());
114 sk_sp<SkImage> image(surface->makeImageSnapshot());
115 if (!image) {
116 return nullptr;
117 }
118 return as_IB(image)->asTextureProxyRef();
119 }
120 #endif
121