Home | History | Annotate | Download | only in core
      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