fmalita | 1dedc3d | 2015-08-04 13:53:14 -0700 | [diff] [blame] | 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" |
fmalita | 1dedc3d | 2015-08-04 13:53:14 -0700 | [diff] [blame] | 9 | #include "SkCanvas.h" |
| 10 | #include "SkMatrix.h" |
| 11 | #include "SkPaint.h" |
| 12 | #include "SkPicture.h" |
reed | 8f34372 | 2015-08-13 13:32:39 -0700 | [diff] [blame] | 13 | #include "SkSurface.h" |
bungeman | d3ebb48 | 2015-08-05 13:57:49 -0700 | [diff] [blame] | 14 | #include "SkTLazy.h" |
fmalita | 1dedc3d | 2015-08-04 13:53:14 -0700 | [diff] [blame] | 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; |
reed | 7850eb2 | 2015-12-02 14:19:47 -0800 | [diff] [blame] | 24 | bool onComputeScaledDimensions(SkScalar scale, SupportedSizes*) override; |
| 25 | bool onGenerateScaledPixels(const SkISize&, const SkIPoint&, const SkPixmap&) override; |
| 26 | |
reed | 8f34372 | 2015-08-13 13:32:39 -0700 | [diff] [blame] | 27 | #if SK_SUPPORT_GPU |
bsalomon | 5f5527f | 2015-10-15 12:14:55 -0700 | [diff] [blame] | 28 | GrTexture* onGenerateTexture(GrContext*, const SkIRect*) override; |
reed | 8f34372 | 2015-08-13 13:32:39 -0700 | [diff] [blame] | 29 | #endif |
fmalita | 1dedc3d | 2015-08-04 13:53:14 -0700 | [diff] [blame] | 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 | |
| 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 | |
halcanary | 385fe4d | 2015-08-26 13:07:48 -0700 | [diff] [blame] | 47 | return new SkPictureImageGenerator(size, picture, matrix, paint); |
fmalita | 1dedc3d | 2015-08-04 13:53:14 -0700 | [diff] [blame] | 48 | } |
| 49 | |
| 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 | |
| 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 | |
reed | 7850eb2 | 2015-12-02 14:19:47 -0800 | [diff] [blame] | 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 | |
| 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; |
halcanary | e36ec87 | 2015-12-09 11:36:59 -0800 | [diff] [blame] | 111 | if (!bitmap.installPixels(scaledPixels)) { |
reed | 7850eb2 | 2015-12-02 14:19:47 -0800 | [diff] [blame] | 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 | |
fmalita | 1dedc3d | 2015-08-04 13:53:14 -0700 | [diff] [blame] | 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 | } |
reed | 8f34372 | 2015-08-13 13:32:39 -0700 | [diff] [blame] | 128 | |
| 129 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
| 130 | |
| 131 | #if SK_SUPPORT_GPU |
| 132 | #include "GrTexture.h" |
| 133 | |
bsalomon | 5f5527f | 2015-10-15 12:14:55 -0700 | [diff] [blame] | 134 | GrTexture* SkPictureImageGenerator::onGenerateTexture(GrContext* ctx, const SkIRect* subset) { |
reed | 935d6cf | 2015-08-18 11:16:09 -0700 | [diff] [blame] | 135 | const SkImageInfo& info = this->getInfo(); |
| 136 | SkImageInfo surfaceInfo = subset ? info.makeWH(subset->width(), subset->height()) : info; |
| 137 | |
reed | 8f34372 | 2015-08-13 13:32:39 -0700 | [diff] [blame] | 138 | // |
| 139 | // TODO: respect the usage, by possibly creating a different (pow2) surface |
| 140 | // |
| 141 | SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(ctx, |
| 142 | SkSurface::kYes_Budgeted, |
reed | 935d6cf | 2015-08-18 11:16:09 -0700 | [diff] [blame] | 143 | surfaceInfo)); |
reed | 8f34372 | 2015-08-13 13:32:39 -0700 | [diff] [blame] | 144 | if (!surface.get()) { |
| 145 | return nullptr; |
| 146 | } |
reed | 935d6cf | 2015-08-18 11:16:09 -0700 | [diff] [blame] | 147 | |
| 148 | SkMatrix matrix = fMatrix; |
| 149 | if (subset) { |
| 150 | matrix.postTranslate(-subset->x(), -subset->y()); |
| 151 | } |
reed | 8f34372 | 2015-08-13 13:32:39 -0700 | [diff] [blame] | 152 | surface->getCanvas()->clear(0); // does NewRenderTarget promise to do this for us? |
reed | 935d6cf | 2015-08-18 11:16:09 -0700 | [diff] [blame] | 153 | surface->getCanvas()->drawPicture(fPicture, &matrix, fPaint.getMaybeNull()); |
reed | 8f34372 | 2015-08-13 13:32:39 -0700 | [diff] [blame] | 154 | SkAutoTUnref<SkImage> image(surface->newImageSnapshot()); |
| 155 | if (!image.get()) { |
| 156 | return nullptr; |
| 157 | } |
| 158 | return SkSafeRef(image->getTexture()); |
| 159 | } |
| 160 | #endif |