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     SkImageInfo canvasInfo = useXformCanvas ? info.makeColorSpace(nullptr) : info;
     67     std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(canvasInfo, pixels, rowBytes);
     68     if (!canvas) {
     69         return false;
     70     }
     71     canvas->clear(0);
     72 
     73     SkCanvas* canvasPtr = canvas.get();
     74     std::unique_ptr<SkCanvas> xformCanvas;
     75     if (useXformCanvas) {
     76         xformCanvas = SkCreateColorSpaceXformCanvas(canvas.get(), info.refColorSpace());
     77         canvasPtr = xformCanvas.get();
     78     }
     79 
     80     canvasPtr->drawPicture(fPicture, &fMatrix, fPaint.getMaybeNull());
     81     return true;
     82 }
     83 
     84 ///////////////////////////////////////////////////////////////////////////////////////////////////
     85 
     86 std::unique_ptr<SkImageGenerator>
     87 SkImageGenerator::MakeFromPicture(const SkISize& size, sk_sp<SkPicture> picture,
     88                                   const SkMatrix* matrix, const SkPaint* paint,
     89                                   SkImage::BitDepth bitDepth, sk_sp<SkColorSpace> colorSpace) {
     90     // Check this here (rather than in SkPictureImageGenerator::Create) so SkPictureShader
     91     // has a private entry point to create legacy picture backed images.
     92     if (!colorSpace) {
     93         return nullptr;
     94     }
     95 
     96     return SkPictureImageGenerator::Make(size, std::move(picture), matrix, paint, bitDepth,
     97                                          std::move(colorSpace));
     98 }
     99 
    100 ///////////////////////////////////////////////////////////////////////////////////////////////////
    101 
    102 #if SK_SUPPORT_GPU
    103 sk_sp<GrTextureProxy> SkPictureImageGenerator::onGenerateTexture(
    104         GrContext* ctx, const SkImageInfo& info, const SkIPoint& origin,
    105         SkTransferFunctionBehavior behavior) {
    106     SkASSERT(ctx);
    107     bool useXformCanvas = SkTransferFunctionBehavior::kIgnore == behavior && info.colorSpace();
    108 
    109     //
    110     // TODO: respect the usage, by possibly creating a different (pow2) surface
    111     //
    112     SkImageInfo surfaceInfo = useXformCanvas ? info.makeColorSpace(nullptr) : info;
    113     sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kYes, surfaceInfo));
    114     if (!surface) {
    115         return nullptr;
    116     }
    117 
    118     SkCanvas* canvas = surface->getCanvas();
    119     std::unique_ptr<SkCanvas> xformCanvas;
    120     if (useXformCanvas) {
    121         xformCanvas = SkCreateColorSpaceXformCanvas(canvas, info.refColorSpace());
    122         canvas = xformCanvas.get();
    123     }
    124 
    125     SkMatrix matrix = fMatrix;
    126     matrix.postTranslate(-origin.x(), -origin.y());
    127     canvas->clear(0);  // does NewRenderTarget promise to do this for us?
    128     canvas->drawPicture(fPicture.get(), &matrix, fPaint.getMaybeNull());
    129     sk_sp<SkImage> image(surface->makeImageSnapshot());
    130     if (!image) {
    131         return nullptr;
    132     }
    133     return as_IB(image)->asTextureProxyRef();
    134 }
    135 #endif
    136