| Index: gm/image.cpp
|
| diff --git a/gm/image.cpp b/gm/image.cpp
|
| index 991b4014f02aa3bfff0a2a3126a29f5210a21591..ac72f63b36f96dc2ab271778578d9e31a588b35e 100644
|
| --- a/gm/image.cpp
|
| +++ b/gm/image.cpp
|
| @@ -240,33 +240,33 @@ static void draw_contents(SkCanvas* canvas) {
|
| canvas->drawCircle(50, 50, 35, paint);
|
| }
|
|
|
| -static SkImage* make_raster(const SkImageInfo& info, GrContext*) {
|
| +static SkImage* make_raster(const SkImageInfo& info, GrContext*, void (*draw)(SkCanvas*)) {
|
| SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
|
| - draw_contents(surface->getCanvas());
|
| + draw(surface->getCanvas());
|
| return surface->newImageSnapshot();
|
| }
|
|
|
| -static SkImage* make_picture(const SkImageInfo& info, GrContext*) {
|
| +static SkImage* make_picture(const SkImageInfo& info, GrContext*, void (*draw)(SkCanvas*)) {
|
| SkPictureRecorder recorder;
|
| - draw_contents(recorder.beginRecording(SkRect::MakeIWH(info.width(), info.height())));
|
| + draw(recorder.beginRecording(SkRect::MakeIWH(info.width(), info.height())));
|
| SkAutoTUnref<SkPicture> pict(recorder.endRecording());
|
| return SkImage::NewFromPicture(pict, info.dimensions(), nullptr, nullptr);
|
| }
|
|
|
| -static SkImage* make_codec(const SkImageInfo& info, GrContext*) {
|
| - SkAutoTUnref<SkImage> image(make_raster(info, nullptr));
|
| +static SkImage* make_codec(const SkImageInfo& info, GrContext*, void (*draw)(SkCanvas*)) {
|
| + SkAutoTUnref<SkImage> image(make_raster(info, nullptr, draw));
|
| SkAutoTUnref<SkData> data(image->encode());
|
| return SkImage::NewFromEncoded(data);
|
| }
|
|
|
| -static SkImage* make_gpu(const SkImageInfo& info, GrContext* ctx) {
|
| +static SkImage* make_gpu(const SkImageInfo& info, GrContext* ctx, void (*draw)(SkCanvas*)) {
|
| if (!ctx) { return nullptr; }
|
| SkAutoTUnref<SkSurface> surface(SkSurface::NewRenderTarget(ctx, SkSurface::kNo_Budgeted, info));
|
| - draw_contents(surface->getCanvas());
|
| + draw(surface->getCanvas());
|
| return surface->newImageSnapshot();
|
| }
|
|
|
| -typedef SkImage* (*ImageMakerProc)(const SkImageInfo&, GrContext*);
|
| +typedef SkImage* (*ImageMakerProc)(const SkImageInfo&, GrContext*, void (*)(SkCanvas*));
|
|
|
| class ScalePixelsGM : public skiagm::GM {
|
| public:
|
| @@ -288,7 +288,7 @@ protected:
|
| make_codec, make_raster, make_picture, make_codec, make_gpu,
|
| };
|
| for (auto& proc : procs) {
|
| - SkAutoTUnref<SkImage> image(proc(info, canvas->getGrContext()));
|
| + SkAutoTUnref<SkImage> image(proc(info, canvas->getGrContext(), draw_contents));
|
| if (image) {
|
| show_scaled_pixels(canvas, image);
|
| }
|
| @@ -300,3 +300,132 @@ private:
|
| typedef skiagm::GM INHERITED;
|
| };
|
| DEF_GM( return new ScalePixelsGM; )
|
| +
|
| +///////////////////////////////////////////////////////////////////////////////////////////////////
|
| +
|
| +#include "SkImageGenerator.h"
|
| +
|
| +static SkImageInfo make_info(SkImage* img) {
|
| + return SkImageInfo::MakeN32(img->width(), img->height(),
|
| + img->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
|
| +}
|
| +
|
| +// 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:
|
| + SkAutoTUnref<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) {
|
| + SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
|
| + draw_opaque_contents(surface->getCanvas());
|
| + SkAutoTUnref<SkImage> img(surface->newImageSnapshot());
|
| + return new ImageGeneratorFromImage(img);
|
| +}
|
| +
|
| +static SkImageGenerator* gen_picture(const SkImageInfo& info) {
|
| + SkPictureRecorder recorder;
|
| + draw_opaque_contents(recorder.beginRecording(SkRect::MakeIWH(info.width(), info.height())));
|
| + SkAutoTUnref<SkPicture> pict(recorder.endRecording());
|
| + return SkImageGenerator::NewFromPicture(info.dimensions(), pict, nullptr, nullptr);
|
| +}
|
| +
|
| +static SkImageGenerator* gen_png(const SkImageInfo& info) {
|
| + SkAutoTUnref<SkImage> image(make_raster(info, nullptr, draw_opaque_contents));
|
| + SkAutoTUnref<SkData> data(image->encode(SkImageEncoder::kPNG_Type, 100));
|
| + return SkImageGenerator::NewFromEncoded(data);
|
| +}
|
| +
|
| +static SkImageGenerator* gen_jpg(const SkImageInfo& info) {
|
| + SkAutoTUnref<SkImage> image(make_raster(info, nullptr, draw_opaque_contents));
|
| + SkAutoTUnref<SkData> data(image->encode(SkImageEncoder::kJPEG_Type, 100));
|
| + return SkImageGenerator::NewFromEncoded(data);
|
| +}
|
| +
|
| +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) {
|
| + SkAutoTDelete<SkImageGenerator> gen(proc(info));
|
| + if (gen) {
|
| + show_scaled_generator(canvas, gen);
|
| + }
|
| + canvas->translate(0, 120);
|
| + }
|
| + }
|
| +
|
| +private:
|
| + typedef skiagm::GM INHERITED;
|
| +};
|
| +DEF_GM( return new ScaleGeneratorGM; )
|
|
|