blob: fc91d6b7f1624795d8fe203f637bed7b8d7a427c [file] [log] [blame]
mike@reedtribe.org70e35902012-07-29 20:38:16 +00001/*
2 * Copyright 2011 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
bsalomon8e74f802016-01-30 10:01:40 -08008#include <functional>
mike@reedtribe.org70e35902012-07-29 20:38:16 +00009#include "gm.h"
Mike Klein33d20552017-03-22 13:47:51 -040010#include "sk_tool_utils.h"
robertphillipsc5035e72016-03-17 06:58:39 -070011#include "SkAutoPixmapStorage.h"
Mike Reed5dd202d2018-02-06 23:05:36 +000012#include "SkColorPriv.h"
mike@reedtribe.orgd829b5c2012-07-31 03:57:11 +000013#include "SkData.h"
reedf803da12015-01-23 05:58:07 -080014#include "SkCanvas.h"
15#include "SkRandom.h"
16#include "SkStream.h"
17#include "SkSurface.h"
mike@reedtribe.orgd829b5c2012-07-31 03:57:11 +000018
robertphillips@google.com97b6b072012-10-31 14:48:39 +000019#if SK_SUPPORT_GPU
20#include "GrContext.h"
robertphillips@google.com97b6b072012-10-31 14:48:39 +000021#endif
reed@google.com97af1a62012-08-28 12:19:02 +000022
mike@reedtribe.org70e35902012-07-29 20:38:16 +000023static void drawContents(SkSurface* surface, SkColor fillC) {
skia.committer@gmail.com04ba4482012-09-07 02:01:30 +000024 SkSize size = SkSize::Make(SkIntToScalar(surface->width()),
robertphillips@google.com94acc702012-09-06 18:43:21 +000025 SkIntToScalar(surface->height()));
mike@reedtribe.orgd2782ed2012-07-31 02:45:15 +000026 SkCanvas* canvas = surface->getCanvas();
mike@reedtribe.org70e35902012-07-29 20:38:16 +000027
28 SkScalar stroke = size.fWidth / 10;
29 SkScalar radius = (size.fWidth - stroke) / 2;
30
31 SkPaint paint;
rmistry@google.comae933ce2012-08-23 18:19:56 +000032
mike@reedtribe.org70e35902012-07-29 20:38:16 +000033 paint.setAntiAlias(true);
34 paint.setColor(fillC);
35 canvas->drawCircle(size.fWidth/2, size.fHeight/2, radius, paint);
rmistry@google.comae933ce2012-08-23 18:19:56 +000036
mike@reedtribe.org70e35902012-07-29 20:38:16 +000037 paint.setStyle(SkPaint::kStroke_Style);
38 paint.setStrokeWidth(stroke);
39 paint.setColor(SK_ColorBLACK);
40 canvas->drawCircle(size.fWidth/2, size.fHeight/2, radius, paint);
41}
42
commit-bot@chromium.orgdfec28d2013-07-23 15:52:16 +000043static void test_surface(SkCanvas* canvas, SkSurface* surf, bool usePaint) {
mike@reedtribe.org70e35902012-07-29 20:38:16 +000044 drawContents(surf, SK_ColorRED);
reed9ce9d672016-03-17 10:51:11 -070045 sk_sp<SkImage> imgR = surf->makeImageSnapshot();
mike@reedtribe.org70e35902012-07-29 20:38:16 +000046
reed@google.com97af1a62012-08-28 12:19:02 +000047 if (true) {
reed9ce9d672016-03-17 10:51:11 -070048 sk_sp<SkImage> imgR2 = surf->makeImageSnapshot();
reed@google.com97af1a62012-08-28 12:19:02 +000049 SkASSERT(imgR == imgR2);
reed@google.com97af1a62012-08-28 12:19:02 +000050 }
51
mike@reedtribe.org70e35902012-07-29 20:38:16 +000052 drawContents(surf, SK_ColorGREEN);
reed9ce9d672016-03-17 10:51:11 -070053 sk_sp<SkImage> imgG = surf->makeImageSnapshot();
mike@reedtribe.org70e35902012-07-29 20:38:16 +000054
reed@google.com97af1a62012-08-28 12:19:02 +000055 // since we've drawn after we snapped imgR, imgG will be a different obj
56 SkASSERT(imgR != imgG);
57
mike@reedtribe.org70e35902012-07-29 20:38:16 +000058 drawContents(surf, SK_ColorBLUE);
59
mike@reedtribe.orgd2782ed2012-07-31 02:45:15 +000060 SkPaint paint;
61// paint.setFilterBitmap(true);
62// paint.setAlpha(0x80);
63
reedfe630452016-03-25 09:08:00 -070064 canvas->drawImage(imgR, 0, 0, usePaint ? &paint : nullptr);
65 canvas->drawImage(imgG, 0, 80, usePaint ? &paint : nullptr);
halcanary96fcdcc2015-08-27 07:41:13 -070066 surf->draw(canvas, 0, 160, usePaint ? &paint : nullptr);
commit-bot@chromium.orgdfec28d2013-07-23 15:52:16 +000067
68 SkRect src1, src2, src3;
69 src1.iset(0, 0, surf->width(), surf->height());
skia.committer@gmail.com7f1af502013-07-24 07:01:12 +000070 src2.iset(-surf->width() / 2, -surf->height() / 2,
commit-bot@chromium.orgdfec28d2013-07-23 15:52:16 +000071 surf->width(), surf->height());
72 src3.iset(0, 0, surf->width() / 2, surf->height() / 2);
73
74 SkRect dst1, dst2, dst3, dst4;
75 dst1.set(0, 240, 65, 305);
76 dst2.set(0, 320, 65, 385);
77 dst3.set(0, 400, 65, 465);
78 dst4.set(0, 480, 65, 545);
79
reedfe630452016-03-25 09:08:00 -070080 canvas->drawImageRect(imgR, src1, dst1, usePaint ? &paint : nullptr);
81 canvas->drawImageRect(imgG, src2, dst2, usePaint ? &paint : nullptr);
82 canvas->drawImageRect(imgR, src3, dst3, usePaint ? &paint : nullptr);
83 canvas->drawImageRect(imgG, dst4, usePaint ? &paint : nullptr);
mike@reedtribe.org70e35902012-07-29 20:38:16 +000084}
85
86class ImageGM : public skiagm::GM {
87 void* fBuffer;
reed@google.com58b21ec2012-07-30 18:20:12 +000088 size_t fBufferSize;
mike@reedtribe.org70e35902012-07-29 20:38:16 +000089 SkSize fSize;
90 enum {
91 W = 64,
92 H = 64,
93 RB = W * 4 + 8,
94 };
95public:
96 ImageGM() {
reed@google.com58b21ec2012-07-30 18:20:12 +000097 fBufferSize = RB * H;
98 fBuffer = sk_malloc_throw(fBufferSize);
mike@reedtribe.org70e35902012-07-29 20:38:16 +000099 fSize.set(SkIntToScalar(W), SkIntToScalar(H));
100 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000101
Brian Salomond3b65972017-03-22 12:05:03 -0400102 ~ImageGM() override {
mike@reedtribe.org70e35902012-07-29 20:38:16 +0000103 sk_free(fBuffer);
104 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000105
mike@reedtribe.org70e35902012-07-29 20:38:16 +0000106protected:
mtklein36352bf2015-03-25 18:17:31 -0700107 SkString onShortName() override {
robertphillips@google.com97b6b072012-10-31 14:48:39 +0000108 return SkString("image-surface");
mike@reedtribe.org70e35902012-07-29 20:38:16 +0000109 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000110
mtklein36352bf2015-03-25 18:17:31 -0700111 SkISize onISize() override {
commit-bot@chromium.orgdfec28d2013-07-23 15:52:16 +0000112 return SkISize::Make(960, 1200);
mike@reedtribe.org70e35902012-07-29 20:38:16 +0000113 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000114
mtklein36352bf2015-03-25 18:17:31 -0700115 void onDraw(SkCanvas* canvas) override {
mike@reedtribe.orgd2782ed2012-07-31 02:45:15 +0000116 canvas->scale(2, 2);
117
mtkleindbfd7ab2016-09-01 11:24:54 -0700118 const char* kLabel1 = "Original Img";
119 const char* kLabel2 = "Modified Img";
120 const char* kLabel3 = "Cur Surface";
121 const char* kLabel4 = "Full Crop";
122 const char* kLabel5 = "Over-crop";
123 const char* kLabel6 = "Upper-left";
124 const char* kLabel7 = "No Crop";
robertphillips@google.com97b6b072012-10-31 14:48:39 +0000125
mtkleindbfd7ab2016-09-01 11:24:54 -0700126 const char* kLabel8 = "Pre-Alloc Img";
127 const char* kLabel9 = "New Alloc Img";
128 const char* kLabel10 = "GPU";
robertphillips@google.com97b6b072012-10-31 14:48:39 +0000129
130 SkPaint textPaint;
commit-bot@chromium.orgcae54f12014-04-11 18:34:35 +0000131 textPaint.setAntiAlias(true);
caryclark1818acb2015-07-24 12:09:25 -0700132 sk_tool_utils::set_portable_typeface(&textPaint);
commit-bot@chromium.orgcae54f12014-04-11 18:34:35 +0000133 textPaint.setTextSize(8);
robertphillips@google.com97b6b072012-10-31 14:48:39 +0000134
Cary Clark2a475ea2017-04-28 15:35:12 -0400135 canvas->drawString(kLabel1, 10, 60, textPaint);
136 canvas->drawString(kLabel2, 10, 140, textPaint);
137 canvas->drawString(kLabel3, 10, 220, textPaint);
138 canvas->drawString(kLabel4, 10, 300, textPaint);
139 canvas->drawString(kLabel5, 10, 380, textPaint);
140 canvas->drawString(kLabel6, 10, 460, textPaint);
141 canvas->drawString(kLabel7, 10, 540, textPaint);
robertphillips@google.com97b6b072012-10-31 14:48:39 +0000142
Cary Clark2a475ea2017-04-28 15:35:12 -0400143 canvas->drawString(kLabel8, 80, 10, textPaint);
144 canvas->drawString(kLabel9, 160, 10, textPaint);
145 canvas->drawString(kLabel10, 265, 10, textPaint);
robertphillips@google.com97b6b072012-10-31 14:48:39 +0000146
147 canvas->translate(80, 20);
148
reed@google.com58b21ec2012-07-30 18:20:12 +0000149 // since we draw into this directly, we need to start fresh
150 sk_bzero(fBuffer, fBufferSize);
151
commit-bot@chromium.org32678d92014-01-15 02:38:22 +0000152 SkImageInfo info = SkImageInfo::MakeN32Premul(W, H);
reede8f30622016-03-23 18:59:25 -0700153 sk_sp<SkSurface> surf0(SkSurface::MakeRasterDirect(info, fBuffer, RB));
154 sk_sp<SkSurface> surf1(SkSurface::MakeRaster(info));
155 sk_sp<SkSurface> surf2; // gpu
robertphillips@google.com97b6b072012-10-31 14:48:39 +0000156
reeda9cb8712015-01-16 14:21:40 -0800157#if SK_SUPPORT_GPU
reede8f30622016-03-23 18:59:25 -0700158 surf2 = SkSurface::MakeRenderTarget(canvas->getGrContext(), SkBudgeted::kNo, info);
robertphillips@google.com97b6b072012-10-31 14:48:39 +0000159#endif
mike@reedtribe.org70e35902012-07-29 20:38:16 +0000160
reede8f30622016-03-23 18:59:25 -0700161 test_surface(canvas, surf0.get(), true);
mike@reedtribe.org70e35902012-07-29 20:38:16 +0000162 canvas->translate(80, 0);
reede8f30622016-03-23 18:59:25 -0700163 test_surface(canvas, surf1.get(), true);
reeda9cb8712015-01-16 14:21:40 -0800164 if (surf2) {
robertphillips@google.com97b6b072012-10-31 14:48:39 +0000165 canvas->translate(80, 0);
reede8f30622016-03-23 18:59:25 -0700166 test_surface(canvas, surf2.get(), true);
robertphillips@google.com97b6b072012-10-31 14:48:39 +0000167 }
mike@reedtribe.org70e35902012-07-29 20:38:16 +0000168 }
rmistry@google.comae933ce2012-08-23 18:19:56 +0000169
mike@reedtribe.org70e35902012-07-29 20:38:16 +0000170private:
171 typedef skiagm::GM INHERITED;
172};
reeda9cb8712015-01-16 14:21:40 -0800173DEF_GM( return new ImageGM; )
reed09553032015-11-23 12:32:16 -0800174
175///////////////////////////////////////////////////////////////////////////////////////////////////
176
177#include "SkPictureRecorder.h"
178
179static void draw_pixmap(SkCanvas* canvas, const SkPixmap& pmap) {
180 SkBitmap bitmap;
halcanarye36ec872015-12-09 11:36:59 -0800181 bitmap.installPixels(pmap);
reed09553032015-11-23 12:32:16 -0800182 canvas->drawBitmap(bitmap, 0, 0, nullptr);
183}
184
185static void show_scaled_pixels(SkCanvas* canvas, SkImage* image) {
186 SkAutoCanvasRestore acr(canvas, true);
187
188 canvas->drawImage(image, 0, 0, nullptr);
189 canvas->translate(110, 10);
190
191 const SkImageInfo info = SkImageInfo::MakeN32Premul(40, 40);
192 SkAutoPixmapStorage storage;
193 storage.alloc(info);
194
195 const SkImage::CachingHint chints[] = {
reed6868c3f2015-11-24 11:44:47 -0800196 SkImage::kAllow_CachingHint, SkImage::kDisallow_CachingHint,
reed09553032015-11-23 12:32:16 -0800197 };
198 const SkFilterQuality qualities[] = {
199 kNone_SkFilterQuality, kLow_SkFilterQuality, kMedium_SkFilterQuality, kHigh_SkFilterQuality,
200 };
201
202 for (auto ch : chints) {
203 canvas->save();
204 for (auto q : qualities) {
205 if (image->scalePixels(storage, q, ch)) {
206 draw_pixmap(canvas, storage);
207 }
208 canvas->translate(70, 0);
209 }
210 canvas->restore();
211 canvas->translate(0, 45);
212 }
213}
214
215static void draw_contents(SkCanvas* canvas) {
216 SkPaint paint;
217 paint.setStyle(SkPaint::kStroke_Style);
218 paint.setStrokeWidth(20);
219 canvas->drawCircle(50, 50, 35, paint);
220}
221
reed9ce9d672016-03-17 10:51:11 -0700222static sk_sp<SkImage> make_raster(const SkImageInfo& info, GrContext*, void (*draw)(SkCanvas*)) {
reede8f30622016-03-23 18:59:25 -0700223 auto surface(SkSurface::MakeRaster(info));
reed7850eb22015-12-02 14:19:47 -0800224 draw(surface->getCanvas());
reed9ce9d672016-03-17 10:51:11 -0700225 return surface->makeImageSnapshot();
reed09553032015-11-23 12:32:16 -0800226}
227
reed9ce9d672016-03-17 10:51:11 -0700228static sk_sp<SkImage> make_picture(const SkImageInfo& info, GrContext*, void (*draw)(SkCanvas*)) {
reed09553032015-11-23 12:32:16 -0800229 SkPictureRecorder recorder;
reed7850eb22015-12-02 14:19:47 -0800230 draw(recorder.beginRecording(SkRect::MakeIWH(info.width(), info.height())));
reedca2622b2016-03-18 07:25:55 -0700231 return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
Matt Sarette94255d2017-01-09 12:38:59 -0500232 info.dimensions(), nullptr, nullptr, SkImage::BitDepth::kU8,
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500233 SkColorSpace::MakeSRGB());
reed09553032015-11-23 12:32:16 -0800234}
235
reed9ce9d672016-03-17 10:51:11 -0700236static sk_sp<SkImage> make_codec(const SkImageInfo& info, GrContext*, void (*draw)(SkCanvas*)) {
237 sk_sp<SkImage> image(make_raster(info, nullptr, draw));
Mike Reed6409f842017-07-11 16:03:13 -0400238 return SkImage::MakeFromEncoded(image->encodeToData());
reed09553032015-11-23 12:32:16 -0800239}
240
reed9ce9d672016-03-17 10:51:11 -0700241static sk_sp<SkImage> make_gpu(const SkImageInfo& info, GrContext* ctx, void (*draw)(SkCanvas*)) {
reed09553032015-11-23 12:32:16 -0800242 if (!ctx) { return nullptr; }
reede8f30622016-03-23 18:59:25 -0700243 auto surface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info));
scroggoe6f0d6e2016-05-13 07:25:44 -0700244 if (!surface) { return nullptr; }
reed7850eb22015-12-02 14:19:47 -0800245 draw(surface->getCanvas());
reed9ce9d672016-03-17 10:51:11 -0700246 return surface->makeImageSnapshot();
reed09553032015-11-23 12:32:16 -0800247}
248
reed9ce9d672016-03-17 10:51:11 -0700249typedef sk_sp<SkImage> (*ImageMakerProc)(const SkImageInfo&, GrContext*, void (*)(SkCanvas*));
reed09553032015-11-23 12:32:16 -0800250
251class ScalePixelsGM : public skiagm::GM {
252public:
253 ScalePixelsGM() {}
254
255protected:
256 SkString onShortName() override {
257 return SkString("scale-pixels");
258 }
259
260 SkISize onISize() override {
261 return SkISize::Make(960, 1200);
262 }
263
264 void onDraw(SkCanvas* canvas) override {
265 const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
266
267 const ImageMakerProc procs[] = {
reed6868c3f2015-11-24 11:44:47 -0800268 make_codec, make_raster, make_picture, make_codec, make_gpu,
reed09553032015-11-23 12:32:16 -0800269 };
270 for (auto& proc : procs) {
reed9ce9d672016-03-17 10:51:11 -0700271 sk_sp<SkImage> image(proc(info, canvas->getGrContext(), draw_contents));
reed09553032015-11-23 12:32:16 -0800272 if (image) {
reed9ce9d672016-03-17 10:51:11 -0700273 show_scaled_pixels(canvas, image.get());
reed09553032015-11-23 12:32:16 -0800274 }
275 canvas->translate(0, 120);
276 }
277 }
halcanary9d524f22016-03-29 09:03:52 -0700278
reed09553032015-11-23 12:32:16 -0800279private:
280 typedef skiagm::GM INHERITED;
281};
282DEF_GM( return new ScalePixelsGM; )
reed7850eb22015-12-02 14:19:47 -0800283
284///////////////////////////////////////////////////////////////////////////////////////////////////
285
Brian Osmane8827d22017-02-07 12:31:02 -0500286DEF_SIMPLE_GM(new_texture_image, canvas, 280, 60) {
287 GrContext* context = canvas->getGrContext();
Brian Osman041f7df2017-02-07 11:23:28 -0500288 if (!context) {
289 skiagm::GM::DrawGpuOnlyMessage(canvas);
290 return;
291 }
292
293 auto render_image = [](SkCanvas* canvas) {
294 canvas->clear(SK_ColorBLUE);
295 SkPaint paint;
296 paint.setColor(SK_ColorRED);
297 canvas->drawRect(SkRect::MakeXYWH(10.f,10.f,10.f,10.f), paint);
298 paint.setColor(SK_ColorGREEN);
299 canvas->drawRect(SkRect::MakeXYWH(30.f,10.f,10.f,10.f), paint);
300 paint.setColor(SK_ColorYELLOW);
301 canvas->drawRect(SkRect::MakeXYWH(10.f,30.f,10.f,10.f), paint);
302 paint.setColor(SK_ColorCYAN);
303 canvas->drawRect(SkRect::MakeXYWH(30.f,30.f,10.f,10.f), paint);
304 };
305
306 static constexpr int kSize = 50;
307 SkBitmap bmp;
308 bmp.allocPixels(SkImageInfo::MakeS32(kSize, kSize, kPremul_SkAlphaType));
309 SkCanvas bmpCanvas(bmp);
310 render_image(&bmpCanvas);
311
312 std::function<sk_sp<SkImage>()> imageFactories[] = {
313 // Create sw raster image.
314 [bmp] {
315 return SkImage::MakeFromBitmap(bmp);
316 },
317 // Create encoded image.
318 [bmp] {
319 sk_sp<SkData> src(
320 sk_tool_utils::EncodeImageToData(bmp, SkEncodedImageFormat::kPNG, 100));
321 return SkImage::MakeFromEncoded(std::move(src));
322 },
Brian Osmane8827d22017-02-07 12:31:02 -0500323 // Create YUV encoded image.
324 [bmp] {
325 sk_sp<SkData> src(
326 sk_tool_utils::EncodeImageToData(bmp, SkEncodedImageFormat::kJPEG, 100));
327 return SkImage::MakeFromEncoded(std::move(src));
328 },
Brian Osman041f7df2017-02-07 11:23:28 -0500329 // Create a picture image.
330 [render_image] {
331 SkPictureRecorder recorder;
332 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kSize), SkIntToScalar(kSize));
333 render_image(canvas);
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500334 sk_sp<SkColorSpace> srgbColorSpace = SkColorSpace::MakeSRGB();
Brian Osman041f7df2017-02-07 11:23:28 -0500335 return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
336 SkISize::Make(kSize, kSize), nullptr, nullptr,
337 SkImage::BitDepth::kU8, srgbColorSpace);
338 },
339 // Create a texture image
340 [context, render_image]() -> sk_sp<SkImage> {
341 auto surface(SkSurface::MakeRenderTarget(context, SkBudgeted::kYes,
342 SkImageInfo::MakeS32(kSize, kSize,
343 kPremul_SkAlphaType)));
344 if (!surface) {
345 return nullptr;
346 }
347 render_image(surface->getCanvas());
348 return surface->makeImageSnapshot();
349 }
350 };
351
352 constexpr SkScalar kPad = 5.f;
353 canvas->translate(kPad, kPad);
354 for (auto factory : imageFactories) {
355 auto image(factory());
Brian Osmane8827d22017-02-07 12:31:02 -0500356 if (image) {
Brian Osman041f7df2017-02-07 11:23:28 -0500357 sk_sp<SkImage> texImage(image->makeTextureImage(context,
358 canvas->imageInfo().colorSpace()));
359 if (texImage) {
360 canvas->drawImage(texImage, 0, 0);
361 }
362 }
Robert Phillips5bea6512017-02-10 08:04:06 -0500363 canvas->translate(kSize + kPad, 0);
Brian Osman041f7df2017-02-07 11:23:28 -0500364 }
365}
Mike Reedba61af92017-11-16 10:01:16 -0500366
367static void draw_pixmap(SkCanvas* canvas, const SkPixmap& pm, SkScalar x, SkScalar y) {
368 canvas->drawImage(SkImage::MakeRasterCopy(pm), x, y, nullptr);
369}
370
371static void slam_ff(const SkPixmap& pm) {
372 for (int y = 0; y < pm.height(); ++y) {
373 for (int x = 0; x < pm.width(); ++x) {
374 *pm.writable_addr32(x, y) = *pm.addr32(x, y) | SkPackARGB32(0xFF, 0, 0, 0);
375 }
376 }
377}
378
379DEF_SIMPLE_GM(scalepixels_unpremul, canvas, 1080, 280) {
380 SkImageInfo info = SkImageInfo::MakeN32(16, 16, kUnpremul_SkAlphaType);
381 SkAutoPixmapStorage pm;
382 pm.alloc(info);
383 for (int y = 0; y < 16; ++y) {
384 for (int x = 0; x < 16; ++x) {
385 *pm.writable_addr32(x, y) = SkPackARGB32NoCheck(0, (y << 4) | y, (x << 4) | x, 0xFF);
386 }
387 }
388 SkAutoPixmapStorage pm2;
389 pm2.alloc(SkImageInfo::MakeN32(256, 256, kUnpremul_SkAlphaType));
390
391 const SkFilterQuality qualities[] = {
392 kNone_SkFilterQuality, kLow_SkFilterQuality, kMedium_SkFilterQuality, kHigh_SkFilterQuality
393 };
394
395 for (auto fq : qualities) {
396 pm.scalePixels(pm2, fq);
397 slam_ff(pm2);
398 draw_pixmap(canvas, pm2, 10, 10);
399 canvas->translate(pm2.width() + 10.0f, 0);
400 }
401}