blob: 11eb24c999505b3b36edfb57a2cc91e6ce0a4baf [file] [log] [blame]
Cary Clark8032b982017-07-28 11:04:54 -04001#Topic Canvas
Cary Clark137b8742018-05-30 09:21:49 -04002#Alias Canvas_Reference ##
Cary Clark8032b982017-07-28 11:04:54 -04003
Cary Clarke4aa3712017-09-15 02:56:12 -04004#Class SkCanvas
5
Cary Clark61313f32018-10-08 14:57:48 -04006#Code
7#Populate
8##
9
Cary Clark8032b982017-07-28 11:04:54 -040010Canvas provides an interface for drawing, and how the drawing is clipped and transformed.
11Canvas contains a stack of Matrix and Clip values.
12
13Canvas and Paint together provide the state to draw into Surface or Device.
Cary Clarkbad5ad72017-08-03 17:14:08 -040014Each Canvas draw call transforms the geometry of the object by the concatenation of all
15Matrix values in the stack. The transformed geometry is clipped by the intersection
16of all of Clip values in the stack. The Canvas draw calls use Paint to supply drawing
17state such as Color, Typeface, text size, stroke width, Shader and so on.
Cary Clark8032b982017-07-28 11:04:54 -040018
Herb Derbyefe39bc2018-05-01 17:06:20 -040019To draw to a pixel-based destination, create Raster_Surface or GPU_Surface.
20Request Canvas from Surface to obtain the interface to draw.
21Canvas generated by Raster_Surface draws to memory visible to the CPU.
Cary Clark8032b982017-07-28 11:04:54 -040022Canvas generated by GPU_Surface uses Vulkan or OpenGL to draw to the GPU.
23
Cary Clarkbad5ad72017-08-03 17:14:08 -040024To draw to a document, obtain Canvas from SVG_Canvas, Document_PDF, or Picture_Recorder.
Cary Clark09d80c02018-10-31 12:14:03 -040025Document based Canvas and other Canvas subclasses reference Device describing the
Cary Clarkbad5ad72017-08-03 17:14:08 -040026destination.
27
Cary Clark8032b982017-07-28 11:04:54 -040028Canvas can be constructed to draw to Bitmap without first creating Raster_Surface.
Herb Derbyefe39bc2018-05-01 17:06:20 -040029This approach may be deprecated in the future.
Cary Clark8032b982017-07-28 11:04:54 -040030
Cary Clark09d80c02018-10-31 12:14:03 -040031Canvas may be created directly when no Surface is required; some Canvas methods
32implicitly create Raster_Surface.
Cary Clark8032b982017-07-28 11:04:54 -040033
34# ------------------------------------------------------------------------------
35
Cary Clarka560c472017-11-27 10:44:06 -050036#Method static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo& info, void* pixels,
37 size_t rowBytes,
38 const SkSurfaceProps* props = nullptr)
Cary Clark61313f32018-10-08 14:57:48 -040039#In Constructors
Cary Clarkab2621d2018-01-30 10:08:57 -050040#Line # creates from SkImageInfo and Pixel_Storage ##
Cary Clark09d80c02018-10-31 12:14:03 -040041#Populate
Cary Clark8032b982017-07-28 11:04:54 -040042
43#Example
44 #Description
45 Allocates a three by three bitmap, clears it to white, and draws a black pixel
46 in the center.
47 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -040048void draw(SkCanvas* ) {
Cary Clarkce101242017-09-01 15:51:02 -040049 SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3); // device aligned, 32 bpp, Premultiplied
Cary Clarkbad5ad72017-08-03 17:14:08 -040050 const size_t minRowBytes = info.minRowBytes(); // bytes used by one bitmap row
Cary Clarka560c472017-11-27 10:44:06 -050051 const size_t size = info.computeMinByteSize(); // bytes used by all rows
Cary Clarkbad5ad72017-08-03 17:14:08 -040052 SkAutoTMalloc<SkPMColor> storage(size); // allocate storage for pixels
53 SkPMColor* pixels = storage.get(); // get pointer to allocated storage
54 // create a SkCanvas backed by a raster device, and delete it when the
55 // function goes out of scope.
56 std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(info, pixels, minRowBytes);
Cary Clarkce101242017-09-01 15:51:02 -040057 canvas->clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order
Cary Clarkbad5ad72017-08-03 17:14:08 -040058 canvas->flush(); // ensure that pixels are cleared
Cary Clarkce101242017-09-01 15:51:02 -040059 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary
Cary Clarkbad5ad72017-08-03 17:14:08 -040060 SkPaint paint; // by default, draws black
61 canvas->drawPoint(1, 1, paint); // draw in the center
62 canvas->flush(); // ensure that point was drawn
63 for (int y = 0; y < info.height(); ++y) {
64 for (int x = 0; x < info.width(); ++x) {
65 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
66 }
67 SkDebugf("\n");
68 }
Cary Clark8032b982017-07-28 11:04:54 -040069}
70 #StdOut
71 ---
72 -x-
73 ---
74 ##
75##
76
Cary Clark8032b982017-07-28 11:04:54 -040077#SeeAlso MakeRasterDirectN32 SkSurface::MakeRasterDirect
Cary Clark2ade9972017-11-02 17:49:34 -040078
Cary Clark8032b982017-07-28 11:04:54 -040079##
80
81# ------------------------------------------------------------------------------
82
83#Method static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels,
Herb Derbyefe39bc2018-05-01 17:06:20 -040084 size_t rowBytes)
Cary Clark61313f32018-10-08 14:57:48 -040085#In Constructors
Cary Clarkab2621d2018-01-30 10:08:57 -050086#Line # creates from image data and Pixel_Storage ##
Cary Clark09d80c02018-10-31 12:14:03 -040087#Populate
Cary Clark8032b982017-07-28 11:04:54 -040088
89#Example
90 #Description
91 Allocates a three by three bitmap, clears it to white, and draws a black pixel
92 in the center.
93 ##
94void draw(SkCanvas* ) {
95 const int width = 3;
96 const int height = 3;
Cary Clark77b3f3a2018-11-07 14:59:03 -050097 SkPMColor pixels[height][width]; // allocate a 3 by 3 Premultiplied bitmap on the stack
Cary Clark8032b982017-07-28 11:04:54 -040098 // create a SkCanvas backed by a raster device, and delete it when the
99 // function goes out of scope.
100 std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirectN32(
101 width,
102 height,
Cary Clarkbc5697d2017-10-04 14:31:33 -0400103 pixels[0], // top-left of the bitmap
Cary Clark8032b982017-07-28 11:04:54 -0400104 sizeof(pixels[0])); // byte width of the each row
Cary Clark682c58d2018-05-16 07:07:07 -0400105 // write a Premultiplied value for white into all pixels in the bitmap
Cary Clark8032b982017-07-28 11:04:54 -0400106 canvas->clear(SK_ColorWHITE);
Cary Clarkce101242017-09-01 15:51:02 -0400107 SkPMColor pmWhite = pixels[0][0]; // the Premultiplied format may vary
Cary Clark8032b982017-07-28 11:04:54 -0400108 SkPaint paint; // by default, draws black
109 canvas->drawPoint(1, 1, paint); // draw in the center
110 canvas->flush(); // ensure that pixels is ready to be read
111 for (int y = 0; y < height; ++y) {
112 for (int x = 0; x < width; ++x) {
113 SkDebugf("%c", pixels[y][x] == pmWhite ? '-' : 'x');
114 }
115 SkDebugf("\n");
116 }
117}
118 #StdOut
119 ---
120 -x-
121 ---
122 ##
123##
124
Cary Clark2ade9972017-11-02 17:49:34 -0400125#SeeAlso MakeRasterDirect SkSurface::MakeRasterDirect SkImageInfo::MakeN32Premul
Cary Clark8032b982017-07-28 11:04:54 -0400126
127##
128
129# ------------------------------------------------------------------------------
130
131#Method SkCanvas()
132
Cary Clarkab2621d2018-01-30 10:08:57 -0500133#Line # creates with no Surface, no dimensions ##
Cary Clark09d80c02018-10-31 12:14:03 -0400134#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400135
136#Example
137
138#Description
139Passes a placeholder to a function that requires one.
140##
141
142#Function
Mike Reed07055a32018-10-23 13:57:46 -0400143static void check_for_rotated_ctm(const SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -0400144 const SkMatrix& matrix = canvas->getTotalMatrix();
Mike Reed07055a32018-10-23 13:57:46 -0400145 SkDebugf("rect stays rect is %s\n", matrix.rectStaysRect() ? "true" : "false");
Cary Clarkbad5ad72017-08-03 17:14:08 -0400146}
147
Cary Clark8032b982017-07-28 11:04:54 -0400148##
Cary Clarkbad5ad72017-08-03 17:14:08 -0400149void draw(SkCanvas* canvas) {
Mike Reed07055a32018-10-23 13:57:46 -0400150 check_for_rotated_ctm(canvas);
151 canvas->rotate(30);
152 check_for_rotated_ctm(canvas);
153
154 SkCanvas defaultCanvas;
155 check_for_rotated_ctm(&defaultCanvas);
Cary Clarkbad5ad72017-08-03 17:14:08 -0400156}
Cary Clark8032b982017-07-28 11:04:54 -0400157
158 #StdOut
Mike Reed07055a32018-10-23 13:57:46 -0400159 rect stays rect is true
160 rect stays rect is false
161 rect stays rect is true
Cary Clark8032b982017-07-28 11:04:54 -0400162 ##
163##
164
Cary Clark2ade9972017-11-02 17:49:34 -0400165#SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas
Cary Clark8032b982017-07-28 11:04:54 -0400166
167##
168
169# ------------------------------------------------------------------------------
170
Cary Clark73fa9722017-08-29 17:36:51 -0400171#Method SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr)
Cary Clark8032b982017-07-28 11:04:54 -0400172
Cary Clark682c58d2018-05-16 07:07:07 -0400173#Line # creates with no Surface, set dimensions, Surface_Properties ##
Cary Clark09d80c02018-10-31 12:14:03 -0400174#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400175
176#Example
177 SkCanvas canvas(10, 20); // 10 units wide, 20 units high
178 canvas.clipRect(SkRect::MakeXYWH(30, 40, 5, 10)); // clip is outside canvas' device
179 SkDebugf("canvas %s empty\n", canvas.getDeviceClipBounds().isEmpty() ? "is" : "is not");
180
181 #StdOut
182 canvas is empty
183 ##
184##
185
Cary Clark2ade9972017-11-02 17:49:34 -0400186#SeeAlso MakeRasterDirect SkSurfaceProps SkPixelGeometry SkCreateColorSpaceXformCanvas
Cary Clark8032b982017-07-28 11:04:54 -0400187
188##
189
190# ------------------------------------------------------------------------------
191
Herb Derbyefe39bc2018-05-01 17:06:20 -0400192#Method explicit SkCanvas(sk_sp<SkBaseDevice> device)
Cary Clark4855f782018-02-06 09:41:53 -0500193#Deprecated soon
Cary Clark8032b982017-07-28 11:04:54 -0400194##
195
196# ------------------------------------------------------------------------------
197
198#Method explicit SkCanvas(const SkBitmap& bitmap)
199
Cary Clarkab2621d2018-01-30 10:08:57 -0500200#Line # uses existing Bitmap ##
Cary Clark09d80c02018-10-31 12:14:03 -0400201#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400202
203#Example
204#Description
205The actual output depends on the installed fonts.
206##
207 SkBitmap bitmap;
208 // create a bitmap 5 wide and 11 high
209 bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11));
210 SkCanvas canvas(bitmap);
Cary Clarkce101242017-09-01 15:51:02 -0400211 canvas.clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order
Cary Clark8032b982017-07-28 11:04:54 -0400212 SkPixmap pixmap; // provides guaranteed access to the drawn pixels
213 if (!canvas.peekPixels(&pixmap)) {
214 SkDebugf("peekPixels should never fail.\n");
215 }
Cary Clarkbc5697d2017-10-04 14:31:33 -0400216 const SkPMColor* pixels = pixmap.addr32(); // points to top-left of bitmap
Cary Clarkce101242017-09-01 15:51:02 -0400217 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary
Cary Clark8032b982017-07-28 11:04:54 -0400218 SkPaint paint; // by default, draws black, 12 point text
219 canvas.drawString("!", 1, 10, paint); // 1 char at baseline (1, 10)
220 for (int y = 0; y < bitmap.height(); ++y) {
221 for (int x = 0; x < bitmap.width(); ++x) {
222 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
223 }
224 SkDebugf("\n");
225 }
226
227 #StdOut
Cary Clarkd0530ba2017-09-14 11:25:39 -0400228 -----
229 ---x-
230 ---x-
231 ---x-
232 ---x-
233 ---x-
234 ---x-
235 -----
236 ---x-
237 ---x-
Cary Clark8032b982017-07-28 11:04:54 -0400238 -----
239 #StdOut ##
240##
241
Cary Clark2ade9972017-11-02 17:49:34 -0400242#SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas
Cary Clark8032b982017-07-28 11:04:54 -0400243
244##
245
Cary Clarkbad5ad72017-08-03 17:14:08 -0400246#EnumClass ColorBehavior
Cary Clark682c58d2018-05-16 07:07:07 -0400247#Line # exists for Android framework only ##
Cary Clark8032b982017-07-28 11:04:54 -0400248#Private
249Android framework only.
250##
251
252#Code
Cary Clark61313f32018-10-08 14:57:48 -0400253#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400254##
255#Const kLegacy 0
Cary Clark682c58d2018-05-16 07:07:07 -0400256#Line # placeholder ##
Cary Clarkbad5ad72017-08-03 17:14:08 -0400257 Is a placeholder to allow specialized constructor; has no meaning.
Cary Clark8032b982017-07-28 11:04:54 -0400258##
259##
260
Cary Clarkbad5ad72017-08-03 17:14:08 -0400261#Method SkCanvas(const SkBitmap& bitmap, ColorBehavior behavior)
262
Cary Clark682c58d2018-05-16 07:07:07 -0400263#Line # exists for Android framework only ##
Cary Clark09d80c02018-10-31 12:14:03 -0400264#Populate
Cary Clarkbad5ad72017-08-03 17:14:08 -0400265
266#NoExample
267##
268##
Cary Clark8032b982017-07-28 11:04:54 -0400269
270# ------------------------------------------------------------------------------
271
272#Method SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
273
Cary Clarkab2621d2018-01-30 10:08:57 -0500274#Line # uses existing Bitmap and Surface_Properties ##
Cary Clark09d80c02018-10-31 12:14:03 -0400275#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400276
277#Example
278#Description
279The actual output depends on the installed fonts.
280##
281 SkBitmap bitmap;
282 // create a bitmap 5 wide and 11 high
283 bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11));
284 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
Cary Clarkce101242017-09-01 15:51:02 -0400285 canvas.clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order
Cary Clark8032b982017-07-28 11:04:54 -0400286 SkPixmap pixmap; // provides guaranteed access to the drawn pixels
287 if (!canvas.peekPixels(&pixmap)) {
288 SkDebugf("peekPixels should never fail.\n");
289 }
Cary Clarkbc5697d2017-10-04 14:31:33 -0400290 const SkPMColor* pixels = pixmap.addr32(); // points to top-left of bitmap
Cary Clarkce101242017-09-01 15:51:02 -0400291 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary
Cary Clark8032b982017-07-28 11:04:54 -0400292 SkPaint paint; // by default, draws black, 12 point text
293 canvas.drawString("!", 1, 10, paint); // 1 char at baseline (1, 10)
294 for (int y = 0; y < bitmap.height(); ++y) {
295 for (int x = 0; x < bitmap.width(); ++x) {
296 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
297 }
298 SkDebugf("\n");
299 }
300
301 #StdOut
302 -----
303 ---x-
304 ---x-
305 ---x-
306 ---x-
307 ---x-
308 ---x-
309 -----
310 ---x-
311 ---x-
312 -----
313 #StdOut ##
314##
315
Cary Clark2ade9972017-11-02 17:49:34 -0400316#SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas
Cary Clark8032b982017-07-28 11:04:54 -0400317
318##
319
320# ------------------------------------------------------------------------------
321
322#Method virtual ~SkCanvas()
323
Cary Clarkab2621d2018-01-30 10:08:57 -0500324#Line # draws saved Layers, frees resources ##
Cary Clark09d80c02018-10-31 12:14:03 -0400325#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400326
327#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -0400328#Description
Cary Clarkce101242017-09-01 15:51:02 -0400329Canvas Layer draws into bitmap. saveLayerAlpha sets up an additional
330drawing surface that blends with the bitmap. When Layer goes out of
Cary Clark09d80c02018-10-31 12:14:03 -0400331scope, Layer destructor is called. The saved Layer is restored, drawing
Cary Clarkbad5ad72017-08-03 17:14:08 -0400332transparent letters.
333##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400334void draw(SkCanvas* canvas) {
335 SkBitmap bitmap;
336 bitmap.allocPixels(SkImageInfo::MakeN32Premul(200, 200));
337 {
338 SkCanvas offscreen(bitmap);
339 SkPaint paint;
340 paint.setTextSize(100);
341 offscreen.drawString("ABC", 20, 160, paint);
342 SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192);
343 offscreen.saveLayerAlpha(&layerBounds, 128);
344 offscreen.clear(SK_ColorWHITE);
345 offscreen.drawString("DEF", 20, 160, paint);
346 }
347 canvas->drawBitmap(bitmap, 0, 0, nullptr);
Cary Clarkbad5ad72017-08-03 17:14:08 -0400348}
Cary Clark8032b982017-07-28 11:04:54 -0400349##
350
Cary Clarkbad5ad72017-08-03 17:14:08 -0400351#SeeAlso State_Stack
Cary Clark8032b982017-07-28 11:04:54 -0400352
353##
354
355# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -0500356#Subtopic Property
Cary Clark78de7512018-02-07 07:27:09 -0500357#Line # metrics and attributes ##
358##
Cary Clark8032b982017-07-28 11:04:54 -0400359
360#Method SkMetaData& getMetaData()
Cary Clark78de7512018-02-07 07:27:09 -0500361#In Property
362#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -0500363#Line # associates additional data with the canvas ##
Cary Clark09d80c02018-10-31 12:14:03 -0400364#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400365
366#Example
367 const char* kHelloMetaData = "HelloMetaData";
368 SkCanvas canvas;
369 SkMetaData& metaData = canvas.getMetaData();
370 SkDebugf("before: %s\n", metaData.findString(kHelloMetaData));
371 metaData.setString(kHelloMetaData, "Hello!");
372 SkDebugf("during: %s\n", metaData.findString(kHelloMetaData));
373 metaData.removeString(kHelloMetaData);
374 SkDebugf("after: %s\n", metaData.findString(kHelloMetaData));
375
376 #StdOut
377 before: (null)
378 during: Hello!
379 after: (null)
380 #StdOut ##
381##
382
Cary Clark2ade9972017-11-02 17:49:34 -0400383#SeeAlso SkMetaData
Cary Clark8032b982017-07-28 11:04:54 -0400384
385##
386
387# ------------------------------------------------------------------------------
388
389#Method SkImageInfo imageInfo() const
Cary Clark78de7512018-02-07 07:27:09 -0500390#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500391#Line # returns Image_Info for Canvas ##
Cary Clark09d80c02018-10-31 12:14:03 -0400392#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400393
394#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -0400395 SkCanvas emptyCanvas;
396 SkImageInfo canvasInfo = emptyCanvas.imageInfo();
397 SkImageInfo emptyInfo;
398 SkDebugf("emptyInfo %c= canvasInfo\n", emptyInfo == canvasInfo ? '=' : '!');
399
400 #StdOut
401 emptyInfo == canvasInfo
402 ##
Cary Clark8032b982017-07-28 11:04:54 -0400403##
404
Cary Clark2ade9972017-11-02 17:49:34 -0400405#SeeAlso SkImageInfo MakeRasterDirect makeSurface
Cary Clark8032b982017-07-28 11:04:54 -0400406
407##
408
409# ------------------------------------------------------------------------------
410
411#Method bool getProps(SkSurfaceProps* props) const
Cary Clark78de7512018-02-07 07:27:09 -0500412#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500413#Line # copies Surface_Properties if available ##
Cary Clark09d80c02018-10-31 12:14:03 -0400414#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400415
416#Example
417 SkBitmap bitmap;
418 SkCanvas canvas(bitmap, SkSurfaceProps(0, kRGB_V_SkPixelGeometry));
419 SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
420 SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry()));
421 if (!canvas.getProps(&surfaceProps)) {
422 SkDebugf("getProps failed unexpectedly.\n");
423 }
424 SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry()));
425
426 #StdOut
427 isRGB:0
428 isRGB:1
429 #StdOut ##
430##
431
Cary Clark2ade9972017-11-02 17:49:34 -0400432#SeeAlso SkSurfaceProps makeSurface
Cary Clark8032b982017-07-28 11:04:54 -0400433
434##
435
436# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -0500437#Subtopic Utility
Cary Clark78de7512018-02-07 07:27:09 -0500438#Line # rarely called management functions ##
439##
Cary Clark8032b982017-07-28 11:04:54 -0400440
441#Method void flush()
Cary Clark78de7512018-02-07 07:27:09 -0500442#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -0500443#Line # triggers execution of all pending draw operations ##
Cary Clark09d80c02018-10-31 12:14:03 -0400444#Populate
Cary Clark2ade9972017-11-02 17:49:34 -0400445
Cary Clark08895c42018-02-01 09:37:32 -0500446#NoExample
Cary Clark8032b982017-07-28 11:04:54 -0400447##
448
Cary Clark77b3f3a2018-11-07 14:59:03 -0500449#SeeAlso peekPixels SkSurface::flush GrContext::flush SkSurface::prepareForExternalIO GrContext::abandonContext
Cary Clark8032b982017-07-28 11:04:54 -0400450
451##
452
453# ------------------------------------------------------------------------------
454
455#Method virtual SkISize getBaseLayerSize() const
Cary Clark78de7512018-02-07 07:27:09 -0500456#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500457#Line # returns size of base Layer in global coordinates ##
Cary Clark09d80c02018-10-31 12:14:03 -0400458#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400459
460#Example
461 SkBitmap bitmap;
462 bitmap.allocPixels(SkImageInfo::MakeN32Premul(20, 30));
463 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
464 canvas.clipRect(SkRect::MakeWH(10, 40));
465 SkIRect clipDeviceBounds = canvas.getDeviceClipBounds();
466 if (clipDeviceBounds.isEmpty()) {
467 SkDebugf("Empty clip bounds is unexpected!\n");
468 }
469 SkDebugf("clip=%d,%d\n", clipDeviceBounds.width(), clipDeviceBounds.height());
470 SkISize baseLayerSize = canvas.getBaseLayerSize();
471 SkDebugf("size=%d,%d\n", baseLayerSize.width(), baseLayerSize.height());
472
473 #StdOut
474 clip=10,30
475 size=20,30
476 ##
477##
478
479#ToDo is this the same as the width and height of surface? ##
480
Cary Clark2ade9972017-11-02 17:49:34 -0400481#SeeAlso getDeviceClipBounds
482
Cary Clark8032b982017-07-28 11:04:54 -0400483##
484
485# ------------------------------------------------------------------------------
486
487#Method sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr)
Cary Clark61313f32018-10-08 14:57:48 -0400488#In Constructors
Cary Clarkab2621d2018-01-30 10:08:57 -0500489#Line # creates Surface matching SkImageInfo and SkSurfaceProps ##
Cary Clark09d80c02018-10-31 12:14:03 -0400490#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400491
492#Example
493 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(5, 6);
494 SkCanvas* smallCanvas = surface->getCanvas();
495 SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(3, 4);
496 sk_sp<SkSurface> compatible = smallCanvas->makeSurface(imageInfo);
497 SkDebugf("compatible %c= nullptr\n", compatible == nullptr ? '=' : '!');
498 SkDebugf("size = %d, %d\n", compatible->width(), compatible->height());
499
500 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -0400501 compatible != nullptr
Cary Clark8032b982017-07-28 11:04:54 -0400502 size = 3, 4
503 ##
504##
505
Cary Clark2ade9972017-11-02 17:49:34 -0400506#SeeAlso SkSurface SkSurface::makeSurface SkImageInfo SkSurfaceProps
Cary Clark8032b982017-07-28 11:04:54 -0400507
508##
509
510# ------------------------------------------------------------------------------
511
512#Method virtual GrContext* getGrContext()
Cary Clark78de7512018-02-07 07:27:09 -0500513#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500514#Line # returns GPU_Context of the GPU_Surface ##
Cary Clark09d80c02018-10-31 12:14:03 -0400515#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400516
517#Example
518void draw(SkCanvas* canvas) {
519 if (canvas->getGrContext()) {
520 canvas->clear(SK_ColorRED);
521 } else {
522 canvas->clear(SK_ColorBLUE);
523 }
524}
525##
526
527#ToDo fiddle should show both CPU and GPU out ##
528
Herb Derbyefe39bc2018-05-01 17:06:20 -0400529#SeeAlso GrContext
Cary Clark2ade9972017-11-02 17:49:34 -0400530
Cary Clark8032b982017-07-28 11:04:54 -0400531##
532
533# ------------------------------------------------------------------------------
534
Cary Clark73fa9722017-08-29 17:36:51 -0400535#Method void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = nullptr)
Cary Clark78de7512018-02-07 07:27:09 -0500536#In Utility
537#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500538#Line # returns writable pixel access if available ##
Cary Clark09d80c02018-10-31 12:14:03 -0400539#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400540
541#Example
542void draw(SkCanvas* canvas) {
543 if (canvas->accessTopLayerPixels(nullptr, nullptr)) {
544 canvas->clear(SK_ColorRED);
545 } else {
546 canvas->clear(SK_ColorBLUE);
547 }
548}
549##
550
551#Example
552#Description
Cary Clarkce101242017-09-01 15:51:02 -0400553Draws "ABC" on the device. Then draws "DEF" in Layer, and reads
554Layer to add a large dotted "DEF". Finally blends Layer with the
Herb Derbyefe39bc2018-05-01 17:06:20 -0400555device.
Cary Clark8032b982017-07-28 11:04:54 -0400556
Cary Clarkce101242017-09-01 15:51:02 -0400557The Layer and blended result appear on the CPU and GPU but the large dotted
Cary Clark8032b982017-07-28 11:04:54 -0400558"DEF" appear only on the CPU.
559##
560void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -0400561 SkPaint paint;
562 paint.setTextSize(100);
563 canvas->drawString("ABC", 20, 160, paint);
564 SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192);
565 canvas->saveLayerAlpha(&layerBounds, 128);
566 canvas->clear(SK_ColorWHITE);
567 canvas->drawString("DEF", 20, 160, paint);
568 SkImageInfo imageInfo;
569 size_t rowBytes;
570 SkIPoint origin;
571 uint32_t* access = (uint32_t*) canvas->accessTopLayerPixels(&imageInfo, &rowBytes, &origin);
572 if (access) {
573 int h = imageInfo.height();
574 int v = imageInfo.width();
575 int rowWords = rowBytes / sizeof(uint32_t);
576 for (int y = 0; y < h; ++y) {
577 int newY = (y - h / 2) * 2 + h / 2;
578 if (newY < 0 || newY >= h) {
579 continue;
580 }
581 for (int x = 0; x < v; ++x) {
582 int newX = (x - v / 2) * 2 + v / 2;
583 if (newX < 0 || newX >= v) {
584 continue;
585 }
586 if (access[y * rowWords + x] == SK_ColorBLACK) {
587 access[newY * rowWords + newX] = SK_ColorGRAY;
588 }
589 }
590 }
591
592 }
Cary Clark8032b982017-07-28 11:04:54 -0400593 canvas->restore();
594}
595##
596
597#ToDo there are no callers of this that I can find. Deprecate? ##
598#ToDo fiddle should show both CPU and GPU out ##
599
Cary Clark2ade9972017-11-02 17:49:34 -0400600#SeeAlso SkImageInfo SkPixmap
601
Cary Clark8032b982017-07-28 11:04:54 -0400602##
603
604# ------------------------------------------------------------------------------
605
606#Method SkRasterHandleAllocator::Handle accessTopRasterHandle() const
Cary Clark78de7512018-02-07 07:27:09 -0500607#In Utility
608#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500609#Line # returns context that tracks Clip and Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -0400610#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400611
612#Example
613#Description
614#ToDo ##
615##
616#Function
617 static void DeleteCallback(void*, void* context) {
618 delete (char*) context;
619 }
620
621 class CustomAllocator : public SkRasterHandleAllocator {
622 public:
623 bool allocHandle(const SkImageInfo& info, Rec* rec) override {
624 char* context = new char[4]{'s', 'k', 'i', 'a'};
625 rec->fReleaseProc = DeleteCallback;
626 rec->fReleaseCtx = context;
627 rec->fHandle = context;
628 rec->fPixels = context;
629 rec->fRowBytes = 4;
630 return true;
631 }
632
633 void updateHandle(Handle handle, const SkMatrix& ctm, const SkIRect& clip_bounds) override {
634 // apply canvas matrix and clip to custom environment
635 }
636 };
637
638##
639 void draw(SkCanvas* canvas) {
640 const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
641 std::unique_ptr<SkCanvas> c2 =
642 SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<CustomAllocator>(
643 new CustomAllocator()), info);
644 char* context = (char*) c2->accessTopRasterHandle();
645 SkDebugf("context = %.4s\n", context);
646
647 }
648 #StdOut
649 context = skia
650 ##
651 #ToDo skstd::make_unique could not be used because def is private -- note to fix in c++14? ##
652##
653
654#SeeAlso SkRasterHandleAllocator
655
656##
657
658# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -0500659#Subtopic Pixels
Cary Clark78de7512018-02-07 07:27:09 -0500660#Line # read and write pixel values ##
661##
Cary Clark8032b982017-07-28 11:04:54 -0400662
663#Method bool peekPixels(SkPixmap* pixmap)
Cary Clark78de7512018-02-07 07:27:09 -0500664#In Pixels
Cary Clarkab2621d2018-01-30 10:08:57 -0500665#Line # returns if Canvas has direct access to its pixels ##
Cary Clark09d80c02018-10-31 12:14:03 -0400666#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400667
668#Example
669 SkPixmap pixmap;
670 if (canvas->peekPixels(&pixmap)) {
671 SkDebugf("width=%d height=%d\n", pixmap.bounds().width(), pixmap.bounds().height());
672 }
673 #StdOut
674 width=256 height=256
675 ##
676##
677
Cary Clark2ade9972017-11-02 17:49:34 -0400678#SeeAlso readPixels SkBitmap::peekPixels SkImage::peekPixels SkSurface::peekPixels
679
Cary Clark8032b982017-07-28 11:04:54 -0400680##
681
682# ------------------------------------------------------------------------------
683
684#Method bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
685 int srcX, int srcY)
Cary Clark78de7512018-02-07 07:27:09 -0500686#In Pixels
Cary Clarkab2621d2018-01-30 10:08:57 -0500687#Line # copies and converts rectangle of pixels from Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -0400688
Cary Clark154beea2017-10-26 07:58:48 -0400689Copies Rect of pixels from Canvas into dstPixels. Matrix and Clip are
Herb Derbyefe39bc2018-05-01 17:06:20 -0400690ignored.
Cary Clark6fc50412017-09-21 12:31:06 -0400691
Cary Clarka560c472017-11-27 10:44:06 -0500692Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
693Destination Rect corners are (0, 0) and (dstInfo.width(), dstInfo.height()).
Cary Clark6fc50412017-09-21 12:31:06 -0400694Copies each readable pixel intersecting both rectangles, without scaling,
Cary Clarkf05bdda2017-08-24 12:59:48 -0400695converting to dstInfo.colorType() and dstInfo.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400696
Cary Clarkf05bdda2017-08-24 12:59:48 -0400697Pixels are readable when Device is raster, or backed by a GPU.
698Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
699returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
Brian Osman46fe9c72018-03-09 15:44:34 -0500700class like SkDebugCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400701
Cary Clarkf05bdda2017-08-24 12:59:48 -0400702The destination pixel storage must be allocated by the caller.
Cary Clark8032b982017-07-28 11:04:54 -0400703
Cary Clark2dc84ad2018-01-26 12:56:22 -0500704Pixel values are converted only if Color_Type and Alpha_Type
Cary Clarkf05bdda2017-08-24 12:59:48 -0400705do not match. Only pixels within both source and destination rectangles
Cary Clark154beea2017-10-26 07:58:48 -0400706are copied. dstPixels contents outside Rect intersection are unchanged.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400707
708Pass negative values for srcX or srcY to offset pixels across or down destination.
Cary Clark8032b982017-07-28 11:04:54 -0400709
710Does not copy, and returns false if:
711
712#List
Cary Clarkf05bdda2017-08-24 12:59:48 -0400713# Source and destination rectangles do not intersect. ##
714# Canvas pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType(). ##
715# Canvas pixels are not readable; for instance, Canvas is document-based. ##
Cary Clark8032b982017-07-28 11:04:54 -0400716# dstRowBytes is too small to contain one row of pixels. ##
717##
718
Cary Clark2dc84ad2018-01-26 12:56:22 -0500719#Param dstInfo width, height, Color_Type, and Alpha_Type of dstPixels ##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400720#Param dstPixels storage for pixels; dstInfo.height() times dstRowBytes, or larger ##
721#Param dstRowBytes size of one destination row; dstInfo.width() times pixel size, or larger ##
Cary Clark5538c132018-06-14 12:28:14 -0400722#Param srcX offset into readable pixels on x-axis; may be negative ##
723#Param srcY offset into readable pixels on y-axis; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -0400724
Cary Clarkbad5ad72017-08-03 17:14:08 -0400725#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -0400726
727#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -0400728#Width 64
729#Height 64
730#Description
731 A black circle drawn on a blue background provides an image to copy.
732 readPixels copies one quarter of the canvas into each of the four corners.
Cary Clarka560c472017-11-27 10:44:06 -0500733 The copied quarter circles overdraw the original circle.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400734##
735 canvas->clear(SK_ColorBLUE);
736 SkPaint paint;
737 canvas->drawCircle(32, 32, 28, paint);
738 SkImageInfo info = SkImageInfo::Make(64, 64, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
739 sk_sp<SkData> data(SkData::MakeUninitialized(info.minRowBytes() * info.height()));
740 sk_bzero(data->writable_data(), info.minRowBytes() * info.height());
741 for (int x : { 32, -32 } ) {
742 for (int y : { 32, -32 } ) {
743 canvas->readPixels(info, data->writable_data(), info.minRowBytes(), x, y);
Herb Derbyefe39bc2018-05-01 17:06:20 -0400744 }
Cary Clarkf05bdda2017-08-24 12:59:48 -0400745 }
746 sk_sp<SkImage> image = SkImage::MakeRasterData(info, data, info.minRowBytes());
747 canvas->drawImage(image, 0, 0);
748##
749
750#Example
Cary Clark8032b982017-07-28 11:04:54 -0400751#Description
Cary Clarkce101242017-09-01 15:51:02 -0400752 Canvas returned by Raster_Surface has Premultiplied pixel values.
753 clear() takes Unpremultiplied input with Color_Alpha equal 0x80
Cary Clarkffb3d682018-05-17 12:17:28 -0400754 and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha
Cary Clarkce101242017-09-01 15:51:02 -0400755 to generate Premultiplied value 0x802B5580. readPixels converts pixel back
756 to Unpremultiplied value 0x8056A9FF, introducing error.
Cary Clark8032b982017-07-28 11:04:54 -0400757##
758 canvas->clear(0x8055aaff);
759 for (SkAlphaType alphaType : { kPremul_SkAlphaType, kUnpremul_SkAlphaType } ) {
760 uint32_t pixel = 0;
761 SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, alphaType);
762 if (canvas->readPixels(info, &pixel, 4, 0, 0)) {
763 SkDebugf("pixel = %08x\n", pixel);
764 }
765 }
766
767 #StdOut
768 pixel = 802b5580
769 pixel = 8056a9ff
770 ##
771##
772
Cary Clark2ade9972017-11-02 17:49:34 -0400773#SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels
Cary Clark8032b982017-07-28 11:04:54 -0400774
775##
776
777# ------------------------------------------------------------------------------
778
779#Method bool readPixels(const SkPixmap& pixmap, int srcX, int srcY)
780
Cary Clark154beea2017-10-26 07:58:48 -0400781Copies Rect of pixels from Canvas into pixmap. Matrix and Clip are
Cary Clarka560c472017-11-27 10:44:06 -0500782ignored.
Cary Clark6fc50412017-09-21 12:31:06 -0400783
Cary Clarka560c472017-11-27 10:44:06 -0500784Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
785Destination Rect corners are (0, 0) and (pixmap.width(), pixmap.height()).
Cary Clark6fc50412017-09-21 12:31:06 -0400786Copies each readable pixel intersecting both rectangles, without scaling,
Cary Clarkf05bdda2017-08-24 12:59:48 -0400787converting to pixmap.colorType() and pixmap.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400788
Cary Clarkf05bdda2017-08-24 12:59:48 -0400789Pixels are readable when Device is raster, or backed by a GPU.
790Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
791returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
Brian Osman46fe9c72018-03-09 15:44:34 -0500792class like SkDebugCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400793
Cary Clark6fc50412017-09-21 12:31:06 -0400794Caller must allocate pixel storage in pixmap if needed.
Cary Clark8032b982017-07-28 11:04:54 -0400795
Cary Clark2dc84ad2018-01-26 12:56:22 -0500796Pixel values are converted only if Color_Type and Alpha_Type
Cary Clark154beea2017-10-26 07:58:48 -0400797do not match. Only pixels within both source and destination Rects
798are copied. pixmap pixels contents outside Rect intersection are unchanged.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400799
800Pass negative values for srcX or srcY to offset pixels across or down pixmap.
Cary Clark8032b982017-07-28 11:04:54 -0400801
802Does not copy, and returns false if:
803
804#List
Cary Clarkf05bdda2017-08-24 12:59:48 -0400805# Source and destination rectangles do not intersect. ##
806# Canvas pixels could not be converted to pixmap.colorType() or pixmap.alphaType(). ##
807# Canvas pixels are not readable; for instance, Canvas is document-based. ##
808# Pixmap pixels could not be allocated. ##
809# pixmap.rowBytes() is too small to contain one row of pixels. ##
Cary Clark8032b982017-07-28 11:04:54 -0400810##
811
Cary Clarkbad5ad72017-08-03 17:14:08 -0400812#Param pixmap storage for pixels copied from Canvas ##
Cary Clark5538c132018-06-14 12:28:14 -0400813#Param srcX offset into readable pixels on x-axis; may be negative ##
814#Param srcY offset into readable pixels on y-axis; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -0400815
Cary Clarkbad5ad72017-08-03 17:14:08 -0400816#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -0400817
818#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -0400819 #Description
Cary Clarkce101242017-09-01 15:51:02 -0400820 clear() takes Unpremultiplied input with Color_Alpha equal 0x80
Cary Clarkffb3d682018-05-17 12:17:28 -0400821 and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha
Cary Clarkce101242017-09-01 15:51:02 -0400822 to generate Premultiplied value 0x802B5580.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400823 ##
824 void draw(SkCanvas* canvas) {
825 canvas->clear(0x8055aaff);
826 uint32_t pixels[1] = { 0 };
827 SkPixmap pixmap(SkImageInfo::MakeN32Premul(1, 1), pixels, 4);
828 canvas->readPixels(pixmap, 0, 0);
829 SkDebugf("pixel = %08x\n", pixels[0]);
830 }
Cary Clark8032b982017-07-28 11:04:54 -0400831 #StdOut
832 pixel = 802b5580
833 ##
834##
835
Cary Clark2ade9972017-11-02 17:49:34 -0400836#SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels
Cary Clark8032b982017-07-28 11:04:54 -0400837
838##
839
840# ------------------------------------------------------------------------------
841
842#Method bool readPixels(const SkBitmap& bitmap, int srcX, int srcY)
843
Cary Clark154beea2017-10-26 07:58:48 -0400844Copies Rect of pixels from Canvas into bitmap. Matrix and Clip are
Cary Clarka560c472017-11-27 10:44:06 -0500845ignored.
Cary Clark6fc50412017-09-21 12:31:06 -0400846
Cary Clarka560c472017-11-27 10:44:06 -0500847Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
Cary Clark154beea2017-10-26 07:58:48 -0400848Destination Rect corners are (0, 0) and (bitmap.width(), bitmap.height()).
Cary Clarkf05bdda2017-08-24 12:59:48 -0400849Copies each readable pixel intersecting both rectangles, without scaling,
850converting to bitmap.colorType() and bitmap.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400851
Cary Clarkf05bdda2017-08-24 12:59:48 -0400852Pixels are readable when Device is raster, or backed by a GPU.
853Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
854returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
Brian Osman46fe9c72018-03-09 15:44:34 -0500855class like SkDebugCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400856
Cary Clark6fc50412017-09-21 12:31:06 -0400857Caller must allocate pixel storage in bitmap if needed.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400858
Cary Clark2dc84ad2018-01-26 12:56:22 -0500859Bitmap values are converted only if Color_Type and Alpha_Type
Cary Clarkf05bdda2017-08-24 12:59:48 -0400860do not match. Only pixels within both source and destination rectangles
Cary Clark154beea2017-10-26 07:58:48 -0400861are copied. Bitmap pixels outside Rect intersection are unchanged.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400862
863Pass negative values for srcX or srcY to offset pixels across or down bitmap.
Cary Clark8032b982017-07-28 11:04:54 -0400864
865Does not copy, and returns false if:
866
867#List
Cary Clarkf05bdda2017-08-24 12:59:48 -0400868# Source and destination rectangles do not intersect. ##
869# Canvas pixels could not be converted to bitmap.colorType() or bitmap.alphaType(). ##
870# Canvas pixels are not readable; for instance, Canvas is document-based. ##
Cary Clark8032b982017-07-28 11:04:54 -0400871# bitmap pixels could not be allocated. ##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400872# bitmap.rowBytes() is too small to contain one row of pixels. ##
Cary Clark8032b982017-07-28 11:04:54 -0400873##
874
Cary Clarkbad5ad72017-08-03 17:14:08 -0400875#Param bitmap storage for pixels copied from Canvas ##
Cary Clark5538c132018-06-14 12:28:14 -0400876#Param srcX offset into readable pixels on x-axis; may be negative ##
877#Param srcY offset into readable pixels on y-axis; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -0400878
Cary Clarkbad5ad72017-08-03 17:14:08 -0400879#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -0400880
881#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -0400882 #Description
Cary Clarkce101242017-09-01 15:51:02 -0400883 clear() takes Unpremultiplied input with Color_Alpha equal 0x80
Cary Clarkffb3d682018-05-17 12:17:28 -0400884 and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha
Cary Clarkce101242017-09-01 15:51:02 -0400885 to generate Premultiplied value 0x802B5580.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400886 ##
Cary Clark8032b982017-07-28 11:04:54 -0400887void draw(SkCanvas* canvas) {
888 canvas->clear(0x8055aaff);
889 SkBitmap bitmap;
890 bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1));
891 canvas->readPixels(bitmap, 0, 0);
892 SkDebugf("pixel = %08x\n", bitmap.getAddr32(0, 0)[0]);
893}
894 #StdOut
895 pixel = 802b5580
896 ##
897##
898
Cary Clark2ade9972017-11-02 17:49:34 -0400899#SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels
Cary Clark8032b982017-07-28 11:04:54 -0400900
901##
902
903# ------------------------------------------------------------------------------
904
905#Method bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y)
Cary Clark78de7512018-02-07 07:27:09 -0500906#In Pixels
Cary Clarkab2621d2018-01-30 10:08:57 -0500907#Line # copies and converts rectangle of pixels to Canvas ##
Cary Clark154beea2017-10-26 07:58:48 -0400908Copies Rect from pixels to Canvas. Matrix and Clip are ignored.
909Source Rect corners are (0, 0) and (info.width(), info.height()).
910Destination Rect corners are (x, y) and
911(imageInfo().width(), imageInfo().height()).
Cary Clark6fc50412017-09-21 12:31:06 -0400912
913Copies each readable pixel intersecting both rectangles, without scaling,
Cary Clark154beea2017-10-26 07:58:48 -0400914converting to imageInfo().colorType() and imageInfo().alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400915
Cary Clarkf05bdda2017-08-24 12:59:48 -0400916Pixels are writable when Device is raster, or backed by a GPU.
917Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
918returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
Brian Osman46fe9c72018-03-09 15:44:34 -0500919class like SkDebugCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400920
Cary Clark2dc84ad2018-01-26 12:56:22 -0500921Pixel values are converted only if Color_Type and Alpha_Type
Cary Clarkf05bdda2017-08-24 12:59:48 -0400922do not match. Only pixels within both source and destination rectangles
Cary Clark154beea2017-10-26 07:58:48 -0400923are copied. Canvas pixels outside Rect intersection are unchanged.
Cary Clark8032b982017-07-28 11:04:54 -0400924
Cary Clarkf05bdda2017-08-24 12:59:48 -0400925Pass negative values for x or y to offset pixels to the left or
926above Canvas pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400927
928Does not copy, and returns false if:
929
930#List
Cary Clarkf05bdda2017-08-24 12:59:48 -0400931# Source and destination rectangles do not intersect. ##
Cary Clarkac47b882018-01-11 10:35:44 -0500932# pixels could not be converted to Canvas imageInfo().colorType() or
933 imageInfo().alphaType(). ##
Cary Clark8032b982017-07-28 11:04:54 -0400934# Canvas pixels are not writable; for instance, Canvas is document-based. ##
935# rowBytes is too small to contain one row of pixels. ##
936##
937
Cary Clark2dc84ad2018-01-26 12:56:22 -0500938#Param info width, height, Color_Type, and Alpha_Type of pixels ##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400939#Param pixels pixels to copy, of size info.height() times rowBytes, or larger ##
Cary Clarkd0530ba2017-09-14 11:25:39 -0400940#Param rowBytes size of one row of pixels; info.width() times pixel size, or larger ##
Cary Clark5538c132018-06-14 12:28:14 -0400941#Param x offset into Canvas writable pixels on x-axis; may be negative ##
942#Param y offset into Canvas writable pixels on y-axis; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -0400943
Cary Clarkbad5ad72017-08-03 17:14:08 -0400944#Return true if pixels were written to Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -0400945
946#Example
947 SkImageInfo imageInfo = SkImageInfo::MakeN32(256, 1, kPremul_SkAlphaType);
948 for (int y = 0; y < 256; ++y) {
949 uint32_t pixels[256];
950 for (int x = 0; x < 256; ++x) {
951 pixels[x] = SkColorSetARGB(x, x + y, x, x - y);
952 }
953 canvas->writePixels(imageInfo, &pixels, sizeof(pixels), 0, y);
954 }
955##
956
Cary Clark2ade9972017-11-02 17:49:34 -0400957#SeeAlso readPixels drawBitmap drawImage SkBitmap::writePixels
Cary Clark8032b982017-07-28 11:04:54 -0400958
959##
960
961# ------------------------------------------------------------------------------
962
963#Method bool writePixels(const SkBitmap& bitmap, int x, int y)
964
Cary Clark154beea2017-10-26 07:58:48 -0400965Copies Rect from pixels to Canvas. Matrix and Clip are ignored.
966Source Rect corners are (0, 0) and (bitmap.width(), bitmap.height()).
Cary Clark6fc50412017-09-21 12:31:06 -0400967
Cary Clark154beea2017-10-26 07:58:48 -0400968Destination Rect corners are (x, y) and
969(imageInfo().width(), imageInfo().height()).
Cary Clark6fc50412017-09-21 12:31:06 -0400970
971Copies each readable pixel intersecting both rectangles, without scaling,
Cary Clark154beea2017-10-26 07:58:48 -0400972converting to imageInfo().colorType() and imageInfo().alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400973
Cary Clarkf05bdda2017-08-24 12:59:48 -0400974Pixels are writable when Device is raster, or backed by a GPU.
975Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
976returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
Brian Osman46fe9c72018-03-09 15:44:34 -0500977class like SkDebugCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400978
Cary Clark2dc84ad2018-01-26 12:56:22 -0500979Pixel values are converted only if Color_Type and Alpha_Type
Cary Clarkf05bdda2017-08-24 12:59:48 -0400980do not match. Only pixels within both source and destination rectangles
Cary Clark154beea2017-10-26 07:58:48 -0400981are copied. Canvas pixels outside Rect intersection are unchanged.
Cary Clark8032b982017-07-28 11:04:54 -0400982
Cary Clarkf05bdda2017-08-24 12:59:48 -0400983Pass negative values for x or y to offset pixels to the left or
984above Canvas pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400985
986Does not copy, and returns false if:
987
988#List
Cary Clarkf05bdda2017-08-24 12:59:48 -0400989# Source and destination rectangles do not intersect. ##
Cary Clark8032b982017-07-28 11:04:54 -0400990# bitmap does not have allocated pixels. ##
Cary Clarkac47b882018-01-11 10:35:44 -0500991# bitmap pixels could not be converted to Canvas imageInfo().colorType() or
992 imageInfo().alphaType(). ##
Cary Clarkce101242017-09-01 15:51:02 -0400993# Canvas pixels are not writable; for instance, Canvas is document based. ##
Cary Clark8032b982017-07-28 11:04:54 -0400994# bitmap pixels are inaccessible; for instance, bitmap wraps a texture. ##
995##
996
Cary Clarkbad5ad72017-08-03 17:14:08 -0400997#Param bitmap contains pixels copied to Canvas ##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400998#Param x offset into Canvas writable pixels in x; may be negative ##
999#Param y offset into Canvas writable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -04001000
Cary Clarkbad5ad72017-08-03 17:14:08 -04001001#Return true if pixels were written to Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -04001002
1003#Example
1004void draw(SkCanvas* canvas) {
1005 SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(2, 2);
1006 SkBitmap bitmap;
1007 bitmap.setInfo(imageInfo);
1008 uint32_t pixels[4];
1009 bitmap.setPixels(pixels);
1010 for (int y = 0; y < 256; y += 2) {
1011 for (int x = 0; x < 256; x += 2) {
1012 pixels[0] = SkColorSetRGB(x, y, x | y);
1013 pixels[1] = SkColorSetRGB(x ^ y, y, x);
1014 pixels[2] = SkColorSetRGB(x, x & y, y);
1015 pixels[3] = SkColorSetRGB(~x, ~y, x);
1016 canvas->writePixels(bitmap, x, y);
1017 }
1018 }
1019}
1020##
1021
Cary Clark2ade9972017-11-02 17:49:34 -04001022#SeeAlso readPixels drawBitmap drawImage SkBitmap::writePixels
Cary Clark8032b982017-07-28 11:04:54 -04001023
1024##
1025
1026# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001027#Subtopic State_Stack
1028#Line # stack of state for hierarchical drawing ##
Cary Clark8032b982017-07-28 11:04:54 -04001029
1030Canvas maintains a stack of state that allows hierarchical drawing, commonly used
Cary Clarkbad5ad72017-08-03 17:14:08 -04001031to implement windows and views. The initial state has an identity matrix and and
1032an infinite clip. Even with a wide-open clip, drawing is constrained by the
1033bounds of the Canvas Surface or Device.
Cary Clark8032b982017-07-28 11:04:54 -04001034
Cary Clark939fd6c2018-07-12 08:40:13 -04001035Canvas savable state consists of Clip and Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04001036Clip describes the area that may be drawn to.
1037Matrix transforms the geometry.
Cary Clark8032b982017-07-28 11:04:54 -04001038
1039save(), saveLayer, saveLayerPreserveLCDTextRequests, and saveLayerAlpha
1040save state and return the depth of the stack.
1041
Cary Clarkbad5ad72017-08-03 17:14:08 -04001042restore(), restoreToCount, and ~SkCanvas() revert state to its value when saved.
Cary Clark8032b982017-07-28 11:04:54 -04001043
1044Each state on the stack intersects Clip with the previous Clip,
1045and concatenates Matrix with the previous Matrix.
1046The intersected Clip makes the drawing area the same or smaller;
1047the concatenated Matrix may move the origin and potentially scale or rotate
1048the coordinate space.
1049
1050Canvas does not require balancing the state stack but it is a good idea
1051to do so. Calling save() without restore() will eventually cause Skia to fail;
1052mismatched save() and restore() create hard to find bugs.
1053
1054It is not possible to use state to draw outside of the clip defined by the
1055previous state.
1056
1057#Example
1058#Description
1059Draw to ever smaller clips; then restore drawing to full canvas.
1060Note that the second clipRect is not permitted to enlarge Clip.
1061##
1062#Height 160
Cary Clarkbad5ad72017-08-03 17:14:08 -04001063void draw(SkCanvas* canvas) {
1064 SkPaint paint;
Herb Derbyefe39bc2018-05-01 17:06:20 -04001065 canvas->save(); // records stack depth to restore
Cary Clarkbad5ad72017-08-03 17:14:08 -04001066 canvas->clipRect(SkRect::MakeWH(100, 100)); // constrains drawing to clip
1067 canvas->clear(SK_ColorRED); // draws to limit of clip
Herb Derbyefe39bc2018-05-01 17:06:20 -04001068 canvas->save(); // records stack depth to restore
Cary Clarkbad5ad72017-08-03 17:14:08 -04001069 canvas->clipRect(SkRect::MakeWH(50, 150)); // Rect below 100 is ignored
1070 canvas->clear(SK_ColorBLUE); // draws to smaller clip
1071 canvas->restore(); // enlarges clip
1072 canvas->drawLine(20, 20, 150, 150, paint); // line below 100 is not drawn
1073 canvas->restore(); // enlarges clip
1074 canvas->drawLine(150, 20, 50, 120, paint); // line below 100 is drawn
Cary Clark8032b982017-07-28 11:04:54 -04001075}
Herb Derbyefe39bc2018-05-01 17:06:20 -04001076##
Cary Clark8032b982017-07-28 11:04:54 -04001077
1078Each Clip uses the current Matrix for its coordinates.
1079
1080#Example
1081#Description
1082While clipRect is given the same rectangle twice, Matrix makes the second
1083clipRect draw at half the size of the first.
1084##
1085#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001086void draw(SkCanvas* canvas) {
1087 canvas->clipRect(SkRect::MakeWH(100, 100));
1088 canvas->clear(SK_ColorRED);
1089 canvas->scale(.5, .5);
1090 canvas->clipRect(SkRect::MakeWH(100, 100));
1091 canvas->clear(SK_ColorBLUE);
Cary Clark8032b982017-07-28 11:04:54 -04001092}
1093##
1094
Cary Clarka90ea222018-10-16 10:30:28 -04001095#SeeAlso save saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha restore() restoreToCount
Cary Clark8032b982017-07-28 11:04:54 -04001096
1097#Method int save()
1098
Cary Clarkab2621d2018-01-30 10:08:57 -05001099#In State_Stack
1100#Line # saves Clip and Matrix on stack ##
Cary Clark09d80c02018-10-31 12:14:03 -04001101#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001102
1103#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04001104#Description
Cary Clark8032b982017-07-28 11:04:54 -04001105The black square is translated 50 pixels down and to the right.
1106Restoring Canvas state removes translate() from Canvas stack;
1107the red square is not translated, and is drawn at the origin.
1108##
1109#Height 100
1110void draw(SkCanvas* canvas) {
1111 SkPaint paint;
1112 SkRect rect = { 0, 0, 25, 25 };
1113 canvas->drawRect(rect, paint);
1114 canvas->save();
1115 canvas->translate(50, 50);
1116 canvas->drawRect(rect, paint);
1117 canvas->restore();
1118 paint.setColor(SK_ColorRED);
1119 canvas->drawRect(rect, paint);
1120}
1121##
1122
Cary Clarka90ea222018-10-16 10:30:28 -04001123#SeeAlso saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha restore restoreToCount
Cary Clark8032b982017-07-28 11:04:54 -04001124
1125##
1126
1127# ------------------------------------------------------------------------------
Cary Clark8032b982017-07-28 11:04:54 -04001128
1129#Method void restore()
1130
Cary Clarkab2621d2018-01-30 10:08:57 -05001131#In State_Stack
1132#Line # restores changes to Clip and Matrix, pops save stack ##
Cary Clark09d80c02018-10-31 12:14:03 -04001133#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001134
1135#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001136void draw(SkCanvas* canvas) {
1137 SkCanvas simple;
1138 SkDebugf("depth = %d\n", simple.getSaveCount());
1139 simple.restore();
1140 SkDebugf("depth = %d\n", simple.getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001141}
1142##
1143
Cary Clarka90ea222018-10-16 10:30:28 -04001144#SeeAlso save saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha restoreToCount
Cary Clark2ade9972017-11-02 17:49:34 -04001145
Cary Clark8032b982017-07-28 11:04:54 -04001146##
1147
1148# ------------------------------------------------------------------------------
1149
1150#Method int getSaveCount() const
1151
Cary Clarkab2621d2018-01-30 10:08:57 -05001152#In State_Stack
1153#Line # returns depth of stack containing Clip and Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001154#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001155
1156#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001157void draw(SkCanvas* canvas) {
1158 SkCanvas simple;
1159 SkDebugf("depth = %d\n", simple.getSaveCount());
1160 simple.save();
1161 SkDebugf("depth = %d\n", simple.getSaveCount());
1162 simple.restore();
1163 SkDebugf("depth = %d\n", simple.getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001164}
1165#StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04001166depth = 1
1167depth = 2
Cary Clark8032b982017-07-28 11:04:54 -04001168depth = 1
1169##
1170##
1171
Cary Clarka90ea222018-10-16 10:30:28 -04001172#SeeAlso save restore restoreToCount
Cary Clark2ade9972017-11-02 17:49:34 -04001173
Cary Clark8032b982017-07-28 11:04:54 -04001174##
1175
1176# ------------------------------------------------------------------------------
1177
1178#Method void restoreToCount(int saveCount)
1179
Cary Clarkab2621d2018-01-30 10:08:57 -05001180#In State_Stack
1181#Line # restores changes to Clip and Matrix to given depth ##
Cary Clark09d80c02018-10-31 12:14:03 -04001182#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001183
1184#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001185void draw(SkCanvas* canvas) {
1186 SkDebugf("depth = %d\n", canvas->getSaveCount());
1187 canvas->save();
1188 canvas->save();
1189 SkDebugf("depth = %d\n", canvas->getSaveCount());
1190 canvas->restoreToCount(0);
1191 SkDebugf("depth = %d\n", canvas->getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001192}
1193#StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04001194depth = 1
1195depth = 3
Cary Clark8032b982017-07-28 11:04:54 -04001196depth = 1
1197##
1198##
1199
Cary Clarka90ea222018-10-16 10:30:28 -04001200#SeeAlso restore getSaveCount save
Cary Clark2ade9972017-11-02 17:49:34 -04001201
Cary Clark8032b982017-07-28 11:04:54 -04001202##
1203
Cary Clark08895c42018-02-01 09:37:32 -05001204#Subtopic State_Stack ##
Cary Clark8032b982017-07-28 11:04:54 -04001205
1206# ------------------------------------------------------------------------------
Cary Clarkce101242017-09-01 15:51:02 -04001207
Cary Clark08895c42018-02-01 09:37:32 -05001208#Subtopic Layer
Cary Clarkd0530ba2017-09-14 11:25:39 -04001209#Substitute layer
Cary Clarkce101242017-09-01 15:51:02 -04001210#Alias Layers
Cary Clark137b8742018-05-30 09:21:49 -04001211#Substitute layers
1212##
Cary Clark08895c42018-02-01 09:37:32 -05001213#Line # temporary Bitmap to draw into ##
Cary Clarkce101242017-09-01 15:51:02 -04001214
1215Layer allocates a temporary Bitmap to draw into. When the drawing is
Herb Derbyefe39bc2018-05-01 17:06:20 -04001216complete, the Bitmap is drawn into the Canvas.
Cary Clarkce101242017-09-01 15:51:02 -04001217
1218Layer is saved in a stack along with other saved state. When state with a Layer
1219is restored, the Bitmap is drawn into the previous Layer.
1220
1221Layer may be initialized with the contents of the previous Layer. When Layer is
1222restored, its Bitmap can be modified by Paint passed to Layer to apply
1223Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode.
1224
1225#Method int saveLayer(const SkRect* bounds, const SkPaint* paint)
1226
Cary Clarkab2621d2018-01-30 10:08:57 -05001227#In Layer
1228#Line # saves Clip and Matrix on stack; creates Layer ##
Cary Clark09d80c02018-10-31 12:14:03 -04001229#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001230
1231#Example
1232#Description
1233Rectangles are blurred by Image_Filter when restore() draws Layer to main
1234Canvas.
1235##
1236#Height 128
Cary Clark81abc432018-06-25 16:30:08 -04001237#Function
1238###$
1239#include "SkBlurImageFilter.h"
1240$$$#
1241##
1242
Cary Clarkce101242017-09-01 15:51:02 -04001243void draw(SkCanvas* canvas) {
1244 SkPaint paint, blur;
Cary Clarka560c472017-11-27 10:44:06 -05001245 blur.setImageFilter(SkBlurImageFilter::Make(3, 3, nullptr));
Cary Clarkce101242017-09-01 15:51:02 -04001246 canvas->saveLayer(nullptr, &blur);
1247 SkRect rect = { 25, 25, 50, 50};
1248 canvas->drawRect(rect, paint);
1249 canvas->translate(50, 50);
1250 paint.setColor(SK_ColorRED);
1251 canvas->drawRect(rect, paint);
1252 canvas->restore();
1253}
1254##
1255
Cary Clarka90ea222018-10-16 10:30:28 -04001256#SeeAlso save restore saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha SaveLayerRec
Cary Clarkce101242017-09-01 15:51:02 -04001257
1258##
1259
Herb Derbyefe39bc2018-05-01 17:06:20 -04001260#Method int saveLayer(const SkRect& bounds, const SkPaint* paint)
Cary Clarkce101242017-09-01 15:51:02 -04001261
Cary Clarkab2621d2018-01-30 10:08:57 -05001262#In Layer
Cary Clark09d80c02018-10-31 12:14:03 -04001263#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001264
1265#Example
1266#Description
1267Rectangles are blurred by Image_Filter when restore() draws Layer to main Canvas.
Herb Derbyefe39bc2018-05-01 17:06:20 -04001268The red rectangle is clipped; it does not fully fit on Layer.
Cary Clarkce101242017-09-01 15:51:02 -04001269Image_Filter blurs past edge of Layer so red rectangle is blurred on all sides.
1270##
1271#Height 128
Cary Clark81abc432018-06-25 16:30:08 -04001272#Function
1273###$
1274#include "SkBlurImageFilter.h"
1275$$$#
1276##
1277
Cary Clarkce101242017-09-01 15:51:02 -04001278void draw(SkCanvas* canvas) {
1279 SkPaint paint, blur;
Cary Clarka560c472017-11-27 10:44:06 -05001280 blur.setImageFilter(SkBlurImageFilter::Make(3, 3, nullptr));
Cary Clarkce101242017-09-01 15:51:02 -04001281 canvas->saveLayer(SkRect::MakeWH(90, 90), &blur);
1282 SkRect rect = { 25, 25, 50, 50};
1283 canvas->drawRect(rect, paint);
1284 canvas->translate(50, 50);
1285 paint.setColor(SK_ColorRED);
1286 canvas->drawRect(rect, paint);
1287 canvas->restore();
1288}
1289##
1290
Cary Clarka90ea222018-10-16 10:30:28 -04001291#SeeAlso save restore saveLayerPreserveLCDTextRequests saveLayerAlpha SaveLayerRec
Cary Clarkce101242017-09-01 15:51:02 -04001292
1293##
1294
1295#Method int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint)
1296
Cary Clarkab2621d2018-01-30 10:08:57 -05001297#In Layer
1298#Line # saves Clip and Matrix on stack; creates Layer for LCD text ##
Cary Clark09d80c02018-10-31 12:14:03 -04001299#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001300
1301#Example
1302 SkPaint paint;
1303 paint.setAntiAlias(true);
1304 paint.setLCDRenderText(true);
1305 paint.setTextSize(20);
1306 for (auto preserve : { false, true } ) {
1307 preserve ? canvas->saveLayerPreserveLCDTextRequests(nullptr, nullptr)
1308 : canvas->saveLayer(nullptr, nullptr);
1309 SkPaint p;
1310 p.setColor(SK_ColorWHITE);
1311 // Comment out the next line to draw on a non-opaque background.
1312 canvas->drawRect(SkRect::MakeLTRB(25, 40, 200, 70), p);
1313 canvas->drawString("Hamburgefons", 30, 60, paint);
1314
1315 p.setColor(0xFFCCCCCC);
1316 canvas->drawRect(SkRect::MakeLTRB(25, 70, 200, 100), p);
1317 canvas->drawString("Hamburgefons", 30, 90, paint);
1318
1319 canvas->restore();
1320 canvas->translate(0, 80);
1321 }
1322 ##
1323
Cary Clarka90ea222018-10-16 10:30:28 -04001324#SeeAlso save restore saveLayer saveLayerAlpha SaveLayerRec
Cary Clarkce101242017-09-01 15:51:02 -04001325
1326##
1327
1328#Method int saveLayerAlpha(const SkRect* bounds, U8CPU alpha)
1329
Cary Clarkab2621d2018-01-30 10:08:57 -05001330#In Layer
1331#Line # saves Clip and Matrix on stack; creates Layer; sets opacity ##
Cary Clark09d80c02018-10-31 12:14:03 -04001332#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001333
1334#Example
1335 SkPaint paint;
1336 paint.setColor(SK_ColorRED);
1337 canvas->drawCircle(50, 50, 50, paint);
1338 canvas->saveLayerAlpha(nullptr, 128);
1339 paint.setColor(SK_ColorBLUE);
1340 canvas->drawCircle(100, 50, 50, paint);
1341 paint.setColor(SK_ColorGREEN);
1342 paint.setAlpha(128);
1343 canvas->drawCircle(75, 90, 50, paint);
1344 canvas->restore();
1345##
1346
Cary Clarka90ea222018-10-16 10:30:28 -04001347#SeeAlso save restore saveLayer saveLayerPreserveLCDTextRequests SaveLayerRec
Cary Clarkce101242017-09-01 15:51:02 -04001348
1349##
1350
Cary Clarkd98f78c2018-04-26 08:32:37 -04001351#Enum SaveLayerFlagsSet
Cary Clark08895c42018-02-01 09:37:32 -05001352#Line # sets SaveLayerRec options ##
Cary Clarkce101242017-09-01 15:51:02 -04001353#Code
Cary Clark61313f32018-10-08 14:57:48 -04001354#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001355##
1356
Cary Clark682c58d2018-05-16 07:07:07 -04001357
1358#Typedef uint32_t SaveLayerFlags
1359#Line # options for SaveLayerRec ##
Cary Clark137b8742018-05-30 09:21:49 -04001360##
Cary Clark682c58d2018-05-16 07:07:07 -04001361
Cary Clarkce101242017-09-01 15:51:02 -04001362SaveLayerFlags provides options that may be used in any combination in SaveLayerRec,
Cary Clark682c58d2018-05-16 07:07:07 -04001363defining how Layer allocated by saveLayer operates. It may be set to zero,
1364kPreserveLCDText_SaveLayerFlag, kInitWithPrevious_SaveLayerFlag, or both flags.
1365
Cary Clarkce101242017-09-01 15:51:02 -04001366#Const kPreserveLCDText_SaveLayerFlag 2
Cary Clark682c58d2018-05-16 07:07:07 -04001367#Line # creates Layer for LCD text ##
Cary Clarkce101242017-09-01 15:51:02 -04001368 Creates Layer for LCD text. Flag is ignored if Layer Paint contains
1369 Image_Filter or Color_Filter.
1370##
1371
1372#Const kInitWithPrevious_SaveLayerFlag 4
Cary Clark682c58d2018-05-16 07:07:07 -04001373#Line # initializes with previous contents ##
Cary Clarkce101242017-09-01 15:51:02 -04001374 Initializes Layer with the contents of the previous Layer.
1375##
1376
Mike Reed910ca0f2018-04-25 13:04:05 -04001377#Const kMaskAgainstCoverage_EXPERIMENTAL_DONT_USE_SaveLayerFlag 8
Cary Clark682c58d2018-05-16 07:07:07 -04001378#Experimental do not use
Mike Reed910ca0f2018-04-25 13:04:05 -04001379##
1380
Cary Clarkce101242017-09-01 15:51:02 -04001381#Const kDontClipToLayer_Legacy_SaveLayerFlag 0x80000000
Cary Clark4855f782018-02-06 09:41:53 -05001382#Deprecated soon
Cary Clarkce101242017-09-01 15:51:02 -04001383##
1384
1385#Example
1386#Height 160
1387#Description
1388Canvas Layer captures red and blue circles scaled up by four.
Herb Derbyefe39bc2018-05-01 17:06:20 -04001389scalePaint blends Layer back with transparency.
Cary Clarkce101242017-09-01 15:51:02 -04001390##
1391void draw(SkCanvas* canvas) {
1392 SkPaint redPaint, bluePaint, scalePaint;
1393 redPaint.setColor(SK_ColorRED);
1394 canvas->drawCircle(21, 21, 8, redPaint);
1395 bluePaint.setColor(SK_ColorBLUE);
1396 canvas->drawCircle(31, 21, 8, bluePaint);
1397 SkMatrix matrix;
1398 matrix.setScale(4, 4);
1399 scalePaint.setAlpha(0x40);
1400 scalePaint.setImageFilter(
1401 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
1402 SkCanvas::SaveLayerRec saveLayerRec(nullptr, &scalePaint,
Herb Derbyefe39bc2018-05-01 17:06:20 -04001403 SkCanvas::kInitWithPrevious_SaveLayerFlag);
Cary Clarkce101242017-09-01 15:51:02 -04001404 canvas->saveLayer(saveLayerRec);
1405 canvas->restore();
1406}
1407##
1408
Cary Clarka90ea222018-10-16 10:30:28 -04001409#SeeAlso save restore saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha SaveLayerRec
Cary Clarkce101242017-09-01 15:51:02 -04001410
1411#Enum ##
1412
Cary Clark682c58d2018-05-16 07:07:07 -04001413#Subtopic SaveLayerRec
1414#Line # contains the state used to create the Layer ##
Cary Clarka560c472017-11-27 10:44:06 -05001415
Cary Clarkce101242017-09-01 15:51:02 -04001416#Struct SaveLayerRec
Cary Clark08895c42018-02-01 09:37:32 -05001417#Line # contains the state used to create the Layer ##
Cary Clark682c58d2018-05-16 07:07:07 -04001418
Cary Clarkce101242017-09-01 15:51:02 -04001419#Code
Cary Clark61313f32018-10-08 14:57:48 -04001420#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001421##
1422
Cary Clark137b8742018-05-30 09:21:49 -04001423SaveLayerRec contains the state used to create the Layer.
1424
Cary Clarkce101242017-09-01 15:51:02 -04001425#Member const SkRect* fBounds
Cary Clark682c58d2018-05-16 07:07:07 -04001426#Line # hints at Layer size limit ##
Cary Clarkce101242017-09-01 15:51:02 -04001427 fBounds is used as a hint to limit the size of Layer; may be nullptr.
1428 fBounds suggests but does not define Layer size. To clip drawing to
1429 a specific rectangle, use clipRect.
1430##
1431
1432#Member const SkPaint* fPaint
Cary Clark682c58d2018-05-16 07:07:07 -04001433#Line # modifies overlay ##
Cary Clarkce101242017-09-01 15:51:02 -04001434 fPaint modifies how Layer overlays the prior Layer; may be nullptr.
1435 Color_Alpha, Blend_Mode, Color_Filter, Draw_Looper, Image_Filter, and
1436 Mask_Filter affect Layer draw.
1437##
1438
1439#Member const SkImageFilter* fBackdrop
Cary Clark682c58d2018-05-16 07:07:07 -04001440#Line # applies Image_Filter to prior Layer ##
Cary Clarkce101242017-09-01 15:51:02 -04001441 fBackdrop applies Image_Filter to the prior Layer when copying to the Layer;
1442 may be nullptr. Use kInitWithPrevious_SaveLayerFlag to copy the
1443 prior Layer without an Image_Filter.
1444##
1445
1446#Member const SkImage* fClipMask
Cary Clark682c58d2018-05-16 07:07:07 -04001447#Line # clips Layer with Mask_Alpha ##
Cary Clarkce101242017-09-01 15:51:02 -04001448 restore() clips Layer by the Color_Alpha channel of fClipMask when
1449 Layer is copied to Device. fClipMask may be nullptr. .
1450##
1451
1452#Member const SkMatrix* fClipMatrix
Cary Clark682c58d2018-05-16 07:07:07 -04001453#Line # transforms Mask_Alpha used to clip ##
Herb Derbyefe39bc2018-05-01 17:06:20 -04001454 fClipMatrix transforms fClipMask before it clips Layer. If
Cary Clarkce101242017-09-01 15:51:02 -04001455 fClipMask describes a translucent gradient, it may be scaled and rotated
1456 without introducing artifacts. fClipMatrix may be nullptr.
1457##
1458
1459#Member SaveLayerFlags fSaveLayerFlags
Cary Clark682c58d2018-05-16 07:07:07 -04001460#Line # preserves LCD Text, creates with prior Layer contents ##
Cary Clarkce101242017-09-01 15:51:02 -04001461 fSaveLayerFlags are used to create Layer without transparency,
1462 create Layer for LCD text, and to create Layer with the
1463 contents of the previous Layer.
1464##
1465
1466#Example
1467#Height 160
1468#Description
Cary Clarkffb3d682018-05-17 12:17:28 -04001469Canvas Layer captures a red Anti_Aliased circle and a blue Aliased circle scaled
Cary Clarkce101242017-09-01 15:51:02 -04001470up by four. After drawing another red circle without scaling on top, the Layer is
Herb Derbyefe39bc2018-05-01 17:06:20 -04001471transferred to the main canvas.
Cary Clarkce101242017-09-01 15:51:02 -04001472##
1473void draw(SkCanvas* canvas) {
1474 SkPaint redPaint, bluePaint;
1475 redPaint.setAntiAlias(true);
1476 redPaint.setColor(SK_ColorRED);
1477 canvas->drawCircle(21, 21, 8, redPaint);
1478 bluePaint.setColor(SK_ColorBLUE);
1479 canvas->drawCircle(31, 21, 8, bluePaint);
1480 SkMatrix matrix;
1481 matrix.setScale(4, 4);
1482 auto scaler = SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr);
Herb Derbyefe39bc2018-05-01 17:06:20 -04001483 SkCanvas::SaveLayerRec saveLayerRec(nullptr, nullptr, scaler.get(), 0);
Cary Clarkce101242017-09-01 15:51:02 -04001484 canvas->saveLayer(saveLayerRec);
1485 canvas->drawCircle(125, 85, 8, redPaint);
1486 canvas->restore();
1487}
1488##
1489
Cary Clark61313f32018-10-08 14:57:48 -04001490#Subtopic Constructors
Cary Clark682c58d2018-05-16 07:07:07 -04001491##
Cary Clarkce101242017-09-01 15:51:02 -04001492
Cary Clark682c58d2018-05-16 07:07:07 -04001493#Method SaveLayerRec()
1494#Line # constructs SaveLayerRec ##
Cary Clark09d80c02018-10-31 12:14:03 -04001495#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001496
1497#Example
1498 SkCanvas::SaveLayerRec rec1;
Mike Kleine083f7c2018-02-07 12:54:27 -05001499 rec1.fSaveLayerFlags = SkCanvas::kPreserveLCDText_SaveLayerFlag;
1500 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, SkCanvas::kPreserveLCDText_SaveLayerFlag);
Cary Clarkce101242017-09-01 15:51:02 -04001501 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1502 && rec1.fPaint == rec2.fPaint
1503 && rec1.fBackdrop == rec2.fBackdrop
1504 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1505 #StdOut
1506 rec1 == rec2
1507 ##
1508##
1509
Cary Clarka90ea222018-10-16 10:30:28 -04001510#SeeAlso save restore saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha
Cary Clark2ade9972017-11-02 17:49:34 -04001511
Cary Clarkce101242017-09-01 15:51:02 -04001512##
1513
Cary Clark224c7002018-06-27 11:00:21 -04001514#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
Cary Clark09d80c02018-10-31 12:14:03 -04001515#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001516
1517#Example
1518 SkCanvas::SaveLayerRec rec1;
1519 SkCanvas::SaveLayerRec rec2(nullptr, nullptr);
1520 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1521 && rec1.fPaint == rec2.fPaint
1522 && rec1.fBackdrop == rec2.fBackdrop
1523 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1524 #StdOut
1525 rec1 == rec2
1526 ##
1527##
1528
Cary Clarka90ea222018-10-16 10:30:28 -04001529#SeeAlso save restore saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha
Cary Clark2ade9972017-11-02 17:49:34 -04001530
Cary Clarkce101242017-09-01 15:51:02 -04001531##
1532
1533#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
1534 SaveLayerFlags saveLayerFlags)
Cary Clark09d80c02018-10-31 12:14:03 -04001535#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001536
1537#Example
1538 SkCanvas::SaveLayerRec rec1;
1539 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, nullptr, 0);
1540 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1541 && rec1.fPaint == rec2.fPaint
1542 && rec1.fBackdrop == rec2.fBackdrop
1543 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1544 #StdOut
1545 rec1 == rec2
1546 ##
1547##
1548
Cary Clarka90ea222018-10-16 10:30:28 -04001549#SeeAlso save restore saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha
Cary Clark2ade9972017-11-02 17:49:34 -04001550
Cary Clarkce101242017-09-01 15:51:02 -04001551##
1552
1553#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
1554 const SkImage* clipMask, const SkMatrix* clipMatrix,
1555 SaveLayerFlags saveLayerFlags)
1556
Cary Clark682c58d2018-05-16 07:07:07 -04001557#Experimental not ready
Cary Clarkce101242017-09-01 15:51:02 -04001558
1559Sets fBounds, fPaint, fBackdrop, fClipMask, fClipMatrix, and fSaveLayerFlags.
1560clipMatrix uses Color_Alpha channel of image, transformed by clipMatrix, to clip
1561Layer when drawn to Canvas.
1562
Cary Clark2ade9972017-11-02 17:49:34 -04001563Implementation is not complete; has no effect if Device is GPU-backed.
Cary Clarkce101242017-09-01 15:51:02 -04001564
1565#Param bounds Layer dimensions; may be nullptr ##
1566#Param paint graphics state applied to Layer when overlaying prior
1567 Layer; may be nullptr
1568##
1569#Param backdrop prior Layer copied with Image_Filter;
1570 may be nullptr
1571##
1572#Param clipMask clip applied to Layer; may be nullptr ##
1573#Param clipMatrix matrix applied to clipMask; may be nullptr to use
Herb Derbyefe39bc2018-05-01 17:06:20 -04001574 identity matrix
Cary Clarkce101242017-09-01 15:51:02 -04001575##
1576#Param saveLayerFlags SaveLayerRec options to modify Layer ##
1577
1578#Return SaveLayerRec fully specified ##
1579
Cary Clarka90ea222018-10-16 10:30:28 -04001580#SeeAlso save restore saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha
Cary Clarkce101242017-09-01 15:51:02 -04001581
1582##
1583
1584#Struct ##
1585
Cary Clark682c58d2018-05-16 07:07:07 -04001586#Subtopic ##
1587
Cary Clarkce101242017-09-01 15:51:02 -04001588#Method int saveLayer(const SaveLayerRec& layerRec)
1589
Cary Clarkab2621d2018-01-30 10:08:57 -05001590#In Layer
Cary Clark09d80c02018-10-31 12:14:03 -04001591#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001592
1593#Example
1594#Description
1595The example draws an image, and saves it into a Layer with kInitWithPrevious_SaveLayerFlag.
1596Next it punches a hole in Layer and restore with SkBlendMode::kPlus.
1597Where Layer was cleared, the original image will draw unchanged.
1598Outside of the circle the mandrill is brightened.
1599##
1600 #Image 3
Hal Canaryc465d132017-12-08 10:21:31 -05001601 // sk_sp<SkImage> image = GetResourceAsImage("images/mandrill_256.png");
Cary Clarkce101242017-09-01 15:51:02 -04001602 canvas->drawImage(image, 0, 0, nullptr);
1603 SkCanvas::SaveLayerRec rec;
1604 SkPaint paint;
1605 paint.setBlendMode(SkBlendMode::kPlus);
1606 rec.fSaveLayerFlags = SkCanvas::kInitWithPrevious_SaveLayerFlag;
1607 rec.fPaint = &paint;
1608 canvas->saveLayer(rec);
1609 paint.setBlendMode(SkBlendMode::kClear);
1610 canvas->drawCircle(128, 128, 96, paint);
1611 canvas->restore();
1612##
1613
1614#ToDo above example needs to replace GetResourceAsImage with way to select image in fiddle ##
1615
Cary Clarka90ea222018-10-16 10:30:28 -04001616#SeeAlso save restore saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha
Cary Clark2ade9972017-11-02 17:49:34 -04001617
Cary Clarkce101242017-09-01 15:51:02 -04001618##
1619
Cary Clark08895c42018-02-01 09:37:32 -05001620#Subtopic Layer ##
Cary Clarkce101242017-09-01 15:51:02 -04001621
1622# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001623#Subtopic Matrix
1624#Line # coordinate transformation ##
Cary Clark8032b982017-07-28 11:04:54 -04001625
1626#Method void translate(SkScalar dx, SkScalar dy)
1627
Cary Clarkab2621d2018-01-30 10:08:57 -05001628#In Matrix
1629#Line # translates Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001630#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001631
1632#Example
1633#Height 128
1634#Description
1635scale() followed by translate() produces different results from translate() followed
Herb Derbyefe39bc2018-05-01 17:06:20 -04001636by scale().
Cary Clark8032b982017-07-28 11:04:54 -04001637
1638The blue stroke follows translate of (50, 50); a black
Herb Derbyefe39bc2018-05-01 17:06:20 -04001639fill follows scale of (2, 1/2.f). After restoring the clip, which resets
Cary Clark8032b982017-07-28 11:04:54 -04001640Matrix, a red frame follows the same scale of (2, 1/2.f); a gray fill
1641follows translate of (50, 50).
1642##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001643void draw(SkCanvas* canvas) {
1644 SkPaint filledPaint;
1645 SkPaint outlinePaint;
1646 outlinePaint.setStyle(SkPaint::kStroke_Style);
1647 outlinePaint.setColor(SK_ColorBLUE);
1648 canvas->save();
1649 canvas->translate(50, 50);
1650 canvas->drawCircle(28, 28, 15, outlinePaint); // blue center: (50+28, 50+28)
1651 canvas->scale(2, 1/2.f);
1652 canvas->drawCircle(28, 28, 15, filledPaint); // black center: (50+(28*2), 50+(28/2))
1653 canvas->restore();
1654 filledPaint.setColor(SK_ColorGRAY);
1655 outlinePaint.setColor(SK_ColorRED);
1656 canvas->scale(2, 1/2.f);
1657 canvas->drawCircle(28, 28, 15, outlinePaint); // red center: (28*2, 28/2)
1658 canvas->translate(50, 50);
1659 canvas->drawCircle(28, 28, 15, filledPaint); // gray center: ((50+28)*2, (50+28)/2)
Cary Clark8032b982017-07-28 11:04:54 -04001660}
1661##
1662
Cary Clark2ade9972017-11-02 17:49:34 -04001663#SeeAlso concat() scale() skew() rotate() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001664
1665##
1666
1667# ------------------------------------------------------------------------------
1668
1669#Method void scale(SkScalar sx, SkScalar sy)
1670
Cary Clarkab2621d2018-01-30 10:08:57 -05001671#In Matrix
1672#Line # scales Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001673#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001674
1675#Example
1676#Height 160
Cary Clarkbad5ad72017-08-03 17:14:08 -04001677void draw(SkCanvas* canvas) {
1678 SkPaint paint;
1679 SkRect rect = { 10, 20, 60, 120 };
1680 canvas->translate(20, 20);
1681 canvas->drawRect(rect, paint);
1682 canvas->scale(2, .5f);
1683 paint.setColor(SK_ColorGRAY);
1684 canvas->drawRect(rect, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001685}
1686##
1687
Cary Clark2ade9972017-11-02 17:49:34 -04001688#SeeAlso concat() translate() skew() rotate() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001689
1690##
1691
1692# ------------------------------------------------------------------------------
1693
1694#Method void rotate(SkScalar degrees)
1695
Cary Clarkab2621d2018-01-30 10:08:57 -05001696#In Matrix
1697#Line # rotates Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001698#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001699
1700#Example
1701#Description
1702Draw clock hands at time 5:10. The hour hand and minute hand point up and
1703are rotated clockwise.
1704##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001705void draw(SkCanvas* canvas) {
1706 SkPaint paint;
1707 paint.setStyle(SkPaint::kStroke_Style);
1708 canvas->translate(128, 128);
1709 canvas->drawCircle(0, 0, 60, paint);
1710 canvas->save();
1711 canvas->rotate(10 * 360 / 60); // 10 minutes of 60 scaled to 360 degrees
Herb Derbyefe39bc2018-05-01 17:06:20 -04001712 canvas->drawLine(0, 0, 0, -50, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001713 canvas->restore();
1714 canvas->rotate((5 + 10.f/60) * 360 / 12); // 5 and 10/60 hours of 12 scaled to 360 degrees
1715 canvas->drawLine(0, 0, 0, -30, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001716}
1717##
1718
Cary Clark2ade9972017-11-02 17:49:34 -04001719#SeeAlso concat() translate() skew() scale() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001720
1721##
1722
1723# ------------------------------------------------------------------------------
1724
1725#Method void rotate(SkScalar degrees, SkScalar px, SkScalar py)
1726
Cary Clarkab2621d2018-01-30 10:08:57 -05001727#In Matrix
Cary Clark09d80c02018-10-31 12:14:03 -04001728#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001729
1730#Example
1731#Height 192
Cary Clarkbad5ad72017-08-03 17:14:08 -04001732void draw(SkCanvas* canvas) {
1733 SkPaint paint;
1734 paint.setTextSize(96);
1735 canvas->drawString("A1", 130, 100, paint);
1736 canvas->rotate(180, 130, 100);
1737 canvas->drawString("A1", 130, 100, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001738}
1739##
1740
Cary Clark2ade9972017-11-02 17:49:34 -04001741#SeeAlso concat() translate() skew() scale() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001742
1743##
1744
1745# ------------------------------------------------------------------------------
1746
1747#Method void skew(SkScalar sx, SkScalar sy)
1748
Cary Clarkab2621d2018-01-30 10:08:57 -05001749#In Matrix
1750#Line # skews Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001751#Populate
Cary Clarkbad5ad72017-08-03 17:14:08 -04001752
Cary Clark8032b982017-07-28 11:04:54 -04001753#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04001754 #Description
Cary Clark5538c132018-06-14 12:28:14 -04001755 Black text mimics an oblique text style by using a negative skew on x-axis
1756 that shifts the geometry to the right as the y-axis values decrease.
1757 Red text uses a positive skew on y-axis to shift the geometry down
1758 as the x-axis values increase.
1759 Blue text combines sx and sy skew to rotate and scale.
Cary Clark8032b982017-07-28 11:04:54 -04001760 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001761 SkPaint paint;
1762 paint.setTextSize(128);
1763 canvas->translate(30, 130);
1764 canvas->save();
1765 canvas->skew(-.5, 0);
1766 canvas->drawString("A1", 0, 0, paint);
1767 canvas->restore();
1768 canvas->save();
1769 canvas->skew(0, .5);
1770 paint.setColor(SK_ColorRED);
1771 canvas->drawString("A1", 0, 0, paint);
1772 canvas->restore();
1773 canvas->skew(-.5, .5);
1774 paint.setColor(SK_ColorBLUE);
Cary Clark8032b982017-07-28 11:04:54 -04001775 canvas->drawString("A1", 0, 0, paint);
1776##
1777
Cary Clark2ade9972017-11-02 17:49:34 -04001778#SeeAlso concat() translate() rotate() scale() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001779
1780##
1781
1782# ------------------------------------------------------------------------------
1783
1784#Method void concat(const SkMatrix& matrix)
1785
Cary Clarkab2621d2018-01-30 10:08:57 -05001786#In Matrix
1787#Line # multiplies Matrix by Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001788#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001789
1790#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001791void draw(SkCanvas* canvas) {
1792 SkPaint paint;
1793 paint.setTextSize(80);
1794 paint.setTextScaleX(.3);
1795 SkMatrix matrix;
1796 SkRect rect[2] = {{ 10, 20, 90, 110 }, { 40, 130, 140, 180 }};
1797 matrix.setRectToRect(rect[0], rect[1], SkMatrix::kFill_ScaleToFit);
1798 canvas->drawRect(rect[0], paint);
1799 canvas->drawRect(rect[1], paint);
1800 paint.setColor(SK_ColorWHITE);
1801 canvas->drawString("Here", rect[0].fLeft + 10, rect[0].fBottom - 10, paint);
1802 canvas->concat(matrix);
1803 canvas->drawString("There", rect[0].fLeft + 10, rect[0].fBottom - 10, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001804}
1805##
1806
Cary Clark2ade9972017-11-02 17:49:34 -04001807#SeeAlso translate() rotate() scale() skew() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001808
1809##
1810
1811# ------------------------------------------------------------------------------
1812
1813#Method void setMatrix(const SkMatrix& matrix)
1814
Cary Clarkab2621d2018-01-30 10:08:57 -05001815#In Matrix
1816#Line # sets Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001817#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001818
1819#Example
1820#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001821void draw(SkCanvas* canvas) {
1822 SkPaint paint;
1823 canvas->scale(4, 6);
1824 canvas->drawString("truth", 2, 10, paint);
1825 SkMatrix matrix;
1826 matrix.setScale(2.8f, 6);
1827 canvas->setMatrix(matrix);
1828 canvas->drawString("consequences", 2, 20, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001829}
1830##
1831
Cary Clark2ade9972017-11-02 17:49:34 -04001832#SeeAlso resetMatrix concat() translate() rotate() scale() skew()
Cary Clark8032b982017-07-28 11:04:54 -04001833
1834##
1835
1836# ------------------------------------------------------------------------------
1837
1838#Method void resetMatrix()
1839
Cary Clarkab2621d2018-01-30 10:08:57 -05001840#In Matrix
1841#Line # resets Matrix to identity ##
Cary Clark09d80c02018-10-31 12:14:03 -04001842#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001843
1844#Example
1845#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001846void draw(SkCanvas* canvas) {
1847 SkPaint paint;
1848 canvas->scale(4, 6);
1849 canvas->drawString("truth", 2, 10, paint);
1850 canvas->resetMatrix();
1851 canvas->scale(2.8f, 6);
1852 canvas->drawString("consequences", 2, 20, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001853}
1854##
1855
Cary Clark2ade9972017-11-02 17:49:34 -04001856#SeeAlso setMatrix concat() translate() rotate() scale() skew()
Cary Clark8032b982017-07-28 11:04:54 -04001857
1858##
1859
1860# ------------------------------------------------------------------------------
1861
1862#Method const SkMatrix& getTotalMatrix() const
1863
Cary Clarkab2621d2018-01-30 10:08:57 -05001864#In Matrix
1865#Line # returns Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001866#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001867
1868#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001869 SkDebugf("isIdentity %s\n", canvas->getTotalMatrix().isIdentity() ? "true" : "false");
1870 #StdOut
1871 isIdentity true
1872 ##
Cary Clark8032b982017-07-28 11:04:54 -04001873##
1874
Cary Clark2ade9972017-11-02 17:49:34 -04001875#SeeAlso setMatrix resetMatrix concat()
Cary Clark8032b982017-07-28 11:04:54 -04001876
1877##
1878
Cary Clark08895c42018-02-01 09:37:32 -05001879#Subtopic Matrix ##
Cary Clark8032b982017-07-28 11:04:54 -04001880
1881# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001882#Subtopic Clip
1883#Line # stack of clipping Paths ##
Cary Clark8032b982017-07-28 11:04:54 -04001884
1885Clip is built from a stack of clipping paths. Each Path in the
Herb Derbyefe39bc2018-05-01 17:06:20 -04001886stack can be constructed from one or more Path_Contour elements. The
Cary Clark8032b982017-07-28 11:04:54 -04001887Path_Contour may be composed of any number of Path_Verb segments. Each
1888Path_Contour forms a closed area; Path_Fill_Type defines the area enclosed
1889by Path_Contour.
1890
1891Clip stack of Path elements successfully restrict the Path area. Each
Herb Derbyefe39bc2018-05-01 17:06:20 -04001892Path is transformed by Matrix, then intersected with or subtracted from the
Cary Clark8032b982017-07-28 11:04:54 -04001893prior Clip to form the replacement Clip. Use SkClipOp::kDifference
1894to subtract Path from Clip; use SkClipOp::kIntersect to intersect Path
1895with Clip.
1896
Cary Clarkffb3d682018-05-17 12:17:28 -04001897A clipping Path may be Anti_Aliased; if Path, after transformation, is
1898composed of horizontal and vertical lines, clearing Anti_Alias allows whole pixels
Cary Clarkce101242017-09-01 15:51:02 -04001899to either be inside or outside the clip. The fastest drawing has a Aliased,
1900rectangular clip.
Cary Clark8032b982017-07-28 11:04:54 -04001901
Cary Clarkffb3d682018-05-17 12:17:28 -04001902If clipping Path has Anti_Alias set, clip may partially clip a pixel, requiring
Herb Derbyefe39bc2018-05-01 17:06:20 -04001903that drawing blend partially with the destination along the edge. A rotated
Cary Clarkffb3d682018-05-17 12:17:28 -04001904rectangular Anti_Aliased clip looks smoother but draws slower.
Cary Clark8032b982017-07-28 11:04:54 -04001905
1906Clip can combine with Rect and Round_Rect primitives; like
1907Path, these are transformed by Matrix before they are combined with Clip.
1908
1909Clip can combine with Region. Region is assumed to be in Device coordinates
1910and is unaffected by Matrix.
1911
1912#Example
1913#Height 90
1914 #Description
Cary Clarkffb3d682018-05-17 12:17:28 -04001915 Draw a red circle with an Aliased clip and an Anti_Aliased clip.
Cary Clark8032b982017-07-28 11:04:54 -04001916 Use an image filter to zoom into the pixels drawn.
Cary Clarkce101242017-09-01 15:51:02 -04001917 The edge of the Aliased clip fully draws pixels in the red circle.
Cary Clarkffb3d682018-05-17 12:17:28 -04001918 The edge of the Anti_Aliased clip partially draws pixels in the red circle.
Cary Clark8032b982017-07-28 11:04:54 -04001919 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001920 SkPaint redPaint, scalePaint;
1921 redPaint.setAntiAlias(true);
1922 redPaint.setColor(SK_ColorRED);
1923 canvas->save();
1924 for (bool antialias : { false, true } ) {
1925 canvas->save();
1926 canvas->clipRect(SkRect::MakeWH(19.5f, 11.5f), antialias);
1927 canvas->drawCircle(17, 11, 8, redPaint);
1928 canvas->restore();
1929 canvas->translate(16, 0);
1930 }
1931 canvas->restore();
1932 SkMatrix matrix;
1933 matrix.setScale(6, 6);
1934 scalePaint.setImageFilter(
1935 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
1936 SkCanvas::SaveLayerRec saveLayerRec(
Herb Derbyefe39bc2018-05-01 17:06:20 -04001937 nullptr, &scalePaint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001938 canvas->saveLayer(saveLayerRec);
Cary Clark8032b982017-07-28 11:04:54 -04001939 canvas->restore();
1940##
1941
1942#Method void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias)
1943
Cary Clarkab2621d2018-01-30 10:08:57 -05001944#In Clip
1945#Line # combines Clip with Rect ##
Cary Clark09d80c02018-10-31 12:14:03 -04001946#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001947
1948#Example
1949#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001950void draw(SkCanvas* canvas) {
1951 canvas->rotate(10);
1952 SkPaint paint;
1953 paint.setAntiAlias(true);
1954 for (auto alias: { false, true } ) {
1955 canvas->save();
1956 canvas->clipRect(SkRect::MakeWH(90, 80), SkClipOp::kIntersect, alias);
1957 canvas->drawCircle(100, 60, 60, paint);
1958 canvas->restore();
1959 canvas->translate(80, 0);
1960 }
Cary Clark8032b982017-07-28 11:04:54 -04001961}
1962##
1963
Cary Clark2ade9972017-11-02 17:49:34 -04001964#SeeAlso clipRRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001965
1966##
1967
Herb Derbyefe39bc2018-05-01 17:06:20 -04001968#Method void clipRect(const SkRect& rect, SkClipOp op)
Cary Clark8032b982017-07-28 11:04:54 -04001969
Cary Clarkab2621d2018-01-30 10:08:57 -05001970#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04001971#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001972
1973#Example
1974#Height 192
1975#Width 280
Cary Clarkbad5ad72017-08-03 17:14:08 -04001976void draw(SkCanvas* canvas) {
1977 SkPaint paint;
1978 for (SkClipOp op: { SkClipOp::kIntersect, SkClipOp::kDifference } ) {
1979 canvas->save();
1980 canvas->clipRect(SkRect::MakeWH(90, 120), op, false);
1981 canvas->drawCircle(100, 100, 60, paint);
1982 canvas->restore();
1983 canvas->translate(80, 0);
1984 }
Cary Clark8032b982017-07-28 11:04:54 -04001985}
1986##
1987
Cary Clark2ade9972017-11-02 17:49:34 -04001988#SeeAlso clipRRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001989
1990##
1991
Herb Derbyefe39bc2018-05-01 17:06:20 -04001992#Method void clipRect(const SkRect& rect, bool doAntiAlias = false)
Cary Clark8032b982017-07-28 11:04:54 -04001993
Cary Clarkab2621d2018-01-30 10:08:57 -05001994#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04001995#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001996
1997#Example
1998#Height 133
1999 #Description
Cary Clarkce101242017-09-01 15:51:02 -04002000 A circle drawn in pieces looks uniform when drawn Aliased.
Cary Clarkffb3d682018-05-17 12:17:28 -04002001 The same circle pieces blend with pixels more than once when Anti_Aliased,
Cary Clark8032b982017-07-28 11:04:54 -04002002 visible as a thin pair of lines through the right circle.
2003 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002004void draw(SkCanvas* canvas) {
2005 canvas->clear(SK_ColorWHITE);
2006 SkPaint paint;
2007 paint.setAntiAlias(true);
2008 paint.setColor(0x8055aaff);
2009 SkRect clipRect = { 0, 0, 87.4f, 87.4f };
2010 for (auto alias: { false, true } ) {
2011 canvas->save();
2012 canvas->clipRect(clipRect, SkClipOp::kIntersect, alias);
2013 canvas->drawCircle(67, 67, 60, paint);
2014 canvas->restore();
2015 canvas->save();
2016 canvas->clipRect(clipRect, SkClipOp::kDifference, alias);
2017 canvas->drawCircle(67, 67, 60, paint);
2018 canvas->restore();
2019 canvas->translate(120, 0);
2020 }
Cary Clark8032b982017-07-28 11:04:54 -04002021}
2022##
2023
Cary Clark2ade9972017-11-02 17:49:34 -04002024#SeeAlso clipRRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04002025
2026##
2027
2028#Method void androidFramework_setDeviceClipRestriction(const SkIRect& rect)
2029
Cary Clarkab2621d2018-01-30 10:08:57 -05002030#In Clip
Cary Clark682c58d2018-05-16 07:07:07 -04002031#Line # exists for use by Android framework ##
Cary Clarkce101242017-09-01 15:51:02 -04002032Sets the maximum clip rectangle, which can be set by clipRect, clipRRect and
Cary Clark8032b982017-07-28 11:04:54 -04002033clipPath and intersect the current clip with the specified rect.
Cary Clarkce101242017-09-01 15:51:02 -04002034The maximum clip affects only future clipping operations; it is not retroactive.
Cary Clark8032b982017-07-28 11:04:54 -04002035The clip restriction is not recorded in pictures.
2036
Herb Derbyefe39bc2018-05-01 17:06:20 -04002037Pass an empty rect to disable maximum clip.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002038
Cary Clark8032b982017-07-28 11:04:54 -04002039#Private
Cary Clark137b8742018-05-30 09:21:49 -04002040This private API is for use by Android framework only.
Cary Clark8032b982017-07-28 11:04:54 -04002041##
2042
Cary Clarkbad5ad72017-08-03 17:14:08 -04002043#Param rect maximum allowed clip in device coordinates
Cary Clark579985c2017-07-31 11:48:27 -04002044#Param ##
Cary Clark8032b982017-07-28 11:04:54 -04002045
2046##
2047
2048#Method void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias)
2049
Cary Clarkab2621d2018-01-30 10:08:57 -05002050#In Clip
2051#Line # combines Clip with Round_Rect ##
Cary Clark09d80c02018-10-31 12:14:03 -04002052#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002053
2054#Example
2055#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002056void draw(SkCanvas* canvas) {
2057 canvas->clear(SK_ColorWHITE);
2058 SkPaint paint;
2059 paint.setAntiAlias(true);
2060 paint.setColor(0x8055aaff);
2061 SkRRect oval;
2062 oval.setOval({10, 20, 90, 100});
2063 canvas->clipRRect(oval, SkClipOp::kIntersect, true);
2064 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002065}
2066##
2067
Cary Clark2ade9972017-11-02 17:49:34 -04002068#SeeAlso clipRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04002069
2070##
2071
Herb Derbyefe39bc2018-05-01 17:06:20 -04002072#Method void clipRRect(const SkRRect& rrect, SkClipOp op)
Cary Clark8032b982017-07-28 11:04:54 -04002073
Cary Clarkab2621d2018-01-30 10:08:57 -05002074#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002075#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002076
2077#Example
2078#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002079void draw(SkCanvas* canvas) {
2080 SkPaint paint;
2081 paint.setColor(0x8055aaff);
2082 auto oval = SkRRect::MakeOval({10, 20, 90, 100});
2083 canvas->clipRRect(oval, SkClipOp::kIntersect);
2084 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002085}
2086##
2087
Cary Clark2ade9972017-11-02 17:49:34 -04002088#SeeAlso clipRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04002089
2090##
2091
Herb Derbyefe39bc2018-05-01 17:06:20 -04002092#Method void clipRRect(const SkRRect& rrect, bool doAntiAlias = false)
Cary Clark8032b982017-07-28 11:04:54 -04002093
Cary Clarkab2621d2018-01-30 10:08:57 -05002094#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002095#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002096
2097#Example
2098#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002099void draw(SkCanvas* canvas) {
2100 SkPaint paint;
2101 paint.setAntiAlias(true);
2102 auto oval = SkRRect::MakeRectXY({10, 20, 90, 100}, 9, 13);
2103 canvas->clipRRect(oval, true);
2104 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002105}
2106##
2107
Cary Clark2ade9972017-11-02 17:49:34 -04002108#SeeAlso clipRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04002109
2110##
2111
2112#Method void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias)
2113
Cary Clarkab2621d2018-01-30 10:08:57 -05002114#In Clip
2115#Line # combines Clip with Path ##
Cary Clark09d80c02018-10-31 12:14:03 -04002116#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002117
2118#Example
2119#Description
2120Top figure uses SkPath::kInverseWinding_FillType and SkClipOp::kDifference;
2121area outside clip is subtracted from circle.
2122
2123Bottom figure uses SkPath::kWinding_FillType and SkClipOp::kIntersect;
2124area inside clip is intersected with circle.
2125##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002126void draw(SkCanvas* canvas) {
2127 SkPaint paint;
2128 paint.setAntiAlias(true);
2129 SkPath path;
2130 path.addRect({20, 30, 100, 110});
2131 path.setFillType(SkPath::kInverseWinding_FillType);
2132 canvas->save();
2133 canvas->clipPath(path, SkClipOp::kDifference, false);
2134 canvas->drawCircle(70, 100, 60, paint);
2135 canvas->restore();
2136 canvas->translate(100, 100);
2137 path.setFillType(SkPath::kWinding_FillType);
2138 canvas->clipPath(path, SkClipOp::kIntersect, false);
2139 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002140}
2141##
2142
Cary Clark2ade9972017-11-02 17:49:34 -04002143#SeeAlso clipRect clipRRect clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04002144
2145##
2146
Herb Derbyefe39bc2018-05-01 17:06:20 -04002147#Method void clipPath(const SkPath& path, SkClipOp op)
Cary Clark8032b982017-07-28 11:04:54 -04002148
Cary Clarkab2621d2018-01-30 10:08:57 -05002149#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002150#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002151
2152#Example
2153#Description
Cary Clarkbc5697d2017-10-04 14:31:33 -04002154Overlapping Rects form a clip. When clip Path_Fill_Type is set to
Herb Derbyefe39bc2018-05-01 17:06:20 -04002155SkPath::kWinding_FillType, the overlap is included. Set to
Cary Clark8032b982017-07-28 11:04:54 -04002156SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
2157##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002158void draw(SkCanvas* canvas) {
2159 SkPaint paint;
2160 paint.setAntiAlias(true);
2161 SkPath path;
2162 path.addRect({20, 15, 100, 95});
2163 path.addRect({50, 65, 130, 135});
2164 path.setFillType(SkPath::kWinding_FillType);
2165 canvas->save();
2166 canvas->clipPath(path, SkClipOp::kIntersect);
2167 canvas->drawCircle(70, 85, 60, paint);
2168 canvas->restore();
2169 canvas->translate(100, 100);
2170 path.setFillType(SkPath::kEvenOdd_FillType);
2171 canvas->clipPath(path, SkClipOp::kIntersect);
2172 canvas->drawCircle(70, 85, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002173}
2174##
2175
Cary Clark2ade9972017-11-02 17:49:34 -04002176#SeeAlso clipRect clipRRect clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04002177
2178##
2179
Herb Derbyefe39bc2018-05-01 17:06:20 -04002180#Method void clipPath(const SkPath& path, bool doAntiAlias = false)
Cary Clark8032b982017-07-28 11:04:54 -04002181
Cary Clarkab2621d2018-01-30 10:08:57 -05002182#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002183#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002184
2185#Example
2186#Height 212
2187#Description
Herb Derbyefe39bc2018-05-01 17:06:20 -04002188Clip loops over itself covering its center twice. When clip Path_Fill_Type
2189is set to SkPath::kWinding_FillType, the overlap is included. Set to
Cary Clark8032b982017-07-28 11:04:54 -04002190SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
2191##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002192void draw(SkCanvas* canvas) {
2193 SkPaint paint;
2194 paint.setAntiAlias(true);
2195 SkPath path;
2196 SkPoint poly[] = {{20, 20}, { 80, 20}, { 80, 80}, {40, 80},
2197 {40, 40}, {100, 40}, {100, 100}, {20, 100}};
2198 path.addPoly(poly, SK_ARRAY_COUNT(poly), true);
2199 path.setFillType(SkPath::kWinding_FillType);
2200 canvas->save();
2201 canvas->clipPath(path, SkClipOp::kIntersect);
2202 canvas->drawCircle(50, 50, 45, paint);
2203 canvas->restore();
2204 canvas->translate(100, 100);
2205 path.setFillType(SkPath::kEvenOdd_FillType);
2206 canvas->clipPath(path, SkClipOp::kIntersect);
2207 canvas->drawCircle(50, 50, 45, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002208}
2209##
2210
Cary Clark2ade9972017-11-02 17:49:34 -04002211#SeeAlso clipRect clipRRect clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04002212
2213##
2214
2215# ------------------------------------------------------------------------------
2216
Herb Derbyefe39bc2018-05-01 17:06:20 -04002217#Method void setAllowSimplifyClip(bool allow)
Cary Clark8032b982017-07-28 11:04:54 -04002218
Cary Clarkab2621d2018-01-30 10:08:57 -05002219#In Clip
Cary Clark682c58d2018-05-16 07:07:07 -04002220#Experimental testing
Cary Clark8032b982017-07-28 11:04:54 -04002221
Cary Clarkce101242017-09-01 15:51:02 -04002222Set to simplify clip stack using PathOps.
Cary Clark8032b982017-07-28 11:04:54 -04002223
2224##
2225
2226# ------------------------------------------------------------------------------
2227
2228#Method void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect)
2229
Cary Clarkab2621d2018-01-30 10:08:57 -05002230#In Clip
2231#Line # combines Clip with Region ##
Cary Clark09d80c02018-10-31 12:14:03 -04002232#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002233
2234#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002235#Description
Cary Clarkce101242017-09-01 15:51:02 -04002236 region is unaffected by canvas rotation; iRect is affected by canvas rotation.
2237 Both clips are Aliased; this is not noticeable on Region clip because it
Cary Clarkbad5ad72017-08-03 17:14:08 -04002238 aligns to pixel boundaries.
2239##
2240void draw(SkCanvas* canvas) {
2241 SkPaint paint;
2242 paint.setAntiAlias(true);
2243 SkIRect iRect = {30, 40, 120, 130 };
2244 SkRegion region(iRect);
2245 canvas->rotate(10);
2246 canvas->save();
2247 canvas->clipRegion(region, SkClipOp::kIntersect);
2248 canvas->drawCircle(50, 50, 45, paint);
2249 canvas->restore();
2250 canvas->translate(100, 100);
2251 canvas->clipRect(SkRect::Make(iRect), SkClipOp::kIntersect);
2252 canvas->drawCircle(50, 50, 45, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002253}
2254##
2255
Cary Clark2ade9972017-11-02 17:49:34 -04002256#SeeAlso clipRect clipRRect clipPath
Cary Clark8032b982017-07-28 11:04:54 -04002257
2258##
2259
2260#Method bool quickReject(const SkRect& rect) const
2261
Cary Clarkab2621d2018-01-30 10:08:57 -05002262#In Clip
2263#Line # returns if Rect is outside Clip ##
Cary Clark09d80c02018-10-31 12:14:03 -04002264#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002265
2266#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002267void draw(SkCanvas* canvas) {
Herb Derbyefe39bc2018-05-01 17:06:20 -04002268 SkRect testRect = {30, 30, 120, 129 };
2269 SkRect clipRect = {30, 130, 120, 230 };
Cary Clarkbad5ad72017-08-03 17:14:08 -04002270 canvas->save();
2271 canvas->clipRect(clipRect);
2272 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
2273 canvas->restore();
2274 canvas->rotate(10);
2275 canvas->clipRect(clipRect);
2276 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
Cary Clark8032b982017-07-28 11:04:54 -04002277}
2278 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002279 quickReject true
Cary Clark8032b982017-07-28 11:04:54 -04002280 quickReject false
2281 ##
2282##
2283
Cary Clark2ade9972017-11-02 17:49:34 -04002284#SeeAlso getLocalClipBounds getTotalMatrix SkBitmap::drawsNothing
Cary Clark8032b982017-07-28 11:04:54 -04002285
2286##
2287
2288#Method bool quickReject(const SkPath& path) const
2289
Cary Clarkab2621d2018-01-30 10:08:57 -05002290#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002291#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002292
2293#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002294void draw(SkCanvas* canvas) {
Herb Derbyefe39bc2018-05-01 17:06:20 -04002295 SkPoint testPoints[] = {{30, 30}, {120, 30}, {120, 129} };
2296 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
Cary Clarkbad5ad72017-08-03 17:14:08 -04002297 SkPath testPath, clipPath;
2298 testPath.addPoly(testPoints, SK_ARRAY_COUNT(testPoints), true);
2299 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2300 canvas->save();
2301 canvas->clipPath(clipPath);
2302 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
2303 canvas->restore();
2304 canvas->rotate(10);
2305 canvas->clipPath(clipPath);
2306 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
Cary Clark8032b982017-07-28 11:04:54 -04002307 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002308 quickReject true
Cary Clark8032b982017-07-28 11:04:54 -04002309 quickReject false
2310 ##
2311}
2312##
2313
Cary Clark2ade9972017-11-02 17:49:34 -04002314#SeeAlso getLocalClipBounds getTotalMatrix SkBitmap::drawsNothing
Cary Clark8032b982017-07-28 11:04:54 -04002315
2316##
2317
Herb Derbyefe39bc2018-05-01 17:06:20 -04002318#Method SkRect getLocalClipBounds() const
Cary Clark8032b982017-07-28 11:04:54 -04002319
Cary Clarkab2621d2018-01-30 10:08:57 -05002320#In Clip
2321#Line # returns Clip bounds in source coordinates ##
Cary Clark09d80c02018-10-31 12:14:03 -04002322#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002323
2324#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04002325 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002326 Initial bounds is device bounds outset by 1 on all sides.
2327 Clipped bounds is clipPath bounds outset by 1 on all sides.
Cary Clark5538c132018-06-14 12:28:14 -04002328 Scaling the canvas by two on both axes scales the local bounds by 1/2
2329 on both axes.
Cary Clark8032b982017-07-28 11:04:54 -04002330 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002331 SkCanvas local(256, 256);
2332 canvas = &local;
2333 SkRect bounds = canvas->getLocalClipBounds();
2334 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2335 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002336 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
Cary Clarkbad5ad72017-08-03 17:14:08 -04002337 SkPath clipPath;
2338 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2339 canvas->clipPath(clipPath);
2340 bounds = canvas->getLocalClipBounds();
2341 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2342 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2343 canvas->scale(2, 2);
2344 bounds = canvas->getLocalClipBounds();
2345 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2346 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2347 #StdOut
2348 left:-1 top:-1 right:257 bottom:257
2349 left:29 top:129 right:121 bottom:231
2350 left:14.5 top:64.5 right:60.5 bottom:115.5
2351 ##
Cary Clark8032b982017-07-28 11:04:54 -04002352##
2353
2354# local canvas in example works around bug in fiddle ##
Cary Clark4855f782018-02-06 09:41:53 -05002355#Bug 6524
Cary Clark2ade9972017-11-02 17:49:34 -04002356#SeeAlso getDeviceClipBounds getBaseLayerSize quickReject
Cary Clark8032b982017-07-28 11:04:54 -04002357
2358##
2359
Herb Derbyefe39bc2018-05-01 17:06:20 -04002360#Method bool getLocalClipBounds(SkRect* bounds) const
Cary Clark8032b982017-07-28 11:04:54 -04002361
Cary Clarkab2621d2018-01-30 10:08:57 -05002362#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002363#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002364
2365#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002366 void draw(SkCanvas* canvas) {
2367 SkCanvas local(256, 256);
2368 canvas = &local;
2369 SkRect bounds;
2370 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
2371 ? "false" : "true");
2372 SkPath path;
2373 canvas->clipPath(path);
2374 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
2375 ? "false" : "true");
Cary Clark8032b982017-07-28 11:04:54 -04002376 }
2377 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002378 local bounds empty = false
Cary Clark8032b982017-07-28 11:04:54 -04002379 local bounds empty = true
2380 ##
2381##
2382
2383# local canvas in example works around bug in fiddle ##
Cary Clark4855f782018-02-06 09:41:53 -05002384#Bug 6524
Cary Clark2ade9972017-11-02 17:49:34 -04002385#SeeAlso getDeviceClipBounds getBaseLayerSize quickReject
Cary Clark8032b982017-07-28 11:04:54 -04002386
2387##
2388
Herb Derbyefe39bc2018-05-01 17:06:20 -04002389#Method SkIRect getDeviceClipBounds() const
Cary Clark8032b982017-07-28 11:04:54 -04002390
Cary Clarkab2621d2018-01-30 10:08:57 -05002391#In Clip
2392#Line # returns IRect bounds of Clip ##
Cary Clark09d80c02018-10-31 12:14:03 -04002393#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002394
2395#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002396void draw(SkCanvas* canvas) {
2397 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002398 Initial bounds is device bounds, not outset.
2399 Clipped bounds is clipPath bounds, not outset.
Cary Clark5538c132018-06-14 12:28:14 -04002400 Scaling the canvas by 1/2 on both axes scales the device bounds by 1/2
2401 on both axes.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002402 ##
2403 SkCanvas device(256, 256);
2404 canvas = &device;
2405 SkIRect bounds = canvas->getDeviceClipBounds();
2406 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2407 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002408 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
Cary Clarkbad5ad72017-08-03 17:14:08 -04002409 SkPath clipPath;
2410 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2411 canvas->save();
2412 canvas->clipPath(clipPath);
2413 bounds = canvas->getDeviceClipBounds();
2414 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2415 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2416 canvas->restore();
2417 canvas->scale(1.f/2, 1.f/2);
2418 canvas->clipPath(clipPath);
2419 bounds = canvas->getDeviceClipBounds();
2420 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2421 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
Cary Clark8032b982017-07-28 11:04:54 -04002422 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002423 left:0 top:0 right:256 bottom:256
2424 left:30 top:130 right:120 bottom:230
Cary Clark8032b982017-07-28 11:04:54 -04002425 left:15 top:65 right:60 bottom:115
2426 ##
2427}
2428##
2429
2430#ToDo some confusion on why with an identity Matrix local and device are different ##
Cary Clark2ade9972017-11-02 17:49:34 -04002431#SeeAlso getLocalClipBounds getBaseLayerSize quickReject
Cary Clark8032b982017-07-28 11:04:54 -04002432
2433# device canvas in example works around bug in fiddle ##
Cary Clark4855f782018-02-06 09:41:53 -05002434#Bug 6524
Cary Clark8032b982017-07-28 11:04:54 -04002435
2436##
2437
Herb Derbyefe39bc2018-05-01 17:06:20 -04002438#Method bool getDeviceClipBounds(SkIRect* bounds) const
Cary Clark8032b982017-07-28 11:04:54 -04002439
Cary Clarkab2621d2018-01-30 10:08:57 -05002440#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002441#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002442
2443#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002444 void draw(SkCanvas* canvas) {
2445 SkIRect bounds;
2446 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
2447 ? "false" : "true");
2448 SkPath path;
2449 canvas->clipPath(path);
2450 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
2451 ? "false" : "true");
Cary Clark8032b982017-07-28 11:04:54 -04002452 }
2453 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002454 device bounds empty = false
Cary Clark8032b982017-07-28 11:04:54 -04002455 device bounds empty = true
2456 ##
2457##
2458
Cary Clark2ade9972017-11-02 17:49:34 -04002459#SeeAlso getLocalClipBounds getBaseLayerSize quickReject
Cary Clark8032b982017-07-28 11:04:54 -04002460
2461##
2462
Cary Clark08895c42018-02-01 09:37:32 -05002463#Subtopic Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002464
2465# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -05002466#Subtopic Draw
Cary Clark78de7512018-02-07 07:27:09 -05002467#Line # draws into Canvas ##
2468##
Cary Clark8032b982017-07-28 11:04:54 -04002469
2470#Method void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver)
Cary Clark78de7512018-02-07 07:27:09 -05002471#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002472#Line # fills Clip with Color and Blend_Mode ##
Cary Clark09d80c02018-10-31 12:14:03 -04002473#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002474
2475#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002476 canvas->drawColor(SK_ColorRED);
2477 canvas->clipRect(SkRect::MakeWH(150, 150));
2478 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00), SkBlendMode::kPlus);
2479 canvas->clipRect(SkRect::MakeWH(75, 75));
2480 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF), SkBlendMode::kPlus);
Cary Clark8032b982017-07-28 11:04:54 -04002481##
2482
Cary Clark2ade9972017-11-02 17:49:34 -04002483#SeeAlso clear SkBitmap::erase drawPaint
Cary Clark8032b982017-07-28 11:04:54 -04002484
2485##
2486
2487# ------------------------------------------------------------------------------
2488
Herb Derbyefe39bc2018-05-01 17:06:20 -04002489#Method void clear(SkColor color)
Cary Clark78de7512018-02-07 07:27:09 -05002490#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002491#Line # fills Clip with Color ##
Cary Clark09d80c02018-10-31 12:14:03 -04002492#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002493
2494#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002495void draw(SkCanvas* canvas) {
2496 canvas->save();
2497 canvas->clipRect(SkRect::MakeWH(256, 128));
Herb Derbyefe39bc2018-05-01 17:06:20 -04002498 canvas->clear(SkColorSetARGB(0x80, 0xFF, 0x00, 0x00));
Cary Clarkbad5ad72017-08-03 17:14:08 -04002499 canvas->restore();
2500 canvas->save();
2501 canvas->clipRect(SkRect::MakeWH(150, 192));
2502 canvas->clear(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00));
2503 canvas->restore();
2504 canvas->clipRect(SkRect::MakeWH(75, 256));
2505 canvas->clear(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF));
Cary Clark8032b982017-07-28 11:04:54 -04002506}
2507##
2508
Cary Clark2ade9972017-11-02 17:49:34 -04002509#SeeAlso drawColor SkBitmap::erase drawPaint
Cary Clark8032b982017-07-28 11:04:54 -04002510
2511##
2512
2513# ------------------------------------------------------------------------------
2514
Herb Derbyefe39bc2018-05-01 17:06:20 -04002515#Method void discard()
Cary Clark78de7512018-02-07 07:27:09 -05002516#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05002517#Line # makes Canvas contents undefined ##
Cary Clark09d80c02018-10-31 12:14:03 -04002518#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002519
Herb Derbyefe39bc2018-05-01 17:06:20 -04002520#NoExample
Cary Clark8032b982017-07-28 11:04:54 -04002521##
2522
Cary Clark09d80c02018-10-31 12:14:03 -04002523#SeeAlso flush() SkSurface::prepareForExternalIO GrContext::abandonContext
2524
Cary Clark8032b982017-07-28 11:04:54 -04002525##
2526
2527# ------------------------------------------------------------------------------
2528
2529#Method void drawPaint(const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002530#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002531#Line # fills Clip with Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002532#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002533
2534#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002535void draw(SkCanvas* canvas) {
2536 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
2537 SkScalar pos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
2538 SkPaint paint;
2539 paint.setShader(SkGradientShader::MakeSweep(256, 256, colors, pos, SK_ARRAY_COUNT(colors)));
2540 canvas->drawPaint(paint);
Cary Clark8032b982017-07-28 11:04:54 -04002541}
2542##
2543
Cary Clark2ade9972017-11-02 17:49:34 -04002544#SeeAlso clear drawColor SkBitmap::erase
Cary Clark8032b982017-07-28 11:04:54 -04002545
2546##
2547
2548# ------------------------------------------------------------------------------
2549
2550#Enum PointMode
Cary Clark08895c42018-02-01 09:37:32 -05002551#Line # sets drawPoints options ##
Cary Clark8032b982017-07-28 11:04:54 -04002552
2553#Code
Cary Clark61313f32018-10-08 14:57:48 -04002554#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002555##
2556
2557Selects if an array of points are drawn as discrete points, as lines, or as
2558an open polygon.
2559
2560#Const kPoints_PointMode 0
Cary Clark682c58d2018-05-16 07:07:07 -04002561#Line # draw each point separately ##
Cary Clark8032b982017-07-28 11:04:54 -04002562##
2563
2564#Const kLines_PointMode 1
Cary Clark682c58d2018-05-16 07:07:07 -04002565#Line # draw each pair of points as a line segment ##
Cary Clark8032b982017-07-28 11:04:54 -04002566##
2567
2568#Const kPolygon_PointMode 2
Cary Clark682c58d2018-05-16 07:07:07 -04002569#Line # draw the array of points as a open polygon ##
Cary Clark8032b982017-07-28 11:04:54 -04002570##
2571
2572#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04002573 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002574 The upper left corner shows three squares when drawn as points.
2575 The upper right corner shows one line; when drawn as lines, two points are required per line.
2576 The lower right corner shows two lines; when draw as polygon, no miter is drawn at the corner.
2577 The lower left corner shows two lines with a miter when path contains polygon.
2578 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002579void draw(SkCanvas* canvas) {
2580 SkPaint paint;
2581 paint.setStyle(SkPaint::kStroke_Style);
2582 paint.setStrokeWidth(10);
2583 SkPoint points[] = {{64, 32}, {96, 96}, {32, 96}};
2584 canvas->drawPoints(SkCanvas::kPoints_PointMode, 3, points, paint);
2585 canvas->translate(128, 0);
2586 canvas->drawPoints(SkCanvas::kLines_PointMode, 3, points, paint);
2587 canvas->translate(0, 128);
2588 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, points, paint);
2589 SkPath path;
2590 path.addPoly(points, 3, false);
2591 canvas->translate(-128, 0);
2592 canvas->drawPath(path, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002593}
2594##
2595
Cary Clark2ade9972017-11-02 17:49:34 -04002596#SeeAlso drawLine drawPoint drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002597
2598##
2599
2600# ------------------------------------------------------------------------------
2601
2602#Method void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002603#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002604#Line # draws array as points, lines, polygon ##
Cary Clark09d80c02018-10-31 12:14:03 -04002605#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002606
2607#Example
2608#Height 200
Herb Derbyefe39bc2018-05-01 17:06:20 -04002609 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002610 #List
2611 # The first column draws points. ##
2612 # The second column draws points as lines. ##
2613 # The third column draws points as a polygon. ##
2614 # The fourth column draws points as a polygonal path. ##
2615 # The first row uses a round cap and round join. ##
2616 # The second row uses a square cap and a miter join. ##
2617 # The third row uses a butt cap and a bevel join. ##
2618 ##
2619 The transparent color makes multiple line draws visible;
2620 the path is drawn all at once.
2621 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002622void draw(SkCanvas* canvas) {
2623 SkPaint paint;
2624 paint.setAntiAlias(true);
2625 paint.setStyle(SkPaint::kStroke_Style);
2626 paint.setStrokeWidth(10);
2627 paint.setColor(0x80349a45);
2628 const SkPoint points[] = {{32, 16}, {48, 48}, {16, 32}};
Herb Derbyefe39bc2018-05-01 17:06:20 -04002629 const SkPaint::Join join[] = { SkPaint::kRound_Join,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002630 SkPaint::kMiter_Join,
2631 SkPaint::kBevel_Join };
2632 int joinIndex = 0;
2633 SkPath path;
2634 path.addPoly(points, 3, false);
2635 for (const auto cap : { SkPaint::kRound_Cap, SkPaint::kSquare_Cap, SkPaint::kButt_Cap } ) {
2636 paint.setStrokeCap(cap);
2637 paint.setStrokeJoin(join[joinIndex++]);
2638 for (const auto mode : { SkCanvas::kPoints_PointMode,
2639 SkCanvas::kLines_PointMode,
2640 SkCanvas::kPolygon_PointMode } ) {
2641 canvas->drawPoints(mode, 3, points, paint);
2642 canvas->translate(64, 0);
2643 }
2644 canvas->drawPath(path, paint);
2645 canvas->translate(-192, 64);
2646 }
Cary Clark8032b982017-07-28 11:04:54 -04002647}
2648##
2649
Cary Clark2ade9972017-11-02 17:49:34 -04002650#SeeAlso drawLine drawPoint drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002651
2652##
2653
2654# ------------------------------------------------------------------------------
2655
2656#Method void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002657#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002658#Line # draws point at (x, y) position ##
Cary Clark09d80c02018-10-31 12:14:03 -04002659#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002660
2661#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002662void draw(SkCanvas* canvas) {
2663 SkPaint paint;
2664 paint.setAntiAlias(true);
2665 paint.setColor(0x80349a45);
2666 paint.setStyle(SkPaint::kStroke_Style);
2667 paint.setStrokeWidth(100);
2668 paint.setStrokeCap(SkPaint::kRound_Cap);
2669 canvas->scale(1, 1.2f);
2670 canvas->drawPoint(64, 96, paint);
2671 canvas->scale(.6f, .8f);
2672 paint.setColor(SK_ColorWHITE);
2673 canvas->drawPoint(106, 120, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002674}
2675##
2676
Cary Clark2ade9972017-11-02 17:49:34 -04002677#SeeAlso drawPoints drawCircle drawRect drawLine drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002678
2679##
2680
Cary Clarkbad5ad72017-08-03 17:14:08 -04002681#Method void drawPoint(SkPoint p, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04002682#Populate
Cary Clarkbad5ad72017-08-03 17:14:08 -04002683
2684#Example
2685void draw(SkCanvas* canvas) {
2686 SkPaint paint;
2687 paint.setAntiAlias(true);
2688 paint.setColor(0x80349a45);
2689 paint.setStyle(SkPaint::kStroke_Style);
2690 paint.setStrokeWidth(100);
2691 paint.setStrokeCap(SkPaint::kSquare_Cap);
2692 canvas->scale(1, 1.2f);
2693 canvas->drawPoint({64, 96}, paint);
2694 canvas->scale(.6f, .8f);
2695 paint.setColor(SK_ColorWHITE);
2696 canvas->drawPoint(106, 120, paint);
2697}
2698##
2699
Cary Clark2ade9972017-11-02 17:49:34 -04002700#SeeAlso drawPoints drawCircle drawRect drawLine drawPath
Cary Clarkbad5ad72017-08-03 17:14:08 -04002701
2702##
2703
Cary Clark8032b982017-07-28 11:04:54 -04002704# ------------------------------------------------------------------------------
2705
2706#Method void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002707#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002708#Line # draws line segment between two points ##
Cary Clark09d80c02018-10-31 12:14:03 -04002709#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002710
2711#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002712 SkPaint paint;
2713 paint.setAntiAlias(true);
2714 paint.setColor(0xFF9a67be);
2715 paint.setStrokeWidth(20);
2716 canvas->skew(1, 0);
2717 canvas->drawLine(32, 96, 32, 160, paint);
2718 canvas->skew(-2, 0);
2719 canvas->drawLine(288, 96, 288, 160, paint);
2720##
2721
Cary Clark2ade9972017-11-02 17:49:34 -04002722#SeeAlso drawPoint drawCircle drawRect drawPath
Cary Clarkbad5ad72017-08-03 17:14:08 -04002723
2724##
2725
2726#Method void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04002727#Populate
Cary Clarkbad5ad72017-08-03 17:14:08 -04002728
2729#Example
2730 SkPaint paint;
2731 paint.setAntiAlias(true);
2732 paint.setColor(0xFF9a67be);
2733 paint.setStrokeWidth(20);
2734 canvas->skew(1, 0);
2735 canvas->drawLine({32, 96}, {32, 160}, paint);
2736 canvas->skew(-2, 0);
2737 canvas->drawLine({288, 96}, {288, 160}, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002738##
2739
Cary Clark2ade9972017-11-02 17:49:34 -04002740#SeeAlso drawPoint drawCircle drawRect drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002741
2742##
2743
2744# ------------------------------------------------------------------------------
2745
2746#Method void drawRect(const SkRect& rect, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002747#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002748#Line # draws Rect using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002749#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002750
2751#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002752void draw(SkCanvas* canvas) {
2753 SkPoint rectPts[] = { {64, 48}, {192, 160} };
2754 SkPaint paint;
2755 paint.setAntiAlias(true);
2756 paint.setStyle(SkPaint::kStroke_Style);
2757 paint.setStrokeWidth(20);
2758 paint.setStrokeJoin(SkPaint::kRound_Join);
2759 SkMatrix rotator;
2760 rotator.setRotate(30, 128, 128);
2761 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
2762 paint.setColor(color);
2763 SkRect rect;
2764 rect.set(rectPts[0], rectPts[1]);
2765 canvas->drawRect(rect, paint);
2766 rotator.mapPoints(rectPts, 2);
2767 }
Cary Clark8032b982017-07-28 11:04:54 -04002768}
2769##
2770
Herb Derbyefe39bc2018-05-01 17:06:20 -04002771#SeeAlso drawIRect drawRRect drawRoundRect drawRegion drawPath drawLine
Cary Clark8032b982017-07-28 11:04:54 -04002772
2773##
2774
2775# ------------------------------------------------------------------------------
2776
Herb Derbyefe39bc2018-05-01 17:06:20 -04002777#Method void drawIRect(const SkIRect& rect, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002778#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002779#Line # draws IRect using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002780#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002781
2782#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002783 SkIRect rect = { 64, 48, 192, 160 };
2784 SkPaint paint;
2785 paint.setAntiAlias(true);
2786 paint.setStyle(SkPaint::kStroke_Style);
2787 paint.setStrokeWidth(20);
2788 paint.setStrokeJoin(SkPaint::kRound_Join);
2789 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
2790 paint.setColor(color);
2791 canvas->drawIRect(rect, paint);
2792 canvas->rotate(30, 128, 128);
2793 }
Cary Clark8032b982017-07-28 11:04:54 -04002794##
2795
Cary Clark2ade9972017-11-02 17:49:34 -04002796#SeeAlso drawRect drawRRect drawRoundRect drawRegion drawPath drawLine
Cary Clark8032b982017-07-28 11:04:54 -04002797
2798##
2799
2800# ------------------------------------------------------------------------------
2801
2802#Method void drawRegion(const SkRegion& region, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002803#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002804#Line # draws Region using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002805#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002806
2807#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002808void draw(SkCanvas* canvas) {
2809 SkRegion region;
2810 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
2811 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
2812 SkPaint paint;
2813 paint.setAntiAlias(true);
2814 paint.setStyle(SkPaint::kStroke_Style);
2815 paint.setStrokeWidth(20);
2816 paint.setStrokeJoin(SkPaint::kRound_Join);
2817 canvas->drawRegion(region, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002818}
2819##
2820
Cary Clark2ade9972017-11-02 17:49:34 -04002821#SeeAlso drawRect drawIRect drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002822
2823##
2824
2825# ------------------------------------------------------------------------------
2826
2827#Method void drawOval(const SkRect& oval, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002828#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002829#Line # draws Oval using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002830#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002831
2832#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002833void draw(SkCanvas* canvas) {
2834 canvas->clear(0xFF3f5f9f);
2835 SkColor kColor1 = SkColorSetARGB(0xff, 0xff, 0x7f, 0);
2836 SkColor g1Colors[] = { kColor1, SkColorSetA(kColor1, 0x20) };
2837 SkPoint g1Points[] = { { 0, 0 }, { 0, 100 } };
2838 SkScalar pos[] = { 0.2f, 1.0f };
2839 SkRect bounds = SkRect::MakeWH(80, 70);
2840 SkPaint paint;
2841 paint.setAntiAlias(true);
2842 paint.setShader(SkGradientShader::MakeLinear(g1Points, g1Colors, pos, SK_ARRAY_COUNT(g1Colors),
2843 SkShader::kClamp_TileMode));
2844 canvas->drawOval(bounds , paint);
Cary Clark8032b982017-07-28 11:04:54 -04002845}
2846##
2847
Cary Clark2ade9972017-11-02 17:49:34 -04002848#SeeAlso drawCircle drawPoint drawPath drawRRect drawRoundRect
Cary Clark8032b982017-07-28 11:04:54 -04002849
2850##
2851
2852# ------------------------------------------------------------------------------
2853
2854#Method void drawRRect(const SkRRect& rrect, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002855#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002856#Line # draws Round_Rect using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002857#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002858
2859#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002860void draw(SkCanvas* canvas) {
2861 SkPaint paint;
2862 paint.setAntiAlias(true);
2863 SkRect outer = {30, 40, 210, 220};
2864 SkRect radii = {30, 50, 70, 90 };
2865 SkRRect rRect;
2866 rRect.setNinePatch(outer, radii.fLeft, radii.fTop, radii.fRight, radii.fBottom);
2867 canvas->drawRRect(rRect, paint);
2868 paint.setColor(SK_ColorWHITE);
2869 canvas->drawLine(outer.fLeft + radii.fLeft, outer.fTop,
2870 outer.fLeft + radii.fLeft, outer.fBottom, paint);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002871 canvas->drawLine(outer.fRight - radii.fRight, outer.fTop,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002872 outer.fRight - radii.fRight, outer.fBottom, paint);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002873 canvas->drawLine(outer.fLeft, outer.fTop + radii.fTop,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002874 outer.fRight, outer.fTop + radii.fTop, paint);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002875 canvas->drawLine(outer.fLeft, outer.fBottom - radii.fBottom,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002876 outer.fRight, outer.fBottom - radii.fBottom, paint);
2877}
Cary Clark8032b982017-07-28 11:04:54 -04002878##
2879
Cary Clark2ade9972017-11-02 17:49:34 -04002880#SeeAlso drawRect drawRoundRect drawDRRect drawCircle drawOval drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002881
2882##
2883
2884# ------------------------------------------------------------------------------
2885
2886#Method void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002887#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002888#Line # draws double Round_Rect stroked or filled ##
Cary Clark09d80c02018-10-31 12:14:03 -04002889#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002890
2891#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002892void draw(SkCanvas* canvas) {
2893 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
2894 SkRRect inner = SkRRect::MakeOval({60, 70, 170, 160});
2895 SkPaint paint;
2896 canvas->drawDRRect(outer, inner, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002897}
2898##
2899
2900#Example
2901#Description
2902 Outer Rect has no corner radii, but stroke join is rounded.
2903 Inner Round_Rect has corner radii; outset stroke increases radii of corners.
2904 Stroke join does not affect inner Round_Rect since it has no sharp corners.
2905##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002906void draw(SkCanvas* canvas) {
2907 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
2908 SkRRect inner = SkRRect::MakeRectXY({60, 70, 170, 160}, 10, 10);
2909 SkPaint paint;
2910 paint.setAntiAlias(true);
2911 paint.setStyle(SkPaint::kStroke_Style);
2912 paint.setStrokeWidth(20);
2913 paint.setStrokeJoin(SkPaint::kRound_Join);
2914 canvas->drawDRRect(outer, inner, paint);
2915 paint.setStrokeWidth(1);
2916 paint.setColor(SK_ColorWHITE);
2917 canvas->drawDRRect(outer, inner, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002918}
2919##
2920
Cary Clark2ade9972017-11-02 17:49:34 -04002921#SeeAlso drawRect drawRoundRect drawRRect drawCircle drawOval drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002922
2923##
2924
2925# ------------------------------------------------------------------------------
2926
2927#Method void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002928#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002929#Line # draws Circle using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002930#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002931
2932#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002933 void draw(SkCanvas* canvas) {
2934 SkPaint paint;
2935 paint.setAntiAlias(true);
2936 canvas->drawCircle(128, 128, 90, paint);
2937 paint.setColor(SK_ColorWHITE);
2938 canvas->drawCircle(86, 86, 20, paint);
2939 canvas->drawCircle(160, 76, 20, paint);
2940 canvas->drawCircle(140, 150, 35, paint);
2941 }
2942##
2943
Cary Clark2ade9972017-11-02 17:49:34 -04002944#SeeAlso drawOval drawRRect drawRoundRect drawPath drawArc drawPoint drawLine
Cary Clarkbad5ad72017-08-03 17:14:08 -04002945
2946##
2947
2948#Method void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04002949#Populate
Cary Clarkbad5ad72017-08-03 17:14:08 -04002950
2951#Example
2952 void draw(SkCanvas* canvas) {
2953 SkPaint paint;
2954 paint.setAntiAlias(true);
2955 canvas->drawCircle(128, 128, 90, paint);
2956 paint.setColor(SK_ColorWHITE);
2957 canvas->drawCircle({86, 86}, 20, paint);
2958 canvas->drawCircle({160, 76}, 20, paint);
2959 canvas->drawCircle({140, 150}, 35, paint);
2960 }
Cary Clark8032b982017-07-28 11:04:54 -04002961##
2962
Cary Clark2ade9972017-11-02 17:49:34 -04002963#SeeAlso drawOval drawRRect drawRoundRect drawPath drawArc drawPoint drawLine
Cary Clark8032b982017-07-28 11:04:54 -04002964
2965##
2966
2967# ------------------------------------------------------------------------------
2968
2969#Method void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
2970 bool useCenter, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002971#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002972#Line # draws Arc using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002973#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002974
2975#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002976 void draw(SkCanvas* canvas) {
2977 SkPaint paint;
2978 paint.setAntiAlias(true);
2979 SkRect oval = { 4, 4, 60, 60};
2980 for (auto useCenter : { false, true } ) {
2981 for (auto style : { SkPaint::kFill_Style, SkPaint::kStroke_Style } ) {
2982 paint.setStyle(style);
2983 for (auto degrees : { 45, 90, 180, 360} ) {
2984 canvas->drawArc(oval, 0, degrees , useCenter, paint);
2985 canvas->translate(64, 0);
2986 }
2987 canvas->translate(-256, 64);
2988 }
2989 }
Cary Clark8032b982017-07-28 11:04:54 -04002990 }
2991##
2992
2993#Example
2994#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04002995 void draw(SkCanvas* canvas) {
2996 SkPaint paint;
2997 paint.setAntiAlias(true);
2998 paint.setStyle(SkPaint::kStroke_Style);
2999 paint.setStrokeWidth(4);
3000 SkRect oval = { 4, 4, 60, 60};
3001 float intervals[] = { 5, 5 };
3002 paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
3003 for (auto degrees : { 270, 360, 540, 720 } ) {
3004 canvas->drawArc(oval, 0, degrees, false, paint);
3005 canvas->translate(64, 0);
3006 }
Cary Clark8032b982017-07-28 11:04:54 -04003007 }
3008##
3009
Cary Clark2ade9972017-11-02 17:49:34 -04003010#SeeAlso SkPath::arcTo drawCircle drawOval drawPath
Cary Clark8032b982017-07-28 11:04:54 -04003011
3012##
3013
3014# ------------------------------------------------------------------------------
3015
3016#Method void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05003017#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003018#Line # draws Round_Rect using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04003019#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003020
3021#Example
3022#Description
3023 Top row has a zero radius a generates a rectangle.
3024 Second row radii sum to less than sides.
3025 Third row radii sum equals sides.
3026 Fourth row radii sum exceeds sides; radii are scaled to fit.
3027##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003028 void draw(SkCanvas* canvas) {
3029 SkVector radii[] = { {0, 20}, {10, 10}, {10, 20}, {10, 40} };
3030 SkPaint paint;
3031 paint.setStrokeWidth(15);
3032 paint.setStrokeJoin(SkPaint::kRound_Join);
3033 paint.setAntiAlias(true);
3034 for (auto style : { SkPaint::kStroke_Style, SkPaint::kFill_Style } ) {
3035 paint.setStyle(style );
3036 for (size_t i = 0; i < SK_ARRAY_COUNT(radii); ++i) {
3037 canvas->drawRoundRect({10, 10, 60, 40}, radii[i].fX, radii[i].fY, paint);
3038 canvas->translate(0, 60);
3039 }
3040 canvas->translate(80, -240);
3041 }
Cary Clark8032b982017-07-28 11:04:54 -04003042 }
3043##
3044
Cary Clark77b3f3a2018-11-07 14:59:03 -05003045#SeeAlso drawRRect drawRect drawDRRect drawPath drawCircle drawOval drawPoint
Cary Clark8032b982017-07-28 11:04:54 -04003046
3047##
3048
3049# ------------------------------------------------------------------------------
3050
3051#Method void drawPath(const SkPath& path, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05003052#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003053#Line # draws Path using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04003054#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003055
3056#Example
3057#Description
3058 Top rows draw stroked path with combinations of joins and caps. The open contour
3059 is affected by caps; the closed contour is affected by joins.
Herb Derbyefe39bc2018-05-01 17:06:20 -04003060 Bottom row draws fill the same for open and closed contour.
Cary Clark8032b982017-07-28 11:04:54 -04003061 First bottom column shows winding fills overlap.
3062 Second bottom column shows even odd fills exclude overlap.
3063 Third bottom column shows inverse winding fills area outside both contours.
3064##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003065void draw(SkCanvas* canvas) {
3066 SkPath path;
3067 path.moveTo(20, 20);
3068 path.quadTo(60, 20, 60, 60);
3069 path.close();
3070 path.moveTo(60, 20);
3071 path.quadTo(60, 60, 20, 60);
3072 SkPaint paint;
3073 paint.setStrokeWidth(10);
3074 paint.setAntiAlias(true);
3075 paint.setStyle(SkPaint::kStroke_Style);
3076 for (auto join: { SkPaint::kBevel_Join, SkPaint::kRound_Join, SkPaint::kMiter_Join } ) {
3077 paint.setStrokeJoin(join);
3078 for (auto cap: { SkPaint::kButt_Cap, SkPaint::kSquare_Cap, SkPaint::kRound_Cap } ) {
3079 paint.setStrokeCap(cap);
3080 canvas->drawPath(path, paint);
3081 canvas->translate(80, 0);
3082 }
3083 canvas->translate(-240, 60);
3084 }
3085 paint.setStyle(SkPaint::kFill_Style);
Herb Derbyefe39bc2018-05-01 17:06:20 -04003086 for (auto fill : { SkPath::kWinding_FillType,
3087 SkPath::kEvenOdd_FillType,
Cary Clarkbad5ad72017-08-03 17:14:08 -04003088 SkPath::kInverseWinding_FillType } ) {
3089 path.setFillType(fill);
3090 canvas->save();
3091 canvas->clipRect({0, 10, 80, 70});
3092 canvas->drawPath(path, paint);
3093 canvas->restore();
3094 canvas->translate(80, 0);
3095 }
Cary Clark8032b982017-07-28 11:04:54 -04003096}
3097##
3098
Cary Clark2ade9972017-11-02 17:49:34 -04003099#SeeAlso SkPath drawLine drawArc drawRect drawPoints
Cary Clark8032b982017-07-28 11:04:54 -04003100
3101##
3102
3103# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003104#Subtopic Draw_Image
3105#Line # draws Image to Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -04003106
Cary Clarkbad5ad72017-08-03 17:14:08 -04003107drawImage, drawImageRect, and drawImageNine can be called with a bare pointer or
3108a smart pointer as a convenience. The pairs of calls are otherwise identical.
Cary Clark8032b982017-07-28 11:04:54 -04003109
Cary Clark73fa9722017-08-29 17:36:51 -04003110#Method void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003111#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003112#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003113#Line # draws Image at (x, y) position ##
Cary Clark09d80c02018-10-31 12:14:03 -04003114#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003115
3116#Example
3117#Height 64
3118#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003119void draw(SkCanvas* canvas) {
3120 // sk_sp<SkImage> image;
3121 SkImage* imagePtr = image.get();
3122 canvas->drawImage(imagePtr, 0, 0);
3123 SkPaint paint;
3124 canvas->drawImage(imagePtr, 80, 0, &paint);
3125 paint.setAlpha(0x80);
3126 canvas->drawImage(imagePtr, 160, 0, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04003127}
3128##
3129
Cary Clark2ade9972017-11-02 17:49:34 -04003130#SeeAlso drawBitmap drawImageLattice drawImageNine drawImageRect SkPaint::setImageFilter
Cary Clark8032b982017-07-28 11:04:54 -04003131
3132##
3133
3134# ------------------------------------------------------------------------------
3135
3136#Method void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
Herb Derbyefe39bc2018-05-01 17:06:20 -04003137 const SkPaint* paint = nullptr)
Cary Clark09d80c02018-10-31 12:14:03 -04003138#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003139
3140#Example
3141#Height 64
3142#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003143void draw(SkCanvas* canvas) {
3144 // sk_sp<SkImage> image;
3145 canvas->drawImage(image, 0, 0);
3146 SkPaint paint;
3147 canvas->drawImage(image, 80, 0, &paint);
3148 paint.setAlpha(0x80);
3149 canvas->drawImage(image, 160, 0, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04003150}
3151##
3152
Cary Clark2ade9972017-11-02 17:49:34 -04003153#SeeAlso drawBitmap drawImageLattice drawImageNine drawImageRect SkPaint::setImageFilter
Cary Clark8032b982017-07-28 11:04:54 -04003154
3155##
3156
3157# ------------------------------------------------------------------------------
3158
3159#Enum SrcRectConstraint
Cary Clark08895c42018-02-01 09:37:32 -05003160#Line # sets drawImageRect options ##
Cary Clark8032b982017-07-28 11:04:54 -04003161
3162#Code
Cary Clark61313f32018-10-08 14:57:48 -04003163#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003164##
3165
Cary Clarkce101242017-09-01 15:51:02 -04003166SrcRectConstraint controls the behavior at the edge of source Rect,
3167provided to drawImageRect, trading off speed for precision.
Cary Clark8032b982017-07-28 11:04:54 -04003168
Cary Clarkce101242017-09-01 15:51:02 -04003169Image_Filter in Paint may sample multiple pixels in the image. Source Rect
Cary Clarkbad5ad72017-08-03 17:14:08 -04003170restricts the bounds of pixels that may be read. Image_Filter may slow down if
Herb Derbyefe39bc2018-05-01 17:06:20 -04003171it cannot read outside the bounds, when sampling near the edge of source Rect.
Cary Clark8032b982017-07-28 11:04:54 -04003172SrcRectConstraint specifies whether an Image_Filter is allowed to read pixels
Cary Clarkce101242017-09-01 15:51:02 -04003173outside source Rect.
Cary Clark8032b982017-07-28 11:04:54 -04003174
Cary Clark682c58d2018-05-16 07:07:07 -04003175#Const kStrict_SrcRectConstraint 0
3176#Line # sample only inside bounds; slower ##
Cary Clarkce101242017-09-01 15:51:02 -04003177 Requires Image_Filter to respect source Rect,
Cary Clark8032b982017-07-28 11:04:54 -04003178 sampling only inside of its bounds, possibly with a performance penalty.
3179##
3180
Cary Clark682c58d2018-05-16 07:07:07 -04003181#Const kFast_SrcRectConstraint 1
3182#Line # sample outside bounds; faster ##
Cary Clarkce101242017-09-01 15:51:02 -04003183 Permits Image_Filter to sample outside of source Rect
Cary Clark8032b982017-07-28 11:04:54 -04003184 by half the width of Image_Filter, permitting it to run faster but with
3185 error at the image edges.
3186##
3187
3188#Example
3189#Height 64
3190#Description
3191 redBorder contains a black and white checkerboard bordered by red.
3192 redBorder is drawn scaled by 16 on the left.
Cary Clarkce101242017-09-01 15:51:02 -04003193 The middle and right bitmaps are filtered checkerboards.
Cary Clark8032b982017-07-28 11:04:54 -04003194 Drawing the checkerboard with kStrict_SrcRectConstraint shows only a blur of black and white.
3195 Drawing the checkerboard with kFast_SrcRectConstraint allows red to bleed in the corners.
3196##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003197void draw(SkCanvas* canvas) {
3198 SkBitmap redBorder;
3199 redBorder.allocPixels(SkImageInfo::MakeN32Premul(4, 4));
3200 SkCanvas checkRed(redBorder);
3201 checkRed.clear(SK_ColorRED);
3202 uint32_t checkers[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
3203 { SK_ColorWHITE, SK_ColorBLACK } };
3204 checkRed.writePixels(
3205 SkImageInfo::MakeN32Premul(2, 2), (void*) checkers, sizeof(checkers[0]), 1, 1);
3206 canvas->scale(16, 16);
3207 canvas->drawBitmap(redBorder, 0, 0, nullptr);
3208 canvas->resetMatrix();
3209 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
3210 SkPaint lowPaint;
3211 lowPaint.setFilterQuality(kLow_SkFilterQuality);
3212 for (auto constraint : { SkCanvas::kStrict_SrcRectConstraint,
3213 SkCanvas::kFast_SrcRectConstraint } ) {
3214 canvas->translate(80, 0);
3215 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
3216 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
3217 }
Cary Clark8032b982017-07-28 11:04:54 -04003218}
3219##
3220
Cary Clark2ade9972017-11-02 17:49:34 -04003221#SeeAlso drawImageRect drawImage SkPaint::setImageFilter
Cary Clark8032b982017-07-28 11:04:54 -04003222
3223##
3224
3225# ------------------------------------------------------------------------------
3226
3227#Method void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
3228 const SkPaint* paint,
3229 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003230#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003231#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003232#Line # draws Image, source Rect to destination Rect ##
Cary Clark09d80c02018-10-31 12:14:03 -04003233#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003234
3235#Example
3236#Height 64
3237#Description
3238 The left bitmap draws with Paint default kNone_SkFilterQuality, and stays within
Cary Clarkbc5697d2017-10-04 14:31:33 -04003239 its bounds; there is no bleeding with kFast_SrcRectConstraint.
Cary Clark8032b982017-07-28 11:04:54 -04003240 the middle and right bitmaps draw with kLow_SkFilterQuality; with
3241 kStrict_SrcRectConstraint, the filter remains within the checkerboard, and
3242 with kFast_SrcRectConstraint red bleeds on the edges.
3243##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003244void draw(SkCanvas* canvas) {
Herb Derbyefe39bc2018-05-01 17:06:20 -04003245 uint32_t pixels[][4] = {
Cary Clarkbad5ad72017-08-03 17:14:08 -04003246 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 },
3247 { 0xFFFF0000, 0xFF000000, 0xFFFFFFFF, 0xFFFF0000 },
3248 { 0xFFFF0000, 0xFFFFFFFF, 0xFF000000, 0xFFFF0000 },
3249 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 } };
3250 SkBitmap redBorder;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003251 redBorder.installPixels(SkImageInfo::MakeN32Premul(4, 4),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003252 (void*) pixels, sizeof(pixels[0]));
3253 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
3254 SkPaint lowPaint;
3255 for (auto constraint : {
3256 SkCanvas::kFast_SrcRectConstraint,
3257 SkCanvas::kStrict_SrcRectConstraint,
3258 SkCanvas::kFast_SrcRectConstraint } ) {
3259 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
3260 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
3261 lowPaint.setFilterQuality(kLow_SkFilterQuality);
3262 canvas->translate(80, 0);
3263 }
3264}
Cary Clark8032b982017-07-28 11:04:54 -04003265##
3266
Cary Clark2ade9972017-11-02 17:49:34 -04003267#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003268
3269##
3270
3271# ------------------------------------------------------------------------------
3272
3273#Method void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
3274 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003275#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003276#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003277#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003278
3279#Example
3280#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003281void draw(SkCanvas* canvas) {
3282 // sk_sp<SkImage> image;
3283 for (auto i : { 1, 2, 4, 8 } ) {
Herb Derbyefe39bc2018-05-01 17:06:20 -04003284 canvas->drawImageRect(image.get(), SkIRect::MakeLTRB(0, 0, 100, 100),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003285 SkRect::MakeXYWH(i * 20, i * 20, i * 20, i * 20), nullptr);
3286 }
Cary Clark8032b982017-07-28 11:04:54 -04003287}
3288##
3289
Cary Clark2ade9972017-11-02 17:49:34 -04003290#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003291
3292##
3293
3294# ------------------------------------------------------------------------------
3295
Cary Clark0ac0edd2018-10-29 11:28:43 -04003296#Method void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003297#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003298#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003299#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003300
3301#Example
3302#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003303void draw(SkCanvas* canvas) {
3304 // sk_sp<SkImage> image;
3305 for (auto i : { 20, 40, 80, 160 } ) {
3306 canvas->drawImageRect(image.get(), SkRect::MakeXYWH(i, i, i, i), nullptr);
3307 }
Cary Clark8032b982017-07-28 11:04:54 -04003308}
3309##
3310
Cary Clark2ade9972017-11-02 17:49:34 -04003311#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003312
3313##
3314
3315# ------------------------------------------------------------------------------
3316
3317#Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
3318 const SkPaint* paint,
Herb Derbyefe39bc2018-05-01 17:06:20 -04003319 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003320#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003321#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003322#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003323
3324#Example
3325#Height 64
3326#Description
3327 Canvas scales and translates; transformation from src to dst also scales.
3328 The two matrices are concatenated to create the final transformation.
3329##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003330void draw(SkCanvas* canvas) {
3331 uint32_t pixels[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
3332 { SK_ColorWHITE, SK_ColorBLACK } };
3333 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003334 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003335 (void*) pixels, sizeof(pixels[0]));
3336 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3337 SkPaint paint;
3338 canvas->scale(4, 4);
3339 for (auto alpha : { 50, 100, 150, 255 } ) {
3340 paint.setAlpha(alpha);
3341 canvas->drawImageRect(image, SkRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
3342 canvas->translate(8, 0);
3343 }
3344}
Cary Clark8032b982017-07-28 11:04:54 -04003345##
3346
Cary Clark2ade9972017-11-02 17:49:34 -04003347#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003348
3349##
3350
3351# ------------------------------------------------------------------------------
3352
3353#Method void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst,
Herb Derbyefe39bc2018-05-01 17:06:20 -04003354 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003355#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003356#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003357#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003358
3359#Example
3360#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003361void draw(SkCanvas* canvas) {
3362 uint32_t pixels[][2] = { { 0x00000000, 0x55555555},
3363 { 0xAAAAAAAA, 0xFFFFFFFF} };
3364 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003365 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003366 (void*) pixels, sizeof(pixels[0]));
3367 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3368 SkPaint paint;
3369 canvas->scale(4, 4);
3370 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
3371 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
3372 canvas->drawImageRect(image, SkIRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
3373 canvas->translate(8, 0);
3374 }
Cary Clark8032b982017-07-28 11:04:54 -04003375}
3376##
3377
Cary Clark2ade9972017-11-02 17:49:34 -04003378#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
3379
Cary Clark8032b982017-07-28 11:04:54 -04003380##
3381
3382# ------------------------------------------------------------------------------
3383
Cary Clark0ac0edd2018-10-29 11:28:43 -04003384#Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003385#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003386#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003387#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003388
3389#Example
3390#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003391void draw(SkCanvas* canvas) {
3392 uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
3393 { 0xAAAA0000, 0xFFFF0000} };
3394 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003395 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003396 (void*) pixels, sizeof(pixels[0]));
3397 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3398 SkPaint paint;
3399 canvas->scale(4, 4);
3400 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
3401 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
3402 canvas->drawImageRect(image, SkRect::MakeWH(8, 8), &paint);
3403 canvas->translate(8, 0);
3404 }
Cary Clark8032b982017-07-28 11:04:54 -04003405}
3406##
3407
Cary Clark2ade9972017-11-02 17:49:34 -04003408#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003409
3410##
3411
3412# ------------------------------------------------------------------------------
3413
3414#Method void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
3415 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003416#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003417#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003418#Line # draws Nine_Patch Image ##
Cary Clark8032b982017-07-28 11:04:54 -04003419
Cary Clark80247e52018-07-11 16:18:41 -04003420Draws Image image stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003421IRect center divides the image into nine sections: four sides, four corners, and
Cary Clarkce101242017-09-01 15:51:02 -04003422the center. Corners are unmodified or scaled down proportionately if their sides
Cary Clarkbad5ad72017-08-03 17:14:08 -04003423are larger than dst; center and four sides are scaled to fit remaining space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003424
Cary Clarkbad5ad72017-08-03 17:14:08 -04003425Additionally transform draw using Clip, Matrix, and optional Paint paint.
3426
Cary Clark682c58d2018-05-16 07:07:07 -04003427#paint_as_used_by_draw_lattice_or_draw_nine(image)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003428
3429If generated mask extends beyond image bounds, replicate image edge colors, just
3430as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
Cary Clarkbc5697d2017-10-04 14:31:33 -04003431replicates the image edge color when it samples outside of its bounds.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003432
3433#Param image Image containing pixels, dimensions, and format ##
3434#Param center IRect edge of image corners and sides ##
3435#Param dst destination Rect of image to draw to ##
3436#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3437 and so on; or nullptr
3438##
Cary Clark8032b982017-07-28 11:04:54 -04003439
3440#Example
3441#Height 128
3442#Description
3443 The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
Cary Clarkce101242017-09-01 15:51:02 -04003444 The second image equals the size of center; only corners are drawn without scaling.
3445 The remaining images are larger than center. All corners draw without scaling.
3446 The sides and center are scaled if needed to take up the remaining space.
Cary Clark8032b982017-07-28 11:04:54 -04003447##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003448void draw(SkCanvas* canvas) {
3449 SkIRect center = { 20, 10, 50, 40 };
3450 SkBitmap bitmap;
3451 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3452 SkCanvas bitCanvas(bitmap);
3453 SkPaint paint;
3454 SkColor gray = 0xFF000000;
3455 int left = 0;
3456 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3457 int top = 0;
3458 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3459 paint.setColor(gray);
3460 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3461 gray += 0x001f1f1f;
3462 top = bottom;
3463 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003464 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003465 }
3466 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3467 SkImage* imagePtr = image.get();
3468 for (auto dest: { 20, 30, 40, 60, 90 } ) {
3469 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
3470 canvas->translate(dest + 4, 0);
3471 }
Cary Clark8032b982017-07-28 11:04:54 -04003472}
3473##
3474
Cary Clark2ade9972017-11-02 17:49:34 -04003475#SeeAlso drawImage drawBitmapNine drawImageLattice drawImageRect
Cary Clark8032b982017-07-28 11:04:54 -04003476
3477##
3478
3479# ------------------------------------------------------------------------------
3480
3481#Method void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst,
Herb Derbyefe39bc2018-05-01 17:06:20 -04003482 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003483#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003484#In Draw
Cary Clark80247e52018-07-11 16:18:41 -04003485Draws Image image stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003486IRect center divides the image into nine sections: four sides, four corners, and
Cary Clarkce101242017-09-01 15:51:02 -04003487the center. Corners are not scaled, or scaled down proportionately if their sides
Cary Clarkbad5ad72017-08-03 17:14:08 -04003488are larger than dst; center and four sides are scaled to fit remaining space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003489
Cary Clarkbad5ad72017-08-03 17:14:08 -04003490Additionally transform draw using Clip, Matrix, and optional Paint paint.
3491
Cary Clark137b8742018-05-30 09:21:49 -04003492#paint_as_used_by_draw_lattice_or_draw_nine(image)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003493
3494If generated mask extends beyond image bounds, replicate image edge colors, just
3495as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
Cary Clarkbc5697d2017-10-04 14:31:33 -04003496replicates the image edge color when it samples outside of its bounds.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003497
3498#Param image Image containing pixels, dimensions, and format ##
3499#Param center IRect edge of image corners and sides ##
3500#Param dst destination Rect of image to draw to ##
3501#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3502 and so on; or nullptr
3503##
Cary Clark8032b982017-07-28 11:04:54 -04003504
3505#Example
3506#Height 128
3507#Description
3508 The two leftmost images has four corners and sides to the left and right of center.
3509 The leftmost image scales the width of corners proportionately to fit.
Herb Derbyefe39bc2018-05-01 17:06:20 -04003510 The third and fourth image corners are not scaled; the sides and center are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04003511 fill the remaining space.
3512 The rightmost image has four corners scaled vertically to fit, and uses sides above
3513 and below center to fill the remaining space.
3514##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003515void draw(SkCanvas* canvas) {
3516 SkIRect center = { 20, 10, 50, 40 };
3517 SkBitmap bitmap;
3518 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3519 SkCanvas bitCanvas(bitmap);
3520 SkPaint paint;
3521 SkColor gray = 0xFF000000;
3522 int left = 0;
3523 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3524 int top = 0;
3525 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3526 paint.setColor(gray);
3527 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3528 gray += 0x001f1f1f;
3529 top = bottom;
3530 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003531 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003532 }
3533 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3534 for (auto dest: { 20, 30, 40, 60, 90 } ) {
3535 canvas->drawImageNine(image, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
3536 canvas->translate(dest + 4, 0);
3537 }
Cary Clark8032b982017-07-28 11:04:54 -04003538}
3539##
3540
Cary Clark2ade9972017-11-02 17:49:34 -04003541#SeeAlso drawImage drawBitmapNine drawImageLattice drawImageRect
Cary Clark8032b982017-07-28 11:04:54 -04003542
3543##
3544
3545# ------------------------------------------------------------------------------
3546
3547#Method void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
Cary Clark73fa9722017-08-29 17:36:51 -04003548 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003549#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003550#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003551#Line # draws Bitmap at (x, y) position ##
Cary Clark09d80c02018-10-31 12:14:03 -04003552#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003553
3554#Example
3555#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003556void draw(SkCanvas* canvas) {
3557 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
3558 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
3559 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
3560 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
3561 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
3562 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
3563 { 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00},
3564 { 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF} };
3565 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003566 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003567 (void*) pixels, sizeof(pixels[0]));
3568 SkPaint paint;
3569 canvas->scale(4, 4);
3570 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
3571 paint.setColor(color);
3572 canvas->drawBitmap(bitmap, 0, 0, &paint);
3573 canvas->translate(12, 0);
3574 }
Cary Clark8032b982017-07-28 11:04:54 -04003575}
3576##
3577
Cary Clark2ade9972017-11-02 17:49:34 -04003578#SeeAlso drawImage drawBitmapLattice drawBitmapNine drawBitmapRect SkBitmap::readPixels SkBitmap::writePixels
Cary Clark8032b982017-07-28 11:04:54 -04003579
3580##
3581
3582# ------------------------------------------------------------------------------
3583
3584#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
3585 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003586#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003587#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003588#Line # draws Bitmap, source Rect to destination Rect ##
Cary Clark09d80c02018-10-31 12:14:03 -04003589#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003590
3591#Example
3592#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003593void draw(SkCanvas* canvas) {
3594 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
3595 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
3596 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
3597 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
3598 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
3599 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
3600 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
3601 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00} };
3602 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003603 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003604 (void*) pixels, sizeof(pixels[0]));
3605 SkPaint paint;
Cary Clark681287e2018-03-16 11:34:15 -04003606 paint.setMaskFilter(SkMaskFilter::MakeBlur(kSolid_SkBlurStyle, 6));
Cary Clarkbad5ad72017-08-03 17:14:08 -04003607 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
3608 paint.setColor(color);
3609 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
3610 canvas->translate(48, 0);
3611 }
Cary Clark8032b982017-07-28 11:04:54 -04003612}
3613##
3614
Cary Clark2ade9972017-11-02 17:49:34 -04003615#SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
Cary Clark8032b982017-07-28 11:04:54 -04003616
3617##
3618
3619# ------------------------------------------------------------------------------
3620
3621#Method void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
3622 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003623#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003624#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003625#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003626
3627#Example
3628#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003629void draw(SkCanvas* canvas) {
3630 uint8_t pixels[][8] = { { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
3631 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
3632 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
3633 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
3634 { 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF},
3635 { 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF},
3636 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
3637 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00} };
3638 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003639 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003640 (void*) pixels, sizeof(pixels[0]));
3641 SkPaint paint;
3642 paint.setFilterQuality(kHigh_SkFilterQuality);
3643 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00, 0xFF7f007f} ) {
3644 paint.setColor(color);
3645 canvas->drawBitmapRect(bitmap, SkIRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
3646 canvas->translate(48.25f, 0);
3647 }
Cary Clark8032b982017-07-28 11:04:54 -04003648}
3649##
3650
Cary Clark2ade9972017-11-02 17:49:34 -04003651#SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
Cary Clark8032b982017-07-28 11:04:54 -04003652
3653##
3654
3655# ------------------------------------------------------------------------------
3656
3657#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
3658 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003659#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003660#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003661#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003662
3663#Example
3664#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003665void draw(SkCanvas* canvas) {
3666 uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
3667 { 0xAAAA0000, 0xFFFF0000} };
3668 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003669 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003670 (void*) pixels, sizeof(pixels[0]));
3671 SkPaint paint;
3672 canvas->scale(4, 4);
3673 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
3674 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
3675 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), &paint);
3676 canvas->translate(8, 0);
3677 }
Cary Clark8032b982017-07-28 11:04:54 -04003678}
3679##
3680
Cary Clark2ade9972017-11-02 17:49:34 -04003681#SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
Cary Clark8032b982017-07-28 11:04:54 -04003682
3683##
3684
3685# ------------------------------------------------------------------------------
3686
Cary Clark682c58d2018-05-16 07:07:07 -04003687#PhraseDef paint_as_used_by_draw_lattice_or_draw_nine(bitmap_or_image)
3688If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
3689Blend_Mode, and Draw_Looper. If #bitmap_or_image# is kAlpha_8_SkColorType, apply Shader.
3690If paint contains Mask_Filter, generate mask from #bitmap_or_image# bounds. If paint
3691Filter_Quality set to kNone_SkFilterQuality, disable pixel filtering. For all
3692other values of paint Filter_Quality, use kLow_SkFilterQuality to filter pixels.
Cary Clark137b8742018-05-30 09:21:49 -04003693Any SkMaskFilter on paint is ignored as is paint Anti_Aliasing state.
Cary Clark682c58d2018-05-16 07:07:07 -04003694##
3695
Cary Clark8032b982017-07-28 11:04:54 -04003696#Method void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
Cary Clark73fa9722017-08-29 17:36:51 -04003697 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003698#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003699#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003700#Line # draws Nine_Patch Bitmap ##
Cary Clark8032b982017-07-28 11:04:54 -04003701
Cary Clark80247e52018-07-11 16:18:41 -04003702Draws Bitmap bitmap stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003703IRect center divides the bitmap into nine sections: four sides, four corners,
Cary Clarkce101242017-09-01 15:51:02 -04003704and the center. Corners are not scaled, or scaled down proportionately if their
Cary Clarkbad5ad72017-08-03 17:14:08 -04003705sides are larger than dst; center and four sides are scaled to fit remaining
3706space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003707
Cary Clarkbad5ad72017-08-03 17:14:08 -04003708Additionally transform draw using Clip, Matrix, and optional Paint paint.
3709
Cary Clark682c58d2018-05-16 07:07:07 -04003710#paint_as_used_by_draw_lattice_or_draw_nine(bitmap)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003711
3712If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
3713just as Shader made from SkShader::MakeBitmapShader with
Cary Clarkbc5697d2017-10-04 14:31:33 -04003714SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
Cary Clarkbad5ad72017-08-03 17:14:08 -04003715outside of its bounds.
3716
3717#Param bitmap Bitmap containing pixels, dimensions, and format ##
3718#Param center IRect edge of image corners and sides ##
3719#Param dst destination Rect of image to draw to ##
3720#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3721 and so on; or nullptr
3722##
Cary Clark8032b982017-07-28 11:04:54 -04003723
3724#Example
3725#Height 128
3726#Description
3727 The two leftmost bitmap draws has four corners and sides to the left and right of center.
3728 The leftmost bitmap draw scales the width of corners proportionately to fit.
Herb Derbyefe39bc2018-05-01 17:06:20 -04003729 The third and fourth draw corners are not scaled; the sides and center are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04003730 fill the remaining space.
3731 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
3732 and below center to fill the remaining space.
3733##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003734void draw(SkCanvas* canvas) {
3735 SkIRect center = { 20, 10, 50, 40 };
3736 SkBitmap bitmap;
3737 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3738 SkCanvas bitCanvas(bitmap);
3739 SkPaint paint;
3740 SkColor gray = 0xFF000000;
3741 int left = 0;
3742 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3743 int top = 0;
3744 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3745 paint.setColor(gray);
3746 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3747 gray += 0x001f1f1f;
3748 top = bottom;
3749 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003750 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003751 }
3752 for (auto dest: { 20, 30, 40, 60, 90 } ) {
3753 canvas->drawBitmapNine(bitmap, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
3754 canvas->translate(dest + 4, 0);
3755 }
Cary Clark8032b982017-07-28 11:04:54 -04003756}
3757##
3758
Cary Clark2ade9972017-11-02 17:49:34 -04003759#SeeAlso drawImageNine drawBitmap drawBitmapLattice drawBitmapRect
Cary Clark8032b982017-07-28 11:04:54 -04003760
3761##
3762
3763# ------------------------------------------------------------------------------
Cary Clark682c58d2018-05-16 07:07:07 -04003764#Subtopic Lattice
3765#Line # divides Bitmap or Image into a rectangular grid ##
3766
Cary Clark8032b982017-07-28 11:04:54 -04003767#Struct Lattice
Cary Clark08895c42018-02-01 09:37:32 -05003768#Line # divides Bitmap or Image into a rectangular grid ##
Cary Clark682c58d2018-05-16 07:07:07 -04003769
Cary Clark8032b982017-07-28 11:04:54 -04003770#Code
Cary Clark61313f32018-10-08 14:57:48 -04003771#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003772##
3773
Cary Clark137b8742018-05-30 09:21:49 -04003774Lattice divides Bitmap or Image into a rectangular grid.
3775Grid entries on even columns and even rows are fixed; these entries are
3776always drawn at their original size if the destination is large enough.
3777If the destination side is too small to hold the fixed entries, all fixed
3778entries are proportionately scaled down to fit.
3779The grid entries not on even columns and rows are scaled to fit the
3780remaining space, if any.
3781
Cary Clark2f466242017-12-11 16:03:17 -05003782 #Enum RectType
Cary Clark682c58d2018-05-16 07:07:07 -04003783 #Line # optional setting per rectangular grid entry ##
Cary Clark8032b982017-07-28 11:04:54 -04003784 #Code
Cary Clark61313f32018-10-08 14:57:48 -04003785 #Populate
Cary Clark8032b982017-07-28 11:04:54 -04003786 ##
3787
Cary Clark2f466242017-12-11 16:03:17 -05003788 Optional setting per rectangular grid entry to make it transparent,
3789 or to fill the grid entry with a color.
Cary Clark8032b982017-07-28 11:04:54 -04003790
Cary Clark2f466242017-12-11 16:03:17 -05003791 #Const kDefault 0
Cary Clark682c58d2018-05-16 07:07:07 -04003792 #Line # draws Bitmap into lattice rectangle ##
Cary Clark2f466242017-12-11 16:03:17 -05003793 ##
3794
3795 #Const kTransparent 1
Cary Clark682c58d2018-05-16 07:07:07 -04003796 #Line # skips lattice rectangle by making it transparent ##
Cary Clark2f466242017-12-11 16:03:17 -05003797 ##
3798
3799 #Const kFixedColor 2
Cary Clark682c58d2018-05-16 07:07:07 -04003800 #Line # draws one of fColors into lattice rectangle ##
Cary Clark8032b982017-07-28 11:04:54 -04003801 ##
3802 ##
3803
Cary Clark61313f32018-10-08 14:57:48 -04003804#Subtopic Members
Cary Clark682c58d2018-05-16 07:07:07 -04003805##
3806
Cary Clark8032b982017-07-28 11:04:54 -04003807 #Member const int* fXDivs
Cary Clark5538c132018-06-14 12:28:14 -04003808 #Line # x-axis values dividing bitmap ##
3809 Array of x-axis values that divide the bitmap vertically.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003810 Array entries must be unique, increasing, greater than or equal to
3811 fBounds left edge, and less than fBounds right edge.
3812 Set the first element to fBounds left to collapse the left column of
3813 fixed grid entries.
Cary Clark8032b982017-07-28 11:04:54 -04003814 ##
3815
3816 #Member const int* fYDivs
Cary Clark5538c132018-06-14 12:28:14 -04003817 #Line # y-axis values dividing bitmap ##
3818 Array of y-axis values that divide the bitmap horizontally.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003819 Array entries must be unique, increasing, greater than or equal to
3820 fBounds top edge, and less than fBounds bottom edge.
3821 Set the first element to fBounds top to collapse the top row of fixed
3822 grid entries.
Cary Clark8032b982017-07-28 11:04:54 -04003823 ##
3824
Cary Clark2f466242017-12-11 16:03:17 -05003825 #Member const RectType* fRectTypes
Cary Clark682c58d2018-05-16 07:07:07 -04003826 #Line # array of fill types ##
Cary Clark2f466242017-12-11 16:03:17 -05003827 Optional array of fill types, one per rectangular grid entry:
Cary Clark2be81cf2018-09-13 12:04:30 -04003828 array length must be #Formula # (fXCount + 1) * (fYCount + 1) ##.
Cary Clark6fc50412017-09-21 12:31:06 -04003829
Cary Clark2f466242017-12-11 16:03:17 -05003830 Each RectType is one of: kDefault, kTransparent, kFixedColor.
3831
Cary Clark8032b982017-07-28 11:04:54 -04003832 Array entries correspond to the rectangular grid entries, ascending
3833 left to right and then top to bottom.
3834 ##
3835
3836 #Member int fXCount
Cary Clark682c58d2018-05-16 07:07:07 -04003837 #Line # number of x-coordinates ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003838 Number of entries in fXDivs array; one less than the number of
3839 horizontal divisions.
Cary Clark8032b982017-07-28 11:04:54 -04003840 ##
3841
3842 #Member int fYCount
Cary Clark682c58d2018-05-16 07:07:07 -04003843 #Line # number of y-coordinates ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003844 Number of entries in fYDivs array; one less than the number of vertical
3845 divisions.
Cary Clark8032b982017-07-28 11:04:54 -04003846 ##
3847
3848 #Member const SkIRect* fBounds
Cary Clark682c58d2018-05-16 07:07:07 -04003849 #Line # source bounds to draw from ##
Cary Clark8032b982017-07-28 11:04:54 -04003850 Optional subset IRect source to draw from.
3851 If nullptr, source bounds is dimensions of Bitmap or Image.
3852 ##
3853
Cary Clark2f466242017-12-11 16:03:17 -05003854 #Member const SkColor* fColors
Cary Clark682c58d2018-05-16 07:07:07 -04003855 #Line # array of colors ##
Cary Clark2f466242017-12-11 16:03:17 -05003856 Optional array of colors, one per rectangular grid entry.
Cary Clark2be81cf2018-09-13 12:04:30 -04003857 Array length must be #Formula # (fXCount + 1) * (fYCount + 1) ##.
Cary Clark2f466242017-12-11 16:03:17 -05003858
3859 Array entries correspond to the rectangular grid entries, ascending
3860 left to right, then top to bottom.
3861 ##
3862
Cary Clark8032b982017-07-28 11:04:54 -04003863#Struct Lattice ##
3864
3865#Method void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
3866 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003867#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003868#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003869#Line # draws proportionally stretched Bitmap ##
Cary Clark8032b982017-07-28 11:04:54 -04003870
Cary Clark80247e52018-07-11 16:18:41 -04003871Draws Bitmap bitmap stretched proportionally to fit into Rect dst.
Cary Clark8032b982017-07-28 11:04:54 -04003872
3873Lattice lattice divides bitmap into a rectangular grid.
3874Each intersection of an even-numbered row and column is fixed; like the corners
Cary Clarkbad5ad72017-08-03 17:14:08 -04003875of drawBitmapNine, fixed lattice elements never scale larger than their initial
Cary Clarkbc5697d2017-10-04 14:31:33 -04003876size and shrink proportionately when all fixed elements exceed the bitmap
Cary Clarkbad5ad72017-08-03 17:14:08 -04003877dimension. All other grid elements scale to fill the available space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003878
3879Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04003880
Cary Clark682c58d2018-05-16 07:07:07 -04003881#paint_as_used_by_draw_lattice_or_draw_nine(bitmap)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003882
3883If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
3884just as Shader made from SkShader::MakeBitmapShader with
Cary Clarkbc5697d2017-10-04 14:31:33 -04003885SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
Cary Clarkbad5ad72017-08-03 17:14:08 -04003886outside of its bounds.
3887
3888#Param bitmap Bitmap containing pixels, dimensions, and format ##
3889#Param lattice division of bitmap into fixed and variable rectangles ##
3890#Param dst destination Rect of image to draw to ##
3891#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3892 and so on; or nullptr
3893##
Cary Clark8032b982017-07-28 11:04:54 -04003894
3895#Example
3896#Height 128
3897#Description
3898 The two leftmost bitmap draws has four corners and sides to the left and right of center.
3899 The leftmost bitmap draw scales the width of corners proportionately to fit.
Herb Derbyefe39bc2018-05-01 17:06:20 -04003900 The third and fourth draw corners are not scaled; the sides are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04003901 fill the remaining space; the center is transparent.
3902 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
3903 and below center to fill the remaining space.
3904##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003905void draw(SkCanvas* canvas) {
3906 SkIRect center = { 20, 10, 50, 40 };
3907 SkBitmap bitmap;
3908 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3909 SkCanvas bitCanvas(bitmap);
3910 SkPaint paint;
3911 SkColor gray = 0xFF000000;
3912 int left = 0;
3913 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3914 int top = 0;
3915 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3916 paint.setColor(gray);
3917 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3918 gray += 0x001f1f1f;
3919 top = bottom;
3920 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003921 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003922 }
3923 const int xDivs[] = { center.fLeft, center.fRight };
3924 const int yDivs[] = { center.fTop, center.fBottom };
Cary Clarkca3ebcd2017-12-12 11:22:38 -05003925 SkCanvas::Lattice::RectType fillTypes[3][3];
3926 memset(fillTypes, 0, sizeof(fillTypes));
3927 fillTypes[1][1] = SkCanvas::Lattice::kTransparent;
3928 SkColor dummy[9]; // temporary pending bug fix
3929 SkCanvas::Lattice lattice = { xDivs, yDivs, fillTypes[0], SK_ARRAY_COUNT(xDivs),
3930 SK_ARRAY_COUNT(yDivs), nullptr, dummy };
Cary Clarkbad5ad72017-08-03 17:14:08 -04003931 for (auto dest: { 20, 30, 40, 60, 90 } ) {
Cary Clarkca3ebcd2017-12-12 11:22:38 -05003932 canvas->drawBitmapLattice(bitmap, lattice, SkRect::MakeWH(dest, 110 - dest), nullptr);
Cary Clarkbad5ad72017-08-03 17:14:08 -04003933 canvas->translate(dest + 4, 0);
3934 }
Cary Clark8032b982017-07-28 11:04:54 -04003935}
3936##
3937
Cary Clark2ade9972017-11-02 17:49:34 -04003938#SeeAlso drawImageLattice drawBitmap drawBitmapNine Lattice
Cary Clark8032b982017-07-28 11:04:54 -04003939
3940##
3941
3942# ------------------------------------------------------------------------------
3943
3944#Method void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
3945 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003946#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003947#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003948#Line # draws proportionally stretched Image ##
Cary Clark8032b982017-07-28 11:04:54 -04003949
Cary Clark80247e52018-07-11 16:18:41 -04003950Draws Image image stretched proportionally to fit into Rect dst.
Cary Clark8032b982017-07-28 11:04:54 -04003951
3952Lattice lattice divides image into a rectangular grid.
3953Each intersection of an even-numbered row and column is fixed; like the corners
Cary Clarkbad5ad72017-08-03 17:14:08 -04003954of drawBitmapNine, fixed lattice elements never scale larger than their initial
Cary Clarkbc5697d2017-10-04 14:31:33 -04003955size and shrink proportionately when all fixed elements exceed the bitmap
Cary Clarkbad5ad72017-08-03 17:14:08 -04003956dimension. All other grid elements scale to fill the available space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003957
3958Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04003959
Cary Clark682c58d2018-05-16 07:07:07 -04003960#paint_as_used_by_draw_lattice_or_draw_nine(image)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003961
3962If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
3963just as Shader made from SkShader::MakeBitmapShader with
Cary Clarkbc5697d2017-10-04 14:31:33 -04003964SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
Cary Clarkbad5ad72017-08-03 17:14:08 -04003965outside of its bounds.
3966
3967#Param image Image containing pixels, dimensions, and format ##
3968#Param lattice division of bitmap into fixed and variable rectangles ##
3969#Param dst destination Rect of image to draw to ##
3970#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3971 and so on; or nullptr
3972##
Cary Clark8032b982017-07-28 11:04:54 -04003973
3974#Example
3975#Height 128
3976#Description
3977 The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
Cary Clarkce101242017-09-01 15:51:02 -04003978 The second image equals the size of center; only corners are drawn without scaling.
3979 The remaining images are larger than center. All corners draw without scaling. The sides
Cary Clark8032b982017-07-28 11:04:54 -04003980 are scaled if needed to take up the remaining space; the center is transparent.
3981##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003982void draw(SkCanvas* canvas) {
3983 SkIRect center = { 20, 10, 50, 40 };
3984 SkBitmap bitmap;
3985 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3986 SkCanvas bitCanvas(bitmap);
3987 SkPaint paint;
3988 SkColor gray = 0xFF000000;
3989 int left = 0;
3990 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3991 int top = 0;
3992 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3993 paint.setColor(gray);
3994 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3995 gray += 0x001f1f1f;
3996 top = bottom;
3997 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003998 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003999 }
Cary Clarkbad5ad72017-08-03 17:14:08 -04004000 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
4001 SkImage* imagePtr = image.get();
4002 for (auto dest: { 20, 30, 40, 60, 90 } ) {
4003 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
4004 canvas->translate(dest + 4, 0);
4005 }
Cary Clark8032b982017-07-28 11:04:54 -04004006}
4007##
4008
Cary Clark2ade9972017-11-02 17:49:34 -04004009#SeeAlso drawBitmapLattice drawImage drawImageNine Lattice
Cary Clark8032b982017-07-28 11:04:54 -04004010
4011##
4012
Cary Clark682c58d2018-05-16 07:07:07 -04004013#Subtopic Lattice ##
4014
Brian Salomond7065e72018-10-12 11:42:02 -04004015# ------------------------------------------------------------------------------
4016
4017#Enum QuadAAFlags
Cary Clark77b3f3a2018-11-07 14:59:03 -05004018#Line # do not use this ##
Brian Salomon5d878922018-10-12 16:33:11 -04004019#Code
4020#Populate
4021##
4022
Brian Salomond7065e72018-10-12 11:42:02 -04004023#Private
Cary Clarkb0ba2ac2018-10-15 11:38:31 -04004024Do not use.
Brian Salomond7065e72018-10-12 11:42:02 -04004025##
Brian Salomon5d878922018-10-12 16:33:11 -04004026
4027#Const kLeft_QuadAAFlag 1
4028#Line # antialias the left edge ##
4029##
4030
4031#Const kTop_QuadAAFlag 2
4032#Line # antialias the top edge ##
4033##
4034
4035#Const kRight_QuadAAFlag 4
4036#Line # antialias the right edge ##
4037##
4038
4039#Const kBottom_QuadAAFlag 8
4040#Line # antialias the bottom edge ##
4041##
4042
4043#Const kNone_QuadAAFlags 0
4044#Line # antialias none of the edges ##
4045##
4046
4047#Const kAll_QuadAAFlags 15
4048#Line # antialias all of the edges ##
4049##
4050
Brian Salomond7065e72018-10-12 11:42:02 -04004051#NoExample
4052##
4053##
4054
4055# ------------------------------------------------------------------------------
4056
4057#Struct ImageSetEntry
Cary Clark77b3f3a2018-11-07 14:59:03 -05004058#Line # do not use this ##
Cary Clarkb0ba2ac2018-10-15 11:38:31 -04004059
4060#Code
4061#Populate
4062##
4063
Brian Salomond7065e72018-10-12 11:42:02 -04004064#Private
Cary Clarkb0ba2ac2018-10-15 11:38:31 -04004065Do not use.
Brian Salomond7065e72018-10-12 11:42:02 -04004066##
4067
4068#Member SkImage* fImage
4069#Line # image to draw ##
4070##
4071
4072#Member SkRect fSrcRect
4073#Line # image src rectangle ##
4074##
4075
4076#Member SkRect fDstRect
4077#Line # local space rectangle ##
4078##
4079
4080#Member unsigned fAAFlags
4081#Line # antialiasing flags ##
4082##
4083
4084#NoExample
4085##
4086
4087##
4088
4089# ------------------------------------------------------------------------------
4090
4091#Method void experimental_DrawImageSetV0(const ImageSetEntry imageSet[], int cnt, float alpha,
4092 SkFilterQuality quality, SkBlendMode mode);
4093#Private
Cary Clarkb0ba2ac2018-10-15 11:38:31 -04004094Do not use.
Brian Salomond7065e72018-10-12 11:42:02 -04004095##
4096#In Draw_Image
4097#In Draw
Cary Clark77b3f3a2018-11-07 14:59:03 -05004098#Line # draws a set a of images; do not call this ##
Brian Salomond7065e72018-10-12 11:42:02 -04004099
4100Draws a set of images. Do not use this method.
4101
4102#Param imageSet images ##
4103#Param cnt number of images ##
4104#Param alpha alpha ##
4105#Param quality filter quality ##
4106#Param mode blend mode ##
4107
4108#NoExample
4109##
4110
4111##
4112
Cary Clark08895c42018-02-01 09:37:32 -05004113#Subtopic Draw_Image ##
Cary Clark8032b982017-07-28 11:04:54 -04004114
4115# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -05004116#Subtopic Draw_Text
Cary Clark78de7512018-02-07 07:27:09 -05004117#Line # draws text into Canvas ##
4118##
Cary Clark8032b982017-07-28 11:04:54 -04004119
4120#Method void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
4121 const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05004122#In Draw_Text
4123#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004124#Line # draws text at (x, y), using font advance ##
Cary Clark09d80c02018-10-31 12:14:03 -04004125#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004126
4127#Example
4128#Height 200
4129#Description
4130 The same text is drawn varying Paint_Text_Size and varying
Herb Derbyefe39bc2018-05-01 17:06:20 -04004131 Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04004132##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004133void draw(SkCanvas* canvas) {
4134 SkPaint paint;
4135 paint.setAntiAlias(true);
4136 float textSizes[] = { 12, 18, 24, 36 };
4137 for (auto size: textSizes ) {
4138 paint.setTextSize(size);
4139 canvas->drawText("Aa", 2, 10, 20, paint);
4140 canvas->translate(0, size * 2);
4141 }
4142 paint.reset();
4143 paint.setAntiAlias(true);
4144 float yPos = 20;
4145 for (auto size: textSizes ) {
4146 float scale = size / 12.f;
4147 canvas->resetMatrix();
4148 canvas->translate(100, 0);
4149 canvas->scale(scale, scale);
4150 canvas->drawText("Aa", 2, 10 / scale, yPos / scale, paint);
Herb Derbyefe39bc2018-05-01 17:06:20 -04004151 yPos += size * 2;
Cary Clarkbad5ad72017-08-03 17:14:08 -04004152 }
4153}
Cary Clark8032b982017-07-28 11:04:54 -04004154##
4155
Cary Clark153e76d2018-08-28 11:48:28 -04004156#SeeAlso drawString drawPosText drawPosTextH drawTextBlob drawTextRSXform
Cary Clark8032b982017-07-28 11:04:54 -04004157
4158##
4159
4160#Method void drawString(const char* string, SkScalar x, SkScalar y, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05004161#In Draw_Text
4162#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004163#Line # draws null terminated string at (x, y) using font advance ##
Cary Clark09d80c02018-10-31 12:14:03 -04004164#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004165
4166#Example
Cary Clarkffb3d682018-05-17 12:17:28 -04004167#Height 48
Cary Clark8032b982017-07-28 11:04:54 -04004168 SkPaint paint;
4169 canvas->drawString("a small hello", 20, 20, paint);
4170##
4171
Cary Clark153e76d2018-08-28 11:48:28 -04004172#SeeAlso drawText drawPosText drawPosTextH drawTextBlob drawTextRSXform
Cary Clark8032b982017-07-28 11:04:54 -04004173
4174##
4175
4176#Method void drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004177#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004178
4179#Example
4180 SkPaint paint;
4181 SkString string("a small hello");
4182 canvas->drawString(string, 20, 20, paint);
4183##
4184
Cary Clark153e76d2018-08-28 11:48:28 -04004185#SeeAlso drawText drawPosText drawPosTextH drawTextBlob drawTextRSXform
Cary Clark8032b982017-07-28 11:04:54 -04004186
4187##
4188
4189# ------------------------------------------------------------------------------
4190
4191#Method void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
4192 const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05004193#In Draw_Text
4194#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004195#Line # draws text at array of (x, y) positions ##
Cary Clark09d80c02018-10-31 12:14:03 -04004196#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004197
4198#Example
4199#Height 120
Cary Clarkbad5ad72017-08-03 17:14:08 -04004200void draw(SkCanvas* canvas) {
4201 const char hello[] = "HeLLo!";
4202 const SkPoint pos[] = { {40, 100}, {82, 95}, {115, 110}, {130, 95}, {145, 85},
4203 {172, 100} };
4204 SkPaint paint;
4205 paint.setTextSize(60);
4206 canvas->drawPosText(hello, strlen(hello), pos, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004207}
4208##
4209
Cary Clark153e76d2018-08-28 11:48:28 -04004210#SeeAlso drawText drawPosTextH drawTextBlob drawTextRSXform
Cary Clark8032b982017-07-28 11:04:54 -04004211
4212##
4213
4214# ------------------------------------------------------------------------------
4215
4216#Method void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
4217 const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05004218#In Draw_Text
4219#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004220#Line # draws text at x positions with common baseline ##
Cary Clark09d80c02018-10-31 12:14:03 -04004221#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004222
4223#Example
4224#Height 40
Cary Clarkbad5ad72017-08-03 17:14:08 -04004225 void draw(SkCanvas* canvas) {
4226 SkScalar xpos[] = { 20, 40, 80, 160 };
4227 SkPaint paint;
4228 canvas->drawPosTextH("XXXX", 4, xpos, 20, paint);
4229 }
Cary Clark8032b982017-07-28 11:04:54 -04004230##
4231
Cary Clark153e76d2018-08-28 11:48:28 -04004232#SeeAlso drawText drawPosText drawTextBlob drawTextRSXform
Cary Clark8032b982017-07-28 11:04:54 -04004233
4234##
4235
4236# ------------------------------------------------------------------------------
4237
Cary Clark8032b982017-07-28 11:04:54 -04004238#Method void drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
4239 const SkRect* cullRect, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05004240#In Draw_Text
4241#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004242#Line # draws text with array of RSXform ##
Cary Clark09d80c02018-10-31 12:14:03 -04004243#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004244
4245#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04004246void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04004247 const int iterations = 26;
4248 SkRSXform transforms[iterations];
4249 char alphabet[iterations];
4250 SkScalar angle = 0;
4251 SkScalar scale = 1;
4252 for (size_t i = 0; i < SK_ARRAY_COUNT(transforms); ++i) {
4253 const SkScalar s = SkScalarSin(angle) * scale;
4254 const SkScalar c = SkScalarCos(angle) * scale;
4255 transforms[i] = SkRSXform::Make(-c, -s, -s * 16, c * 16);
4256 angle += .45;
4257 scale += .2;
4258 alphabet[i] = 'A' + i;
4259 }
4260 SkPaint paint;
Cary Clarkbad5ad72017-08-03 17:14:08 -04004261 canvas->translate(110, 138);
4262 canvas->drawTextRSXform(alphabet, sizeof(alphabet), transforms, nullptr, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004263}
4264##
4265
Cary Clark153e76d2018-08-28 11:48:28 -04004266#SeeAlso drawText drawPosText drawTextBlob
Cary Clark8032b982017-07-28 11:04:54 -04004267
4268##
4269
4270# ------------------------------------------------------------------------------
4271
4272#Method void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05004273#In Draw_Text
4274#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004275#Line # draws text with arrays of positions and Paint ##
Cary Clark80247e52018-07-11 16:18:41 -04004276Draws Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004277
Cary Clarkce101242017-09-01 15:51:02 -04004278blob contains Glyphs, their positions, and paint attributes specific to text:
Cary Clarkd2ca79c2018-08-10 13:09:13 -04004279#paint_font_metrics#.
Cary Clark8032b982017-07-28 11:04:54 -04004280
Cary Clark3cd22cc2017-12-01 11:49:58 -05004281Paint_Text_Encoding must be set to SkPaint::kGlyphID_TextEncoding.
4282
Cary Clarkd2ca79c2018-08-10 13:09:13 -04004283Elements of paint: Anti_Alias, Blend_Mode, Color including Color_Alpha,
4284Color_Filter, Paint_Dither, Draw_Looper, Mask_Filter, Path_Effect, Shader, and
Cary Clark61313f32018-10-08 14:57:48 -04004285Paint_Style; apply to blob. If Paint contains SkPaint::kStroke_Style:
Cary Clarkd2ca79c2018-08-10 13:09:13 -04004286Paint_Miter_Limit, Paint_Stroke_Cap, Paint_Stroke_Join, and Paint_Stroke_Width;
4287apply to Path created from blob.
Cary Clark8032b982017-07-28 11:04:54 -04004288
Cary Clarkce101242017-09-01 15:51:02 -04004289#Param blob Glyphs, positions, and their paints' text size, typeface, and so on ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004290#Param x horizontal offset applied to blob ##
4291#Param y vertical offset applied to blob ##
4292#Param paint blend, color, stroking, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04004293
4294#Example
4295#Height 120
Cary Clarke80cd442018-07-17 13:19:56 -04004296void draw(SkCanvas* canvas) {
4297 SkTextBlobBuilder textBlobBuilder;
4298 const char bunny[] = "/(^x^)\\";
4299 const int len = sizeof(bunny) - 1;
4300 uint16_t glyphs[len];
4301 SkPaint paint;
4302 paint.textToGlyphs(bunny, len, glyphs);
4303 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
4304 int runs[] = { 3, 1, 3 };
4305 SkPoint textPos = { 20, 100 };
4306 int glyphIndex = 0;
4307 for (auto runLen : runs) {
4308 paint.setTextSize(1 == runLen ? 20 : 50);
4309 const SkTextBlobBuilder::RunBuffer& run =
4310 textBlobBuilder.allocRun(paint, runLen, textPos.fX, textPos.fY);
4311 memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen);
4312 textPos.fX += paint.measureText(&glyphs[glyphIndex], sizeof(glyphs[0]) * runLen, nullptr);
4313 glyphIndex += runLen;
Cary Clark8032b982017-07-28 11:04:54 -04004314 }
Cary Clarke80cd442018-07-17 13:19:56 -04004315 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
4316 paint.reset();
4317 canvas->drawTextBlob(blob.get(), 0, 0, paint);
4318}
Cary Clark8032b982017-07-28 11:04:54 -04004319##
4320
Cary Clark2ade9972017-11-02 17:49:34 -04004321#SeeAlso drawText drawPosText drawPosTextH
Cary Clark8032b982017-07-28 11:04:54 -04004322
4323##
4324
4325# ------------------------------------------------------------------------------
4326
Herb Derbyefe39bc2018-05-01 17:06:20 -04004327#Method void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint)
Cary Clark8032b982017-07-28 11:04:54 -04004328
Cary Clark80247e52018-07-11 16:18:41 -04004329Draws Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004330
Cary Clarkce101242017-09-01 15:51:02 -04004331blob contains Glyphs, their positions, and paint attributes specific to text:
Cary Clarkd2ca79c2018-08-10 13:09:13 -04004332#paint_font_metrics#.
Cary Clark8032b982017-07-28 11:04:54 -04004333
Cary Clark3cd22cc2017-12-01 11:49:58 -05004334Paint_Text_Encoding must be set to SkPaint::kGlyphID_TextEncoding.
4335
Herb Derbyefe39bc2018-05-01 17:06:20 -04004336Elements of paint: Path_Effect, Mask_Filter, Shader, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -04004337Image_Filter, and Draw_Looper; apply to blob.
4338
Cary Clarkce101242017-09-01 15:51:02 -04004339#Param blob Glyphs, positions, and their paints' text size, typeface, and so on ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004340#Param x horizontal offset applied to blob ##
4341#Param y vertical offset applied to blob ##
4342#Param paint blend, color, stroking, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04004343
4344#Example
4345#Height 120
4346#Description
4347Paint attributes unrelated to text, like color, have no effect on paint in allocated Text_Blob.
4348Paint attributes related to text, like text size, have no effect on paint passed to drawTextBlob.
4349##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004350 void draw(SkCanvas* canvas) {
4351 SkTextBlobBuilder textBlobBuilder;
4352 SkPaint paint;
4353 paint.setTextSize(50);
4354 paint.setColor(SK_ColorRED);
Cary Clark2f466242017-12-11 16:03:17 -05004355 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
Herb Derbyefe39bc2018-05-01 17:06:20 -04004356 const SkTextBlobBuilder::RunBuffer& run =
Cary Clarkbad5ad72017-08-03 17:14:08 -04004357 textBlobBuilder.allocRun(paint, 1, 20, 100);
4358 run.glyphs[0] = 20;
4359 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
4360 paint.setTextSize(10);
4361 paint.setColor(SK_ColorBLUE);
4362 canvas->drawTextBlob(blob.get(), 0, 0, paint);
4363 }
Cary Clark8032b982017-07-28 11:04:54 -04004364##
4365
Cary Clark2ade9972017-11-02 17:49:34 -04004366#SeeAlso drawText drawPosText drawPosTextH
Cary Clark8032b982017-07-28 11:04:54 -04004367
4368##
4369
4370# ------------------------------------------------------------------------------
4371
Herb Derbyefe39bc2018-05-01 17:06:20 -04004372#Method void drawPicture(const SkPicture* picture)
Cary Clark78de7512018-02-07 07:27:09 -05004373#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004374#Line # draws Picture using Clip and Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04004375#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004376
4377#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04004378void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04004379 SkPictureRecorder recorder;
4380 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
4381 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
4382 SkPaint paint;
4383 paint.setColor(color);
4384 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
4385 recordingCanvas->translate(10, 10);
4386 recordingCanvas->scale(1.2f, 1.4f);
4387 }
4388 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
Cary Clarkbad5ad72017-08-03 17:14:08 -04004389 canvas->drawPicture(playback);
4390 canvas->scale(2, 2);
4391 canvas->translate(50, 0);
4392 canvas->drawPicture(playback);
Cary Clark8032b982017-07-28 11:04:54 -04004393}
4394##
4395
Cary Clark2ade9972017-11-02 17:49:34 -04004396#SeeAlso drawDrawable SkPicture SkPicture::playback
Cary Clark8032b982017-07-28 11:04:54 -04004397
4398##
4399
4400# ------------------------------------------------------------------------------
4401
Herb Derbyefe39bc2018-05-01 17:06:20 -04004402#Method void drawPicture(const sk_sp<SkPicture>& picture)
Cary Clark09d80c02018-10-31 12:14:03 -04004403#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004404
4405#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04004406void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04004407 SkPictureRecorder recorder;
4408 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
4409 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
4410 SkPaint paint;
4411 paint.setColor(color);
4412 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
4413 recordingCanvas->translate(10, 10);
4414 recordingCanvas->scale(1.2f, 1.4f);
4415 }
4416 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
4417 canvas->drawPicture(playback);
4418 canvas->scale(2, 2);
4419 canvas->translate(50, 0);
4420 canvas->drawPicture(playback);
Cary Clark8032b982017-07-28 11:04:54 -04004421}
4422##
4423
Cary Clark2ade9972017-11-02 17:49:34 -04004424#SeeAlso drawDrawable SkPicture SkPicture::playback
Cary Clark8032b982017-07-28 11:04:54 -04004425
4426##
4427
4428# ------------------------------------------------------------------------------
4429
4430#Method void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004431#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004432
4433#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04004434void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04004435 SkPaint paint;
4436 SkPictureRecorder recorder;
4437 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
4438 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
4439 paint.setColor(color);
4440 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
4441 recordingCanvas->translate(10, 10);
4442 recordingCanvas->scale(1.2f, 1.4f);
4443 }
4444 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
4445 const SkPicture* playbackPtr = playback.get();
4446 SkMatrix matrix;
4447 matrix.reset();
4448 for (auto alpha : { 70, 140, 210 } ) {
4449 paint.setAlpha(alpha);
4450 canvas->drawPicture(playbackPtr, &matrix, &paint);
4451 matrix.preTranslate(70, 70);
4452 }
Cary Clark8032b982017-07-28 11:04:54 -04004453}
4454##
4455
Cary Clark2ade9972017-11-02 17:49:34 -04004456#SeeAlso drawDrawable SkPicture SkPicture::playback
Cary Clark8032b982017-07-28 11:04:54 -04004457
4458##
4459
4460# ------------------------------------------------------------------------------
4461
Herb Derbyefe39bc2018-05-01 17:06:20 -04004462#Method void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004463#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004464
4465#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04004466void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04004467 SkPaint paint;
4468 SkPictureRecorder recorder;
4469 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
4470 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
4471 paint.setColor(color);
4472 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
4473 recordingCanvas->translate(10, 10);
4474 recordingCanvas->scale(1.2f, 1.4f);
4475 }
4476 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
4477 SkMatrix matrix;
4478 matrix.reset();
4479 for (auto alpha : { 70, 140, 210 } ) {
4480 paint.setAlpha(alpha);
4481 canvas->drawPicture(playback, &matrix, &paint);
4482 matrix.preTranslate(70, 70);
4483 }
Cary Clark8032b982017-07-28 11:04:54 -04004484}
4485##
4486
Cary Clark2ade9972017-11-02 17:49:34 -04004487#SeeAlso drawDrawable SkPicture SkPicture::playback
Cary Clark8032b982017-07-28 11:04:54 -04004488
4489##
4490
4491# ------------------------------------------------------------------------------
4492
4493#Method void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05004494#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004495#Line # draws Vertices, a triangle mesh ##
Cary Clark09d80c02018-10-31 12:14:03 -04004496#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004497
4498#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004499void draw(SkCanvas* canvas) {
4500 SkPaint paint;
4501 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
4502 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4503 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
4504 SK_ARRAY_COUNT(points), points, nullptr, colors);
4505 canvas->drawVertices(vertices.get(), SkBlendMode::kSrc, paint);
4506}
Cary Clark8032b982017-07-28 11:04:54 -04004507##
4508
Cary Clark2ade9972017-11-02 17:49:34 -04004509#SeeAlso drawPatch drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004510
4511##
4512
4513# ------------------------------------------------------------------------------
4514
4515#Method void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004516#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004517
4518#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004519void draw(SkCanvas* canvas) {
4520 SkPaint paint;
4521 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
4522 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
4523 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4524 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
4525 SkShader::kClamp_TileMode));
4526 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
4527 SK_ARRAY_COUNT(points), points, texs, colors);
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004528 canvas->drawVertices(vertices, SkBlendMode::kDarken, paint);
4529}
4530##
4531
4532#SeeAlso drawPatch drawPicture
4533
4534##
4535
4536# ------------------------------------------------------------------------------
4537
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004538#Method void drawVertices(const SkVertices* vertices, const SkVertices::Bone bones[],
4539 int boneCount, SkBlendMode mode, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004540#Populate
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004541
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004542#NoExample
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004543void draw(SkCanvas* canvas) {
4544 SkPaint paint;
4545 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
4546 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
4547 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4548 SkVertices::BoneIndices boneIndices[] = { { 0, 0, 0, 0 },
4549 { 1, 0, 0, 0 },
4550 { 2, 0, 0, 0 },
4551 { 3, 0, 0, 0 } };
4552 SkVertices::BoneWeights boneWeights[] = { { 0.0f, 0.0f, 0.0f, 0.0f },
4553 { 1.0f, 0.0f, 0.0f, 0.0f },
4554 { 1.0f, 0.0f, 0.0f, 0.0f },
4555 { 1.0f, 0.0f, 0.0f, 0.0f } };
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004556 SkVertices::Bone bones[] = { {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }},
4557 {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 20.0f }},
4558 {{ 1.0f, 0.0f, 0.0f, 1.0f, 50.0f, 50.0f }},
4559 {{ 1.0f, 0.0f, 0.0f, 1.0f, 20.0f, 0.0f }} };
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004560 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
4561 SkShader::kClamp_TileMode));
4562 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
4563 SK_ARRAY_COUNT(points), points, texs, colors, boneIndices, boneWeights);
4564 canvas->drawVertices(vertices.get(), bones, SK_ARRAY_COUNT(bones), SkBlendMode::kDarken, paint);
4565}
4566##
4567
4568#SeeAlso drawPatch drawPicture
4569
4570##
4571
4572# ------------------------------------------------------------------------------
4573
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004574#Method void drawVertices(const sk_sp<SkVertices>& vertices, const SkVertices::Bone bones[],
4575 int boneCount, SkBlendMode mode, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004576#Populate
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004577
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004578#NoExample
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004579void draw(SkCanvas* canvas) {
4580 SkPaint paint;
4581 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
4582 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
4583 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4584 SkVertices::BoneIndices boneIndices[] = { { 0, 0, 0, 0 },
4585 { 1, 0, 0, 0 },
4586 { 2, 0, 0, 0 },
4587 { 3, 0, 0, 0 } };
4588 SkVertices::BoneWeights boneWeights[] = { { 0.0f, 0.0f, 0.0f, 0.0f },
4589 { 1.0f, 0.0f, 0.0f, 0.0f },
4590 { 1.0f, 0.0f, 0.0f, 0.0f },
4591 { 1.0f, 0.0f, 0.0f, 0.0f } };
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004592 SkVertices::Bone bones[] = { {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }},
4593 {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 20.0f }},
4594 {{ 1.0f, 0.0f, 0.0f, 1.0f, 50.0f, 50.0f }},
4595 {{ 1.0f, 0.0f, 0.0f, 1.0f, 20.0f, 0.0f }} };
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004596 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
4597 SkShader::kClamp_TileMode));
4598 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
4599 SK_ARRAY_COUNT(points), points, texs, colors, boneIndices, boneWeights);
4600 canvas->drawVertices(vertices, bones, SK_ARRAY_COUNT(bones), SkBlendMode::kDarken, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004601}
4602##
4603
Cary Clark2ade9972017-11-02 17:49:34 -04004604#SeeAlso drawPatch drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004605
4606##
4607
4608# ------------------------------------------------------------------------------
4609
4610#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
4611 const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05004612#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004613#Line # draws Coons_Patch ##
Cary Clark09d80c02018-10-31 12:14:03 -04004614#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004615
4616#Example
4617#Image 5
Cary Clarkbad5ad72017-08-03 17:14:08 -04004618void draw(SkCanvas* canvas) {
4619 // SkBitmap source = cmbkygk;
4620 SkPaint paint;
4621 paint.setFilterQuality(kLow_SkFilterQuality);
4622 paint.setAntiAlias(true);
4623 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
4624 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
4625 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
4626 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
4627 SkColor colors[] = { 0xbfff0000, 0xbf0000ff, 0xbfff00ff, 0xbf00ffff };
4628 SkPoint texCoords[] = { { -30, -30 }, { 162, -30}, { 162, 162}, { -30, 162} };
4629 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
4630 SkShader::kClamp_TileMode, nullptr));
4631 canvas->scale(15, 15);
4632 for (auto blend : { SkBlendMode::kSrcOver, SkBlendMode::kModulate, SkBlendMode::kXor } ) {
4633 canvas->drawPatch(cubics, colors, texCoords, blend, paint);
4634 canvas->translate(4, 4);
4635 }
Cary Clark8032b982017-07-28 11:04:54 -04004636}
4637##
4638
Cary Clark2ade9972017-11-02 17:49:34 -04004639#ToDo can patch use image filter? ##
Cary Clark77b3f3a2018-11-07 14:59:03 -05004640#SeeAlso drawVertices drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004641
4642##
4643
4644# ------------------------------------------------------------------------------
4645
4646#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
Herb Derbyefe39bc2018-05-01 17:06:20 -04004647 const SkPoint texCoords[4], const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004648#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004649
4650#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004651void draw(SkCanvas* canvas) {
4652 SkPaint paint;
4653 paint.setAntiAlias(true);
4654 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
4655 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
4656 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
4657 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
4658 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4659 canvas->scale(30, 30);
4660 canvas->drawPatch(cubics, colors, nullptr, paint);
4661 SkPoint text[] = { {3,0.9f}, {4,2.5f}, {5,0.9f}, {7.5f,3.2f}, {5.5f,4.2f},
4662 {7.5f,5.2f}, {5,7.5f}, {4,5.9f}, {3,7.5f}, {0.5f,5.2f}, {2.5f,4.2f},
4663 {0.5f,3.2f} };
4664 paint.setTextSize(18.f / 30);
Cary Clarkbad5ad72017-08-03 17:14:08 -04004665 for (int i = 0; i< 10; ++i) {
4666 char digit = '0' + i;
4667 canvas->drawText(&digit, 1, text[i].fX, text[i].fY, paint);
4668 }
4669 canvas->drawString("10", text[10].fX, text[10].fY, paint);
4670 canvas->drawString("11", text[11].fX, text[11].fY, paint);
4671 paint.setStyle(SkPaint::kStroke_Style);
4672 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 12, cubics, paint);
4673 canvas->drawLine(cubics[11].fX, cubics[11].fY, cubics[0].fX, cubics[0].fY, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004674}
4675##
4676
4677#Example
4678#Image 6
Cary Clarkbad5ad72017-08-03 17:14:08 -04004679void draw(SkCanvas* canvas) {
4680 // SkBitmap source = checkerboard;
4681 SkPaint paint;
4682 paint.setFilterQuality(kLow_SkFilterQuality);
4683 paint.setAntiAlias(true);
4684 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
4685 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
4686 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
4687 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
4688 SkPoint texCoords[] = { { 0, 0 }, { 0, 62}, { 62, 62}, { 62, 0 } };
4689 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
4690 SkShader::kClamp_TileMode, nullptr));
4691 canvas->scale(30, 30);
4692 canvas->drawPatch(cubics, nullptr, texCoords, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004693}
4694##
4695
Cary Clark2ade9972017-11-02 17:49:34 -04004696#ToDo can patch use image filter? ##
Cary Clark77b3f3a2018-11-07 14:59:03 -05004697#SeeAlso drawVertices drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004698
4699##
4700
4701# ------------------------------------------------------------------------------
4702
4703#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
4704 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
4705 const SkPaint* paint)
Cary Clark78de7512018-02-07 07:27:09 -05004706#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004707#Line # draws sprites using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04004708#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004709
4710#Example
4711#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04004712void draw(SkCanvas* canvas) {
4713 // SkBitmap source = mandrill;
4714 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
4715 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
4716 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
4717 const SkImage* imagePtr = image.get();
4718 canvas->drawAtlas(imagePtr, xforms, tex, colors, 2, SkBlendMode::kSrcOver, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04004719}
4720##
4721
Cary Clark2ade9972017-11-02 17:49:34 -04004722#SeeAlso drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04004723
4724##
4725
4726# ------------------------------------------------------------------------------
4727
4728#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
4729 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
Herb Derbyefe39bc2018-05-01 17:06:20 -04004730 const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004731#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004732
4733#Example
4734#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04004735void draw(SkCanvas* canvas) {
4736 // SkBitmap source = mandrill;
4737 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
4738 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
4739 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
4740 SkPaint paint;
4741 paint.setAlpha(127);
4742 canvas->drawAtlas(image, xforms, tex, colors, 2, SkBlendMode::kPlus, nullptr, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04004743}
4744##
4745
4746#ToDo bug in example on cpu side, gpu looks ok ##
4747
Cary Clark2ade9972017-11-02 17:49:34 -04004748#SeeAlso drawBitmap drawImage
4749
Cary Clark8032b982017-07-28 11:04:54 -04004750##
4751
4752# ------------------------------------------------------------------------------
4753
4754#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
Herb Derbyefe39bc2018-05-01 17:06:20 -04004755 const SkRect* cullRect, const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004756#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004757
4758#Example
4759#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04004760void draw(SkCanvas* canvas) {
4761 // sk_sp<SkImage> image = mandrill;
4762 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
4763 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
4764 const SkImage* imagePtr = image.get();
4765 canvas->drawAtlas(imagePtr, xforms, tex, 2, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04004766}
4767##
4768
Cary Clark2ade9972017-11-02 17:49:34 -04004769#SeeAlso drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04004770
4771##
4772
4773# ------------------------------------------------------------------------------
4774
4775#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
Herb Derbyefe39bc2018-05-01 17:06:20 -04004776 int count, const SkRect* cullRect, const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004777#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004778
4779#Example
4780#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04004781void draw(SkCanvas* canvas) {
4782 // sk_sp<SkImage> image = mandrill;
4783 SkRSXform xforms[] = { { 1, 0, 0, 0 }, {0, 1, 300, 100 } };
4784 SkRect tex[] = { { 0, 0, 200, 200 }, { 200, 0, 400, 200 } };
4785 canvas->drawAtlas(image, xforms, tex, 2, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04004786}
4787##
4788
Cary Clark2ade9972017-11-02 17:49:34 -04004789#SeeAlso drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04004790
4791##
4792
4793# ------------------------------------------------------------------------------
4794
Cary Clark73fa9722017-08-29 17:36:51 -04004795#Method void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr)
Cary Clark78de7512018-02-07 07:27:09 -05004796#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004797#Line # draws Drawable, encapsulated drawing commands ##
Cary Clark09d80c02018-10-31 12:14:03 -04004798#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004799
4800#Example
4801#Height 100
4802#Function
Cary Clarkbad5ad72017-08-03 17:14:08 -04004803struct MyDrawable : public SkDrawable {
4804 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
4805
4806 void onDraw(SkCanvas* canvas) override {
4807 SkPath path;
4808 path.conicTo(10, 90, 50, 90, 0.9f);
4809 SkPaint paint;
4810 paint.setColor(SK_ColorBLUE);
4811 canvas->drawRect(path.getBounds(), paint);
4812 paint.setAntiAlias(true);
4813 paint.setColor(SK_ColorWHITE);
4814 canvas->drawPath(path, paint);
4815 }
4816};
4817
4818#Function ##
4819void draw(SkCanvas* canvas) {
4820 sk_sp<SkDrawable> drawable(new MyDrawable);
4821 SkMatrix matrix;
4822 matrix.setTranslate(10, 10);
4823 canvas->drawDrawable(drawable.get(), &matrix);
Cary Clark8032b982017-07-28 11:04:54 -04004824}
4825##
4826
Cary Clark2ade9972017-11-02 17:49:34 -04004827#SeeAlso SkDrawable drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004828
4829##
4830
4831# ------------------------------------------------------------------------------
4832
4833#Method void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y)
Cary Clark09d80c02018-10-31 12:14:03 -04004834#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004835
4836#Example
4837#Height 100
4838#Function
Cary Clarkbad5ad72017-08-03 17:14:08 -04004839struct MyDrawable : public SkDrawable {
4840 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
4841
4842 void onDraw(SkCanvas* canvas) override {
4843 SkPath path;
4844 path.conicTo(10, 90, 50, 90, 0.9f);
4845 SkPaint paint;
4846 paint.setColor(SK_ColorBLUE);
4847 canvas->drawRect(path.getBounds(), paint);
4848 paint.setAntiAlias(true);
4849 paint.setColor(SK_ColorWHITE);
4850 canvas->drawPath(path, paint);
4851 }
4852};
4853
4854#Function ##
4855void draw(SkCanvas* canvas) {
4856 sk_sp<SkDrawable> drawable(new MyDrawable);
4857 canvas->drawDrawable(drawable.get(), 10, 10);
Cary Clark8032b982017-07-28 11:04:54 -04004858}
4859##
4860
Cary Clark2ade9972017-11-02 17:49:34 -04004861#SeeAlso SkDrawable drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004862
4863##
4864
4865# ------------------------------------------------------------------------------
4866
4867#Method void drawAnnotation(const SkRect& rect, const char key[], SkData* value)
Cary Clark78de7512018-02-07 07:27:09 -05004868#In Draw
4869#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004870#Line # associates a Rect with a key-value pair ##
Cary Clark09d80c02018-10-31 12:14:03 -04004871#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004872
4873#Example
4874 #Height 1
4875 const char text[] = "Click this link!";
4876 SkRect bounds;
4877 SkPaint paint;
4878 paint.setTextSize(40);
4879 (void)paint.measureText(text, strlen(text), &bounds);
4880 const char url[] = "https://www.google.com/";
4881 sk_sp<SkData> urlData(SkData::MakeWithCString(url));
4882 canvas->drawAnnotation(bounds, "url_key", urlData.get());
4883##
4884
Cary Clark2ade9972017-11-02 17:49:34 -04004885#SeeAlso SkPicture SkDocument
Cary Clark8032b982017-07-28 11:04:54 -04004886
4887##
4888
4889# ------------------------------------------------------------------------------
4890
Herb Derbyefe39bc2018-05-01 17:06:20 -04004891#Method void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value)
Cary Clark09d80c02018-10-31 12:14:03 -04004892#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004893
4894#Example
4895#Height 1
4896 const char text[] = "Click this link!";
4897 SkRect bounds;
4898 SkPaint paint;
4899 paint.setTextSize(40);
4900 (void)paint.measureText(text, strlen(text), &bounds);
4901 const char url[] = "https://www.google.com/";
4902 sk_sp<SkData> urlData(SkData::MakeWithCString(url));
4903 canvas->drawAnnotation(bounds, "url_key", urlData.get());
4904##
4905
Cary Clark2ade9972017-11-02 17:49:34 -04004906#SeeAlso SkPicture SkDocument
Cary Clark8032b982017-07-28 11:04:54 -04004907
4908##
4909
Cary Clark8032b982017-07-28 11:04:54 -04004910# ------------------------------------------------------------------------------
4911
4912#Method virtual bool isClipEmpty() const
Cary Clark78de7512018-02-07 07:27:09 -05004913#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -05004914#Line # returns if Clip is empty ##
Cary Clark09d80c02018-10-31 12:14:03 -04004915#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004916
4917#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004918 void draw(SkCanvas* canvas) {
4919 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
4920 SkPath path;
4921 canvas->clipPath(path);
4922 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
Cary Clark8032b982017-07-28 11:04:54 -04004923 }
4924 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04004925 clip is not empty
Cary Clark8032b982017-07-28 11:04:54 -04004926 clip is empty
4927 ##
4928##
4929
Cary Clark2ade9972017-11-02 17:49:34 -04004930#SeeAlso isClipRect getLocalClipBounds getDeviceClipBounds
Cary Clark8032b982017-07-28 11:04:54 -04004931
4932##
4933
4934# ------------------------------------------------------------------------------
4935
4936#Method virtual bool isClipRect() const
Cary Clark78de7512018-02-07 07:27:09 -05004937#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -05004938#Line # returns if Clip is Rect and not empty ##
Cary Clark09d80c02018-10-31 12:14:03 -04004939#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004940
4941#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004942 void draw(SkCanvas* canvas) {
4943 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
4944 canvas->clipRect({0, 0, 0, 0});
4945 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
Cary Clark8032b982017-07-28 11:04:54 -04004946 }
4947 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04004948 clip is rect
Cary Clark8032b982017-07-28 11:04:54 -04004949 clip is not rect
4950 ##
4951##
4952
Cary Clark2ade9972017-11-02 17:49:34 -04004953#SeeAlso isClipEmpty getLocalClipBounds getDeviceClipBounds
Cary Clark8032b982017-07-28 11:04:54 -04004954
4955##
4956
4957#Class SkCanvas ##
Cary Clark884dd7d2017-10-11 10:37:52 -04004958
Cary Clark8032b982017-07-28 11:04:54 -04004959#Topic Canvas ##