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