1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2011 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPixmap.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRasterHandleAllocator.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkMalloc.h"
15*c8dee2aaSAndroid Build Coastguard Worker
16*c8dee2aaSAndroid Build Coastguard Worker class GraphicsPort {
17*c8dee2aaSAndroid Build Coastguard Worker protected:
18*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* fCanvas;
19*c8dee2aaSAndroid Build Coastguard Worker
20*c8dee2aaSAndroid Build Coastguard Worker public:
GraphicsPort(SkCanvas * canvas)21*c8dee2aaSAndroid Build Coastguard Worker GraphicsPort(SkCanvas* canvas) : fCanvas(canvas) {}
~GraphicsPort()22*c8dee2aaSAndroid Build Coastguard Worker virtual ~GraphicsPort() {}
23*c8dee2aaSAndroid Build Coastguard Worker
save()24*c8dee2aaSAndroid Build Coastguard Worker void save() { fCanvas->save(); }
saveLayer(const SkRect & bounds,SkAlpha alpha)25*c8dee2aaSAndroid Build Coastguard Worker void saveLayer(const SkRect& bounds, SkAlpha alpha) {
26*c8dee2aaSAndroid Build Coastguard Worker fCanvas->saveLayerAlpha(&bounds, alpha);
27*c8dee2aaSAndroid Build Coastguard Worker }
restore()28*c8dee2aaSAndroid Build Coastguard Worker void restore() { fCanvas->restore(); }
29*c8dee2aaSAndroid Build Coastguard Worker
translate(float x,float y)30*c8dee2aaSAndroid Build Coastguard Worker void translate(float x, float y) { fCanvas->translate(x, y); }
scale(float s)31*c8dee2aaSAndroid Build Coastguard Worker void scale(float s) { fCanvas->scale(s, s); }
clip(const SkRect & r)32*c8dee2aaSAndroid Build Coastguard Worker void clip(const SkRect& r) { fCanvas->clipRect(r); }
33*c8dee2aaSAndroid Build Coastguard Worker
drawOval(const SkRect & r,SkColor c)34*c8dee2aaSAndroid Build Coastguard Worker void drawOval(const SkRect& r, SkColor c) {
35*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
36*c8dee2aaSAndroid Build Coastguard Worker p.setColor(c);
37*c8dee2aaSAndroid Build Coastguard Worker fCanvas->drawOval(r, p);
38*c8dee2aaSAndroid Build Coastguard Worker }
39*c8dee2aaSAndroid Build Coastguard Worker
drawRect(const SkRect & r,SkColor c)40*c8dee2aaSAndroid Build Coastguard Worker virtual void drawRect(const SkRect& r, SkColor c) {
41*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
42*c8dee2aaSAndroid Build Coastguard Worker p.setColor(c);
43*c8dee2aaSAndroid Build Coastguard Worker fCanvas->drawRect(r, p);
44*c8dee2aaSAndroid Build Coastguard Worker }
45*c8dee2aaSAndroid Build Coastguard Worker
peekCanvas() const46*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* peekCanvas() const { return fCanvas; }
47*c8dee2aaSAndroid Build Coastguard Worker };
48*c8dee2aaSAndroid Build Coastguard Worker
49*c8dee2aaSAndroid Build Coastguard Worker class SkiaGraphicsPort : public GraphicsPort {
50*c8dee2aaSAndroid Build Coastguard Worker public:
SkiaGraphicsPort(SkCanvas * canvas)51*c8dee2aaSAndroid Build Coastguard Worker SkiaGraphicsPort(SkCanvas* canvas) : GraphicsPort(canvas) {}
52*c8dee2aaSAndroid Build Coastguard Worker
drawRect(const SkRect & r,SkColor c)53*c8dee2aaSAndroid Build Coastguard Worker void drawRect(const SkRect& r, SkColor c) override {
54*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = (SkCanvas*)fCanvas->accessTopRasterHandle();
55*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, SkPaint(SkColor4f::FromColor(c)));
56*c8dee2aaSAndroid Build Coastguard Worker }
57*c8dee2aaSAndroid Build Coastguard Worker };
58*c8dee2aaSAndroid Build Coastguard Worker
59*c8dee2aaSAndroid Build Coastguard Worker class SkiaAllocator : public SkRasterHandleAllocator {
60*c8dee2aaSAndroid Build Coastguard Worker public:
SkiaAllocator()61*c8dee2aaSAndroid Build Coastguard Worker SkiaAllocator() {}
62*c8dee2aaSAndroid Build Coastguard Worker
allocHandle(const SkImageInfo & info,Rec * rec)63*c8dee2aaSAndroid Build Coastguard Worker bool allocHandle(const SkImageInfo& info, Rec* rec) override {
64*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface = SkSurfaces::Raster(info);
65*c8dee2aaSAndroid Build Coastguard Worker if (!surface) {
66*c8dee2aaSAndroid Build Coastguard Worker return false;
67*c8dee2aaSAndroid Build Coastguard Worker }
68*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surface->getCanvas();
69*c8dee2aaSAndroid Build Coastguard Worker SkPixmap pixmap;
70*c8dee2aaSAndroid Build Coastguard Worker canvas->peekPixels(&pixmap);
71*c8dee2aaSAndroid Build Coastguard Worker
72*c8dee2aaSAndroid Build Coastguard Worker rec->fReleaseProc = [](void* pixels, void* ctx){ SkSafeUnref((SkSurface*)ctx); };
73*c8dee2aaSAndroid Build Coastguard Worker rec->fReleaseCtx = surface.release();
74*c8dee2aaSAndroid Build Coastguard Worker rec->fPixels = pixmap.writable_addr();
75*c8dee2aaSAndroid Build Coastguard Worker rec->fRowBytes = pixmap.rowBytes();
76*c8dee2aaSAndroid Build Coastguard Worker rec->fHandle = canvas;
77*c8dee2aaSAndroid Build Coastguard Worker canvas->save(); // balanced each time updateHandle is called
78*c8dee2aaSAndroid Build Coastguard Worker return true;
79*c8dee2aaSAndroid Build Coastguard Worker }
80*c8dee2aaSAndroid Build Coastguard Worker
updateHandle(Handle hndl,const SkMatrix & ctm,const SkIRect & clip)81*c8dee2aaSAndroid Build Coastguard Worker void updateHandle(Handle hndl, const SkMatrix& ctm, const SkIRect& clip) override {
82*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = (SkCanvas*)hndl;
83*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
84*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
85*c8dee2aaSAndroid Build Coastguard Worker canvas->clipRect(SkRect::Make(clip));
86*c8dee2aaSAndroid Build Coastguard Worker canvas->concat(ctm);
87*c8dee2aaSAndroid Build Coastguard Worker }
88*c8dee2aaSAndroid Build Coastguard Worker };
89*c8dee2aaSAndroid Build Coastguard Worker
90*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_BUILD_FOR_MAC
91*c8dee2aaSAndroid Build Coastguard Worker
92*c8dee2aaSAndroid Build Coastguard Worker #include "include/utils/mac/SkCGUtils.h"
93*c8dee2aaSAndroid Build Coastguard Worker class CGGraphicsPort : public GraphicsPort {
94*c8dee2aaSAndroid Build Coastguard Worker public:
CGGraphicsPort(SkCanvas * canvas)95*c8dee2aaSAndroid Build Coastguard Worker CGGraphicsPort(SkCanvas* canvas) : GraphicsPort(canvas) {}
96*c8dee2aaSAndroid Build Coastguard Worker
drawRect(const SkRect & r,SkColor c)97*c8dee2aaSAndroid Build Coastguard Worker void drawRect(const SkRect& r, SkColor c) override {
98*c8dee2aaSAndroid Build Coastguard Worker CGContextRef cg = (CGContextRef)fCanvas->accessTopRasterHandle();
99*c8dee2aaSAndroid Build Coastguard Worker
100*c8dee2aaSAndroid Build Coastguard Worker CGColorRef color = CGColorCreateGenericRGB(SkColorGetR(c)/255.f,
101*c8dee2aaSAndroid Build Coastguard Worker SkColorGetG(c)/255.f,
102*c8dee2aaSAndroid Build Coastguard Worker SkColorGetB(c)/255.f,
103*c8dee2aaSAndroid Build Coastguard Worker SkColorGetA(c)/255.f);
104*c8dee2aaSAndroid Build Coastguard Worker
105*c8dee2aaSAndroid Build Coastguard Worker CGContextSetFillColorWithColor(cg, color);
106*c8dee2aaSAndroid Build Coastguard Worker CGContextFillRect(cg, CGRectMake(r.x(), r.y(), r.width(), r.height()));
107*c8dee2aaSAndroid Build Coastguard Worker }
108*c8dee2aaSAndroid Build Coastguard Worker };
109*c8dee2aaSAndroid Build Coastguard Worker
matrix_to_transform(CGContextRef cg,const SkMatrix & ctm)110*c8dee2aaSAndroid Build Coastguard Worker static CGAffineTransform matrix_to_transform(CGContextRef cg, const SkMatrix& ctm) {
111*c8dee2aaSAndroid Build Coastguard Worker SkMatrix matrix;
112*c8dee2aaSAndroid Build Coastguard Worker matrix.setScale(1, -1);
113*c8dee2aaSAndroid Build Coastguard Worker matrix.postTranslate(0, SkIntToScalar(CGBitmapContextGetHeight(cg)));
114*c8dee2aaSAndroid Build Coastguard Worker matrix.preConcat(ctm);
115*c8dee2aaSAndroid Build Coastguard Worker
116*c8dee2aaSAndroid Build Coastguard Worker return CGAffineTransformMake(matrix[SkMatrix::kMScaleX],
117*c8dee2aaSAndroid Build Coastguard Worker matrix[SkMatrix::kMSkewY],
118*c8dee2aaSAndroid Build Coastguard Worker matrix[SkMatrix::kMSkewX],
119*c8dee2aaSAndroid Build Coastguard Worker matrix[SkMatrix::kMScaleY],
120*c8dee2aaSAndroid Build Coastguard Worker matrix[SkMatrix::kMTransX],
121*c8dee2aaSAndroid Build Coastguard Worker matrix[SkMatrix::kMTransY]);
122*c8dee2aaSAndroid Build Coastguard Worker }
123*c8dee2aaSAndroid Build Coastguard Worker
124*c8dee2aaSAndroid Build Coastguard Worker class CGAllocator : public SkRasterHandleAllocator {
125*c8dee2aaSAndroid Build Coastguard Worker public:
CGAllocator()126*c8dee2aaSAndroid Build Coastguard Worker CGAllocator() {}
127*c8dee2aaSAndroid Build Coastguard Worker
allocHandle(const SkImageInfo & info,Rec * rec)128*c8dee2aaSAndroid Build Coastguard Worker bool allocHandle(const SkImageInfo& info, Rec* rec) override {
129*c8dee2aaSAndroid Build Coastguard Worker // let CG allocate the pixels
130*c8dee2aaSAndroid Build Coastguard Worker CGContextRef cg = SkCreateCGContext(SkPixmap(info, nullptr, 0));
131*c8dee2aaSAndroid Build Coastguard Worker if (!cg) {
132*c8dee2aaSAndroid Build Coastguard Worker return false;
133*c8dee2aaSAndroid Build Coastguard Worker }
134*c8dee2aaSAndroid Build Coastguard Worker rec->fReleaseProc = [](void* pixels, void* ctx){ CGContextRelease((CGContextRef)ctx); };
135*c8dee2aaSAndroid Build Coastguard Worker rec->fReleaseCtx = cg;
136*c8dee2aaSAndroid Build Coastguard Worker rec->fPixels = CGBitmapContextGetData(cg);
137*c8dee2aaSAndroid Build Coastguard Worker rec->fRowBytes = CGBitmapContextGetBytesPerRow(cg);
138*c8dee2aaSAndroid Build Coastguard Worker rec->fHandle = cg;
139*c8dee2aaSAndroid Build Coastguard Worker CGContextSaveGState(cg); // balanced each time updateHandle is called
140*c8dee2aaSAndroid Build Coastguard Worker return true;
141*c8dee2aaSAndroid Build Coastguard Worker }
142*c8dee2aaSAndroid Build Coastguard Worker
updateHandle(Handle hndl,const SkMatrix & ctm,const SkIRect & clip)143*c8dee2aaSAndroid Build Coastguard Worker void updateHandle(Handle hndl, const SkMatrix& ctm, const SkIRect& clip) override {
144*c8dee2aaSAndroid Build Coastguard Worker CGContextRef cg = (CGContextRef)hndl;
145*c8dee2aaSAndroid Build Coastguard Worker
146*c8dee2aaSAndroid Build Coastguard Worker CGContextRestoreGState(cg);
147*c8dee2aaSAndroid Build Coastguard Worker CGContextSaveGState(cg);
148*c8dee2aaSAndroid Build Coastguard Worker CGContextClipToRect(cg, CGRectMake(clip.x(), clip.y(), clip.width(), clip.height()));
149*c8dee2aaSAndroid Build Coastguard Worker CGContextConcatCTM(cg, matrix_to_transform(cg, ctm));
150*c8dee2aaSAndroid Build Coastguard Worker }
151*c8dee2aaSAndroid Build Coastguard Worker };
152*c8dee2aaSAndroid Build Coastguard Worker
153*c8dee2aaSAndroid Build Coastguard Worker using MyPort = CGGraphicsPort;
154*c8dee2aaSAndroid Build Coastguard Worker using MyAllocator = CGAllocator;
155*c8dee2aaSAndroid Build Coastguard Worker
156*c8dee2aaSAndroid Build Coastguard Worker #elif defined(SK_BUILD_FOR_WIN)
157*c8dee2aaSAndroid Build Coastguard Worker
158*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkLeanWindows.h"
159*c8dee2aaSAndroid Build Coastguard Worker
toRECT(const SkIRect & r)160*c8dee2aaSAndroid Build Coastguard Worker static RECT toRECT(const SkIRect& r) {
161*c8dee2aaSAndroid Build Coastguard Worker return { r.left(), r.top(), r.right(), r.bottom() };
162*c8dee2aaSAndroid Build Coastguard Worker }
163*c8dee2aaSAndroid Build Coastguard Worker
164*c8dee2aaSAndroid Build Coastguard Worker class GDIGraphicsPort : public GraphicsPort {
165*c8dee2aaSAndroid Build Coastguard Worker public:
GDIGraphicsPort(SkCanvas * canvas)166*c8dee2aaSAndroid Build Coastguard Worker GDIGraphicsPort(SkCanvas* canvas) : GraphicsPort(canvas) {}
167*c8dee2aaSAndroid Build Coastguard Worker
drawRect(const SkRect & r,SkColor c)168*c8dee2aaSAndroid Build Coastguard Worker void drawRect(const SkRect& r, SkColor c) override {
169*c8dee2aaSAndroid Build Coastguard Worker HDC hdc = (HDC)fCanvas->accessTopRasterHandle();
170*c8dee2aaSAndroid Build Coastguard Worker
171*c8dee2aaSAndroid Build Coastguard Worker COLORREF cr = RGB(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c));// SkEndian_Swap32(c) >> 8;
172*c8dee2aaSAndroid Build Coastguard Worker RECT rounded = toRECT(r.round());
173*c8dee2aaSAndroid Build Coastguard Worker FillRect(hdc, &rounded, CreateSolidBrush(cr));
174*c8dee2aaSAndroid Build Coastguard Worker
175*c8dee2aaSAndroid Build Coastguard Worker // Assuming GDI wrote zeros for alpha, this will or-in 0xFF for alpha
176*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
177*c8dee2aaSAndroid Build Coastguard Worker paint.setBlendMode(SkBlendMode::kDstATop);
178*c8dee2aaSAndroid Build Coastguard Worker fCanvas->drawRect(r, paint);
179*c8dee2aaSAndroid Build Coastguard Worker }
180*c8dee2aaSAndroid Build Coastguard Worker };
181*c8dee2aaSAndroid Build Coastguard Worker
182*c8dee2aaSAndroid Build Coastguard Worker // We use this static factory function instead of the regular constructor so
183*c8dee2aaSAndroid Build Coastguard Worker // that we can create the pixel data before calling the constructor. This is
184*c8dee2aaSAndroid Build Coastguard Worker // required so that we can call the base class' constructor with the pixel
185*c8dee2aaSAndroid Build Coastguard Worker // data.
Create(int width,int height,bool is_opaque,SkRasterHandleAllocator::Rec * rec)186*c8dee2aaSAndroid Build Coastguard Worker static bool Create(int width, int height, bool is_opaque, SkRasterHandleAllocator::Rec* rec) {
187*c8dee2aaSAndroid Build Coastguard Worker BITMAPINFOHEADER hdr;
188*c8dee2aaSAndroid Build Coastguard Worker memset(&hdr, 0, sizeof(hdr));
189*c8dee2aaSAndroid Build Coastguard Worker hdr.biSize = sizeof(BITMAPINFOHEADER);
190*c8dee2aaSAndroid Build Coastguard Worker hdr.biWidth = width;
191*c8dee2aaSAndroid Build Coastguard Worker hdr.biHeight = -height; // Minus means top-down bitmap.
192*c8dee2aaSAndroid Build Coastguard Worker hdr.biPlanes = 1;
193*c8dee2aaSAndroid Build Coastguard Worker hdr.biBitCount = 32;
194*c8dee2aaSAndroid Build Coastguard Worker hdr.biCompression = BI_RGB; // No compression.
195*c8dee2aaSAndroid Build Coastguard Worker hdr.biSizeImage = 0;
196*c8dee2aaSAndroid Build Coastguard Worker hdr.biXPelsPerMeter = 1;
197*c8dee2aaSAndroid Build Coastguard Worker hdr.biYPelsPerMeter = 1;
198*c8dee2aaSAndroid Build Coastguard Worker void* pixels;
199*c8dee2aaSAndroid Build Coastguard Worker HBITMAP hbitmap = CreateDIBSection(nullptr, (const BITMAPINFO*)&hdr, 0, &pixels, 0, 0);
200*c8dee2aaSAndroid Build Coastguard Worker if (!hbitmap) {
201*c8dee2aaSAndroid Build Coastguard Worker return false;
202*c8dee2aaSAndroid Build Coastguard Worker }
203*c8dee2aaSAndroid Build Coastguard Worker
204*c8dee2aaSAndroid Build Coastguard Worker size_t row_bytes = width * sizeof(SkPMColor);
205*c8dee2aaSAndroid Build Coastguard Worker sk_bzero(pixels, row_bytes * height);
206*c8dee2aaSAndroid Build Coastguard Worker
207*c8dee2aaSAndroid Build Coastguard Worker HDC hdc = CreateCompatibleDC(nullptr);
208*c8dee2aaSAndroid Build Coastguard Worker if (!hdc) {
209*c8dee2aaSAndroid Build Coastguard Worker DeleteObject(hbitmap);
210*c8dee2aaSAndroid Build Coastguard Worker return false;
211*c8dee2aaSAndroid Build Coastguard Worker }
212*c8dee2aaSAndroid Build Coastguard Worker SetGraphicsMode(hdc, GM_ADVANCED);
213*c8dee2aaSAndroid Build Coastguard Worker HGDIOBJ origBitmap = SelectObject(hdc, hbitmap);
214*c8dee2aaSAndroid Build Coastguard Worker
215*c8dee2aaSAndroid Build Coastguard Worker struct ReleaseContext {
216*c8dee2aaSAndroid Build Coastguard Worker HDC hdc;
217*c8dee2aaSAndroid Build Coastguard Worker HGDIOBJ hbitmap;
218*c8dee2aaSAndroid Build Coastguard Worker };
219*c8dee2aaSAndroid Build Coastguard Worker rec->fReleaseProc = [](void*, void* context) {
220*c8dee2aaSAndroid Build Coastguard Worker ReleaseContext* ctx = static_cast<ReleaseContext*>(context);
221*c8dee2aaSAndroid Build Coastguard Worker HBITMAP hbitmap = static_cast<HBITMAP>(SelectObject(ctx->hdc, ctx->hbitmap));
222*c8dee2aaSAndroid Build Coastguard Worker DeleteObject(hbitmap);
223*c8dee2aaSAndroid Build Coastguard Worker DeleteDC(ctx->hdc);
224*c8dee2aaSAndroid Build Coastguard Worker delete ctx;
225*c8dee2aaSAndroid Build Coastguard Worker };
226*c8dee2aaSAndroid Build Coastguard Worker rec->fReleaseCtx = new ReleaseContext{hdc, origBitmap};
227*c8dee2aaSAndroid Build Coastguard Worker rec->fPixels = pixels;
228*c8dee2aaSAndroid Build Coastguard Worker rec->fRowBytes = row_bytes;
229*c8dee2aaSAndroid Build Coastguard Worker rec->fHandle = hdc;
230*c8dee2aaSAndroid Build Coastguard Worker return true;
231*c8dee2aaSAndroid Build Coastguard Worker }
232*c8dee2aaSAndroid Build Coastguard Worker
233*c8dee2aaSAndroid Build Coastguard Worker /**
234*c8dee2aaSAndroid Build Coastguard Worker * Subclass of SkRasterHandleAllocator that returns an HDC as its "handle".
235*c8dee2aaSAndroid Build Coastguard Worker */
236*c8dee2aaSAndroid Build Coastguard Worker class GDIAllocator : public SkRasterHandleAllocator {
237*c8dee2aaSAndroid Build Coastguard Worker public:
GDIAllocator()238*c8dee2aaSAndroid Build Coastguard Worker GDIAllocator() {}
239*c8dee2aaSAndroid Build Coastguard Worker
allocHandle(const SkImageInfo & info,Rec * rec)240*c8dee2aaSAndroid Build Coastguard Worker bool allocHandle(const SkImageInfo& info, Rec* rec) override {
241*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(info.colorType() == kN32_SkColorType);
242*c8dee2aaSAndroid Build Coastguard Worker return Create(info.width(), info.height(), info.isOpaque(), rec);
243*c8dee2aaSAndroid Build Coastguard Worker }
244*c8dee2aaSAndroid Build Coastguard Worker
updateHandle(Handle handle,const SkMatrix & ctm,const SkIRect & clip_bounds)245*c8dee2aaSAndroid Build Coastguard Worker void updateHandle(Handle handle, const SkMatrix& ctm, const SkIRect& clip_bounds) override {
246*c8dee2aaSAndroid Build Coastguard Worker HDC hdc = static_cast<HDC>(handle);
247*c8dee2aaSAndroid Build Coastguard Worker
248*c8dee2aaSAndroid Build Coastguard Worker XFORM xf;
249*c8dee2aaSAndroid Build Coastguard Worker xf.eM11 = ctm[SkMatrix::kMScaleX];
250*c8dee2aaSAndroid Build Coastguard Worker xf.eM21 = ctm[SkMatrix::kMSkewX];
251*c8dee2aaSAndroid Build Coastguard Worker xf.eDx = ctm[SkMatrix::kMTransX];
252*c8dee2aaSAndroid Build Coastguard Worker xf.eM12 = ctm[SkMatrix::kMSkewY];
253*c8dee2aaSAndroid Build Coastguard Worker xf.eM22 = ctm[SkMatrix::kMScaleY];
254*c8dee2aaSAndroid Build Coastguard Worker xf.eDy = ctm[SkMatrix::kMTransY];
255*c8dee2aaSAndroid Build Coastguard Worker SetWorldTransform(hdc, &xf);
256*c8dee2aaSAndroid Build Coastguard Worker
257*c8dee2aaSAndroid Build Coastguard Worker RECT clip_bounds_RECT = toRECT(clip_bounds);
258*c8dee2aaSAndroid Build Coastguard Worker HRGN hrgn = CreateRectRgnIndirect(&clip_bounds_RECT);
259*c8dee2aaSAndroid Build Coastguard Worker [[maybe_unused]] int result = SelectClipRgn(hdc, hrgn);
260*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(result != ERROR);
261*c8dee2aaSAndroid Build Coastguard Worker result = DeleteObject(hrgn);
262*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(result != 0);
263*c8dee2aaSAndroid Build Coastguard Worker }
264*c8dee2aaSAndroid Build Coastguard Worker };
265*c8dee2aaSAndroid Build Coastguard Worker
266*c8dee2aaSAndroid Build Coastguard Worker using MyPort = GDIGraphicsPort;
267*c8dee2aaSAndroid Build Coastguard Worker using MyAllocator = GDIAllocator;
268*c8dee2aaSAndroid Build Coastguard Worker
269*c8dee2aaSAndroid Build Coastguard Worker #else
270*c8dee2aaSAndroid Build Coastguard Worker
271*c8dee2aaSAndroid Build Coastguard Worker using MyPort = SkiaGraphicsPort;
272*c8dee2aaSAndroid Build Coastguard Worker using MyAllocator = SkiaAllocator;
273*c8dee2aaSAndroid Build Coastguard Worker
274*c8dee2aaSAndroid Build Coastguard Worker #endif
275*c8dee2aaSAndroid Build Coastguard Worker
276*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM(rasterallocator, canvas, 600, 300) {
__anon7f76a8b00402(GraphicsPort* port) 277*c8dee2aaSAndroid Build Coastguard Worker auto doDraw = [](GraphicsPort* port) {
278*c8dee2aaSAndroid Build Coastguard Worker SkAutoCanvasRestore acr(port->peekCanvas(), true);
279*c8dee2aaSAndroid Build Coastguard Worker
280*c8dee2aaSAndroid Build Coastguard Worker port->drawRect({0, 0, 256, 256}, SK_ColorRED);
281*c8dee2aaSAndroid Build Coastguard Worker port->save();
282*c8dee2aaSAndroid Build Coastguard Worker port->translate(30, 30);
283*c8dee2aaSAndroid Build Coastguard Worker port->drawRect({0, 0, 30, 30}, SK_ColorBLUE);
284*c8dee2aaSAndroid Build Coastguard Worker port->drawOval({10, 10, 20, 20}, SK_ColorWHITE);
285*c8dee2aaSAndroid Build Coastguard Worker port->restore();
286*c8dee2aaSAndroid Build Coastguard Worker
287*c8dee2aaSAndroid Build Coastguard Worker port->saveLayer({50, 50, 100, 100}, 0x80);
288*c8dee2aaSAndroid Build Coastguard Worker port->drawRect({55, 55, 95, 95}, SK_ColorGREEN);
289*c8dee2aaSAndroid Build Coastguard Worker port->restore();
290*c8dee2aaSAndroid Build Coastguard Worker
291*c8dee2aaSAndroid Build Coastguard Worker port->clip({150, 50, 200, 200});
292*c8dee2aaSAndroid Build Coastguard Worker port->drawRect({0, 0, 256, 256}, 0xFFCCCCCC);
293*c8dee2aaSAndroid Build Coastguard Worker };
294*c8dee2aaSAndroid Build Coastguard Worker
295*c8dee2aaSAndroid Build Coastguard Worker // TODO: this common code fails pic-8888 and serialize-8888
296*c8dee2aaSAndroid Build Coastguard Worker //GraphicsPort skiaPort(canvas);
297*c8dee2aaSAndroid Build Coastguard Worker //doDraw(&skiaPort);
298*c8dee2aaSAndroid Build Coastguard Worker
299*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo info = SkImageInfo::MakeN32Premul(256, 256);
300*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkCanvas> nativeCanvas =
301*c8dee2aaSAndroid Build Coastguard Worker SkRasterHandleAllocator::MakeCanvas(std::make_unique<MyAllocator>(), info);
302*c8dee2aaSAndroid Build Coastguard Worker MyPort nativePort(nativeCanvas.get());
303*c8dee2aaSAndroid Build Coastguard Worker doDraw(&nativePort);
304*c8dee2aaSAndroid Build Coastguard Worker
305*c8dee2aaSAndroid Build Coastguard Worker SkPixmap pm;
306*c8dee2aaSAndroid Build Coastguard Worker nativeCanvas->peekPixels(&pm);
307*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(SkImages::RasterFromPixmapCopy(pm), 280, 0);
308*c8dee2aaSAndroid Build Coastguard Worker }
309