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