| /* |
| * Copyright 2015 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "SkImageGenerator.h" |
| #include "SkCanvas.h" |
| #include "SkMatrix.h" |
| #include "SkPaint.h" |
| #include "SkPicture.h" |
| #include "SkSurface.h" |
| #include "SkTLazy.h" |
| |
| class SkPictureImageGenerator : SkImageGenerator { |
| public: |
| static SkImageGenerator* Create(const SkISize&, const SkPicture*, const SkMatrix*, |
| const SkPaint*); |
| |
| protected: |
| bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[], |
| int* ctableCount) override; |
| bool onComputeScaledDimensions(SkScalar scale, SupportedSizes*) override; |
| bool onGenerateScaledPixels(const SkISize&, const SkIPoint&, const SkPixmap&) override; |
| |
| #if SK_SUPPORT_GPU |
| GrTexture* onGenerateTexture(GrContext*, const SkIRect*) override; |
| #endif |
| |
| private: |
| SkPictureImageGenerator(const SkISize&, const SkPicture*, const SkMatrix*, const SkPaint*); |
| |
| SkAutoTUnref<const SkPicture> fPicture; |
| SkMatrix fMatrix; |
| SkTLazy<SkPaint> fPaint; |
| |
| typedef SkImageGenerator INHERITED; |
| }; |
| |
| SkImageGenerator* SkPictureImageGenerator::Create(const SkISize& size, const SkPicture* picture, |
| const SkMatrix* matrix, const SkPaint* paint) { |
| if (!picture || size.isEmpty()) { |
| return nullptr; |
| } |
| |
| return new SkPictureImageGenerator(size, picture, matrix, paint); |
| } |
| |
| SkPictureImageGenerator::SkPictureImageGenerator(const SkISize& size, const SkPicture* picture, |
| const SkMatrix* matrix, const SkPaint* paint) |
| : INHERITED(SkImageInfo::MakeN32Premul(size)) |
| , fPicture(SkRef(picture)) { |
| |
| if (matrix) { |
| fMatrix = *matrix; |
| } else { |
| fMatrix.reset(); |
| } |
| |
| if (paint) { |
| fPaint.set(*paint); |
| } |
| } |
| |
| bool SkPictureImageGenerator::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, |
| SkPMColor ctable[], int* ctableCount) { |
| if (info != getInfo() || ctable || ctableCount) { |
| return false; |
| } |
| |
| SkBitmap bitmap; |
| if (!bitmap.installPixels(info, pixels, rowBytes)) { |
| return false; |
| } |
| |
| bitmap.eraseColor(SK_ColorTRANSPARENT); |
| SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry)); |
| canvas.drawPicture(fPicture, &fMatrix, fPaint.getMaybeNull()); |
| |
| return true; |
| } |
| |
| bool SkPictureImageGenerator::onComputeScaledDimensions(SkScalar scale, |
| SupportedSizes* sizes) { |
| SkASSERT(scale > 0 && scale <= 1); |
| const int w = this->getInfo().width(); |
| const int h = this->getInfo().height(); |
| const int sw = SkScalarRoundToInt(scale * w); |
| const int sh = SkScalarRoundToInt(scale * h); |
| if (sw > 0 && sh > 0) { |
| sizes->fSizes[0].set(sw, sh); |
| sizes->fSizes[1].set(sw, sh); |
| return true; |
| } |
| return false; |
| } |
| |
| bool SkPictureImageGenerator::onGenerateScaledPixels(const SkISize& scaledSize, |
| const SkIPoint& scaledOrigin, |
| const SkPixmap& scaledPixels) { |
| int w = scaledSize.width(); |
| int h = scaledSize.height(); |
| |
| const SkScalar scaleX = SkIntToScalar(w) / this->getInfo().width(); |
| const SkScalar scaleY = SkIntToScalar(h) / this->getInfo().height(); |
| SkMatrix matrix = SkMatrix::MakeScale(scaleX, scaleY); |
| matrix.postTranslate(-SkIntToScalar(scaledOrigin.x()), -SkIntToScalar(scaledOrigin.y())); |
| |
| SkBitmap bitmap; |
| if (!bitmap.installPixels(scaledPixels)) { |
| return false; |
| } |
| |
| bitmap.eraseColor(SK_ColorTRANSPARENT); |
| SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry)); |
| matrix.preConcat(fMatrix); |
| canvas.drawPicture(fPicture, &matrix, fPaint.getMaybeNull()); |
| return true; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| SkImageGenerator* SkImageGenerator::NewFromPicture(const SkISize& size, const SkPicture* picture, |
| const SkMatrix* matrix, const SkPaint* paint) { |
| return SkPictureImageGenerator::Create(size, picture, matrix, paint); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| #if SK_SUPPORT_GPU |
| #include "GrTexture.h" |
| |
| GrTexture* SkPictureImageGenerator::onGenerateTexture(GrContext* ctx, const SkIRect* subset) { |
| const SkImageInfo& info = this->getInfo(); |
| SkImageInfo surfaceInfo = subset ? info.makeWH(subset->width(), subset->height()) : info; |
| |
| // |
| // TODO: respect the usage, by possibly creating a different (pow2) surface |
| // |
| SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(ctx, |
| SkSurface::kYes_Budgeted, |
| surfaceInfo)); |
| if (!surface.get()) { |
| return nullptr; |
| } |
| |
| SkMatrix matrix = fMatrix; |
| if (subset) { |
| matrix.postTranslate(-subset->x(), -subset->y()); |
| } |
| surface->getCanvas()->clear(0); // does NewRenderTarget promise to do this for us? |
| surface->getCanvas()->drawPicture(fPicture, &matrix, fPaint.getMaybeNull()); |
| SkAutoTUnref<SkImage> image(surface->newImageSnapshot()); |
| if (!image.get()) { |
| return nullptr; |
| } |
| return SkSafeRef(image->getTexture()); |
| } |
| #endif |