+++ /dev/null
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "gm.h"
-#include "SkCanvas.h"
-#include "SkCodec.h"
-#include "SkCodecImageGenerator.h"
-#include "SkColor.h"
-#include "SkCommandLineFlags.h"
-#include "SkImageGenerator.h"
-#include "SkString.h"
-#include "Resources.h"
-
-DEFINE_string(codec_scaled, "brickwork-texture.jpg", "Image in resources/ to draw scaled.");
-
-class CodecScaledGM : public skiagm::GM {
-private:
- // FIXME: Once generateScaledPixels is plumbed to SkImage, store an SkImage
- // and call SkImage::scalePixels.
- std::unique_ptr<SkImageGenerator> fGenerator;
-
-public:
- CodecScaledGM()
- {}
-
-private:
- SkString onShortName() override {
- return SkString("codec_scaled");
- }
-
- SkISize onISize() override {
- if (this->initCodec()) {
- SkISize dim = fGenerator->getInfo().dimensions();
- // Wide enough to show 8 versions, corresponding to the options JPEG supports.
- dim.fWidth *= 8;
- // Tall enough to display 2 versions - one using computed dimensions, and one
- // with scaling.
- dim.fHeight *= 2;
- return dim;
- }
- return SkISize::Make(640, 480);
- }
-
- void onDrawBackground(SkCanvas* canvas) override {
- canvas->clear(SK_ColorWHITE);
- }
-
- bool initCodec() {
- if (fGenerator) {
- return true;
- }
-
- if (FLAGS_codec_scaled.isEmpty()) {
- SkDebugf("Nothing specified for --codec_scaled!");
- return false;
- }
-
- SkString path = GetResourcePath(FLAGS_codec_scaled[0]);
- sk_sp<SkData> data(SkData::MakeFromFileName(path.c_str()));
- if (!data) {
- return false;
- }
-
- fGenerator.reset(SkCodecImageGenerator::NewFromEncodedCodec(data));
- if (!fGenerator) {
- SkDebugf("Could create codec from %s", FLAGS_codec_scaled[0]);
- return false;
- }
-
- return true;
- }
-
- void onDraw(SkCanvas* canvas) override {
- if (!this->initCodec()) {
- return;
- }
-
- SkAutoCanvasRestore acr(canvas, true);
- for (float scale : { 1.0f, .875f, .750f, .625f, .5f, .375f, .25f, .125f }) {
- // generateScaledPixels does not support index8
- const auto info = fGenerator->getInfo().makeColorType(kN32_SkColorType);
- auto scaledInfo = info;
- SkImageGenerator::SupportedSizes sizes;
- if (fGenerator->computeScaledDimensions(scale, &sizes)) {
- scaledInfo = info.makeWH(sizes.fSizes[0].fWidth, sizes.fSizes[0].fHeight);
- }
-
- SkBitmap bm;
- bm.allocPixels(scaledInfo);
- SkPixmap pixmap(scaledInfo, bm.getPixels(), bm.rowBytes());
- if (fGenerator->generateScaledPixels(pixmap)) {
- canvas->drawBitmap(bm, 0, 0);
- }
-
- bm.allocPixels(info);
- if (fGenerator->getPixels(info, bm.getPixels(), bm.rowBytes())) {
- SkAutoCanvasRestore acr2(canvas, true);
- canvas->translate(0, SkIntToScalar(info.height()));
- canvas->scale(SkFloatToScalar(scale), SkFloatToScalar(scale));
- canvas->drawBitmap(bm, 0, 0);
- }
-
- canvas->translate(SkIntToScalar(info.width()), 0);
- }
- }
-};
-
-DEF_GM(return new CodecScaledGM);
///////////////////////////////////////////////////////////////////////////////////////////////////
-#include "SkImageGenerator.h"
-
-static SkImageInfo make_info(SkImage* img) {
- return SkImageInfo::MakeN32(img->width(), img->height(), img->alphaType());
-}
-
-// Its simple, but I wonder if we should expose this formally?
-//
-class ImageGeneratorFromImage : public SkImageGenerator {
-public:
- ImageGeneratorFromImage(SkImage* img) : INHERITED(make_info(img)), fImg(SkRef(img)) {}
-
-protected:
- bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, SkPMColor ctable[],
- int* ctableCount) override {
- return fImg->readPixels(info, pixels, rowBytes, 0, 0);
- }
-
-private:
- sk_sp<SkImage> fImg;
-
- typedef SkImageGenerator INHERITED;
-};
-
-static void draw_opaque_contents(SkCanvas* canvas) {
- canvas->drawColor(0xFFFF8844);
-
- SkPaint paint;
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setStrokeWidth(20);
- canvas->drawCircle(50, 50, 35, paint);
-}
-
-static SkImageGenerator* gen_raster(const SkImageInfo& info) {
- auto surface(SkSurface::MakeRaster(info));
- draw_opaque_contents(surface->getCanvas());
- return new ImageGeneratorFromImage(surface->makeImageSnapshot().get());
-}
-
-static SkImageGenerator* gen_picture(const SkImageInfo& info) {
- SkPictureRecorder recorder;
- draw_opaque_contents(recorder.beginRecording(SkRect::MakeIWH(info.width(), info.height())));
- sk_sp<SkPicture> pict(recorder.finishRecordingAsPicture());
- return SkImageGenerator::NewFromPicture(info.dimensions(), pict.get(), nullptr, nullptr,
- SkImage::BitDepth::kU8,
- SkColorSpace::MakeSRGB());
-}
-
-static SkImageGenerator* gen_png(const SkImageInfo& info) {
- sk_sp<SkImage> image(make_raster(info, nullptr, draw_opaque_contents));
- sk_sp<SkData> data(image->encode(SkEncodedImageFormat::kPNG, 100));
- return SkImageGenerator::NewFromEncoded(data.get());
-}
-
-static SkImageGenerator* gen_jpg(const SkImageInfo& info) {
- sk_sp<SkImage> image(make_raster(info, nullptr, draw_opaque_contents));
- sk_sp<SkData> data(image->encode(SkEncodedImageFormat::kJPEG, 100));
- return SkImageGenerator::NewFromEncoded(data.get());
-}
-
-typedef SkImageGenerator* (*GeneratorMakerProc)(const SkImageInfo&);
-
-static void show_scaled_generator(SkCanvas* canvas, SkImageGenerator* gen) {
- const SkImageInfo genInfo = gen->getInfo();
-
- SkAutoCanvasRestore acr(canvas, true);
-
- SkBitmap bm;
- bm.allocPixels(genInfo);
- if (gen->getPixels(bm.info(), bm.getPixels(), bm.rowBytes())) {
- canvas->drawBitmap(bm, 0, 0, nullptr);
- }
- canvas->translate(110, 0);
-
- const float scales[] = { 0.75f, 0.5f, 0.25f };
- for (auto scale : scales) {
- SkImageGenerator::SupportedSizes sizes;
- if (gen->computeScaledDimensions(scale, &sizes)) {
- const SkImageInfo info = SkImageInfo::MakeN32Premul(sizes.fSizes[0].width(),
- sizes.fSizes[0].height());
- bm.allocPixels(info);
- SkPixmap pmap;
- bm.peekPixels(&pmap);
- if (gen->generateScaledPixels(pmap)) {
- canvas->drawBitmap(bm, 0, SkIntToScalar(genInfo.height() - info.height())/2);
- }
- }
- canvas->translate(100, 0);
- }
-}
-
-class ScaleGeneratorGM : public skiagm::GM {
-public:
- ScaleGeneratorGM() {}
-
-protected:
- SkString onShortName() override {
- return SkString("scale-generator");
- }
-
- SkISize onISize() override {
- return SkISize::Make(500, 500);
- }
-
- void onDraw(SkCanvas* canvas) override {
- canvas->translate(10, 10);
-
- // explicitly make it opaque, so we can test JPEG (which is only ever opaque)
- const SkImageInfo info = SkImageInfo::MakeN32(100, 100, kOpaque_SkAlphaType);
-
- const GeneratorMakerProc procs[] = {
- gen_raster, gen_picture, gen_png, gen_jpg,
- };
- for (auto& proc : procs) {
- std::unique_ptr<SkImageGenerator> gen(proc(info));
- if (gen) {
- show_scaled_generator(canvas, gen.get());
- }
- canvas->translate(0, 120);
- }
- }
-
-private:
- typedef skiagm::GM INHERITED;
-};
-DEF_GM( return new ScaleGeneratorGM; )
-
DEF_SIMPLE_GM(new_texture_image, canvas, 280, 60) {
GrContext* context = canvas->getGrContext();
if (!context) {
+++ /dev/null
-/*
- * 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 "gm.h"
-#include "SkImage.h"
-#include "SkImageGenerator.h"
-#include "SkMutex.h"
-#include "SkSurface.h"
-#include "SkTArray.h"
-
-namespace {
-
-void release_proc(void*, void* releaseCtx) {
- reinterpret_cast<SkImage*>(releaseCtx)->unref();
-}
-
-class ExternalGenerator : public SkImageGenerator {
-public:
- ExternalGenerator(const SkISize size)
- : INHERITED(SkImageInfo::MakeN32Premul(size.width(), size.height())) {
-
- int level = 0;
- for (int size = kMaxSize; size; size /= 2) {
- sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(size, size);
- DrawRings(surface->getCanvas(), 0xff008000, level++);
- fMips.emplace_back(surface->makeImageSnapshot());
- }
- }
-
- virtual ~ExternalGenerator() {}
-
-protected:
- bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
- SkPMColor[], int*) override {
- sk_sp<SkSurface> s = SkSurface::MakeRasterDirect(info, pixels, rowBytes);
- s->getCanvas()->clear(SK_ColorTRANSPARENT);
- DrawRings(s->getCanvas(), SK_ColorRED);
- return true;
- }
-
- bool onAccessScaledImage(const SkRect& src, const SkMatrix& matrix, SkFilterQuality,
- ScaledImageRec* rec) override {
- // Not strictly needed for this immutable class.
- SkAutoExclusive lock(fMutex);
-
- SkSize scaleSize;
- if (!matrix.decomposeScale(&scaleSize, nullptr)) {
- return false;
- }
- scaleSize.set(scaleSize.width() * this->getInfo().width() / kMaxSize,
- scaleSize.height() * this->getInfo().height() / kMaxSize);
-
- const SkScalar scale = SkTMin(scaleSize.width(), scaleSize.height());
- const int lvl = SkScalarFloorToInt(-SkScalarLog2(scale));
-
- const sk_sp<SkImage>& img = fMips[SkTPin(lvl, 0, fMips.count())];
- SkAssertResult(img->peekPixels(&rec->fPixmap));
-
- const SkRect origBounds = SkRect::Make(this->getInfo().bounds());
- const SkRect newBounds = SkRect::Make(img->bounds());
-
- SkMatrix srcMap = SkMatrix::MakeScale(newBounds.width() / origBounds.width(),
- newBounds.height() / origBounds.height());
- srcMap.preTranslate(src.x(), src.y());
- srcMap.mapRect(&rec->fSrcRect, SkRect::MakeWH(src.width(), src.height()));
-
- rec->fQuality = kLow_SkFilterQuality;
-
- rec->fReleaseProc = release_proc;
- rec->fReleaseCtx = SkRef(img.get());
-
- return true;
- }
-
-private:
- static void DrawRings(SkCanvas* c, SkColor color, int lvl = 0) {
- static constexpr SkScalar kStep = 0.2f;
-
- SkRect rect = SkRect::MakeWH(1, 1);
-
- SkPaint p;
- p.setStyle(SkPaint::kStroke_Style);
- p.setStrokeWidth(0.02f);
- p.setAntiAlias(true);
- p.setColor(color);
-
- c->concat(SkMatrix::MakeRectToRect(SkRect::MakeWH(1, 1),
- SkRect::MakeIWH(c->imageInfo().width(),
- c->imageInfo().height()),
- SkMatrix::kFill_ScaleToFit));
- while (!rect.isEmpty()) {
- c->drawRect(rect, p);
- rect.inset(kStep, kStep);
- }
-
- static constexpr SkScalar kTxtSize = 0.2f;
- SkASSERT(lvl >= 0 && lvl <= 9);
- const char label = '0' + lvl;
- p.setTextSize(kTxtSize);
- p.setLinearText(true);
- p.setStyle(SkPaint::kFill_Style);
- SkRect labelBounds;
- p.measureText(&label, 1, &labelBounds);
-
- c->drawText(&label, 1, 0.5f - labelBounds.width() / 2, 0.5f + labelBounds.height() / 2, p);
- }
-
- SkMutex fMutex;
-
- static constexpr int kMaxSize = 512;
- SkTArray<sk_sp<SkImage>> fMips;
-
- typedef SkImageGenerator INHERITED;
-};
-
-} // anonymous ns
-
-class ImageGenExternalGM : public skiagm::GM {
-public:
- explicit ImageGenExternalGM(bool useShader) : fUseShader(useShader) {}
-
-protected:
- SkString onShortName() override {
- return SkStringPrintf("ImageGeneratorExternal%s", fUseShader ? "_shader" : "_rect");
- }
-
- SkISize onISize() override {
- return SkISize::Make(800, 800);
- }
-
- void onOnceBeforeDraw() override {
- fImage = SkImage::MakeFromGenerator(new ExternalGenerator(SkISize::Make(kGeneratorSize,
- kGeneratorSize)));
- }
-
- void onDraw(SkCanvas* canvas) override {
- static const SkRect gSubsets[] = {
- SkRect::MakeLTRB(0 , 0 , 1 , 1 ),
- SkRect::MakeLTRB(0 , 0 , 0.5f , 0.5f ),
- SkRect::MakeLTRB(0.5f , 0 , 1 , 0.5f ),
- SkRect::MakeLTRB(0.5f , 0.5f , 1 , 1 ),
- SkRect::MakeLTRB(0 , 0.5f , 0.5f , 1 ),
- SkRect::MakeLTRB(0.25f, 0.25f, 0.75f, 0.75f),
- };
-
- SkPaint p;
- p.setFilterQuality(kLow_SkFilterQuality);
-
- for (int i = 1; i <= 4; ++i) {
- const SkRect dst = SkRect::MakeIWH(kGeneratorSize / i, kGeneratorSize / i);
-
- canvas->save();
- for (size_t j = 0; j < SK_ARRAY_COUNT(gSubsets); ++j) {
- SkRect subset = gSubsets[j];
- subset.set(kGeneratorSize * subset.left(),
- kGeneratorSize * subset.top(),
- kGeneratorSize * subset.right(),
- kGeneratorSize * subset.bottom());
- this->drawSubset(canvas, subset, dst, p);
- canvas->translate(kGeneratorSize * 1.1f, 0);
- }
- canvas->restore();
- canvas->translate(0, dst.height() * 1.2f);
- }
- }
-
-private:
- void drawSubset(SkCanvas* canvas, const SkRect& src, const SkRect& dst,
- const SkPaint& paint) const {
- if (fUseShader) {
- SkPaint p(paint);
- SkMatrix localMatrix = SkMatrix::MakeRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
- p.setShader(fImage->makeShader(SkShader::kClamp_TileMode,
- SkShader::kClamp_TileMode,
- &localMatrix));
- canvas->drawRect(dst, p);
- } else {
- canvas->drawImageRect(fImage, src, dst, &paint);
- }
- }
-
- static constexpr int kGeneratorSize = 200;
- sk_sp<SkImage> fImage;
- bool fUseShader;
-
- typedef skiagm::GM INHERITED;
-};
-
-DEF_GM( return new ImageGenExternalGM(false); )
-DEF_GM( return new ImageGenExternalGM(true); )
"$_gm/bug615686.cpp",
"$_gm/cgm.c",
"$_gm/cgms.cpp",
- "$_gm/codec_scaled.cpp",
"$_gm/circles.cpp",
"$_gm/circulararcs.cpp",
"$_gm/circularclips.cpp",
"$_gm/imagefiltersstroked.cpp",
"$_gm/imagefilterstransformed.cpp",
"$_gm/imagefromyuvtextures.cpp",
- "$_gm/imagegeneratorexternal.cpp",
"$_gm/imagemagnifier.cpp",
"$_gm/imagemakewithfilter.cpp",
"$_gm/imagemasksubset.cpp",
*/
GrTexture* generateTexture(GrContext*, const SkImageInfo& info, const SkIPoint& origin);
- struct SupportedSizes {
- SkISize fSizes[2];
- };
-
- /**
- * Some generators can efficiently scale their contents. If this is supported, the generator
- * may only support certain scaled dimensions. Call this with the desired scale factor,
- * and it will return true if scaling is supported, and in supportedSizes[] it will return
- * the nearest supported dimensions.
- *
- * If no native scaling is supported, or scale is invalid (e.g. scale <= 0 || scale > 1)
- * this will return false, and the supportedsizes will be undefined.
- */
- bool computeScaledDimensions(SkScalar scale, SupportedSizes*);
-
- /**
- * Copy the pixels from this generator into the provided pixmap, respecting
- * all of the pixmap's attributes: dimensions, colortype, alphatype, colorspace.
- * returns true on success.
- *
- * Some generators can only scale to certain dimensions (e.g. powers-of-2 smaller).
- * Thus a generator may fail (return false) for some sizes but succeed for other sizes.
- * Call computeScaledDimensions() to know, for a given requested scale, what output size(s)
- * the generator might support.
- *
- * Note: this call does NOT allocate the memory for the pixmap; that must be done
- * by the caller.
- */
- bool generateScaledPixels(const SkPixmap& scaledPixels);
-
- /**
- * External generator API: provides efficient access to externally-managed image data.
- *
- * Skia calls accessScaledPixels() during rasterization, to gain temporary access to
- * the external pixel data. When done, the provided callback is invoked to release the
- * associated resources.
- *
- * @param srcRect the source rect in use for the current draw
- * @param totalMatrix full matrix in effect (mapping srcRect -> device space)
- * @param quality the SkFilterQuality requested for rasterization.
- * @param rec out param, expected to be set when the call succeeds:
- *
- * - fPixmap external pixel data
- * - fSrcRect is an adjusted srcRect
- * - fQuality is the adjusted filter quality
- * - fReleaseProc pixmap release callback, same signature as the
- * SkBitmap::installPixels() callback
- * - fReleaseCtx opaque release context argument
- *
- * @return true on success, false otherwise (error or if this API is not supported;
- * in this case Skia will fall back to its internal scaling and caching
- * heuristics)
- *
- * Implementors can return pixmaps with a different size than requested, by adjusting the
- * src rect. The contract is that Skia will observe the adjusted src rect, and will map it
- * to the same dest as the original draw (the impl doesn't get to control the destination).
- *
- */
-
- struct ScaledImageRec {
- SkPixmap fPixmap;
- SkRect fSrcRect;
- SkFilterQuality fQuality;
-
- using ReleaseProcT = void (*)(void* pixels, void* releaseCtx);
-
- ReleaseProcT fReleaseProc;
- void* fReleaseCtx;
- };
-
- bool accessScaledImage(const SkRect& srcRect, const SkMatrix& totalMatrix,
- SkFilterQuality quality, ScaledImageRec* rec);
-
/**
* If the default image decoder system can interpret the specified (encoded) data, then
* this returns a new ImageGenerator for it. Otherwise this returns NULL. Either way
return nullptr;
}
- virtual bool onComputeScaledDimensions(SkScalar, SupportedSizes*) {
- return false;
- }
- virtual bool onGenerateScaledPixels(const SkPixmap&) {
- return false;
- }
-
- virtual bool onAccessScaledImage(const SkRect&, const SkMatrix&, SkFilterQuality,
- ScaledImageRec*) {
- return false;
- }
-
private:
const SkImageInfo fInfo;
const uint32_t fUniqueID;
}
}
-bool SkCodecImageGenerator::onComputeScaledDimensions(SkScalar scale, SupportedSizes* sizes) {
- SkASSERT(scale > 0 && scale <= 1);
- const auto size = fCodec->getScaledDimensions(SkScalarToFloat(scale));
- if (size == this->getInfo().dimensions()) {
- return false;
- }
-
- // FIXME: Make SkCodec's API return two potential sizes, like this one. For now, set them both
- // to be the same.
- sizes->fSizes[0] = sizes->fSizes[1] = size;
- return true;
-}
-
-bool SkCodecImageGenerator::onGenerateScaledPixels(const SkPixmap& pixmap) {
- if (pixmap.colorType() == kIndex_8_SkColorType) {
- // There is no way to tell the client about the color table with this API.
- return false;
- }
-
- return this->onGetPixels(pixmap.info(), pixmap.writable_addr(), pixmap.rowBytes(),
- nullptr, nullptr);
-}
-
-
bool SkCodecImageGenerator::onQueryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const
{
return fCodec->queryYUV8(sizeInfo, colorSpace);
bool onGetYUV8Planes(const SkYUVSizeInfo&, void* planes[3]) override;
- bool onComputeScaledDimensions(SkScalar, SupportedSizes*) override;
-
- bool onGenerateScaledPixels(const SkPixmap&) override;
-
private:
/*
* Takes ownership of codec
sk_sp<const SkMipMap> fCurrMip;
bool fCanShadeHQ;
- bool processExternalRequest(const SkBitmapProvider&);
bool processHQRequest(const SkBitmapProvider&);
bool processMediumRequest(const SkBitmapProvider&);
};
return size < (maximumAllocation * SkScalarAbs(invScaleSqr));
}
-/*
- * Image generators can provide access to externally managed pixels
- * (external scale/decode caches).
- */
-bool SkDefaultBitmapControllerState::processExternalRequest(const SkBitmapProvider& provider) {
- // TODO: actual srcRect
-
- const SkRect src = SkRect::MakeIWH(provider.width(), provider.height());
- SkRect adjustedSrc;
-
- if (!provider.accessScaledImage(src, fInvMatrix, fQuality,
- &fResultBitmap, &adjustedSrc, &fQuality)) {
- return false;
- }
-
- fInvMatrix.postConcat(SkMatrix::MakeRectToRect(src, adjustedSrc, SkMatrix::kFill_ScaleToFit));
- fResultBitmap.lockPixels();
- SkASSERT(fResultBitmap.getPixels());
-
- return true;
-}
-
/*
* High quality is implemented by performing up-right scale-only filtering and then
* using bilerp for any remaining transformations.
fQuality = qual;
fCanShadeHQ = canShadeHQ;
- bool processed = this->processExternalRequest(provider);
-
- // Externally handled requests are not guaranteed to reduce quality below kMedium -- so we
- // always give our internal processors a shot.
- processed |= this->processHQRequest(provider) || this->processMediumRequest(provider);
+ bool processed = this->processHQRequest(provider) || this->processMediumRequest(provider);
if (processed) {
SkASSERT(fResultBitmap.getPixels());
bool SkBitmapProvider::asBitmap(SkBitmap* bm) const {
return as_IB(fImage)->getROPixels(bm, fDstColorSpace, SkImage::kAllow_CachingHint);
}
-
-bool SkBitmapProvider::accessScaledImage(const SkRect& srcRect,
- const SkMatrix& invMatrix,
- SkFilterQuality fq,
- SkBitmap* scaledBitmap,
- SkRect* adjustedSrcRect,
- SkFilterQuality* adjustedFilterQuality) const {
- if (!fImage) {
- return false;
- }
-
- SkImageCacherator* cacherator = as_IB(fImage)->peekCacherator();
- if (!cacherator) {
- return false;
- }
-
- // TODO: stash the matrix someplace to avoid invert()?
- SkMatrix m;
- if (!invMatrix.invert(&m)) {
- return false;
- }
-
- SkImageGenerator::ScaledImageRec rec;
- if (!cacherator->directAccessScaledImage(srcRect, m, fq, &rec) ||
- !scaledBitmap->installPixels(rec.fPixmap.info(), const_cast<void*>(rec.fPixmap.addr()),
- rec.fPixmap.rowBytes(), rec.fPixmap.ctable(),
- rec.fReleaseProc, rec.fReleaseCtx)) {
- return false;
- }
-
- *adjustedSrcRect = rec.fSrcRect;
- *adjustedFilterQuality = rec.fQuality;
-
- return true;
-}
// ... cause a decode and cache, or gpu-readback
bool asBitmap(SkBitmap*) const;
- bool accessScaledImage(const SkRect& srcRect, const SkMatrix& invMatrix, SkFilterQuality fq,
- SkBitmap* scaledBitmap, SkRect* adjustedSrcRect,
- SkFilterQuality* adjustedFilterQuality) const;
-
private:
// Stack-allocated only.
void* operator new(size_t) = delete;
}
}
-bool SkBaseDevice::drawExternallyScaledImage(const SkDraw& draw,
- const SkImage* image,
- const SkRect* src,
- const SkRect& dst,
- const SkPaint& paint,
- SkCanvas::SrcRectConstraint constraint) {
- SkImageCacherator* cacherator = as_IB(image)->peekCacherator();
- if (!cacherator) {
- return false;
- }
-
- SkTLazy<SkRect> tmpSrc(src);
- if (!tmpSrc.isValid()) {
- tmpSrc.init(SkRect::Make(image->bounds()));
- }
-
- SkMatrix m = *draw.fMatrix;
- m.preConcat(SkMatrix::MakeRectToRect(*tmpSrc.get(), dst, SkMatrix::kFill_ScaleToFit));
-
- // constrain src to our bounds
- if (!image->bounds().contains(*tmpSrc.get()) &&
- !tmpSrc.get()->intersect(SkRect::Make(image->bounds()))) {
- return false;
- }
-
- SkImageGenerator::ScaledImageRec rec;
- if (!cacherator->directAccessScaledImage(*tmpSrc.get(), m, paint.getFilterQuality(), &rec)) {
- return false;
- }
-
- SkBitmap bm;
- if (!bm.installPixels(rec.fPixmap.info(), const_cast<void*>(rec.fPixmap.addr()),
- rec.fPixmap.rowBytes(), rec.fPixmap.ctable(),
- rec.fReleaseProc, rec.fReleaseCtx)) {
- return false;
- }
-
- SkTCopyOnFirstWrite<SkPaint> adjustedPaint(paint);
- if (rec.fQuality != paint.getFilterQuality()) {
- adjustedPaint.writable()->setFilterQuality(rec.fQuality);
- }
-
- this->drawBitmapRect(draw, bm, &rec.fSrcRect, dst, *adjustedPaint, constraint);
-
- return true;
-}
void SkBaseDevice::drawImage(const SkDraw& draw, const SkImage* image, SkScalar x, SkScalar y,
const SkPaint& paint) {
- // Default impl : turns everything into raster bitmap
- if (this->drawExternallyScaledImage(draw, image, nullptr,
- SkRect::Make(image->bounds()).makeOffset(x, y),
- paint, SkCanvas::kFast_SrcRectConstraint)) {
- return;
- }
-
SkBitmap bm;
if (as_IB(image)->getROPixels(&bm, this->imageInfo().colorSpace())) {
this->drawBitmap(draw, bm, SkMatrix::MakeTrans(x, y), paint);
void SkBaseDevice::drawImageRect(const SkDraw& draw, const SkImage* image, const SkRect* src,
const SkRect& dst, const SkPaint& paint,
SkCanvas::SrcRectConstraint constraint) {
- // Default impl : turns everything into raster bitmap
- if (this->drawExternallyScaledImage(draw, image, src, dst, paint, constraint)) {
- return;
- }
-
SkBitmap bm;
if (as_IB(image)->getROPixels(&bm, this->imageInfo().colorSpace())) {
this->drawBitmapRect(draw, bm, src, dst, paint, constraint);
*const_cast<SkImageInfo*>(&fInfo) = fInfo.makeWH(w, h);
}
- bool drawExternallyScaledImage(const SkDraw& draw, const SkImage* image, const SkRect* src,
- const SkRect& dst, const SkPaint& paint,
- SkCanvas::SrcRectConstraint constraint);
-
SkIPoint fOrigin;
const SkImageInfo fInfo;
const SkSurfaceProps fSurfaceProps;
return generator->getPixels(info, pixels, rb);
}
-bool SkImageCacherator::directAccessScaledImage(const SkRect& srcRect,
- const SkMatrix& totalMatrix,
- SkFilterQuality fq,
- SkImageGenerator::ScaledImageRec* rec) {
- return ScopedGenerator(fSharedGenerator)->accessScaledImage(srcRect, totalMatrix, fq, rec);
-}
-
//////////////////////////////////////////////////////////////////////////////////////////////////
bool SkImageCacherator::lockAsBitmapOnlyIfAlreadyCached(SkBitmap* bitmap, CachedFormat format) {
bool directGeneratePixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
int srcX, int srcY);
- bool directAccessScaledImage(const SkRect& srcRect, const SkMatrix& totalMatrix,
- SkFilterQuality, SkImageGenerator::ScaledImageRec*);
-
private:
// Ref-counted tuple(SkImageGenerator, SkMutex) which allows sharing of one generator
// among several cacherators.
return this->onGenerateTexture(ctx, info, origin);
}
-bool SkImageGenerator::computeScaledDimensions(SkScalar scale, SupportedSizes* sizes) {
- if (scale > 0 && scale <= 1) {
- return this->onComputeScaledDimensions(scale, sizes);
- }
- return false;
-}
-
-bool SkImageGenerator::generateScaledPixels(const SkPixmap& scaledPixels) {
- if (scaledPixels.width() <= 0 || scaledPixels.height() <= 0) {
- return false;
- }
- return this->onGenerateScaledPixels(scaledPixels);
-}
-
-bool SkImageGenerator::accessScaledImage(const SkRect& src, const SkMatrix& matrix,
- SkFilterQuality fq, ScaledImageRec* rec) {
- SkASSERT(fInfo.bounds().contains(src));
- return this->onAccessScaledImage(src, matrix, fq, rec);
-}
-
/////////////////////////////////////////////////////////////////////////////////////////////
SkData* SkImageGenerator::onRefEncodedData(GrContext* ctx) {
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 SkPixmap& scaledPixels) {
- int w = scaledPixels.width();
- int h = scaledPixels.height();
-
- const SkScalar scaleX = SkIntToScalar(w) / this->getInfo().width();
- const SkScalar scaleY = SkIntToScalar(h) / this->getInfo().height();
- SkMatrix matrix = SkMatrix::MakeScale(scaleX, scaleY);
-
- 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.get(), &matrix, fPaint.getMaybeNull());
- return true;
-}
-
///////////////////////////////////////////////////////////////////////////////////////////////////
SkImageGenerator* SkImageGenerator::NewFromPicture(const SkISize& size, const SkPicture* picture,
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 SkPixmap&) override;
#if SK_SUPPORT_GPU
GrTexture* onGenerateTexture(GrContext*, const SkImageInfo&, const SkIPoint&) override;