blob: ddfe680f639a83d13b4da0eca1527da16d798c03 [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
Cary Clark8032b982017-07-28 11:04:54 -0400192#Method explicit SkCanvas(const SkBitmap& bitmap)
193
Cary Clarkab2621d2018-01-30 10:08:57 -0500194#Line # uses existing Bitmap ##
Cary Clark09d80c02018-10-31 12:14:03 -0400195#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400196
197#Example
198#Description
199The actual output depends on the installed fonts.
200##
201 SkBitmap bitmap;
202 // create a bitmap 5 wide and 11 high
203 bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11));
204 SkCanvas canvas(bitmap);
Cary Clarkce101242017-09-01 15:51:02 -0400205 canvas.clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order
Cary Clark8032b982017-07-28 11:04:54 -0400206 SkPixmap pixmap; // provides guaranteed access to the drawn pixels
207 if (!canvas.peekPixels(&pixmap)) {
208 SkDebugf("peekPixels should never fail.\n");
209 }
Cary Clarkbc5697d2017-10-04 14:31:33 -0400210 const SkPMColor* pixels = pixmap.addr32(); // points to top-left of bitmap
Cary Clarkce101242017-09-01 15:51:02 -0400211 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary
Cary Clark8032b982017-07-28 11:04:54 -0400212 SkPaint paint; // by default, draws black, 12 point text
Mike Reed33535cb2019-01-09 11:25:18 -0500213 canvas.drawString("!", 1, 10, SkFont(), paint); // 1 char at baseline (1, 10)
Cary Clark8032b982017-07-28 11:04:54 -0400214 for (int y = 0; y < bitmap.height(); ++y) {
215 for (int x = 0; x < bitmap.width(); ++x) {
216 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
217 }
218 SkDebugf("\n");
219 }
220
221 #StdOut
Cary Clarkd0530ba2017-09-14 11:25:39 -0400222 -----
223 ---x-
224 ---x-
225 ---x-
226 ---x-
227 ---x-
228 ---x-
229 -----
230 ---x-
231 ---x-
Cary Clark8032b982017-07-28 11:04:54 -0400232 -----
233 #StdOut ##
234##
235
Cary Clark2ade9972017-11-02 17:49:34 -0400236#SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas
Cary Clark8032b982017-07-28 11:04:54 -0400237
238##
239
Cary Clark8032b982017-07-28 11:04:54 -0400240# ------------------------------------------------------------------------------
241
242#Method SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
243
Cary Clarkab2621d2018-01-30 10:08:57 -0500244#Line # uses existing Bitmap and Surface_Properties ##
Cary Clark09d80c02018-10-31 12:14:03 -0400245#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400246
247#Example
248#Description
249The actual output depends on the installed fonts.
250##
251 SkBitmap bitmap;
252 // create a bitmap 5 wide and 11 high
253 bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11));
254 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
Cary Clarkce101242017-09-01 15:51:02 -0400255 canvas.clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order
Cary Clark8032b982017-07-28 11:04:54 -0400256 SkPixmap pixmap; // provides guaranteed access to the drawn pixels
257 if (!canvas.peekPixels(&pixmap)) {
258 SkDebugf("peekPixels should never fail.\n");
259 }
Cary Clarkbc5697d2017-10-04 14:31:33 -0400260 const SkPMColor* pixels = pixmap.addr32(); // points to top-left of bitmap
Cary Clarkce101242017-09-01 15:51:02 -0400261 SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary
Cary Clark8032b982017-07-28 11:04:54 -0400262 SkPaint paint; // by default, draws black, 12 point text
Mike Reed33535cb2019-01-09 11:25:18 -0500263 canvas.drawString("!", 1, 10, SkFont(), paint); // 1 char at baseline (1, 10)
Cary Clark8032b982017-07-28 11:04:54 -0400264 for (int y = 0; y < bitmap.height(); ++y) {
265 for (int x = 0; x < bitmap.width(); ++x) {
266 SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
267 }
268 SkDebugf("\n");
269 }
270
271 #StdOut
272 -----
273 ---x-
274 ---x-
275 ---x-
276 ---x-
277 ---x-
278 ---x-
279 -----
280 ---x-
281 ---x-
282 -----
283 #StdOut ##
284##
285
Cary Clark2ade9972017-11-02 17:49:34 -0400286#SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas
Cary Clark8032b982017-07-28 11:04:54 -0400287
288##
289
290# ------------------------------------------------------------------------------
291
292#Method virtual ~SkCanvas()
293
Cary Clarkab2621d2018-01-30 10:08:57 -0500294#Line # draws saved Layers, frees resources ##
Cary Clark09d80c02018-10-31 12:14:03 -0400295#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400296
297#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -0400298#Description
Cary Clarkce101242017-09-01 15:51:02 -0400299Canvas Layer draws into bitmap. saveLayerAlpha sets up an additional
300drawing surface that blends with the bitmap. When Layer goes out of
Cary Clark09d80c02018-10-31 12:14:03 -0400301scope, Layer destructor is called. The saved Layer is restored, drawing
Cary Clarkbad5ad72017-08-03 17:14:08 -0400302transparent letters.
303##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400304void draw(SkCanvas* canvas) {
305 SkBitmap bitmap;
306 bitmap.allocPixels(SkImageInfo::MakeN32Premul(200, 200));
307 {
308 SkCanvas offscreen(bitmap);
309 SkPaint paint;
Mike Reed33535cb2019-01-09 11:25:18 -0500310 SkFont font(nullptr, 100);
311 offscreen.drawString("ABC", 20, 160, font, paint);
Cary Clarkf05bdda2017-08-24 12:59:48 -0400312 SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192);
313 offscreen.saveLayerAlpha(&layerBounds, 128);
314 offscreen.clear(SK_ColorWHITE);
Mike Reed33535cb2019-01-09 11:25:18 -0500315 offscreen.drawString("DEF", 20, 160, font, paint);
Cary Clarkf05bdda2017-08-24 12:59:48 -0400316 }
317 canvas->drawBitmap(bitmap, 0, 0, nullptr);
Cary Clarkbad5ad72017-08-03 17:14:08 -0400318}
Cary Clark8032b982017-07-28 11:04:54 -0400319##
320
Cary Clarkbad5ad72017-08-03 17:14:08 -0400321#SeeAlso State_Stack
Cary Clark8032b982017-07-28 11:04:54 -0400322
323##
324
325# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -0500326#Subtopic Property
Cary Clark78de7512018-02-07 07:27:09 -0500327#Line # metrics and attributes ##
328##
Cary Clark8032b982017-07-28 11:04:54 -0400329
330#Method SkMetaData& getMetaData()
Cary Clark78de7512018-02-07 07:27:09 -0500331#In Property
332#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -0500333#Line # associates additional data with the canvas ##
Cary Clark09d80c02018-10-31 12:14:03 -0400334#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400335
336#Example
337 const char* kHelloMetaData = "HelloMetaData";
338 SkCanvas canvas;
339 SkMetaData& metaData = canvas.getMetaData();
340 SkDebugf("before: %s\n", metaData.findString(kHelloMetaData));
341 metaData.setString(kHelloMetaData, "Hello!");
342 SkDebugf("during: %s\n", metaData.findString(kHelloMetaData));
343 metaData.removeString(kHelloMetaData);
344 SkDebugf("after: %s\n", metaData.findString(kHelloMetaData));
345
346 #StdOut
347 before: (null)
348 during: Hello!
349 after: (null)
350 #StdOut ##
351##
352
Cary Clark2ade9972017-11-02 17:49:34 -0400353#SeeAlso SkMetaData
Cary Clark8032b982017-07-28 11:04:54 -0400354
355##
356
357# ------------------------------------------------------------------------------
358
359#Method SkImageInfo imageInfo() const
Cary Clark78de7512018-02-07 07:27:09 -0500360#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500361#Line # returns Image_Info for Canvas ##
Cary Clark09d80c02018-10-31 12:14:03 -0400362#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400363
364#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -0400365 SkCanvas emptyCanvas;
366 SkImageInfo canvasInfo = emptyCanvas.imageInfo();
367 SkImageInfo emptyInfo;
368 SkDebugf("emptyInfo %c= canvasInfo\n", emptyInfo == canvasInfo ? '=' : '!');
369
370 #StdOut
371 emptyInfo == canvasInfo
372 ##
Cary Clark8032b982017-07-28 11:04:54 -0400373##
374
Cary Clark2ade9972017-11-02 17:49:34 -0400375#SeeAlso SkImageInfo MakeRasterDirect makeSurface
Cary Clark8032b982017-07-28 11:04:54 -0400376
377##
378
379# ------------------------------------------------------------------------------
380
381#Method bool getProps(SkSurfaceProps* props) const
Cary Clark78de7512018-02-07 07:27:09 -0500382#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500383#Line # copies Surface_Properties if available ##
Cary Clark09d80c02018-10-31 12:14:03 -0400384#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400385
386#Example
387 SkBitmap bitmap;
388 SkCanvas canvas(bitmap, SkSurfaceProps(0, kRGB_V_SkPixelGeometry));
389 SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
390 SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry()));
391 if (!canvas.getProps(&surfaceProps)) {
392 SkDebugf("getProps failed unexpectedly.\n");
393 }
394 SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry()));
395
396 #StdOut
397 isRGB:0
398 isRGB:1
399 #StdOut ##
400##
401
Cary Clark2ade9972017-11-02 17:49:34 -0400402#SeeAlso SkSurfaceProps makeSurface
Cary Clark8032b982017-07-28 11:04:54 -0400403
404##
405
406# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -0500407#Subtopic Utility
Cary Clark78de7512018-02-07 07:27:09 -0500408#Line # rarely called management functions ##
409##
Cary Clark8032b982017-07-28 11:04:54 -0400410
411#Method void flush()
Cary Clark78de7512018-02-07 07:27:09 -0500412#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -0500413#Line # triggers execution of all pending draw operations ##
Cary Clark09d80c02018-10-31 12:14:03 -0400414#Populate
Cary Clark2ade9972017-11-02 17:49:34 -0400415
Cary Clark08895c42018-02-01 09:37:32 -0500416#NoExample
Cary Clark8032b982017-07-28 11:04:54 -0400417##
418
Cary Clarkabaffd82018-11-15 08:25:12 -0500419#SeeAlso peekPixels SkSurface::flush GrContext::flush GrContext::abandonContext
Cary Clark8032b982017-07-28 11:04:54 -0400420
421##
422
423# ------------------------------------------------------------------------------
424
425#Method virtual SkISize getBaseLayerSize() const
Cary Clark78de7512018-02-07 07:27:09 -0500426#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500427#Line # returns size of base Layer in global coordinates ##
Cary Clark09d80c02018-10-31 12:14:03 -0400428#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400429
430#Example
431 SkBitmap bitmap;
432 bitmap.allocPixels(SkImageInfo::MakeN32Premul(20, 30));
433 SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
434 canvas.clipRect(SkRect::MakeWH(10, 40));
435 SkIRect clipDeviceBounds = canvas.getDeviceClipBounds();
436 if (clipDeviceBounds.isEmpty()) {
437 SkDebugf("Empty clip bounds is unexpected!\n");
438 }
439 SkDebugf("clip=%d,%d\n", clipDeviceBounds.width(), clipDeviceBounds.height());
440 SkISize baseLayerSize = canvas.getBaseLayerSize();
441 SkDebugf("size=%d,%d\n", baseLayerSize.width(), baseLayerSize.height());
442
443 #StdOut
444 clip=10,30
445 size=20,30
446 ##
447##
448
449#ToDo is this the same as the width and height of surface? ##
450
Cary Clark2ade9972017-11-02 17:49:34 -0400451#SeeAlso getDeviceClipBounds
452
Cary Clark8032b982017-07-28 11:04:54 -0400453##
454
455# ------------------------------------------------------------------------------
456
457#Method sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr)
Cary Clark61313f32018-10-08 14:57:48 -0400458#In Constructors
Cary Clarkab2621d2018-01-30 10:08:57 -0500459#Line # creates Surface matching SkImageInfo and SkSurfaceProps ##
Cary Clark09d80c02018-10-31 12:14:03 -0400460#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400461
462#Example
463 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(5, 6);
464 SkCanvas* smallCanvas = surface->getCanvas();
465 SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(3, 4);
466 sk_sp<SkSurface> compatible = smallCanvas->makeSurface(imageInfo);
467 SkDebugf("compatible %c= nullptr\n", compatible == nullptr ? '=' : '!');
468 SkDebugf("size = %d, %d\n", compatible->width(), compatible->height());
469
470 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -0400471 compatible != nullptr
Cary Clark8032b982017-07-28 11:04:54 -0400472 size = 3, 4
473 ##
474##
475
Cary Clark2ade9972017-11-02 17:49:34 -0400476#SeeAlso SkSurface SkSurface::makeSurface SkImageInfo SkSurfaceProps
Cary Clark8032b982017-07-28 11:04:54 -0400477
478##
479
480# ------------------------------------------------------------------------------
481
482#Method virtual GrContext* getGrContext()
Cary Clark78de7512018-02-07 07:27:09 -0500483#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500484#Line # returns GPU_Context of the GPU_Surface ##
Cary Clark09d80c02018-10-31 12:14:03 -0400485#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400486
487#Example
488void draw(SkCanvas* canvas) {
489 if (canvas->getGrContext()) {
490 canvas->clear(SK_ColorRED);
491 } else {
492 canvas->clear(SK_ColorBLUE);
493 }
494}
495##
496
497#ToDo fiddle should show both CPU and GPU out ##
498
Herb Derbyefe39bc2018-05-01 17:06:20 -0400499#SeeAlso GrContext
Cary Clark2ade9972017-11-02 17:49:34 -0400500
Cary Clark8032b982017-07-28 11:04:54 -0400501##
502
503# ------------------------------------------------------------------------------
504
Cary Clark73fa9722017-08-29 17:36:51 -0400505#Method void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = nullptr)
Cary Clark78de7512018-02-07 07:27:09 -0500506#In Utility
507#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500508#Line # returns writable pixel access if available ##
Cary Clark09d80c02018-10-31 12:14:03 -0400509#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400510
511#Example
512void draw(SkCanvas* canvas) {
513 if (canvas->accessTopLayerPixels(nullptr, nullptr)) {
514 canvas->clear(SK_ColorRED);
515 } else {
516 canvas->clear(SK_ColorBLUE);
517 }
518}
519##
520
521#Example
522#Description
Cary Clarkce101242017-09-01 15:51:02 -0400523Draws "ABC" on the device. Then draws "DEF" in Layer, and reads
524Layer to add a large dotted "DEF". Finally blends Layer with the
Herb Derbyefe39bc2018-05-01 17:06:20 -0400525device.
Cary Clark8032b982017-07-28 11:04:54 -0400526
Cary Clarkce101242017-09-01 15:51:02 -0400527The Layer and blended result appear on the CPU and GPU but the large dotted
Cary Clark8032b982017-07-28 11:04:54 -0400528"DEF" appear only on the CPU.
529##
530void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -0400531 SkPaint paint;
Mike Reed33535cb2019-01-09 11:25:18 -0500532 SkFont font(nullptr, 100);
533 canvas->drawString("ABC", 20, 160, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -0400534 SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192);
535 canvas->saveLayerAlpha(&layerBounds, 128);
536 canvas->clear(SK_ColorWHITE);
Mike Reed33535cb2019-01-09 11:25:18 -0500537 canvas->drawString("DEF", 20, 160, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -0400538 SkImageInfo imageInfo;
539 size_t rowBytes;
540 SkIPoint origin;
541 uint32_t* access = (uint32_t*) canvas->accessTopLayerPixels(&imageInfo, &rowBytes, &origin);
542 if (access) {
543 int h = imageInfo.height();
544 int v = imageInfo.width();
545 int rowWords = rowBytes / sizeof(uint32_t);
546 for (int y = 0; y < h; ++y) {
547 int newY = (y - h / 2) * 2 + h / 2;
548 if (newY < 0 || newY >= h) {
549 continue;
550 }
551 for (int x = 0; x < v; ++x) {
552 int newX = (x - v / 2) * 2 + v / 2;
553 if (newX < 0 || newX >= v) {
554 continue;
555 }
556 if (access[y * rowWords + x] == SK_ColorBLACK) {
557 access[newY * rowWords + newX] = SK_ColorGRAY;
558 }
559 }
560 }
561
562 }
Cary Clark8032b982017-07-28 11:04:54 -0400563 canvas->restore();
564}
565##
566
567#ToDo there are no callers of this that I can find. Deprecate? ##
568#ToDo fiddle should show both CPU and GPU out ##
569
Cary Clark2ade9972017-11-02 17:49:34 -0400570#SeeAlso SkImageInfo SkPixmap
571
Cary Clark8032b982017-07-28 11:04:54 -0400572##
573
574# ------------------------------------------------------------------------------
575
576#Method SkRasterHandleAllocator::Handle accessTopRasterHandle() const
Cary Clark78de7512018-02-07 07:27:09 -0500577#In Utility
578#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -0500579#Line # returns context that tracks Clip and Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -0400580#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400581
582#Example
583#Description
584#ToDo ##
585##
586#Function
587 static void DeleteCallback(void*, void* context) {
588 delete (char*) context;
589 }
590
591 class CustomAllocator : public SkRasterHandleAllocator {
592 public:
593 bool allocHandle(const SkImageInfo& info, Rec* rec) override {
594 char* context = new char[4]{'s', 'k', 'i', 'a'};
595 rec->fReleaseProc = DeleteCallback;
596 rec->fReleaseCtx = context;
597 rec->fHandle = context;
598 rec->fPixels = context;
599 rec->fRowBytes = 4;
600 return true;
601 }
602
603 void updateHandle(Handle handle, const SkMatrix& ctm, const SkIRect& clip_bounds) override {
604 // apply canvas matrix and clip to custom environment
605 }
606 };
607
608##
609 void draw(SkCanvas* canvas) {
610 const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
611 std::unique_ptr<SkCanvas> c2 =
612 SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<CustomAllocator>(
613 new CustomAllocator()), info);
614 char* context = (char*) c2->accessTopRasterHandle();
615 SkDebugf("context = %.4s\n", context);
616
617 }
618 #StdOut
619 context = skia
620 ##
621 #ToDo skstd::make_unique could not be used because def is private -- note to fix in c++14? ##
622##
623
624#SeeAlso SkRasterHandleAllocator
625
626##
627
628# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -0500629#Subtopic Pixels
Cary Clark78de7512018-02-07 07:27:09 -0500630#Line # read and write pixel values ##
631##
Cary Clark8032b982017-07-28 11:04:54 -0400632
633#Method bool peekPixels(SkPixmap* pixmap)
Cary Clark78de7512018-02-07 07:27:09 -0500634#In Pixels
Cary Clarkab2621d2018-01-30 10:08:57 -0500635#Line # returns if Canvas has direct access to its pixels ##
Cary Clark09d80c02018-10-31 12:14:03 -0400636#Populate
Cary Clark8032b982017-07-28 11:04:54 -0400637
638#Example
639 SkPixmap pixmap;
640 if (canvas->peekPixels(&pixmap)) {
641 SkDebugf("width=%d height=%d\n", pixmap.bounds().width(), pixmap.bounds().height());
642 }
643 #StdOut
644 width=256 height=256
645 ##
646##
647
Cary Clark2ade9972017-11-02 17:49:34 -0400648#SeeAlso readPixels SkBitmap::peekPixels SkImage::peekPixels SkSurface::peekPixels
649
Cary Clark8032b982017-07-28 11:04:54 -0400650##
651
652# ------------------------------------------------------------------------------
653
654#Method bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
655 int srcX, int srcY)
Cary Clark78de7512018-02-07 07:27:09 -0500656#In Pixels
Cary Clarkab2621d2018-01-30 10:08:57 -0500657#Line # copies and converts rectangle of pixels from Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -0400658
Cary Clark154beea2017-10-26 07:58:48 -0400659Copies Rect of pixels from Canvas into dstPixels. Matrix and Clip are
Herb Derbyefe39bc2018-05-01 17:06:20 -0400660ignored.
Cary Clark6fc50412017-09-21 12:31:06 -0400661
Cary Clarka560c472017-11-27 10:44:06 -0500662Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
663Destination Rect corners are (0, 0) and (dstInfo.width(), dstInfo.height()).
Cary Clark6fc50412017-09-21 12:31:06 -0400664Copies each readable pixel intersecting both rectangles, without scaling,
Cary Clarkf05bdda2017-08-24 12:59:48 -0400665converting to dstInfo.colorType() and dstInfo.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400666
Cary Clarkf05bdda2017-08-24 12:59:48 -0400667Pixels are readable when Device is raster, or backed by a GPU.
668Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
669returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
Brian Osman46fe9c72018-03-09 15:44:34 -0500670class like SkDebugCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400671
Cary Clarkf05bdda2017-08-24 12:59:48 -0400672The destination pixel storage must be allocated by the caller.
Cary Clark8032b982017-07-28 11:04:54 -0400673
Cary Clark2dc84ad2018-01-26 12:56:22 -0500674Pixel values are converted only if Color_Type and Alpha_Type
Cary Clarkf05bdda2017-08-24 12:59:48 -0400675do not match. Only pixels within both source and destination rectangles
Cary Clark154beea2017-10-26 07:58:48 -0400676are copied. dstPixels contents outside Rect intersection are unchanged.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400677
678Pass negative values for srcX or srcY to offset pixels across or down destination.
Cary Clark8032b982017-07-28 11:04:54 -0400679
680Does not copy, and returns false if:
681
682#List
Cary Clarkf05bdda2017-08-24 12:59:48 -0400683# Source and destination rectangles do not intersect. ##
684# Canvas pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType(). ##
685# Canvas pixels are not readable; for instance, Canvas is document-based. ##
Cary Clark8032b982017-07-28 11:04:54 -0400686# dstRowBytes is too small to contain one row of pixels. ##
687##
688
Cary Clark2dc84ad2018-01-26 12:56:22 -0500689#Param dstInfo width, height, Color_Type, and Alpha_Type of dstPixels ##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400690#Param dstPixels storage for pixels; dstInfo.height() times dstRowBytes, or larger ##
691#Param dstRowBytes size of one destination row; dstInfo.width() times pixel size, or larger ##
Cary Clark5538c132018-06-14 12:28:14 -0400692#Param srcX offset into readable pixels on x-axis; may be negative ##
693#Param srcY offset into readable pixels on y-axis; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -0400694
Cary Clarkbad5ad72017-08-03 17:14:08 -0400695#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -0400696
697#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -0400698#Width 64
699#Height 64
700#Description
701 A black circle drawn on a blue background provides an image to copy.
702 readPixels copies one quarter of the canvas into each of the four corners.
Cary Clarka560c472017-11-27 10:44:06 -0500703 The copied quarter circles overdraw the original circle.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400704##
705 canvas->clear(SK_ColorBLUE);
706 SkPaint paint;
707 canvas->drawCircle(32, 32, 28, paint);
708 SkImageInfo info = SkImageInfo::Make(64, 64, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
709 sk_sp<SkData> data(SkData::MakeUninitialized(info.minRowBytes() * info.height()));
710 sk_bzero(data->writable_data(), info.minRowBytes() * info.height());
711 for (int x : { 32, -32 } ) {
712 for (int y : { 32, -32 } ) {
713 canvas->readPixels(info, data->writable_data(), info.minRowBytes(), x, y);
Herb Derbyefe39bc2018-05-01 17:06:20 -0400714 }
Cary Clarkf05bdda2017-08-24 12:59:48 -0400715 }
716 sk_sp<SkImage> image = SkImage::MakeRasterData(info, data, info.minRowBytes());
717 canvas->drawImage(image, 0, 0);
718##
719
720#Example
Cary Clark8032b982017-07-28 11:04:54 -0400721#Description
Cary Clarkce101242017-09-01 15:51:02 -0400722 Canvas returned by Raster_Surface has Premultiplied pixel values.
723 clear() takes Unpremultiplied input with Color_Alpha equal 0x80
Cary Clarkffb3d682018-05-17 12:17:28 -0400724 and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha
Cary Clarkce101242017-09-01 15:51:02 -0400725 to generate Premultiplied value 0x802B5580. readPixels converts pixel back
726 to Unpremultiplied value 0x8056A9FF, introducing error.
Cary Clark8032b982017-07-28 11:04:54 -0400727##
728 canvas->clear(0x8055aaff);
729 for (SkAlphaType alphaType : { kPremul_SkAlphaType, kUnpremul_SkAlphaType } ) {
730 uint32_t pixel = 0;
731 SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, alphaType);
732 if (canvas->readPixels(info, &pixel, 4, 0, 0)) {
733 SkDebugf("pixel = %08x\n", pixel);
734 }
735 }
736
737 #StdOut
738 pixel = 802b5580
739 pixel = 8056a9ff
740 ##
741##
742
Cary Clark2ade9972017-11-02 17:49:34 -0400743#SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels
Cary Clark8032b982017-07-28 11:04:54 -0400744
745##
746
747# ------------------------------------------------------------------------------
748
749#Method bool readPixels(const SkPixmap& pixmap, int srcX, int srcY)
750
Cary Clark154beea2017-10-26 07:58:48 -0400751Copies Rect of pixels from Canvas into pixmap. Matrix and Clip are
Cary Clarka560c472017-11-27 10:44:06 -0500752ignored.
Cary Clark6fc50412017-09-21 12:31:06 -0400753
Cary Clarka560c472017-11-27 10:44:06 -0500754Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
755Destination Rect corners are (0, 0) and (pixmap.width(), pixmap.height()).
Cary Clark6fc50412017-09-21 12:31:06 -0400756Copies each readable pixel intersecting both rectangles, without scaling,
Cary Clarkf05bdda2017-08-24 12:59:48 -0400757converting to pixmap.colorType() and pixmap.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400758
Cary Clarkf05bdda2017-08-24 12:59:48 -0400759Pixels are readable when Device is raster, or backed by a GPU.
760Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
761returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
Brian Osman46fe9c72018-03-09 15:44:34 -0500762class like SkDebugCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400763
Cary Clark6fc50412017-09-21 12:31:06 -0400764Caller must allocate pixel storage in pixmap if needed.
Cary Clark8032b982017-07-28 11:04:54 -0400765
Cary Clark2dc84ad2018-01-26 12:56:22 -0500766Pixel values are converted only if Color_Type and Alpha_Type
Cary Clark154beea2017-10-26 07:58:48 -0400767do not match. Only pixels within both source and destination Rects
768are copied. pixmap pixels contents outside Rect intersection are unchanged.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400769
770Pass negative values for srcX or srcY to offset pixels across or down pixmap.
Cary Clark8032b982017-07-28 11:04:54 -0400771
772Does not copy, and returns false if:
773
774#List
Cary Clarkf05bdda2017-08-24 12:59:48 -0400775# Source and destination rectangles do not intersect. ##
776# Canvas pixels could not be converted to pixmap.colorType() or pixmap.alphaType(). ##
777# Canvas pixels are not readable; for instance, Canvas is document-based. ##
778# Pixmap pixels could not be allocated. ##
779# pixmap.rowBytes() is too small to contain one row of pixels. ##
Cary Clark8032b982017-07-28 11:04:54 -0400780##
781
Cary Clarkbad5ad72017-08-03 17:14:08 -0400782#Param pixmap storage for pixels copied from Canvas ##
Cary Clark5538c132018-06-14 12:28:14 -0400783#Param srcX offset into readable pixels on x-axis; may be negative ##
784#Param srcY offset into readable pixels on y-axis; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -0400785
Cary Clarkbad5ad72017-08-03 17:14:08 -0400786#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -0400787
788#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -0400789 #Description
Cary Clarkce101242017-09-01 15:51:02 -0400790 clear() takes Unpremultiplied input with Color_Alpha equal 0x80
Cary Clarkffb3d682018-05-17 12:17:28 -0400791 and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha
Cary Clarkce101242017-09-01 15:51:02 -0400792 to generate Premultiplied value 0x802B5580.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400793 ##
794 void draw(SkCanvas* canvas) {
795 canvas->clear(0x8055aaff);
796 uint32_t pixels[1] = { 0 };
797 SkPixmap pixmap(SkImageInfo::MakeN32Premul(1, 1), pixels, 4);
798 canvas->readPixels(pixmap, 0, 0);
799 SkDebugf("pixel = %08x\n", pixels[0]);
800 }
Cary Clark8032b982017-07-28 11:04:54 -0400801 #StdOut
802 pixel = 802b5580
803 ##
804##
805
Cary Clark2ade9972017-11-02 17:49:34 -0400806#SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels
Cary Clark8032b982017-07-28 11:04:54 -0400807
808##
809
810# ------------------------------------------------------------------------------
811
812#Method bool readPixels(const SkBitmap& bitmap, int srcX, int srcY)
813
Cary Clark154beea2017-10-26 07:58:48 -0400814Copies Rect of pixels from Canvas into bitmap. Matrix and Clip are
Cary Clarka560c472017-11-27 10:44:06 -0500815ignored.
Cary Clark6fc50412017-09-21 12:31:06 -0400816
Cary Clarka560c472017-11-27 10:44:06 -0500817Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
Cary Clark154beea2017-10-26 07:58:48 -0400818Destination Rect corners are (0, 0) and (bitmap.width(), bitmap.height()).
Cary Clarkf05bdda2017-08-24 12:59:48 -0400819Copies each readable pixel intersecting both rectangles, without scaling,
820converting to bitmap.colorType() and bitmap.alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400821
Cary Clarkf05bdda2017-08-24 12:59:48 -0400822Pixels are readable when Device is raster, or backed by a GPU.
823Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
824returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
Brian Osman46fe9c72018-03-09 15:44:34 -0500825class like SkDebugCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400826
Cary Clark6fc50412017-09-21 12:31:06 -0400827Caller must allocate pixel storage in bitmap if needed.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400828
Cary Clark2dc84ad2018-01-26 12:56:22 -0500829Bitmap values are converted only if Color_Type and Alpha_Type
Cary Clarkf05bdda2017-08-24 12:59:48 -0400830do not match. Only pixels within both source and destination rectangles
Cary Clark154beea2017-10-26 07:58:48 -0400831are copied. Bitmap pixels outside Rect intersection are unchanged.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400832
833Pass negative values for srcX or srcY to offset pixels across or down bitmap.
Cary Clark8032b982017-07-28 11:04:54 -0400834
835Does not copy, and returns false if:
836
837#List
Cary Clarkf05bdda2017-08-24 12:59:48 -0400838# Source and destination rectangles do not intersect. ##
839# Canvas pixels could not be converted to bitmap.colorType() or bitmap.alphaType(). ##
840# Canvas pixels are not readable; for instance, Canvas is document-based. ##
Cary Clark8032b982017-07-28 11:04:54 -0400841# bitmap pixels could not be allocated. ##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400842# bitmap.rowBytes() is too small to contain one row of pixels. ##
Cary Clark8032b982017-07-28 11:04:54 -0400843##
844
Cary Clarkbad5ad72017-08-03 17:14:08 -0400845#Param bitmap storage for pixels copied from Canvas ##
Cary Clark5538c132018-06-14 12:28:14 -0400846#Param srcX offset into readable pixels on x-axis; may be negative ##
847#Param srcY offset into readable pixels on y-axis; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -0400848
Cary Clarkbad5ad72017-08-03 17:14:08 -0400849#Return true if pixels were copied ##
Cary Clark8032b982017-07-28 11:04:54 -0400850
851#Example
Cary Clarkf05bdda2017-08-24 12:59:48 -0400852 #Description
Cary Clarkce101242017-09-01 15:51:02 -0400853 clear() takes Unpremultiplied input with Color_Alpha equal 0x80
Cary Clarkffb3d682018-05-17 12:17:28 -0400854 and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha
Cary Clarkce101242017-09-01 15:51:02 -0400855 to generate Premultiplied value 0x802B5580.
Cary Clarkf05bdda2017-08-24 12:59:48 -0400856 ##
Cary Clark8032b982017-07-28 11:04:54 -0400857void draw(SkCanvas* canvas) {
858 canvas->clear(0x8055aaff);
859 SkBitmap bitmap;
860 bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1));
861 canvas->readPixels(bitmap, 0, 0);
862 SkDebugf("pixel = %08x\n", bitmap.getAddr32(0, 0)[0]);
863}
864 #StdOut
865 pixel = 802b5580
866 ##
867##
868
Cary Clark2ade9972017-11-02 17:49:34 -0400869#SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels
Cary Clark8032b982017-07-28 11:04:54 -0400870
871##
872
873# ------------------------------------------------------------------------------
874
875#Method bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y)
Cary Clark78de7512018-02-07 07:27:09 -0500876#In Pixels
Cary Clarkab2621d2018-01-30 10:08:57 -0500877#Line # copies and converts rectangle of pixels to Canvas ##
Cary Clark154beea2017-10-26 07:58:48 -0400878Copies Rect from pixels to Canvas. Matrix and Clip are ignored.
879Source Rect corners are (0, 0) and (info.width(), info.height()).
880Destination Rect corners are (x, y) and
881(imageInfo().width(), imageInfo().height()).
Cary Clark6fc50412017-09-21 12:31:06 -0400882
883Copies each readable pixel intersecting both rectangles, without scaling,
Cary Clark154beea2017-10-26 07:58:48 -0400884converting to imageInfo().colorType() and imageInfo().alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400885
Cary Clarkf05bdda2017-08-24 12:59:48 -0400886Pixels are writable when Device is raster, or backed by a GPU.
887Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
888returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
Brian Osman46fe9c72018-03-09 15:44:34 -0500889class like SkDebugCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400890
Cary Clark2dc84ad2018-01-26 12:56:22 -0500891Pixel values are converted only if Color_Type and Alpha_Type
Cary Clarkf05bdda2017-08-24 12:59:48 -0400892do not match. Only pixels within both source and destination rectangles
Cary Clark154beea2017-10-26 07:58:48 -0400893are copied. Canvas pixels outside Rect intersection are unchanged.
Cary Clark8032b982017-07-28 11:04:54 -0400894
Cary Clarkf05bdda2017-08-24 12:59:48 -0400895Pass negative values for x or y to offset pixels to the left or
896above Canvas pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400897
898Does not copy, and returns false if:
899
900#List
Cary Clarkf05bdda2017-08-24 12:59:48 -0400901# Source and destination rectangles do not intersect. ##
Cary Clarkac47b882018-01-11 10:35:44 -0500902# pixels could not be converted to Canvas imageInfo().colorType() or
903 imageInfo().alphaType(). ##
Cary Clark8032b982017-07-28 11:04:54 -0400904# Canvas pixels are not writable; for instance, Canvas is document-based. ##
905# rowBytes is too small to contain one row of pixels. ##
906##
907
Cary Clark2dc84ad2018-01-26 12:56:22 -0500908#Param info width, height, Color_Type, and Alpha_Type of pixels ##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400909#Param pixels pixels to copy, of size info.height() times rowBytes, or larger ##
Cary Clarkd0530ba2017-09-14 11:25:39 -0400910#Param rowBytes size of one row of pixels; info.width() times pixel size, or larger ##
Cary Clark5538c132018-06-14 12:28:14 -0400911#Param x offset into Canvas writable pixels on x-axis; may be negative ##
912#Param y offset into Canvas writable pixels on y-axis; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -0400913
Cary Clarkbad5ad72017-08-03 17:14:08 -0400914#Return true if pixels were written to Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -0400915
916#Example
917 SkImageInfo imageInfo = SkImageInfo::MakeN32(256, 1, kPremul_SkAlphaType);
918 for (int y = 0; y < 256; ++y) {
919 uint32_t pixels[256];
920 for (int x = 0; x < 256; ++x) {
921 pixels[x] = SkColorSetARGB(x, x + y, x, x - y);
922 }
923 canvas->writePixels(imageInfo, &pixels, sizeof(pixels), 0, y);
924 }
925##
926
Cary Clark2ade9972017-11-02 17:49:34 -0400927#SeeAlso readPixels drawBitmap drawImage SkBitmap::writePixels
Cary Clark8032b982017-07-28 11:04:54 -0400928
929##
930
931# ------------------------------------------------------------------------------
932
933#Method bool writePixels(const SkBitmap& bitmap, int x, int y)
934
Cary Clark154beea2017-10-26 07:58:48 -0400935Copies Rect from pixels to Canvas. Matrix and Clip are ignored.
936Source Rect corners are (0, 0) and (bitmap.width(), bitmap.height()).
Cary Clark6fc50412017-09-21 12:31:06 -0400937
Cary Clark154beea2017-10-26 07:58:48 -0400938Destination Rect corners are (x, y) and
939(imageInfo().width(), imageInfo().height()).
Cary Clark6fc50412017-09-21 12:31:06 -0400940
941Copies each readable pixel intersecting both rectangles, without scaling,
Cary Clark154beea2017-10-26 07:58:48 -0400942converting to imageInfo().colorType() and imageInfo().alphaType() if required.
Cary Clark8032b982017-07-28 11:04:54 -0400943
Cary Clarkf05bdda2017-08-24 12:59:48 -0400944Pixels are writable when Device is raster, or backed by a GPU.
945Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
946returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
Brian Osman46fe9c72018-03-09 15:44:34 -0500947class like SkDebugCanvas.
Cary Clark8032b982017-07-28 11:04:54 -0400948
Cary Clark2dc84ad2018-01-26 12:56:22 -0500949Pixel values are converted only if Color_Type and Alpha_Type
Cary Clarkf05bdda2017-08-24 12:59:48 -0400950do not match. Only pixels within both source and destination rectangles
Cary Clark154beea2017-10-26 07:58:48 -0400951are copied. Canvas pixels outside Rect intersection are unchanged.
Cary Clark8032b982017-07-28 11:04:54 -0400952
Cary Clarkf05bdda2017-08-24 12:59:48 -0400953Pass negative values for x or y to offset pixels to the left or
954above Canvas pixels.
Cary Clark8032b982017-07-28 11:04:54 -0400955
956Does not copy, and returns false if:
957
958#List
Cary Clarkf05bdda2017-08-24 12:59:48 -0400959# Source and destination rectangles do not intersect. ##
Cary Clark8032b982017-07-28 11:04:54 -0400960# bitmap does not have allocated pixels. ##
Cary Clarkac47b882018-01-11 10:35:44 -0500961# bitmap pixels could not be converted to Canvas imageInfo().colorType() or
962 imageInfo().alphaType(). ##
Cary Clarkce101242017-09-01 15:51:02 -0400963# Canvas pixels are not writable; for instance, Canvas is document based. ##
Cary Clark8032b982017-07-28 11:04:54 -0400964# bitmap pixels are inaccessible; for instance, bitmap wraps a texture. ##
965##
966
Cary Clarkbad5ad72017-08-03 17:14:08 -0400967#Param bitmap contains pixels copied to Canvas ##
Cary Clarkf05bdda2017-08-24 12:59:48 -0400968#Param x offset into Canvas writable pixels in x; may be negative ##
969#Param y offset into Canvas writable pixels in y; may be negative ##
Cary Clark8032b982017-07-28 11:04:54 -0400970
Cary Clarkbad5ad72017-08-03 17:14:08 -0400971#Return true if pixels were written to Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -0400972
973#Example
974void draw(SkCanvas* canvas) {
975 SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(2, 2);
976 SkBitmap bitmap;
977 bitmap.setInfo(imageInfo);
978 uint32_t pixels[4];
979 bitmap.setPixels(pixels);
980 for (int y = 0; y < 256; y += 2) {
981 for (int x = 0; x < 256; x += 2) {
982 pixels[0] = SkColorSetRGB(x, y, x | y);
983 pixels[1] = SkColorSetRGB(x ^ y, y, x);
984 pixels[2] = SkColorSetRGB(x, x & y, y);
985 pixels[3] = SkColorSetRGB(~x, ~y, x);
986 canvas->writePixels(bitmap, x, y);
987 }
988 }
989}
990##
991
Cary Clark2ade9972017-11-02 17:49:34 -0400992#SeeAlso readPixels drawBitmap drawImage SkBitmap::writePixels
Cary Clark8032b982017-07-28 11:04:54 -0400993
994##
995
996# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -0500997#Subtopic State_Stack
998#Line # stack of state for hierarchical drawing ##
Cary Clark8032b982017-07-28 11:04:54 -0400999
1000Canvas maintains a stack of state that allows hierarchical drawing, commonly used
Cary Clarkbad5ad72017-08-03 17:14:08 -04001001to implement windows and views. The initial state has an identity matrix and and
1002an infinite clip. Even with a wide-open clip, drawing is constrained by the
1003bounds of the Canvas Surface or Device.
Cary Clark8032b982017-07-28 11:04:54 -04001004
Cary Clark939fd6c2018-07-12 08:40:13 -04001005Canvas savable state consists of Clip and Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04001006Clip describes the area that may be drawn to.
1007Matrix transforms the geometry.
Cary Clark8032b982017-07-28 11:04:54 -04001008
Mike Reed9a229e92019-01-08 10:52:52 -05001009save(), saveLayer, and saveLayerAlpha
Cary Clark8032b982017-07-28 11:04:54 -04001010save state and return the depth of the stack.
1011
Cary Clarkbad5ad72017-08-03 17:14:08 -04001012restore(), restoreToCount, and ~SkCanvas() revert state to its value when saved.
Cary Clark8032b982017-07-28 11:04:54 -04001013
1014Each state on the stack intersects Clip with the previous Clip,
1015and concatenates Matrix with the previous Matrix.
1016The intersected Clip makes the drawing area the same or smaller;
1017the concatenated Matrix may move the origin and potentially scale or rotate
1018the coordinate space.
1019
1020Canvas does not require balancing the state stack but it is a good idea
1021to do so. Calling save() without restore() will eventually cause Skia to fail;
1022mismatched save() and restore() create hard to find bugs.
1023
1024It is not possible to use state to draw outside of the clip defined by the
1025previous state.
1026
1027#Example
1028#Description
1029Draw to ever smaller clips; then restore drawing to full canvas.
1030Note that the second clipRect is not permitted to enlarge Clip.
1031##
1032#Height 160
Cary Clarkbad5ad72017-08-03 17:14:08 -04001033void draw(SkCanvas* canvas) {
1034 SkPaint paint;
Herb Derbyefe39bc2018-05-01 17:06:20 -04001035 canvas->save(); // records stack depth to restore
Cary Clarkbad5ad72017-08-03 17:14:08 -04001036 canvas->clipRect(SkRect::MakeWH(100, 100)); // constrains drawing to clip
1037 canvas->clear(SK_ColorRED); // draws to limit of clip
Herb Derbyefe39bc2018-05-01 17:06:20 -04001038 canvas->save(); // records stack depth to restore
Cary Clarkbad5ad72017-08-03 17:14:08 -04001039 canvas->clipRect(SkRect::MakeWH(50, 150)); // Rect below 100 is ignored
1040 canvas->clear(SK_ColorBLUE); // draws to smaller clip
1041 canvas->restore(); // enlarges clip
1042 canvas->drawLine(20, 20, 150, 150, paint); // line below 100 is not drawn
1043 canvas->restore(); // enlarges clip
1044 canvas->drawLine(150, 20, 50, 120, paint); // line below 100 is drawn
Cary Clark8032b982017-07-28 11:04:54 -04001045}
Herb Derbyefe39bc2018-05-01 17:06:20 -04001046##
Cary Clark8032b982017-07-28 11:04:54 -04001047
1048Each Clip uses the current Matrix for its coordinates.
1049
1050#Example
1051#Description
1052While clipRect is given the same rectangle twice, Matrix makes the second
1053clipRect draw at half the size of the first.
1054##
1055#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001056void draw(SkCanvas* canvas) {
1057 canvas->clipRect(SkRect::MakeWH(100, 100));
1058 canvas->clear(SK_ColorRED);
1059 canvas->scale(.5, .5);
1060 canvas->clipRect(SkRect::MakeWH(100, 100));
1061 canvas->clear(SK_ColorBLUE);
Cary Clark8032b982017-07-28 11:04:54 -04001062}
1063##
1064
Mike Reed9a229e92019-01-08 10:52:52 -05001065#SeeAlso save saveLayer saveLayerAlpha restore() restoreToCount
Cary Clark8032b982017-07-28 11:04:54 -04001066
1067#Method int save()
1068
Cary Clarkab2621d2018-01-30 10:08:57 -05001069#In State_Stack
1070#Line # saves Clip and Matrix on stack ##
Cary Clark09d80c02018-10-31 12:14:03 -04001071#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001072
1073#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04001074#Description
Cary Clark8032b982017-07-28 11:04:54 -04001075The black square is translated 50 pixels down and to the right.
1076Restoring Canvas state removes translate() from Canvas stack;
1077the red square is not translated, and is drawn at the origin.
1078##
1079#Height 100
1080void draw(SkCanvas* canvas) {
1081 SkPaint paint;
1082 SkRect rect = { 0, 0, 25, 25 };
1083 canvas->drawRect(rect, paint);
1084 canvas->save();
1085 canvas->translate(50, 50);
1086 canvas->drawRect(rect, paint);
1087 canvas->restore();
1088 paint.setColor(SK_ColorRED);
1089 canvas->drawRect(rect, paint);
1090}
1091##
1092
Mike Reed9a229e92019-01-08 10:52:52 -05001093#SeeAlso saveLayer saveLayerAlpha restore restoreToCount
Cary Clark8032b982017-07-28 11:04:54 -04001094
1095##
1096
1097# ------------------------------------------------------------------------------
Cary Clark8032b982017-07-28 11:04:54 -04001098
1099#Method void restore()
1100
Cary Clarkab2621d2018-01-30 10:08:57 -05001101#In State_Stack
1102#Line # restores changes to Clip and Matrix, pops save stack ##
Cary Clark09d80c02018-10-31 12:14:03 -04001103#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001104
1105#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001106void draw(SkCanvas* canvas) {
1107 SkCanvas simple;
1108 SkDebugf("depth = %d\n", simple.getSaveCount());
1109 simple.restore();
1110 SkDebugf("depth = %d\n", simple.getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001111}
1112##
1113
Mike Reed9a229e92019-01-08 10:52:52 -05001114#SeeAlso save saveLayer saveLayerAlpha restoreToCount
Cary Clark2ade9972017-11-02 17:49:34 -04001115
Cary Clark8032b982017-07-28 11:04:54 -04001116##
1117
1118# ------------------------------------------------------------------------------
1119
1120#Method int getSaveCount() const
1121
Cary Clarkab2621d2018-01-30 10:08:57 -05001122#In State_Stack
1123#Line # returns depth of stack containing Clip and Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001124#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001125
1126#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001127void draw(SkCanvas* canvas) {
1128 SkCanvas simple;
1129 SkDebugf("depth = %d\n", simple.getSaveCount());
1130 simple.save();
1131 SkDebugf("depth = %d\n", simple.getSaveCount());
1132 simple.restore();
1133 SkDebugf("depth = %d\n", simple.getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001134}
1135#StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04001136depth = 1
1137depth = 2
Cary Clark8032b982017-07-28 11:04:54 -04001138depth = 1
1139##
1140##
1141
Cary Clarka90ea222018-10-16 10:30:28 -04001142#SeeAlso save restore restoreToCount
Cary Clark2ade9972017-11-02 17:49:34 -04001143
Cary Clark8032b982017-07-28 11:04:54 -04001144##
1145
1146# ------------------------------------------------------------------------------
1147
1148#Method void restoreToCount(int saveCount)
1149
Cary Clarkab2621d2018-01-30 10:08:57 -05001150#In State_Stack
1151#Line # restores changes to Clip and Matrix to given depth ##
Cary Clark09d80c02018-10-31 12:14:03 -04001152#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001153
1154#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001155void draw(SkCanvas* canvas) {
1156 SkDebugf("depth = %d\n", canvas->getSaveCount());
1157 canvas->save();
1158 canvas->save();
1159 SkDebugf("depth = %d\n", canvas->getSaveCount());
1160 canvas->restoreToCount(0);
1161 SkDebugf("depth = %d\n", canvas->getSaveCount());
Cary Clark8032b982017-07-28 11:04:54 -04001162}
1163#StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04001164depth = 1
1165depth = 3
Cary Clark8032b982017-07-28 11:04:54 -04001166depth = 1
1167##
1168##
1169
Cary Clarka90ea222018-10-16 10:30:28 -04001170#SeeAlso restore getSaveCount save
Cary Clark2ade9972017-11-02 17:49:34 -04001171
Cary Clark8032b982017-07-28 11:04:54 -04001172##
1173
Cary Clark08895c42018-02-01 09:37:32 -05001174#Subtopic State_Stack ##
Cary Clark8032b982017-07-28 11:04:54 -04001175
1176# ------------------------------------------------------------------------------
Cary Clarkce101242017-09-01 15:51:02 -04001177
Cary Clark08895c42018-02-01 09:37:32 -05001178#Subtopic Layer
Cary Clarkd0530ba2017-09-14 11:25:39 -04001179#Substitute layer
Cary Clarkce101242017-09-01 15:51:02 -04001180#Alias Layers
Cary Clark137b8742018-05-30 09:21:49 -04001181#Substitute layers
1182##
Cary Clark08895c42018-02-01 09:37:32 -05001183#Line # temporary Bitmap to draw into ##
Cary Clarkce101242017-09-01 15:51:02 -04001184
1185Layer allocates a temporary Bitmap to draw into. When the drawing is
Herb Derbyefe39bc2018-05-01 17:06:20 -04001186complete, the Bitmap is drawn into the Canvas.
Cary Clarkce101242017-09-01 15:51:02 -04001187
1188Layer is saved in a stack along with other saved state. When state with a Layer
1189is restored, the Bitmap is drawn into the previous Layer.
1190
1191Layer may be initialized with the contents of the previous Layer. When Layer is
1192restored, its Bitmap can be modified by Paint passed to Layer to apply
1193Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode.
1194
1195#Method int saveLayer(const SkRect* bounds, const SkPaint* paint)
1196
Cary Clarkab2621d2018-01-30 10:08:57 -05001197#In Layer
1198#Line # saves Clip and Matrix on stack; creates Layer ##
Cary Clark09d80c02018-10-31 12:14:03 -04001199#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001200
1201#Example
1202#Description
1203Rectangles are blurred by Image_Filter when restore() draws Layer to main
1204Canvas.
1205##
1206#Height 128
Cary Clark81abc432018-06-25 16:30:08 -04001207#Function
1208###$
1209#include "SkBlurImageFilter.h"
1210$$$#
1211##
1212
Cary Clarkce101242017-09-01 15:51:02 -04001213void draw(SkCanvas* canvas) {
1214 SkPaint paint, blur;
Cary Clarka560c472017-11-27 10:44:06 -05001215 blur.setImageFilter(SkBlurImageFilter::Make(3, 3, nullptr));
Cary Clarkce101242017-09-01 15:51:02 -04001216 canvas->saveLayer(nullptr, &blur);
1217 SkRect rect = { 25, 25, 50, 50};
1218 canvas->drawRect(rect, paint);
1219 canvas->translate(50, 50);
1220 paint.setColor(SK_ColorRED);
1221 canvas->drawRect(rect, paint);
1222 canvas->restore();
1223}
1224##
1225
Mike Reed9a229e92019-01-08 10:52:52 -05001226#SeeAlso save restore saveLayer saveLayerAlpha SaveLayerRec
Cary Clarkce101242017-09-01 15:51:02 -04001227
1228##
1229
Herb Derbyefe39bc2018-05-01 17:06:20 -04001230#Method int saveLayer(const SkRect& bounds, const SkPaint* paint)
Cary Clarkce101242017-09-01 15:51:02 -04001231
Cary Clarkab2621d2018-01-30 10:08:57 -05001232#In Layer
Cary Clark09d80c02018-10-31 12:14:03 -04001233#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001234
1235#Example
1236#Description
1237Rectangles are blurred by Image_Filter when restore() draws Layer to main Canvas.
Herb Derbyefe39bc2018-05-01 17:06:20 -04001238The red rectangle is clipped; it does not fully fit on Layer.
Cary Clarkce101242017-09-01 15:51:02 -04001239Image_Filter blurs past edge of Layer so red rectangle is blurred on all sides.
1240##
1241#Height 128
Cary Clark81abc432018-06-25 16:30:08 -04001242#Function
1243###$
1244#include "SkBlurImageFilter.h"
1245$$$#
1246##
1247
Cary Clarkce101242017-09-01 15:51:02 -04001248void draw(SkCanvas* canvas) {
1249 SkPaint paint, blur;
Cary Clarka560c472017-11-27 10:44:06 -05001250 blur.setImageFilter(SkBlurImageFilter::Make(3, 3, nullptr));
Cary Clarkce101242017-09-01 15:51:02 -04001251 canvas->saveLayer(SkRect::MakeWH(90, 90), &blur);
1252 SkRect rect = { 25, 25, 50, 50};
1253 canvas->drawRect(rect, paint);
1254 canvas->translate(50, 50);
1255 paint.setColor(SK_ColorRED);
1256 canvas->drawRect(rect, paint);
1257 canvas->restore();
1258}
1259##
1260
Mike Reed9a229e92019-01-08 10:52:52 -05001261#SeeAlso save restore saveLayerAlpha SaveLayerRec
Cary Clarkce101242017-09-01 15:51:02 -04001262
1263##
1264
1265#Method int saveLayerAlpha(const SkRect* bounds, U8CPU alpha)
1266
Cary Clarkab2621d2018-01-30 10:08:57 -05001267#In Layer
1268#Line # saves Clip and Matrix on stack; creates Layer; sets opacity ##
Cary Clark09d80c02018-10-31 12:14:03 -04001269#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001270
1271#Example
1272 SkPaint paint;
1273 paint.setColor(SK_ColorRED);
1274 canvas->drawCircle(50, 50, 50, paint);
1275 canvas->saveLayerAlpha(nullptr, 128);
1276 paint.setColor(SK_ColorBLUE);
1277 canvas->drawCircle(100, 50, 50, paint);
1278 paint.setColor(SK_ColorGREEN);
1279 paint.setAlpha(128);
1280 canvas->drawCircle(75, 90, 50, paint);
1281 canvas->restore();
1282##
1283
Mike Reed9a229e92019-01-08 10:52:52 -05001284#SeeAlso save restore saveLayer SaveLayerRec
Cary Clarkce101242017-09-01 15:51:02 -04001285
1286##
1287
Cary Clarkd98f78c2018-04-26 08:32:37 -04001288#Enum SaveLayerFlagsSet
Cary Clark08895c42018-02-01 09:37:32 -05001289#Line # sets SaveLayerRec options ##
Cary Clarkce101242017-09-01 15:51:02 -04001290#Code
Cary Clark61313f32018-10-08 14:57:48 -04001291#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001292##
1293
Cary Clark682c58d2018-05-16 07:07:07 -04001294
1295#Typedef uint32_t SaveLayerFlags
1296#Line # options for SaveLayerRec ##
Cary Clark137b8742018-05-30 09:21:49 -04001297##
Cary Clark682c58d2018-05-16 07:07:07 -04001298
Cary Clarkce101242017-09-01 15:51:02 -04001299SaveLayerFlags provides options that may be used in any combination in SaveLayerRec,
Mike Reed9a229e92019-01-08 10:52:52 -05001300defining how Layer allocated by saveLayer operates. It may be set to zero or
1301kInitWithPrevious_SaveLayerFlag.
Cary Clarkce101242017-09-01 15:51:02 -04001302
1303#Const kInitWithPrevious_SaveLayerFlag 4
Cary Clark682c58d2018-05-16 07:07:07 -04001304#Line # initializes with previous contents ##
Cary Clarkce101242017-09-01 15:51:02 -04001305 Initializes Layer with the contents of the previous Layer.
1306##
1307
Cary Clarkce101242017-09-01 15:51:02 -04001308#Example
1309#Height 160
1310#Description
1311Canvas Layer captures red and blue circles scaled up by four.
Herb Derbyefe39bc2018-05-01 17:06:20 -04001312scalePaint blends Layer back with transparency.
Cary Clarkce101242017-09-01 15:51:02 -04001313##
1314void draw(SkCanvas* canvas) {
1315 SkPaint redPaint, bluePaint, scalePaint;
1316 redPaint.setColor(SK_ColorRED);
1317 canvas->drawCircle(21, 21, 8, redPaint);
1318 bluePaint.setColor(SK_ColorBLUE);
1319 canvas->drawCircle(31, 21, 8, bluePaint);
1320 SkMatrix matrix;
1321 matrix.setScale(4, 4);
1322 scalePaint.setAlpha(0x40);
1323 scalePaint.setImageFilter(
1324 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
1325 SkCanvas::SaveLayerRec saveLayerRec(nullptr, &scalePaint,
Herb Derbyefe39bc2018-05-01 17:06:20 -04001326 SkCanvas::kInitWithPrevious_SaveLayerFlag);
Cary Clarkce101242017-09-01 15:51:02 -04001327 canvas->saveLayer(saveLayerRec);
1328 canvas->restore();
1329}
1330##
1331
Mike Reed9a229e92019-01-08 10:52:52 -05001332#SeeAlso save restore saveLayer saveLayerAlpha SaveLayerRec
Cary Clarkce101242017-09-01 15:51:02 -04001333
1334#Enum ##
1335
Cary Clark682c58d2018-05-16 07:07:07 -04001336#Subtopic SaveLayerRec
1337#Line # contains the state used to create the Layer ##
Cary Clarka560c472017-11-27 10:44:06 -05001338
Cary Clarkce101242017-09-01 15:51:02 -04001339#Struct SaveLayerRec
Cary Clark08895c42018-02-01 09:37:32 -05001340#Line # contains the state used to create the Layer ##
Cary Clark682c58d2018-05-16 07:07:07 -04001341
Cary Clarkce101242017-09-01 15:51:02 -04001342#Code
Cary Clark61313f32018-10-08 14:57:48 -04001343#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001344##
1345
Cary Clark137b8742018-05-30 09:21:49 -04001346SaveLayerRec contains the state used to create the Layer.
1347
Cary Clarkce101242017-09-01 15:51:02 -04001348#Member const SkRect* fBounds
Cary Clark682c58d2018-05-16 07:07:07 -04001349#Line # hints at Layer size limit ##
Cary Clarkce101242017-09-01 15:51:02 -04001350 fBounds is used as a hint to limit the size of Layer; may be nullptr.
1351 fBounds suggests but does not define Layer size. To clip drawing to
1352 a specific rectangle, use clipRect.
1353##
1354
1355#Member const SkPaint* fPaint
Cary Clark682c58d2018-05-16 07:07:07 -04001356#Line # modifies overlay ##
Cary Clarkce101242017-09-01 15:51:02 -04001357 fPaint modifies how Layer overlays the prior Layer; may be nullptr.
1358 Color_Alpha, Blend_Mode, Color_Filter, Draw_Looper, Image_Filter, and
1359 Mask_Filter affect Layer draw.
1360##
1361
1362#Member const SkImageFilter* fBackdrop
Cary Clark682c58d2018-05-16 07:07:07 -04001363#Line # applies Image_Filter to prior Layer ##
Cary Clarkce101242017-09-01 15:51:02 -04001364 fBackdrop applies Image_Filter to the prior Layer when copying to the Layer;
1365 may be nullptr. Use kInitWithPrevious_SaveLayerFlag to copy the
1366 prior Layer without an Image_Filter.
1367##
1368
1369#Member const SkImage* fClipMask
Cary Clark682c58d2018-05-16 07:07:07 -04001370#Line # clips Layer with Mask_Alpha ##
Cary Clarkce101242017-09-01 15:51:02 -04001371 restore() clips Layer by the Color_Alpha channel of fClipMask when
1372 Layer is copied to Device. fClipMask may be nullptr. .
1373##
1374
1375#Member const SkMatrix* fClipMatrix
Cary Clark682c58d2018-05-16 07:07:07 -04001376#Line # transforms Mask_Alpha used to clip ##
Herb Derbyefe39bc2018-05-01 17:06:20 -04001377 fClipMatrix transforms fClipMask before it clips Layer. If
Cary Clarkce101242017-09-01 15:51:02 -04001378 fClipMask describes a translucent gradient, it may be scaled and rotated
1379 without introducing artifacts. fClipMatrix may be nullptr.
1380##
1381
1382#Member SaveLayerFlags fSaveLayerFlags
Mike Reed9a229e92019-01-08 10:52:52 -05001383#Line # creates with prior Layer contents ##
Cary Clarkce101242017-09-01 15:51:02 -04001384 fSaveLayerFlags are used to create Layer without transparency,
Mike Reed9a229e92019-01-08 10:52:52 -05001385 and to create Layer with the ontents of the previous Layer.
Cary Clarkce101242017-09-01 15:51:02 -04001386##
1387
1388#Example
1389#Height 160
1390#Description
Cary Clarkffb3d682018-05-17 12:17:28 -04001391Canvas Layer captures a red Anti_Aliased circle and a blue Aliased circle scaled
Cary Clarkce101242017-09-01 15:51:02 -04001392up by four. After drawing another red circle without scaling on top, the Layer is
Herb Derbyefe39bc2018-05-01 17:06:20 -04001393transferred to the main canvas.
Cary Clarkce101242017-09-01 15:51:02 -04001394##
1395void draw(SkCanvas* canvas) {
1396 SkPaint redPaint, bluePaint;
1397 redPaint.setAntiAlias(true);
1398 redPaint.setColor(SK_ColorRED);
1399 canvas->drawCircle(21, 21, 8, redPaint);
1400 bluePaint.setColor(SK_ColorBLUE);
1401 canvas->drawCircle(31, 21, 8, bluePaint);
1402 SkMatrix matrix;
1403 matrix.setScale(4, 4);
1404 auto scaler = SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr);
Herb Derbyefe39bc2018-05-01 17:06:20 -04001405 SkCanvas::SaveLayerRec saveLayerRec(nullptr, nullptr, scaler.get(), 0);
Cary Clarkce101242017-09-01 15:51:02 -04001406 canvas->saveLayer(saveLayerRec);
1407 canvas->drawCircle(125, 85, 8, redPaint);
1408 canvas->restore();
1409}
1410##
1411
Cary Clark61313f32018-10-08 14:57:48 -04001412#Subtopic Constructors
Cary Clark682c58d2018-05-16 07:07:07 -04001413##
Cary Clarkce101242017-09-01 15:51:02 -04001414
Cary Clark682c58d2018-05-16 07:07:07 -04001415#Method SaveLayerRec()
1416#Line # constructs SaveLayerRec ##
Cary Clark09d80c02018-10-31 12:14:03 -04001417#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001418
1419#Example
1420 SkCanvas::SaveLayerRec rec1;
Mike Reed9a229e92019-01-08 10:52:52 -05001421 rec1.fSaveLayerFlags = SkCanvas::kInitWithPrevious_SaveLayerFlag;
1422 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, SkCanvas::kInitWithPrevious_SaveLayerFlag);
Cary Clarkce101242017-09-01 15:51:02 -04001423 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1424 && rec1.fPaint == rec2.fPaint
1425 && rec1.fBackdrop == rec2.fBackdrop
1426 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1427 #StdOut
1428 rec1 == rec2
1429 ##
1430##
1431
Mike Reed9a229e92019-01-08 10:52:52 -05001432#SeeAlso save restore saveLayer saveLayerAlpha
Cary Clark2ade9972017-11-02 17:49:34 -04001433
Cary Clarkce101242017-09-01 15:51:02 -04001434##
1435
Cary Clark224c7002018-06-27 11:00:21 -04001436#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
Cary Clark09d80c02018-10-31 12:14:03 -04001437#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001438
1439#Example
1440 SkCanvas::SaveLayerRec rec1;
1441 SkCanvas::SaveLayerRec rec2(nullptr, nullptr);
1442 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1443 && rec1.fPaint == rec2.fPaint
1444 && rec1.fBackdrop == rec2.fBackdrop
1445 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1446 #StdOut
1447 rec1 == rec2
1448 ##
1449##
1450
Mike Reed9a229e92019-01-08 10:52:52 -05001451#SeeAlso save restore saveLayer saveLayerAlpha
Cary Clark2ade9972017-11-02 17:49:34 -04001452
Cary Clarkce101242017-09-01 15:51:02 -04001453##
1454
1455#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
1456 SaveLayerFlags saveLayerFlags)
Cary Clark09d80c02018-10-31 12:14:03 -04001457#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001458
1459#Example
1460 SkCanvas::SaveLayerRec rec1;
1461 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, nullptr, 0);
1462 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1463 && rec1.fPaint == rec2.fPaint
1464 && rec1.fBackdrop == rec2.fBackdrop
1465 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1466 #StdOut
1467 rec1 == rec2
1468 ##
1469##
1470
Mike Reed9a229e92019-01-08 10:52:52 -05001471#SeeAlso save restore saveLayer saveLayerAlpha
Cary Clark2ade9972017-11-02 17:49:34 -04001472
Cary Clarkce101242017-09-01 15:51:02 -04001473##
1474
Cary Clarkce101242017-09-01 15:51:02 -04001475#Struct ##
1476
Cary Clark682c58d2018-05-16 07:07:07 -04001477#Subtopic ##
1478
Cary Clarkce101242017-09-01 15:51:02 -04001479#Method int saveLayer(const SaveLayerRec& layerRec)
1480
Cary Clarkab2621d2018-01-30 10:08:57 -05001481#In Layer
Cary Clark09d80c02018-10-31 12:14:03 -04001482#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001483
1484#Example
1485#Description
1486The example draws an image, and saves it into a Layer with kInitWithPrevious_SaveLayerFlag.
1487Next it punches a hole in Layer and restore with SkBlendMode::kPlus.
1488Where Layer was cleared, the original image will draw unchanged.
1489Outside of the circle the mandrill is brightened.
1490##
1491 #Image 3
Hal Canaryc465d132017-12-08 10:21:31 -05001492 // sk_sp<SkImage> image = GetResourceAsImage("images/mandrill_256.png");
Cary Clarkce101242017-09-01 15:51:02 -04001493 canvas->drawImage(image, 0, 0, nullptr);
1494 SkCanvas::SaveLayerRec rec;
1495 SkPaint paint;
1496 paint.setBlendMode(SkBlendMode::kPlus);
1497 rec.fSaveLayerFlags = SkCanvas::kInitWithPrevious_SaveLayerFlag;
1498 rec.fPaint = &paint;
1499 canvas->saveLayer(rec);
1500 paint.setBlendMode(SkBlendMode::kClear);
1501 canvas->drawCircle(128, 128, 96, paint);
1502 canvas->restore();
1503##
1504
1505#ToDo above example needs to replace GetResourceAsImage with way to select image in fiddle ##
1506
Mike Reed9a229e92019-01-08 10:52:52 -05001507#SeeAlso save restore saveLayer saveLayerAlpha
Cary Clark2ade9972017-11-02 17:49:34 -04001508
Cary Clarkce101242017-09-01 15:51:02 -04001509##
1510
Cary Clark08895c42018-02-01 09:37:32 -05001511#Subtopic Layer ##
Cary Clarkce101242017-09-01 15:51:02 -04001512
1513# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001514#Subtopic Matrix
1515#Line # coordinate transformation ##
Cary Clark8032b982017-07-28 11:04:54 -04001516
1517#Method void translate(SkScalar dx, SkScalar dy)
1518
Cary Clarkab2621d2018-01-30 10:08:57 -05001519#In Matrix
1520#Line # translates Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001521#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001522
1523#Example
1524#Height 128
1525#Description
1526scale() followed by translate() produces different results from translate() followed
Herb Derbyefe39bc2018-05-01 17:06:20 -04001527by scale().
Cary Clark8032b982017-07-28 11:04:54 -04001528
1529The blue stroke follows translate of (50, 50); a black
Herb Derbyefe39bc2018-05-01 17:06:20 -04001530fill follows scale of (2, 1/2.f). After restoring the clip, which resets
Cary Clark8032b982017-07-28 11:04:54 -04001531Matrix, a red frame follows the same scale of (2, 1/2.f); a gray fill
1532follows translate of (50, 50).
1533##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001534void draw(SkCanvas* canvas) {
1535 SkPaint filledPaint;
1536 SkPaint outlinePaint;
1537 outlinePaint.setStyle(SkPaint::kStroke_Style);
1538 outlinePaint.setColor(SK_ColorBLUE);
1539 canvas->save();
1540 canvas->translate(50, 50);
1541 canvas->drawCircle(28, 28, 15, outlinePaint); // blue center: (50+28, 50+28)
1542 canvas->scale(2, 1/2.f);
1543 canvas->drawCircle(28, 28, 15, filledPaint); // black center: (50+(28*2), 50+(28/2))
1544 canvas->restore();
1545 filledPaint.setColor(SK_ColorGRAY);
1546 outlinePaint.setColor(SK_ColorRED);
1547 canvas->scale(2, 1/2.f);
1548 canvas->drawCircle(28, 28, 15, outlinePaint); // red center: (28*2, 28/2)
1549 canvas->translate(50, 50);
1550 canvas->drawCircle(28, 28, 15, filledPaint); // gray center: ((50+28)*2, (50+28)/2)
Cary Clark8032b982017-07-28 11:04:54 -04001551}
1552##
1553
Cary Clark2ade9972017-11-02 17:49:34 -04001554#SeeAlso concat() scale() skew() rotate() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001555
1556##
1557
1558# ------------------------------------------------------------------------------
1559
1560#Method void scale(SkScalar sx, SkScalar sy)
1561
Cary Clarkab2621d2018-01-30 10:08:57 -05001562#In Matrix
1563#Line # scales Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001564#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001565
1566#Example
1567#Height 160
Cary Clarkbad5ad72017-08-03 17:14:08 -04001568void draw(SkCanvas* canvas) {
1569 SkPaint paint;
1570 SkRect rect = { 10, 20, 60, 120 };
1571 canvas->translate(20, 20);
1572 canvas->drawRect(rect, paint);
1573 canvas->scale(2, .5f);
1574 paint.setColor(SK_ColorGRAY);
1575 canvas->drawRect(rect, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001576}
1577##
1578
Cary Clark2ade9972017-11-02 17:49:34 -04001579#SeeAlso concat() translate() skew() rotate() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001580
1581##
1582
1583# ------------------------------------------------------------------------------
1584
1585#Method void rotate(SkScalar degrees)
1586
Cary Clarkab2621d2018-01-30 10:08:57 -05001587#In Matrix
1588#Line # rotates Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001589#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001590
1591#Example
1592#Description
1593Draw clock hands at time 5:10. The hour hand and minute hand point up and
1594are rotated clockwise.
1595##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001596void draw(SkCanvas* canvas) {
1597 SkPaint paint;
1598 paint.setStyle(SkPaint::kStroke_Style);
1599 canvas->translate(128, 128);
1600 canvas->drawCircle(0, 0, 60, paint);
1601 canvas->save();
1602 canvas->rotate(10 * 360 / 60); // 10 minutes of 60 scaled to 360 degrees
Herb Derbyefe39bc2018-05-01 17:06:20 -04001603 canvas->drawLine(0, 0, 0, -50, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001604 canvas->restore();
1605 canvas->rotate((5 + 10.f/60) * 360 / 12); // 5 and 10/60 hours of 12 scaled to 360 degrees
1606 canvas->drawLine(0, 0, 0, -30, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001607}
1608##
1609
Cary Clark2ade9972017-11-02 17:49:34 -04001610#SeeAlso concat() translate() skew() scale() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001611
1612##
1613
1614# ------------------------------------------------------------------------------
1615
1616#Method void rotate(SkScalar degrees, SkScalar px, SkScalar py)
1617
Cary Clarkab2621d2018-01-30 10:08:57 -05001618#In Matrix
Cary Clark09d80c02018-10-31 12:14:03 -04001619#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001620
1621#Example
1622#Height 192
Cary Clarkbad5ad72017-08-03 17:14:08 -04001623void draw(SkCanvas* canvas) {
1624 SkPaint paint;
Mike Reed33535cb2019-01-09 11:25:18 -05001625 SkFont font(nullptr, 96);
1626 canvas->drawString("A1", 130, 100, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001627 canvas->rotate(180, 130, 100);
Mike Reed33535cb2019-01-09 11:25:18 -05001628 canvas->drawString("A1", 130, 100, font, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001629}
1630##
1631
Cary Clark2ade9972017-11-02 17:49:34 -04001632#SeeAlso concat() translate() skew() scale() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001633
1634##
1635
1636# ------------------------------------------------------------------------------
1637
1638#Method void skew(SkScalar sx, SkScalar sy)
1639
Cary Clarkab2621d2018-01-30 10:08:57 -05001640#In Matrix
1641#Line # skews Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001642#Populate
Cary Clarkbad5ad72017-08-03 17:14:08 -04001643
Cary Clark8032b982017-07-28 11:04:54 -04001644#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04001645 #Description
Cary Clark5538c132018-06-14 12:28:14 -04001646 Black text mimics an oblique text style by using a negative skew on x-axis
1647 that shifts the geometry to the right as the y-axis values decrease.
1648 Red text uses a positive skew on y-axis to shift the geometry down
1649 as the x-axis values increase.
1650 Blue text combines sx and sy skew to rotate and scale.
Cary Clark8032b982017-07-28 11:04:54 -04001651 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001652 SkPaint paint;
Mike Reed33535cb2019-01-09 11:25:18 -05001653 SkFont font(nullptr, 128);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001654 canvas->translate(30, 130);
1655 canvas->save();
1656 canvas->skew(-.5, 0);
Mike Reed33535cb2019-01-09 11:25:18 -05001657 canvas->drawString("A1", 0, 0, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001658 canvas->restore();
1659 canvas->save();
1660 canvas->skew(0, .5);
1661 paint.setColor(SK_ColorRED);
Mike Reed33535cb2019-01-09 11:25:18 -05001662 canvas->drawString("A1", 0, 0, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001663 canvas->restore();
1664 canvas->skew(-.5, .5);
1665 paint.setColor(SK_ColorBLUE);
Mike Reed33535cb2019-01-09 11:25:18 -05001666 canvas->drawString("A1", 0, 0, font, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001667##
1668
Cary Clark2ade9972017-11-02 17:49:34 -04001669#SeeAlso concat() translate() rotate() scale() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001670
1671##
1672
1673# ------------------------------------------------------------------------------
1674
1675#Method void concat(const SkMatrix& matrix)
1676
Cary Clarkab2621d2018-01-30 10:08:57 -05001677#In Matrix
1678#Line # multiplies Matrix by Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001679#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001680
1681#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001682void draw(SkCanvas* canvas) {
1683 SkPaint paint;
Mike Reed33535cb2019-01-09 11:25:18 -05001684 SkFont font(nullptr, 80);
1685 font.setScaleX(.3);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001686 SkMatrix matrix;
1687 SkRect rect[2] = {{ 10, 20, 90, 110 }, { 40, 130, 140, 180 }};
1688 matrix.setRectToRect(rect[0], rect[1], SkMatrix::kFill_ScaleToFit);
1689 canvas->drawRect(rect[0], paint);
1690 canvas->drawRect(rect[1], paint);
1691 paint.setColor(SK_ColorWHITE);
Mike Reed33535cb2019-01-09 11:25:18 -05001692 canvas->drawString("Here", rect[0].fLeft + 10, rect[0].fBottom - 10, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001693 canvas->concat(matrix);
Mike Reed33535cb2019-01-09 11:25:18 -05001694 canvas->drawString("There", rect[0].fLeft + 10, rect[0].fBottom - 10, font, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001695}
1696##
1697
Cary Clark2ade9972017-11-02 17:49:34 -04001698#SeeAlso translate() rotate() scale() skew() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001699
1700##
1701
1702# ------------------------------------------------------------------------------
1703
1704#Method void setMatrix(const SkMatrix& matrix)
1705
Cary Clarkab2621d2018-01-30 10:08:57 -05001706#In Matrix
1707#Line # sets Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001708#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001709
1710#Example
1711#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001712void draw(SkCanvas* canvas) {
1713 SkPaint paint;
Mike Reed33535cb2019-01-09 11:25:18 -05001714 SkFont font;
Cary Clarkbad5ad72017-08-03 17:14:08 -04001715 canvas->scale(4, 6);
Mike Reed33535cb2019-01-09 11:25:18 -05001716 canvas->drawString("truth", 2, 10, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001717 SkMatrix matrix;
1718 matrix.setScale(2.8f, 6);
1719 canvas->setMatrix(matrix);
Mike Reed33535cb2019-01-09 11:25:18 -05001720 canvas->drawString("consequences", 2, 20, font, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001721}
1722##
1723
Cary Clark2ade9972017-11-02 17:49:34 -04001724#SeeAlso resetMatrix concat() translate() rotate() scale() skew()
Cary Clark8032b982017-07-28 11:04:54 -04001725
1726##
1727
1728# ------------------------------------------------------------------------------
1729
1730#Method void resetMatrix()
1731
Cary Clarkab2621d2018-01-30 10:08:57 -05001732#In Matrix
1733#Line # resets Matrix to identity ##
Cary Clark09d80c02018-10-31 12:14:03 -04001734#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001735
1736#Example
1737#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001738void draw(SkCanvas* canvas) {
1739 SkPaint paint;
Mike Reed33535cb2019-01-09 11:25:18 -05001740 SkFont font;
Cary Clarkbad5ad72017-08-03 17:14:08 -04001741 canvas->scale(4, 6);
Mike Reed33535cb2019-01-09 11:25:18 -05001742 canvas->drawString("truth", 2, 10, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001743 canvas->resetMatrix();
1744 canvas->scale(2.8f, 6);
Mike Reed33535cb2019-01-09 11:25:18 -05001745 canvas->drawString("consequences", 2, 20, font, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001746}
1747##
1748
Cary Clark2ade9972017-11-02 17:49:34 -04001749#SeeAlso setMatrix concat() translate() rotate() scale() skew()
Cary Clark8032b982017-07-28 11:04:54 -04001750
1751##
1752
1753# ------------------------------------------------------------------------------
1754
1755#Method const SkMatrix& getTotalMatrix() const
1756
Cary Clarkab2621d2018-01-30 10:08:57 -05001757#In Matrix
1758#Line # returns Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001759#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001760
1761#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001762 SkDebugf("isIdentity %s\n", canvas->getTotalMatrix().isIdentity() ? "true" : "false");
1763 #StdOut
1764 isIdentity true
1765 ##
Cary Clark8032b982017-07-28 11:04:54 -04001766##
1767
Cary Clark2ade9972017-11-02 17:49:34 -04001768#SeeAlso setMatrix resetMatrix concat()
Cary Clark8032b982017-07-28 11:04:54 -04001769
1770##
1771
Cary Clark08895c42018-02-01 09:37:32 -05001772#Subtopic Matrix ##
Cary Clark8032b982017-07-28 11:04:54 -04001773
1774# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001775#Subtopic Clip
1776#Line # stack of clipping Paths ##
Cary Clark8032b982017-07-28 11:04:54 -04001777
1778Clip is built from a stack of clipping paths. Each Path in the
Herb Derbyefe39bc2018-05-01 17:06:20 -04001779stack can be constructed from one or more Path_Contour elements. The
Cary Clark8032b982017-07-28 11:04:54 -04001780Path_Contour may be composed of any number of Path_Verb segments. Each
1781Path_Contour forms a closed area; Path_Fill_Type defines the area enclosed
1782by Path_Contour.
1783
1784Clip stack of Path elements successfully restrict the Path area. Each
Herb Derbyefe39bc2018-05-01 17:06:20 -04001785Path is transformed by Matrix, then intersected with or subtracted from the
Cary Clark8032b982017-07-28 11:04:54 -04001786prior Clip to form the replacement Clip. Use SkClipOp::kDifference
1787to subtract Path from Clip; use SkClipOp::kIntersect to intersect Path
1788with Clip.
1789
Cary Clarkffb3d682018-05-17 12:17:28 -04001790A clipping Path may be Anti_Aliased; if Path, after transformation, is
1791composed of horizontal and vertical lines, clearing Anti_Alias allows whole pixels
Cary Clarkce101242017-09-01 15:51:02 -04001792to either be inside or outside the clip. The fastest drawing has a Aliased,
1793rectangular clip.
Cary Clark8032b982017-07-28 11:04:54 -04001794
Cary Clarkffb3d682018-05-17 12:17:28 -04001795If clipping Path has Anti_Alias set, clip may partially clip a pixel, requiring
Herb Derbyefe39bc2018-05-01 17:06:20 -04001796that drawing blend partially with the destination along the edge. A rotated
Cary Clarkffb3d682018-05-17 12:17:28 -04001797rectangular Anti_Aliased clip looks smoother but draws slower.
Cary Clark8032b982017-07-28 11:04:54 -04001798
1799Clip can combine with Rect and Round_Rect primitives; like
1800Path, these are transformed by Matrix before they are combined with Clip.
1801
1802Clip can combine with Region. Region is assumed to be in Device coordinates
1803and is unaffected by Matrix.
1804
1805#Example
1806#Height 90
1807 #Description
Cary Clarkffb3d682018-05-17 12:17:28 -04001808 Draw a red circle with an Aliased clip and an Anti_Aliased clip.
Cary Clark8032b982017-07-28 11:04:54 -04001809 Use an image filter to zoom into the pixels drawn.
Cary Clarkce101242017-09-01 15:51:02 -04001810 The edge of the Aliased clip fully draws pixels in the red circle.
Cary Clarkffb3d682018-05-17 12:17:28 -04001811 The edge of the Anti_Aliased clip partially draws pixels in the red circle.
Cary Clark8032b982017-07-28 11:04:54 -04001812 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001813 SkPaint redPaint, scalePaint;
1814 redPaint.setAntiAlias(true);
1815 redPaint.setColor(SK_ColorRED);
1816 canvas->save();
1817 for (bool antialias : { false, true } ) {
1818 canvas->save();
1819 canvas->clipRect(SkRect::MakeWH(19.5f, 11.5f), antialias);
1820 canvas->drawCircle(17, 11, 8, redPaint);
1821 canvas->restore();
1822 canvas->translate(16, 0);
1823 }
1824 canvas->restore();
1825 SkMatrix matrix;
1826 matrix.setScale(6, 6);
1827 scalePaint.setImageFilter(
1828 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
1829 SkCanvas::SaveLayerRec saveLayerRec(
Herb Derbyefe39bc2018-05-01 17:06:20 -04001830 nullptr, &scalePaint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001831 canvas->saveLayer(saveLayerRec);
Cary Clark8032b982017-07-28 11:04:54 -04001832 canvas->restore();
1833##
1834
1835#Method void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias)
1836
Cary Clarkab2621d2018-01-30 10:08:57 -05001837#In Clip
1838#Line # combines Clip with Rect ##
Cary Clark09d80c02018-10-31 12:14:03 -04001839#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001840
1841#Example
1842#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001843void draw(SkCanvas* canvas) {
1844 canvas->rotate(10);
1845 SkPaint paint;
1846 paint.setAntiAlias(true);
1847 for (auto alias: { false, true } ) {
1848 canvas->save();
1849 canvas->clipRect(SkRect::MakeWH(90, 80), SkClipOp::kIntersect, alias);
1850 canvas->drawCircle(100, 60, 60, paint);
1851 canvas->restore();
1852 canvas->translate(80, 0);
1853 }
Cary Clark8032b982017-07-28 11:04:54 -04001854}
1855##
1856
Cary Clark2ade9972017-11-02 17:49:34 -04001857#SeeAlso clipRRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001858
1859##
1860
Herb Derbyefe39bc2018-05-01 17:06:20 -04001861#Method void clipRect(const SkRect& rect, SkClipOp op)
Cary Clark8032b982017-07-28 11:04:54 -04001862
Cary Clarkab2621d2018-01-30 10:08:57 -05001863#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04001864#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001865
1866#Example
1867#Height 192
1868#Width 280
Cary Clarkbad5ad72017-08-03 17:14:08 -04001869void draw(SkCanvas* canvas) {
1870 SkPaint paint;
1871 for (SkClipOp op: { SkClipOp::kIntersect, SkClipOp::kDifference } ) {
1872 canvas->save();
1873 canvas->clipRect(SkRect::MakeWH(90, 120), op, false);
1874 canvas->drawCircle(100, 100, 60, paint);
1875 canvas->restore();
1876 canvas->translate(80, 0);
1877 }
Cary Clark8032b982017-07-28 11:04:54 -04001878}
1879##
1880
Cary Clark2ade9972017-11-02 17:49:34 -04001881#SeeAlso clipRRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001882
1883##
1884
Herb Derbyefe39bc2018-05-01 17:06:20 -04001885#Method void clipRect(const SkRect& rect, bool doAntiAlias = false)
Cary Clark8032b982017-07-28 11:04:54 -04001886
Cary Clarkab2621d2018-01-30 10:08:57 -05001887#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04001888#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001889
1890#Example
1891#Height 133
1892 #Description
Cary Clarkce101242017-09-01 15:51:02 -04001893 A circle drawn in pieces looks uniform when drawn Aliased.
Cary Clarkffb3d682018-05-17 12:17:28 -04001894 The same circle pieces blend with pixels more than once when Anti_Aliased,
Cary Clark8032b982017-07-28 11:04:54 -04001895 visible as a thin pair of lines through the right circle.
1896 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001897void draw(SkCanvas* canvas) {
1898 canvas->clear(SK_ColorWHITE);
1899 SkPaint paint;
1900 paint.setAntiAlias(true);
1901 paint.setColor(0x8055aaff);
1902 SkRect clipRect = { 0, 0, 87.4f, 87.4f };
1903 for (auto alias: { false, true } ) {
1904 canvas->save();
1905 canvas->clipRect(clipRect, SkClipOp::kIntersect, alias);
1906 canvas->drawCircle(67, 67, 60, paint);
1907 canvas->restore();
1908 canvas->save();
1909 canvas->clipRect(clipRect, SkClipOp::kDifference, alias);
1910 canvas->drawCircle(67, 67, 60, paint);
1911 canvas->restore();
1912 canvas->translate(120, 0);
1913 }
Cary Clark8032b982017-07-28 11:04:54 -04001914}
1915##
1916
Cary Clark2ade9972017-11-02 17:49:34 -04001917#SeeAlso clipRRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001918
1919##
1920
Cary Clark8032b982017-07-28 11:04:54 -04001921#Method void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias)
1922
Cary Clarkab2621d2018-01-30 10:08:57 -05001923#In Clip
1924#Line # combines Clip with Round_Rect ##
Cary Clark09d80c02018-10-31 12:14:03 -04001925#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001926
1927#Example
1928#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001929void draw(SkCanvas* canvas) {
1930 canvas->clear(SK_ColorWHITE);
1931 SkPaint paint;
1932 paint.setAntiAlias(true);
1933 paint.setColor(0x8055aaff);
1934 SkRRect oval;
1935 oval.setOval({10, 20, 90, 100});
1936 canvas->clipRRect(oval, SkClipOp::kIntersect, true);
1937 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001938}
1939##
1940
Cary Clark2ade9972017-11-02 17:49:34 -04001941#SeeAlso clipRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001942
1943##
1944
Herb Derbyefe39bc2018-05-01 17:06:20 -04001945#Method void clipRRect(const SkRRect& rrect, SkClipOp op)
Cary Clark8032b982017-07-28 11:04:54 -04001946
Cary Clarkab2621d2018-01-30 10:08:57 -05001947#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04001948#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001949
1950#Example
1951#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001952void draw(SkCanvas* canvas) {
1953 SkPaint paint;
1954 paint.setColor(0x8055aaff);
1955 auto oval = SkRRect::MakeOval({10, 20, 90, 100});
1956 canvas->clipRRect(oval, SkClipOp::kIntersect);
1957 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001958}
1959##
1960
Cary Clark2ade9972017-11-02 17:49:34 -04001961#SeeAlso clipRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001962
1963##
1964
Herb Derbyefe39bc2018-05-01 17:06:20 -04001965#Method void clipRRect(const SkRRect& rrect, bool doAntiAlias = false)
Cary Clark8032b982017-07-28 11:04:54 -04001966
Cary Clarkab2621d2018-01-30 10:08:57 -05001967#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04001968#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001969
1970#Example
1971#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001972void draw(SkCanvas* canvas) {
1973 SkPaint paint;
1974 paint.setAntiAlias(true);
1975 auto oval = SkRRect::MakeRectXY({10, 20, 90, 100}, 9, 13);
1976 canvas->clipRRect(oval, true);
1977 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001978}
1979##
1980
Cary Clark2ade9972017-11-02 17:49:34 -04001981#SeeAlso clipRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001982
1983##
1984
1985#Method void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias)
1986
Cary Clarkab2621d2018-01-30 10:08:57 -05001987#In Clip
1988#Line # combines Clip with Path ##
Cary Clark09d80c02018-10-31 12:14:03 -04001989#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001990
1991#Example
1992#Description
1993Top figure uses SkPath::kInverseWinding_FillType and SkClipOp::kDifference;
1994area outside clip is subtracted from circle.
1995
1996Bottom figure uses SkPath::kWinding_FillType and SkClipOp::kIntersect;
1997area inside clip is intersected with circle.
1998##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001999void draw(SkCanvas* canvas) {
2000 SkPaint paint;
2001 paint.setAntiAlias(true);
2002 SkPath path;
2003 path.addRect({20, 30, 100, 110});
2004 path.setFillType(SkPath::kInverseWinding_FillType);
2005 canvas->save();
2006 canvas->clipPath(path, SkClipOp::kDifference, false);
2007 canvas->drawCircle(70, 100, 60, paint);
2008 canvas->restore();
2009 canvas->translate(100, 100);
2010 path.setFillType(SkPath::kWinding_FillType);
2011 canvas->clipPath(path, SkClipOp::kIntersect, false);
2012 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002013}
2014##
2015
Cary Clark2ade9972017-11-02 17:49:34 -04002016#SeeAlso clipRect clipRRect clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04002017
2018##
2019
Herb Derbyefe39bc2018-05-01 17:06:20 -04002020#Method void clipPath(const SkPath& path, SkClipOp op)
Cary Clark8032b982017-07-28 11:04:54 -04002021
Cary Clarkab2621d2018-01-30 10:08:57 -05002022#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002023#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002024
2025#Example
2026#Description
Cary Clarkbc5697d2017-10-04 14:31:33 -04002027Overlapping Rects form a clip. When clip Path_Fill_Type is set to
Herb Derbyefe39bc2018-05-01 17:06:20 -04002028SkPath::kWinding_FillType, the overlap is included. Set to
Cary Clark8032b982017-07-28 11:04:54 -04002029SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
2030##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002031void draw(SkCanvas* canvas) {
2032 SkPaint paint;
2033 paint.setAntiAlias(true);
2034 SkPath path;
2035 path.addRect({20, 15, 100, 95});
2036 path.addRect({50, 65, 130, 135});
2037 path.setFillType(SkPath::kWinding_FillType);
2038 canvas->save();
2039 canvas->clipPath(path, SkClipOp::kIntersect);
2040 canvas->drawCircle(70, 85, 60, paint);
2041 canvas->restore();
2042 canvas->translate(100, 100);
2043 path.setFillType(SkPath::kEvenOdd_FillType);
2044 canvas->clipPath(path, SkClipOp::kIntersect);
2045 canvas->drawCircle(70, 85, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002046}
2047##
2048
Cary Clark2ade9972017-11-02 17:49:34 -04002049#SeeAlso clipRect clipRRect clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04002050
2051##
2052
Herb Derbyefe39bc2018-05-01 17:06:20 -04002053#Method void clipPath(const SkPath& path, bool doAntiAlias = false)
Cary Clark8032b982017-07-28 11:04:54 -04002054
Cary Clarkab2621d2018-01-30 10:08:57 -05002055#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002056#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002057
2058#Example
2059#Height 212
2060#Description
Herb Derbyefe39bc2018-05-01 17:06:20 -04002061Clip loops over itself covering its center twice. When clip Path_Fill_Type
2062is set to SkPath::kWinding_FillType, the overlap is included. Set to
Cary Clark8032b982017-07-28 11:04:54 -04002063SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
2064##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002065void draw(SkCanvas* canvas) {
2066 SkPaint paint;
2067 paint.setAntiAlias(true);
2068 SkPath path;
2069 SkPoint poly[] = {{20, 20}, { 80, 20}, { 80, 80}, {40, 80},
2070 {40, 40}, {100, 40}, {100, 100}, {20, 100}};
2071 path.addPoly(poly, SK_ARRAY_COUNT(poly), true);
2072 path.setFillType(SkPath::kWinding_FillType);
2073 canvas->save();
2074 canvas->clipPath(path, SkClipOp::kIntersect);
2075 canvas->drawCircle(50, 50, 45, paint);
2076 canvas->restore();
2077 canvas->translate(100, 100);
2078 path.setFillType(SkPath::kEvenOdd_FillType);
2079 canvas->clipPath(path, SkClipOp::kIntersect);
2080 canvas->drawCircle(50, 50, 45, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002081}
2082##
2083
Cary Clark2ade9972017-11-02 17:49:34 -04002084#SeeAlso clipRect clipRRect clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04002085
2086##
2087
2088# ------------------------------------------------------------------------------
2089
Cary Clark8032b982017-07-28 11:04:54 -04002090#Method void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect)
2091
Cary Clarkab2621d2018-01-30 10:08:57 -05002092#In Clip
2093#Line # combines Clip with Region ##
Cary Clark09d80c02018-10-31 12:14:03 -04002094#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002095
2096#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002097#Description
Cary Clarkce101242017-09-01 15:51:02 -04002098 region is unaffected by canvas rotation; iRect is affected by canvas rotation.
2099 Both clips are Aliased; this is not noticeable on Region clip because it
Cary Clarkbad5ad72017-08-03 17:14:08 -04002100 aligns to pixel boundaries.
2101##
2102void draw(SkCanvas* canvas) {
2103 SkPaint paint;
2104 paint.setAntiAlias(true);
2105 SkIRect iRect = {30, 40, 120, 130 };
2106 SkRegion region(iRect);
2107 canvas->rotate(10);
2108 canvas->save();
2109 canvas->clipRegion(region, SkClipOp::kIntersect);
2110 canvas->drawCircle(50, 50, 45, paint);
2111 canvas->restore();
2112 canvas->translate(100, 100);
2113 canvas->clipRect(SkRect::Make(iRect), SkClipOp::kIntersect);
2114 canvas->drawCircle(50, 50, 45, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002115}
2116##
2117
Cary Clark2ade9972017-11-02 17:49:34 -04002118#SeeAlso clipRect clipRRect clipPath
Cary Clark8032b982017-07-28 11:04:54 -04002119
2120##
2121
2122#Method bool quickReject(const SkRect& rect) const
2123
Cary Clarkab2621d2018-01-30 10:08:57 -05002124#In Clip
2125#Line # returns if Rect is outside Clip ##
Cary Clark09d80c02018-10-31 12:14:03 -04002126#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002127
2128#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002129void draw(SkCanvas* canvas) {
Herb Derbyefe39bc2018-05-01 17:06:20 -04002130 SkRect testRect = {30, 30, 120, 129 };
2131 SkRect clipRect = {30, 130, 120, 230 };
Cary Clarkbad5ad72017-08-03 17:14:08 -04002132 canvas->save();
2133 canvas->clipRect(clipRect);
2134 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
2135 canvas->restore();
2136 canvas->rotate(10);
2137 canvas->clipRect(clipRect);
2138 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
Cary Clark8032b982017-07-28 11:04:54 -04002139}
2140 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002141 quickReject true
Cary Clark8032b982017-07-28 11:04:54 -04002142 quickReject false
2143 ##
2144##
2145
Cary Clark2ade9972017-11-02 17:49:34 -04002146#SeeAlso getLocalClipBounds getTotalMatrix SkBitmap::drawsNothing
Cary Clark8032b982017-07-28 11:04:54 -04002147
2148##
2149
2150#Method bool quickReject(const SkPath& path) const
2151
Cary Clarkab2621d2018-01-30 10:08:57 -05002152#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002153#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002154
2155#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002156void draw(SkCanvas* canvas) {
Herb Derbyefe39bc2018-05-01 17:06:20 -04002157 SkPoint testPoints[] = {{30, 30}, {120, 30}, {120, 129} };
2158 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
Cary Clarkbad5ad72017-08-03 17:14:08 -04002159 SkPath testPath, clipPath;
2160 testPath.addPoly(testPoints, SK_ARRAY_COUNT(testPoints), true);
2161 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2162 canvas->save();
2163 canvas->clipPath(clipPath);
2164 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
2165 canvas->restore();
2166 canvas->rotate(10);
2167 canvas->clipPath(clipPath);
2168 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
Cary Clark8032b982017-07-28 11:04:54 -04002169 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002170 quickReject true
Cary Clark8032b982017-07-28 11:04:54 -04002171 quickReject false
2172 ##
2173}
2174##
2175
Cary Clark2ade9972017-11-02 17:49:34 -04002176#SeeAlso getLocalClipBounds getTotalMatrix SkBitmap::drawsNothing
Cary Clark8032b982017-07-28 11:04:54 -04002177
2178##
2179
Herb Derbyefe39bc2018-05-01 17:06:20 -04002180#Method SkRect getLocalClipBounds() const
Cary Clark8032b982017-07-28 11:04:54 -04002181
Cary Clarkab2621d2018-01-30 10:08:57 -05002182#In Clip
2183#Line # returns Clip bounds in source coordinates ##
Cary Clark09d80c02018-10-31 12:14:03 -04002184#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002185
2186#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04002187 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002188 Initial bounds is device bounds outset by 1 on all sides.
2189 Clipped bounds is clipPath bounds outset by 1 on all sides.
Cary Clark5538c132018-06-14 12:28:14 -04002190 Scaling the canvas by two on both axes scales the local bounds by 1/2
2191 on both axes.
Cary Clark8032b982017-07-28 11:04:54 -04002192 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002193 SkCanvas local(256, 256);
2194 canvas = &local;
2195 SkRect bounds = canvas->getLocalClipBounds();
2196 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2197 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002198 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
Cary Clarkbad5ad72017-08-03 17:14:08 -04002199 SkPath clipPath;
2200 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2201 canvas->clipPath(clipPath);
2202 bounds = canvas->getLocalClipBounds();
2203 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2204 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2205 canvas->scale(2, 2);
2206 bounds = canvas->getLocalClipBounds();
2207 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2208 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2209 #StdOut
2210 left:-1 top:-1 right:257 bottom:257
2211 left:29 top:129 right:121 bottom:231
2212 left:14.5 top:64.5 right:60.5 bottom:115.5
2213 ##
Cary Clark8032b982017-07-28 11:04:54 -04002214##
2215
2216# local canvas in example works around bug in fiddle ##
Cary Clark4855f782018-02-06 09:41:53 -05002217#Bug 6524
Cary Clark2ade9972017-11-02 17:49:34 -04002218#SeeAlso getDeviceClipBounds getBaseLayerSize quickReject
Cary Clark8032b982017-07-28 11:04:54 -04002219
2220##
2221
Herb Derbyefe39bc2018-05-01 17:06:20 -04002222#Method bool getLocalClipBounds(SkRect* bounds) const
Cary Clark8032b982017-07-28 11:04:54 -04002223
Cary Clarkab2621d2018-01-30 10:08:57 -05002224#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002225#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002226
2227#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002228 void draw(SkCanvas* canvas) {
2229 SkCanvas local(256, 256);
2230 canvas = &local;
2231 SkRect bounds;
2232 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
2233 ? "false" : "true");
2234 SkPath path;
2235 canvas->clipPath(path);
2236 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
2237 ? "false" : "true");
Cary Clark8032b982017-07-28 11:04:54 -04002238 }
2239 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002240 local bounds empty = false
Cary Clark8032b982017-07-28 11:04:54 -04002241 local bounds empty = true
2242 ##
2243##
2244
2245# local canvas in example works around bug in fiddle ##
Cary Clark4855f782018-02-06 09:41:53 -05002246#Bug 6524
Cary Clark2ade9972017-11-02 17:49:34 -04002247#SeeAlso getDeviceClipBounds getBaseLayerSize quickReject
Cary Clark8032b982017-07-28 11:04:54 -04002248
2249##
2250
Herb Derbyefe39bc2018-05-01 17:06:20 -04002251#Method SkIRect getDeviceClipBounds() const
Cary Clark8032b982017-07-28 11:04:54 -04002252
Cary Clarkab2621d2018-01-30 10:08:57 -05002253#In Clip
2254#Line # returns IRect bounds of Clip ##
Cary Clark09d80c02018-10-31 12:14:03 -04002255#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002256
2257#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002258void draw(SkCanvas* canvas) {
2259 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002260 Initial bounds is device bounds, not outset.
2261 Clipped bounds is clipPath bounds, not outset.
Cary Clark5538c132018-06-14 12:28:14 -04002262 Scaling the canvas by 1/2 on both axes scales the device bounds by 1/2
2263 on both axes.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002264 ##
2265 SkCanvas device(256, 256);
2266 canvas = &device;
2267 SkIRect bounds = canvas->getDeviceClipBounds();
2268 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2269 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002270 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
Cary Clarkbad5ad72017-08-03 17:14:08 -04002271 SkPath clipPath;
2272 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2273 canvas->save();
2274 canvas->clipPath(clipPath);
2275 bounds = canvas->getDeviceClipBounds();
2276 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2277 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2278 canvas->restore();
2279 canvas->scale(1.f/2, 1.f/2);
2280 canvas->clipPath(clipPath);
2281 bounds = canvas->getDeviceClipBounds();
2282 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2283 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
Cary Clark8032b982017-07-28 11:04:54 -04002284 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002285 left:0 top:0 right:256 bottom:256
2286 left:30 top:130 right:120 bottom:230
Cary Clark8032b982017-07-28 11:04:54 -04002287 left:15 top:65 right:60 bottom:115
2288 ##
2289}
2290##
2291
2292#ToDo some confusion on why with an identity Matrix local and device are different ##
Cary Clark2ade9972017-11-02 17:49:34 -04002293#SeeAlso getLocalClipBounds getBaseLayerSize quickReject
Cary Clark8032b982017-07-28 11:04:54 -04002294
2295# device canvas in example works around bug in fiddle ##
Cary Clark4855f782018-02-06 09:41:53 -05002296#Bug 6524
Cary Clark8032b982017-07-28 11:04:54 -04002297
2298##
2299
Herb Derbyefe39bc2018-05-01 17:06:20 -04002300#Method bool getDeviceClipBounds(SkIRect* bounds) const
Cary Clark8032b982017-07-28 11:04:54 -04002301
Cary Clarkab2621d2018-01-30 10:08:57 -05002302#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002303#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002304
2305#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002306 void draw(SkCanvas* canvas) {
2307 SkIRect bounds;
2308 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
2309 ? "false" : "true");
2310 SkPath path;
2311 canvas->clipPath(path);
2312 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
2313 ? "false" : "true");
Cary Clark8032b982017-07-28 11:04:54 -04002314 }
2315 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002316 device bounds empty = false
Cary Clark8032b982017-07-28 11:04:54 -04002317 device bounds empty = true
2318 ##
2319##
2320
Cary Clark2ade9972017-11-02 17:49:34 -04002321#SeeAlso getLocalClipBounds getBaseLayerSize quickReject
Cary Clark8032b982017-07-28 11:04:54 -04002322
2323##
2324
Cary Clark08895c42018-02-01 09:37:32 -05002325#Subtopic Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002326
2327# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -05002328#Subtopic Draw
Cary Clark78de7512018-02-07 07:27:09 -05002329#Line # draws into Canvas ##
2330##
Cary Clark8032b982017-07-28 11:04:54 -04002331
2332#Method void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver)
Cary Clark78de7512018-02-07 07:27:09 -05002333#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002334#Line # fills Clip with Color and Blend_Mode ##
Cary Clark09d80c02018-10-31 12:14:03 -04002335#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002336
2337#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002338 canvas->drawColor(SK_ColorRED);
2339 canvas->clipRect(SkRect::MakeWH(150, 150));
2340 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00), SkBlendMode::kPlus);
2341 canvas->clipRect(SkRect::MakeWH(75, 75));
2342 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF), SkBlendMode::kPlus);
Cary Clark8032b982017-07-28 11:04:54 -04002343##
2344
Cary Clark2ade9972017-11-02 17:49:34 -04002345#SeeAlso clear SkBitmap::erase drawPaint
Cary Clark8032b982017-07-28 11:04:54 -04002346
2347##
2348
2349# ------------------------------------------------------------------------------
2350
Herb Derbyefe39bc2018-05-01 17:06:20 -04002351#Method void clear(SkColor color)
Cary Clark78de7512018-02-07 07:27:09 -05002352#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002353#Line # fills Clip with Color ##
Cary Clark09d80c02018-10-31 12:14:03 -04002354#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002355
2356#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002357void draw(SkCanvas* canvas) {
2358 canvas->save();
2359 canvas->clipRect(SkRect::MakeWH(256, 128));
Herb Derbyefe39bc2018-05-01 17:06:20 -04002360 canvas->clear(SkColorSetARGB(0x80, 0xFF, 0x00, 0x00));
Cary Clarkbad5ad72017-08-03 17:14:08 -04002361 canvas->restore();
2362 canvas->save();
2363 canvas->clipRect(SkRect::MakeWH(150, 192));
2364 canvas->clear(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00));
2365 canvas->restore();
2366 canvas->clipRect(SkRect::MakeWH(75, 256));
2367 canvas->clear(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF));
Cary Clark8032b982017-07-28 11:04:54 -04002368}
2369##
2370
Cary Clark2ade9972017-11-02 17:49:34 -04002371#SeeAlso drawColor SkBitmap::erase drawPaint
Cary Clark8032b982017-07-28 11:04:54 -04002372
2373##
2374
2375# ------------------------------------------------------------------------------
2376
Herb Derbyefe39bc2018-05-01 17:06:20 -04002377#Method void discard()
Cary Clark78de7512018-02-07 07:27:09 -05002378#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05002379#Line # makes Canvas contents undefined ##
Cary Clark09d80c02018-10-31 12:14:03 -04002380#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002381
Herb Derbyefe39bc2018-05-01 17:06:20 -04002382#NoExample
Cary Clark8032b982017-07-28 11:04:54 -04002383##
2384
Cary Clarkabaffd82018-11-15 08:25:12 -05002385#SeeAlso flush() GrContext::abandonContext
Cary Clark09d80c02018-10-31 12:14:03 -04002386
Cary Clark8032b982017-07-28 11:04:54 -04002387##
2388
2389# ------------------------------------------------------------------------------
2390
2391#Method void drawPaint(const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002392#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002393#Line # fills Clip with Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002394#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002395
2396#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002397void draw(SkCanvas* canvas) {
2398 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
2399 SkScalar pos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
2400 SkPaint paint;
2401 paint.setShader(SkGradientShader::MakeSweep(256, 256, colors, pos, SK_ARRAY_COUNT(colors)));
2402 canvas->drawPaint(paint);
Cary Clark8032b982017-07-28 11:04:54 -04002403}
2404##
2405
Cary Clark2ade9972017-11-02 17:49:34 -04002406#SeeAlso clear drawColor SkBitmap::erase
Cary Clark8032b982017-07-28 11:04:54 -04002407
2408##
2409
2410# ------------------------------------------------------------------------------
2411
2412#Enum PointMode
Cary Clark08895c42018-02-01 09:37:32 -05002413#Line # sets drawPoints options ##
Cary Clark8032b982017-07-28 11:04:54 -04002414
2415#Code
Cary Clark61313f32018-10-08 14:57:48 -04002416#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002417##
2418
2419Selects if an array of points are drawn as discrete points, as lines, or as
2420an open polygon.
2421
2422#Const kPoints_PointMode 0
Cary Clark682c58d2018-05-16 07:07:07 -04002423#Line # draw each point separately ##
Cary Clark8032b982017-07-28 11:04:54 -04002424##
2425
2426#Const kLines_PointMode 1
Cary Clark682c58d2018-05-16 07:07:07 -04002427#Line # draw each pair of points as a line segment ##
Cary Clark8032b982017-07-28 11:04:54 -04002428##
2429
2430#Const kPolygon_PointMode 2
Cary Clark682c58d2018-05-16 07:07:07 -04002431#Line # draw the array of points as a open polygon ##
Cary Clark8032b982017-07-28 11:04:54 -04002432##
2433
2434#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04002435 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002436 The upper left corner shows three squares when drawn as points.
2437 The upper right corner shows one line; when drawn as lines, two points are required per line.
2438 The lower right corner shows two lines; when draw as polygon, no miter is drawn at the corner.
2439 The lower left corner shows two lines with a miter when path contains polygon.
2440 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002441void draw(SkCanvas* canvas) {
2442 SkPaint paint;
2443 paint.setStyle(SkPaint::kStroke_Style);
2444 paint.setStrokeWidth(10);
2445 SkPoint points[] = {{64, 32}, {96, 96}, {32, 96}};
2446 canvas->drawPoints(SkCanvas::kPoints_PointMode, 3, points, paint);
2447 canvas->translate(128, 0);
2448 canvas->drawPoints(SkCanvas::kLines_PointMode, 3, points, paint);
2449 canvas->translate(0, 128);
2450 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, points, paint);
2451 SkPath path;
2452 path.addPoly(points, 3, false);
2453 canvas->translate(-128, 0);
2454 canvas->drawPath(path, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002455}
2456##
2457
Cary Clark2ade9972017-11-02 17:49:34 -04002458#SeeAlso drawLine drawPoint drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002459
2460##
2461
2462# ------------------------------------------------------------------------------
2463
2464#Method void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002465#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002466#Line # draws array as points, lines, polygon ##
Cary Clark09d80c02018-10-31 12:14:03 -04002467#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002468
2469#Example
2470#Height 200
Herb Derbyefe39bc2018-05-01 17:06:20 -04002471 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002472 #List
2473 # The first column draws points. ##
2474 # The second column draws points as lines. ##
2475 # The third column draws points as a polygon. ##
2476 # The fourth column draws points as a polygonal path. ##
2477 # The first row uses a round cap and round join. ##
2478 # The second row uses a square cap and a miter join. ##
2479 # The third row uses a butt cap and a bevel join. ##
2480 ##
2481 The transparent color makes multiple line draws visible;
2482 the path is drawn all at once.
2483 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002484void draw(SkCanvas* canvas) {
2485 SkPaint paint;
2486 paint.setAntiAlias(true);
2487 paint.setStyle(SkPaint::kStroke_Style);
2488 paint.setStrokeWidth(10);
2489 paint.setColor(0x80349a45);
2490 const SkPoint points[] = {{32, 16}, {48, 48}, {16, 32}};
Herb Derbyefe39bc2018-05-01 17:06:20 -04002491 const SkPaint::Join join[] = { SkPaint::kRound_Join,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002492 SkPaint::kMiter_Join,
2493 SkPaint::kBevel_Join };
2494 int joinIndex = 0;
2495 SkPath path;
2496 path.addPoly(points, 3, false);
2497 for (const auto cap : { SkPaint::kRound_Cap, SkPaint::kSquare_Cap, SkPaint::kButt_Cap } ) {
2498 paint.setStrokeCap(cap);
2499 paint.setStrokeJoin(join[joinIndex++]);
2500 for (const auto mode : { SkCanvas::kPoints_PointMode,
2501 SkCanvas::kLines_PointMode,
2502 SkCanvas::kPolygon_PointMode } ) {
2503 canvas->drawPoints(mode, 3, points, paint);
2504 canvas->translate(64, 0);
2505 }
2506 canvas->drawPath(path, paint);
2507 canvas->translate(-192, 64);
2508 }
Cary Clark8032b982017-07-28 11:04:54 -04002509}
2510##
2511
Cary Clark2ade9972017-11-02 17:49:34 -04002512#SeeAlso drawLine drawPoint drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002513
2514##
2515
2516# ------------------------------------------------------------------------------
2517
2518#Method void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002519#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002520#Line # draws point at (x, y) position ##
Cary Clark09d80c02018-10-31 12:14:03 -04002521#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002522
2523#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002524void draw(SkCanvas* canvas) {
2525 SkPaint paint;
2526 paint.setAntiAlias(true);
2527 paint.setColor(0x80349a45);
2528 paint.setStyle(SkPaint::kStroke_Style);
2529 paint.setStrokeWidth(100);
2530 paint.setStrokeCap(SkPaint::kRound_Cap);
2531 canvas->scale(1, 1.2f);
2532 canvas->drawPoint(64, 96, paint);
2533 canvas->scale(.6f, .8f);
2534 paint.setColor(SK_ColorWHITE);
2535 canvas->drawPoint(106, 120, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002536}
2537##
2538
Cary Clark2ade9972017-11-02 17:49:34 -04002539#SeeAlso drawPoints drawCircle drawRect drawLine drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002540
2541##
2542
Cary Clarkbad5ad72017-08-03 17:14:08 -04002543#Method void drawPoint(SkPoint p, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04002544#Populate
Cary Clarkbad5ad72017-08-03 17:14:08 -04002545
2546#Example
2547void draw(SkCanvas* canvas) {
2548 SkPaint paint;
2549 paint.setAntiAlias(true);
2550 paint.setColor(0x80349a45);
2551 paint.setStyle(SkPaint::kStroke_Style);
2552 paint.setStrokeWidth(100);
2553 paint.setStrokeCap(SkPaint::kSquare_Cap);
2554 canvas->scale(1, 1.2f);
2555 canvas->drawPoint({64, 96}, paint);
2556 canvas->scale(.6f, .8f);
2557 paint.setColor(SK_ColorWHITE);
2558 canvas->drawPoint(106, 120, paint);
2559}
2560##
2561
Cary Clark2ade9972017-11-02 17:49:34 -04002562#SeeAlso drawPoints drawCircle drawRect drawLine drawPath
Cary Clarkbad5ad72017-08-03 17:14:08 -04002563
2564##
2565
Cary Clark8032b982017-07-28 11:04:54 -04002566# ------------------------------------------------------------------------------
2567
2568#Method void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002569#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002570#Line # draws line segment between two points ##
Cary Clark09d80c02018-10-31 12:14:03 -04002571#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002572
2573#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002574 SkPaint paint;
2575 paint.setAntiAlias(true);
2576 paint.setColor(0xFF9a67be);
2577 paint.setStrokeWidth(20);
2578 canvas->skew(1, 0);
2579 canvas->drawLine(32, 96, 32, 160, paint);
2580 canvas->skew(-2, 0);
2581 canvas->drawLine(288, 96, 288, 160, paint);
2582##
2583
Cary Clark2ade9972017-11-02 17:49:34 -04002584#SeeAlso drawPoint drawCircle drawRect drawPath
Cary Clarkbad5ad72017-08-03 17:14:08 -04002585
2586##
2587
2588#Method void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04002589#Populate
Cary Clarkbad5ad72017-08-03 17:14:08 -04002590
2591#Example
2592 SkPaint paint;
2593 paint.setAntiAlias(true);
2594 paint.setColor(0xFF9a67be);
2595 paint.setStrokeWidth(20);
2596 canvas->skew(1, 0);
2597 canvas->drawLine({32, 96}, {32, 160}, paint);
2598 canvas->skew(-2, 0);
2599 canvas->drawLine({288, 96}, {288, 160}, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002600##
2601
Cary Clark2ade9972017-11-02 17:49:34 -04002602#SeeAlso drawPoint drawCircle drawRect drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002603
2604##
2605
2606# ------------------------------------------------------------------------------
2607
2608#Method void drawRect(const SkRect& rect, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002609#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002610#Line # draws Rect using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002611#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002612
2613#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002614void draw(SkCanvas* canvas) {
2615 SkPoint rectPts[] = { {64, 48}, {192, 160} };
2616 SkPaint paint;
2617 paint.setAntiAlias(true);
2618 paint.setStyle(SkPaint::kStroke_Style);
2619 paint.setStrokeWidth(20);
2620 paint.setStrokeJoin(SkPaint::kRound_Join);
2621 SkMatrix rotator;
2622 rotator.setRotate(30, 128, 128);
2623 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
2624 paint.setColor(color);
2625 SkRect rect;
2626 rect.set(rectPts[0], rectPts[1]);
2627 canvas->drawRect(rect, paint);
2628 rotator.mapPoints(rectPts, 2);
2629 }
Cary Clark8032b982017-07-28 11:04:54 -04002630}
2631##
2632
Herb Derbyefe39bc2018-05-01 17:06:20 -04002633#SeeAlso drawIRect drawRRect drawRoundRect drawRegion drawPath drawLine
Cary Clark8032b982017-07-28 11:04:54 -04002634
2635##
2636
2637# ------------------------------------------------------------------------------
2638
Herb Derbyefe39bc2018-05-01 17:06:20 -04002639#Method void drawIRect(const SkIRect& rect, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002640#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002641#Line # draws IRect using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002642#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002643
2644#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002645 SkIRect rect = { 64, 48, 192, 160 };
2646 SkPaint paint;
2647 paint.setAntiAlias(true);
2648 paint.setStyle(SkPaint::kStroke_Style);
2649 paint.setStrokeWidth(20);
2650 paint.setStrokeJoin(SkPaint::kRound_Join);
2651 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
2652 paint.setColor(color);
2653 canvas->drawIRect(rect, paint);
2654 canvas->rotate(30, 128, 128);
2655 }
Cary Clark8032b982017-07-28 11:04:54 -04002656##
2657
Cary Clark2ade9972017-11-02 17:49:34 -04002658#SeeAlso drawRect drawRRect drawRoundRect drawRegion drawPath drawLine
Cary Clark8032b982017-07-28 11:04:54 -04002659
2660##
2661
2662# ------------------------------------------------------------------------------
2663
2664#Method void drawRegion(const SkRegion& region, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002665#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002666#Line # draws Region using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002667#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002668
2669#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002670void draw(SkCanvas* canvas) {
2671 SkRegion region;
2672 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
2673 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
2674 SkPaint paint;
2675 paint.setAntiAlias(true);
2676 paint.setStyle(SkPaint::kStroke_Style);
2677 paint.setStrokeWidth(20);
2678 paint.setStrokeJoin(SkPaint::kRound_Join);
2679 canvas->drawRegion(region, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002680}
2681##
2682
Cary Clark2ade9972017-11-02 17:49:34 -04002683#SeeAlso drawRect drawIRect drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002684
2685##
2686
2687# ------------------------------------------------------------------------------
2688
2689#Method void drawOval(const SkRect& oval, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002690#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002691#Line # draws Oval using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002692#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002693
2694#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002695void draw(SkCanvas* canvas) {
2696 canvas->clear(0xFF3f5f9f);
2697 SkColor kColor1 = SkColorSetARGB(0xff, 0xff, 0x7f, 0);
2698 SkColor g1Colors[] = { kColor1, SkColorSetA(kColor1, 0x20) };
2699 SkPoint g1Points[] = { { 0, 0 }, { 0, 100 } };
2700 SkScalar pos[] = { 0.2f, 1.0f };
2701 SkRect bounds = SkRect::MakeWH(80, 70);
2702 SkPaint paint;
2703 paint.setAntiAlias(true);
2704 paint.setShader(SkGradientShader::MakeLinear(g1Points, g1Colors, pos, SK_ARRAY_COUNT(g1Colors),
2705 SkShader::kClamp_TileMode));
2706 canvas->drawOval(bounds , paint);
Cary Clark8032b982017-07-28 11:04:54 -04002707}
2708##
2709
Cary Clark2ade9972017-11-02 17:49:34 -04002710#SeeAlso drawCircle drawPoint drawPath drawRRect drawRoundRect
Cary Clark8032b982017-07-28 11:04:54 -04002711
2712##
2713
2714# ------------------------------------------------------------------------------
2715
2716#Method void drawRRect(const SkRRect& rrect, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002717#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002718#Line # draws Round_Rect using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002719#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002720
2721#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002722void draw(SkCanvas* canvas) {
2723 SkPaint paint;
2724 paint.setAntiAlias(true);
2725 SkRect outer = {30, 40, 210, 220};
2726 SkRect radii = {30, 50, 70, 90 };
2727 SkRRect rRect;
2728 rRect.setNinePatch(outer, radii.fLeft, radii.fTop, radii.fRight, radii.fBottom);
2729 canvas->drawRRect(rRect, paint);
2730 paint.setColor(SK_ColorWHITE);
2731 canvas->drawLine(outer.fLeft + radii.fLeft, outer.fTop,
2732 outer.fLeft + radii.fLeft, outer.fBottom, paint);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002733 canvas->drawLine(outer.fRight - radii.fRight, outer.fTop,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002734 outer.fRight - radii.fRight, outer.fBottom, paint);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002735 canvas->drawLine(outer.fLeft, outer.fTop + radii.fTop,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002736 outer.fRight, outer.fTop + radii.fTop, paint);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002737 canvas->drawLine(outer.fLeft, outer.fBottom - radii.fBottom,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002738 outer.fRight, outer.fBottom - radii.fBottom, paint);
2739}
Cary Clark8032b982017-07-28 11:04:54 -04002740##
2741
Cary Clark2ade9972017-11-02 17:49:34 -04002742#SeeAlso drawRect drawRoundRect drawDRRect drawCircle drawOval drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002743
2744##
2745
2746# ------------------------------------------------------------------------------
2747
2748#Method void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002749#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002750#Line # draws double Round_Rect stroked or filled ##
Cary Clark09d80c02018-10-31 12:14:03 -04002751#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002752
2753#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002754void draw(SkCanvas* canvas) {
2755 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
2756 SkRRect inner = SkRRect::MakeOval({60, 70, 170, 160});
2757 SkPaint paint;
2758 canvas->drawDRRect(outer, inner, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002759}
2760##
2761
2762#Example
2763#Description
2764 Outer Rect has no corner radii, but stroke join is rounded.
2765 Inner Round_Rect has corner radii; outset stroke increases radii of corners.
2766 Stroke join does not affect inner Round_Rect since it has no sharp corners.
2767##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002768void draw(SkCanvas* canvas) {
2769 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
2770 SkRRect inner = SkRRect::MakeRectXY({60, 70, 170, 160}, 10, 10);
2771 SkPaint paint;
2772 paint.setAntiAlias(true);
2773 paint.setStyle(SkPaint::kStroke_Style);
2774 paint.setStrokeWidth(20);
2775 paint.setStrokeJoin(SkPaint::kRound_Join);
2776 canvas->drawDRRect(outer, inner, paint);
2777 paint.setStrokeWidth(1);
2778 paint.setColor(SK_ColorWHITE);
2779 canvas->drawDRRect(outer, inner, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002780}
2781##
2782
Cary Clark2ade9972017-11-02 17:49:34 -04002783#SeeAlso drawRect drawRoundRect drawRRect drawCircle drawOval drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002784
2785##
2786
2787# ------------------------------------------------------------------------------
2788
2789#Method void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002790#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002791#Line # draws Circle using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002792#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002793
2794#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002795 void draw(SkCanvas* canvas) {
2796 SkPaint paint;
2797 paint.setAntiAlias(true);
2798 canvas->drawCircle(128, 128, 90, paint);
2799 paint.setColor(SK_ColorWHITE);
2800 canvas->drawCircle(86, 86, 20, paint);
2801 canvas->drawCircle(160, 76, 20, paint);
2802 canvas->drawCircle(140, 150, 35, paint);
2803 }
2804##
2805
Cary Clark2ade9972017-11-02 17:49:34 -04002806#SeeAlso drawOval drawRRect drawRoundRect drawPath drawArc drawPoint drawLine
Cary Clarkbad5ad72017-08-03 17:14:08 -04002807
2808##
2809
2810#Method void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04002811#Populate
Cary Clarkbad5ad72017-08-03 17:14:08 -04002812
2813#Example
2814 void draw(SkCanvas* canvas) {
2815 SkPaint paint;
2816 paint.setAntiAlias(true);
2817 canvas->drawCircle(128, 128, 90, paint);
2818 paint.setColor(SK_ColorWHITE);
2819 canvas->drawCircle({86, 86}, 20, paint);
2820 canvas->drawCircle({160, 76}, 20, paint);
2821 canvas->drawCircle({140, 150}, 35, paint);
2822 }
Cary Clark8032b982017-07-28 11:04:54 -04002823##
2824
Cary Clark2ade9972017-11-02 17:49:34 -04002825#SeeAlso drawOval drawRRect drawRoundRect drawPath drawArc drawPoint drawLine
Cary Clark8032b982017-07-28 11:04:54 -04002826
2827##
2828
2829# ------------------------------------------------------------------------------
2830
2831#Method void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
2832 bool useCenter, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002833#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002834#Line # draws Arc using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002835#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002836
2837#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002838 void draw(SkCanvas* canvas) {
2839 SkPaint paint;
2840 paint.setAntiAlias(true);
2841 SkRect oval = { 4, 4, 60, 60};
2842 for (auto useCenter : { false, true } ) {
2843 for (auto style : { SkPaint::kFill_Style, SkPaint::kStroke_Style } ) {
2844 paint.setStyle(style);
2845 for (auto degrees : { 45, 90, 180, 360} ) {
2846 canvas->drawArc(oval, 0, degrees , useCenter, paint);
2847 canvas->translate(64, 0);
2848 }
2849 canvas->translate(-256, 64);
2850 }
2851 }
Cary Clark8032b982017-07-28 11:04:54 -04002852 }
2853##
2854
2855#Example
2856#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04002857 void draw(SkCanvas* canvas) {
2858 SkPaint paint;
2859 paint.setAntiAlias(true);
2860 paint.setStyle(SkPaint::kStroke_Style);
2861 paint.setStrokeWidth(4);
2862 SkRect oval = { 4, 4, 60, 60};
2863 float intervals[] = { 5, 5 };
2864 paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
2865 for (auto degrees : { 270, 360, 540, 720 } ) {
2866 canvas->drawArc(oval, 0, degrees, false, paint);
2867 canvas->translate(64, 0);
2868 }
Cary Clark8032b982017-07-28 11:04:54 -04002869 }
2870##
2871
Cary Clark2ade9972017-11-02 17:49:34 -04002872#SeeAlso SkPath::arcTo drawCircle drawOval drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002873
2874##
2875
2876# ------------------------------------------------------------------------------
2877
2878#Method void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002879#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002880#Line # draws Round_Rect using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002881#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002882
2883#Example
2884#Description
2885 Top row has a zero radius a generates a rectangle.
2886 Second row radii sum to less than sides.
2887 Third row radii sum equals sides.
2888 Fourth row radii sum exceeds sides; radii are scaled to fit.
2889##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002890 void draw(SkCanvas* canvas) {
2891 SkVector radii[] = { {0, 20}, {10, 10}, {10, 20}, {10, 40} };
2892 SkPaint paint;
2893 paint.setStrokeWidth(15);
2894 paint.setStrokeJoin(SkPaint::kRound_Join);
2895 paint.setAntiAlias(true);
2896 for (auto style : { SkPaint::kStroke_Style, SkPaint::kFill_Style } ) {
2897 paint.setStyle(style );
2898 for (size_t i = 0; i < SK_ARRAY_COUNT(radii); ++i) {
2899 canvas->drawRoundRect({10, 10, 60, 40}, radii[i].fX, radii[i].fY, paint);
2900 canvas->translate(0, 60);
2901 }
2902 canvas->translate(80, -240);
2903 }
Cary Clark8032b982017-07-28 11:04:54 -04002904 }
2905##
2906
Cary Clark77b3f3a2018-11-07 14:59:03 -05002907#SeeAlso drawRRect drawRect drawDRRect drawPath drawCircle drawOval drawPoint
Cary Clark8032b982017-07-28 11:04:54 -04002908
2909##
2910
2911# ------------------------------------------------------------------------------
2912
2913#Method void drawPath(const SkPath& path, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002914#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002915#Line # draws Path using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002916#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002917
2918#Example
2919#Description
2920 Top rows draw stroked path with combinations of joins and caps. The open contour
2921 is affected by caps; the closed contour is affected by joins.
Herb Derbyefe39bc2018-05-01 17:06:20 -04002922 Bottom row draws fill the same for open and closed contour.
Cary Clark8032b982017-07-28 11:04:54 -04002923 First bottom column shows winding fills overlap.
2924 Second bottom column shows even odd fills exclude overlap.
2925 Third bottom column shows inverse winding fills area outside both contours.
2926##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002927void draw(SkCanvas* canvas) {
2928 SkPath path;
2929 path.moveTo(20, 20);
2930 path.quadTo(60, 20, 60, 60);
2931 path.close();
2932 path.moveTo(60, 20);
2933 path.quadTo(60, 60, 20, 60);
2934 SkPaint paint;
2935 paint.setStrokeWidth(10);
2936 paint.setAntiAlias(true);
2937 paint.setStyle(SkPaint::kStroke_Style);
2938 for (auto join: { SkPaint::kBevel_Join, SkPaint::kRound_Join, SkPaint::kMiter_Join } ) {
2939 paint.setStrokeJoin(join);
2940 for (auto cap: { SkPaint::kButt_Cap, SkPaint::kSquare_Cap, SkPaint::kRound_Cap } ) {
2941 paint.setStrokeCap(cap);
2942 canvas->drawPath(path, paint);
2943 canvas->translate(80, 0);
2944 }
2945 canvas->translate(-240, 60);
2946 }
2947 paint.setStyle(SkPaint::kFill_Style);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002948 for (auto fill : { SkPath::kWinding_FillType,
2949 SkPath::kEvenOdd_FillType,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002950 SkPath::kInverseWinding_FillType } ) {
2951 path.setFillType(fill);
2952 canvas->save();
2953 canvas->clipRect({0, 10, 80, 70});
2954 canvas->drawPath(path, paint);
2955 canvas->restore();
2956 canvas->translate(80, 0);
2957 }
Cary Clark8032b982017-07-28 11:04:54 -04002958}
2959##
2960
Cary Clark2ade9972017-11-02 17:49:34 -04002961#SeeAlso SkPath drawLine drawArc drawRect drawPoints
Cary Clark8032b982017-07-28 11:04:54 -04002962
2963##
2964
2965# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05002966#Subtopic Draw_Image
2967#Line # draws Image to Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -04002968
Cary Clarkbad5ad72017-08-03 17:14:08 -04002969drawImage, drawImageRect, and drawImageNine can be called with a bare pointer or
2970a smart pointer as a convenience. The pairs of calls are otherwise identical.
Cary Clark8032b982017-07-28 11:04:54 -04002971
Cary Clark73fa9722017-08-29 17:36:51 -04002972#Method void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05002973#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05002974#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002975#Line # draws Image at (x, y) position ##
Cary Clark09d80c02018-10-31 12:14:03 -04002976#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002977
2978#Example
2979#Height 64
2980#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04002981void draw(SkCanvas* canvas) {
2982 // sk_sp<SkImage> image;
2983 SkImage* imagePtr = image.get();
2984 canvas->drawImage(imagePtr, 0, 0);
2985 SkPaint paint;
2986 canvas->drawImage(imagePtr, 80, 0, &paint);
2987 paint.setAlpha(0x80);
2988 canvas->drawImage(imagePtr, 160, 0, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04002989}
2990##
2991
Cary Clark2ade9972017-11-02 17:49:34 -04002992#SeeAlso drawBitmap drawImageLattice drawImageNine drawImageRect SkPaint::setImageFilter
Cary Clark8032b982017-07-28 11:04:54 -04002993
2994##
2995
2996# ------------------------------------------------------------------------------
2997
2998#Method void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
Herb Derbyefe39bc2018-05-01 17:06:20 -04002999 const SkPaint* paint = nullptr)
Cary Clark09d80c02018-10-31 12:14:03 -04003000#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003001
3002#Example
3003#Height 64
3004#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003005void draw(SkCanvas* canvas) {
3006 // sk_sp<SkImage> image;
3007 canvas->drawImage(image, 0, 0);
3008 SkPaint paint;
3009 canvas->drawImage(image, 80, 0, &paint);
3010 paint.setAlpha(0x80);
3011 canvas->drawImage(image, 160, 0, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04003012}
3013##
3014
Cary Clark2ade9972017-11-02 17:49:34 -04003015#SeeAlso drawBitmap drawImageLattice drawImageNine drawImageRect SkPaint::setImageFilter
Cary Clark8032b982017-07-28 11:04:54 -04003016
3017##
3018
3019# ------------------------------------------------------------------------------
3020
3021#Enum SrcRectConstraint
Cary Clark08895c42018-02-01 09:37:32 -05003022#Line # sets drawImageRect options ##
Cary Clark8032b982017-07-28 11:04:54 -04003023
3024#Code
Cary Clark61313f32018-10-08 14:57:48 -04003025#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003026##
3027
Cary Clarkce101242017-09-01 15:51:02 -04003028SrcRectConstraint controls the behavior at the edge of source Rect,
3029provided to drawImageRect, trading off speed for precision.
Cary Clark8032b982017-07-28 11:04:54 -04003030
Cary Clarkce101242017-09-01 15:51:02 -04003031Image_Filter in Paint may sample multiple pixels in the image. Source Rect
Cary Clarkbad5ad72017-08-03 17:14:08 -04003032restricts the bounds of pixels that may be read. Image_Filter may slow down if
Herb Derbyefe39bc2018-05-01 17:06:20 -04003033it cannot read outside the bounds, when sampling near the edge of source Rect.
Cary Clark8032b982017-07-28 11:04:54 -04003034SrcRectConstraint specifies whether an Image_Filter is allowed to read pixels
Cary Clarkce101242017-09-01 15:51:02 -04003035outside source Rect.
Cary Clark8032b982017-07-28 11:04:54 -04003036
Cary Clark682c58d2018-05-16 07:07:07 -04003037#Const kStrict_SrcRectConstraint 0
3038#Line # sample only inside bounds; slower ##
Cary Clarkce101242017-09-01 15:51:02 -04003039 Requires Image_Filter to respect source Rect,
Cary Clark8032b982017-07-28 11:04:54 -04003040 sampling only inside of its bounds, possibly with a performance penalty.
3041##
3042
Cary Clark682c58d2018-05-16 07:07:07 -04003043#Const kFast_SrcRectConstraint 1
3044#Line # sample outside bounds; faster ##
Cary Clarkce101242017-09-01 15:51:02 -04003045 Permits Image_Filter to sample outside of source Rect
Cary Clark8032b982017-07-28 11:04:54 -04003046 by half the width of Image_Filter, permitting it to run faster but with
3047 error at the image edges.
3048##
3049
3050#Example
3051#Height 64
3052#Description
3053 redBorder contains a black and white checkerboard bordered by red.
3054 redBorder is drawn scaled by 16 on the left.
Cary Clarkce101242017-09-01 15:51:02 -04003055 The middle and right bitmaps are filtered checkerboards.
Cary Clark8032b982017-07-28 11:04:54 -04003056 Drawing the checkerboard with kStrict_SrcRectConstraint shows only a blur of black and white.
3057 Drawing the checkerboard with kFast_SrcRectConstraint allows red to bleed in the corners.
3058##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003059void draw(SkCanvas* canvas) {
3060 SkBitmap redBorder;
3061 redBorder.allocPixels(SkImageInfo::MakeN32Premul(4, 4));
3062 SkCanvas checkRed(redBorder);
3063 checkRed.clear(SK_ColorRED);
3064 uint32_t checkers[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
3065 { SK_ColorWHITE, SK_ColorBLACK } };
3066 checkRed.writePixels(
3067 SkImageInfo::MakeN32Premul(2, 2), (void*) checkers, sizeof(checkers[0]), 1, 1);
3068 canvas->scale(16, 16);
3069 canvas->drawBitmap(redBorder, 0, 0, nullptr);
3070 canvas->resetMatrix();
3071 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
3072 SkPaint lowPaint;
3073 lowPaint.setFilterQuality(kLow_SkFilterQuality);
3074 for (auto constraint : { SkCanvas::kStrict_SrcRectConstraint,
3075 SkCanvas::kFast_SrcRectConstraint } ) {
3076 canvas->translate(80, 0);
3077 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
3078 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
3079 }
Cary Clark8032b982017-07-28 11:04:54 -04003080}
3081##
3082
Cary Clark2ade9972017-11-02 17:49:34 -04003083#SeeAlso drawImageRect drawImage SkPaint::setImageFilter
Cary Clark8032b982017-07-28 11:04:54 -04003084
3085##
3086
3087# ------------------------------------------------------------------------------
3088
3089#Method void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
3090 const SkPaint* paint,
3091 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003092#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003093#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003094#Line # draws Image, source Rect to destination Rect ##
Cary Clark09d80c02018-10-31 12:14:03 -04003095#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003096
3097#Example
3098#Height 64
3099#Description
3100 The left bitmap draws with Paint default kNone_SkFilterQuality, and stays within
Cary Clarkbc5697d2017-10-04 14:31:33 -04003101 its bounds; there is no bleeding with kFast_SrcRectConstraint.
Cary Clark8032b982017-07-28 11:04:54 -04003102 the middle and right bitmaps draw with kLow_SkFilterQuality; with
3103 kStrict_SrcRectConstraint, the filter remains within the checkerboard, and
3104 with kFast_SrcRectConstraint red bleeds on the edges.
3105##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003106void draw(SkCanvas* canvas) {
Herb Derbyefe39bc2018-05-01 17:06:20 -04003107 uint32_t pixels[][4] = {
Cary Clarkbad5ad72017-08-03 17:14:08 -04003108 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 },
3109 { 0xFFFF0000, 0xFF000000, 0xFFFFFFFF, 0xFFFF0000 },
3110 { 0xFFFF0000, 0xFFFFFFFF, 0xFF000000, 0xFFFF0000 },
3111 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 } };
3112 SkBitmap redBorder;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003113 redBorder.installPixels(SkImageInfo::MakeN32Premul(4, 4),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003114 (void*) pixels, sizeof(pixels[0]));
3115 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
3116 SkPaint lowPaint;
3117 for (auto constraint : {
3118 SkCanvas::kFast_SrcRectConstraint,
3119 SkCanvas::kStrict_SrcRectConstraint,
3120 SkCanvas::kFast_SrcRectConstraint } ) {
3121 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
3122 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
3123 lowPaint.setFilterQuality(kLow_SkFilterQuality);
3124 canvas->translate(80, 0);
3125 }
3126}
Cary Clark8032b982017-07-28 11:04:54 -04003127##
3128
Cary Clark2ade9972017-11-02 17:49:34 -04003129#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003130
3131##
3132
3133# ------------------------------------------------------------------------------
3134
3135#Method void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
3136 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003137#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003138#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003139#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003140
3141#Example
3142#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003143void draw(SkCanvas* canvas) {
3144 // sk_sp<SkImage> image;
3145 for (auto i : { 1, 2, 4, 8 } ) {
Herb Derbyefe39bc2018-05-01 17:06:20 -04003146 canvas->drawImageRect(image.get(), SkIRect::MakeLTRB(0, 0, 100, 100),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003147 SkRect::MakeXYWH(i * 20, i * 20, i * 20, i * 20), nullptr);
3148 }
Cary Clark8032b982017-07-28 11:04:54 -04003149}
3150##
3151
Cary Clark2ade9972017-11-02 17:49:34 -04003152#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003153
3154##
3155
3156# ------------------------------------------------------------------------------
3157
Cary Clark0ac0edd2018-10-29 11:28:43 -04003158#Method void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003159#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003160#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003161#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003162
3163#Example
3164#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003165void draw(SkCanvas* canvas) {
3166 // sk_sp<SkImage> image;
3167 for (auto i : { 20, 40, 80, 160 } ) {
3168 canvas->drawImageRect(image.get(), SkRect::MakeXYWH(i, i, i, i), nullptr);
3169 }
Cary Clark8032b982017-07-28 11:04:54 -04003170}
3171##
3172
Cary Clark2ade9972017-11-02 17:49:34 -04003173#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003174
3175##
3176
3177# ------------------------------------------------------------------------------
3178
3179#Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
3180 const SkPaint* paint,
Herb Derbyefe39bc2018-05-01 17:06:20 -04003181 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003182#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003183#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003184#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003185
3186#Example
3187#Height 64
3188#Description
3189 Canvas scales and translates; transformation from src to dst also scales.
3190 The two matrices are concatenated to create the final transformation.
3191##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003192void draw(SkCanvas* canvas) {
3193 uint32_t pixels[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
3194 { SK_ColorWHITE, SK_ColorBLACK } };
3195 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003196 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003197 (void*) pixels, sizeof(pixels[0]));
3198 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3199 SkPaint paint;
3200 canvas->scale(4, 4);
3201 for (auto alpha : { 50, 100, 150, 255 } ) {
3202 paint.setAlpha(alpha);
3203 canvas->drawImageRect(image, SkRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
3204 canvas->translate(8, 0);
3205 }
3206}
Cary Clark8032b982017-07-28 11:04:54 -04003207##
3208
Cary Clark2ade9972017-11-02 17:49:34 -04003209#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003210
3211##
3212
3213# ------------------------------------------------------------------------------
3214
3215#Method void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst,
Herb Derbyefe39bc2018-05-01 17:06:20 -04003216 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003217#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003218#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003219#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003220
3221#Example
3222#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003223void draw(SkCanvas* canvas) {
3224 uint32_t pixels[][2] = { { 0x00000000, 0x55555555},
3225 { 0xAAAAAAAA, 0xFFFFFFFF} };
3226 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003227 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003228 (void*) pixels, sizeof(pixels[0]));
3229 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3230 SkPaint paint;
3231 canvas->scale(4, 4);
3232 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
3233 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
3234 canvas->drawImageRect(image, SkIRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
3235 canvas->translate(8, 0);
3236 }
Cary Clark8032b982017-07-28 11:04:54 -04003237}
3238##
3239
Cary Clark2ade9972017-11-02 17:49:34 -04003240#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
3241
Cary Clark8032b982017-07-28 11:04:54 -04003242##
3243
3244# ------------------------------------------------------------------------------
3245
Cary Clark0ac0edd2018-10-29 11:28:43 -04003246#Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003247#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003248#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003249#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003250
3251#Example
3252#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003253void draw(SkCanvas* canvas) {
3254 uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
3255 { 0xAAAA0000, 0xFFFF0000} };
3256 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003257 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003258 (void*) pixels, sizeof(pixels[0]));
3259 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3260 SkPaint paint;
3261 canvas->scale(4, 4);
3262 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
3263 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
3264 canvas->drawImageRect(image, SkRect::MakeWH(8, 8), &paint);
3265 canvas->translate(8, 0);
3266 }
Cary Clark8032b982017-07-28 11:04:54 -04003267}
3268##
3269
Cary Clark2ade9972017-11-02 17:49:34 -04003270#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003271
3272##
3273
3274# ------------------------------------------------------------------------------
3275
3276#Method void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
3277 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003278#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003279#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003280#Line # draws Nine_Patch Image ##
Cary Clark8032b982017-07-28 11:04:54 -04003281
Cary Clark80247e52018-07-11 16:18:41 -04003282Draws Image image stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003283IRect center divides the image into nine sections: four sides, four corners, and
Cary Clarkce101242017-09-01 15:51:02 -04003284the center. Corners are unmodified or scaled down proportionately if their sides
Cary Clarkbad5ad72017-08-03 17:14:08 -04003285are larger than dst; center and four sides are scaled to fit remaining space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003286
Cary Clarkbad5ad72017-08-03 17:14:08 -04003287Additionally transform draw using Clip, Matrix, and optional Paint paint.
3288
Cary Clark682c58d2018-05-16 07:07:07 -04003289#paint_as_used_by_draw_lattice_or_draw_nine(image)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003290
3291If generated mask extends beyond image bounds, replicate image edge colors, just
3292as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
Cary Clarkbc5697d2017-10-04 14:31:33 -04003293replicates the image edge color when it samples outside of its bounds.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003294
3295#Param image Image containing pixels, dimensions, and format ##
3296#Param center IRect edge of image corners and sides ##
3297#Param dst destination Rect of image to draw to ##
3298#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3299 and so on; or nullptr
3300##
Cary Clark8032b982017-07-28 11:04:54 -04003301
3302#Example
3303#Height 128
3304#Description
3305 The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
Cary Clarkce101242017-09-01 15:51:02 -04003306 The second image equals the size of center; only corners are drawn without scaling.
3307 The remaining images are larger than center. All corners draw without scaling.
3308 The sides and center are scaled if needed to take up the remaining space.
Cary Clark8032b982017-07-28 11:04:54 -04003309##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003310void draw(SkCanvas* canvas) {
3311 SkIRect center = { 20, 10, 50, 40 };
3312 SkBitmap bitmap;
3313 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3314 SkCanvas bitCanvas(bitmap);
3315 SkPaint paint;
3316 SkColor gray = 0xFF000000;
3317 int left = 0;
3318 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3319 int top = 0;
3320 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3321 paint.setColor(gray);
3322 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3323 gray += 0x001f1f1f;
3324 top = bottom;
3325 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003326 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003327 }
3328 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3329 SkImage* imagePtr = image.get();
3330 for (auto dest: { 20, 30, 40, 60, 90 } ) {
3331 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
3332 canvas->translate(dest + 4, 0);
3333 }
Cary Clark8032b982017-07-28 11:04:54 -04003334}
3335##
3336
Cary Clark2ade9972017-11-02 17:49:34 -04003337#SeeAlso drawImage drawBitmapNine drawImageLattice drawImageRect
Cary Clark8032b982017-07-28 11:04:54 -04003338
3339##
3340
3341# ------------------------------------------------------------------------------
3342
3343#Method void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst,
Herb Derbyefe39bc2018-05-01 17:06:20 -04003344 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003345#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003346#In Draw
Cary Clark80247e52018-07-11 16:18:41 -04003347Draws Image image stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003348IRect center divides the image into nine sections: four sides, four corners, and
Cary Clarkce101242017-09-01 15:51:02 -04003349the center. Corners are not scaled, or scaled down proportionately if their sides
Cary Clarkbad5ad72017-08-03 17:14:08 -04003350are larger than dst; center and four sides are scaled to fit remaining space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003351
Cary Clarkbad5ad72017-08-03 17:14:08 -04003352Additionally transform draw using Clip, Matrix, and optional Paint paint.
3353
Cary Clark137b8742018-05-30 09:21:49 -04003354#paint_as_used_by_draw_lattice_or_draw_nine(image)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003355
3356If generated mask extends beyond image bounds, replicate image edge colors, just
3357as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
Cary Clarkbc5697d2017-10-04 14:31:33 -04003358replicates the image edge color when it samples outside of its bounds.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003359
3360#Param image Image containing pixels, dimensions, and format ##
3361#Param center IRect edge of image corners and sides ##
3362#Param dst destination Rect of image to draw to ##
3363#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3364 and so on; or nullptr
3365##
Cary Clark8032b982017-07-28 11:04:54 -04003366
3367#Example
3368#Height 128
3369#Description
3370 The two leftmost images has four corners and sides to the left and right of center.
3371 The leftmost image scales the width of corners proportionately to fit.
Herb Derbyefe39bc2018-05-01 17:06:20 -04003372 The third and fourth image corners are not scaled; the sides and center are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04003373 fill the remaining space.
3374 The rightmost image has four corners scaled vertically to fit, and uses sides above
3375 and below center to fill the remaining space.
3376##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003377void draw(SkCanvas* canvas) {
3378 SkIRect center = { 20, 10, 50, 40 };
3379 SkBitmap bitmap;
3380 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3381 SkCanvas bitCanvas(bitmap);
3382 SkPaint paint;
3383 SkColor gray = 0xFF000000;
3384 int left = 0;
3385 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3386 int top = 0;
3387 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3388 paint.setColor(gray);
3389 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3390 gray += 0x001f1f1f;
3391 top = bottom;
3392 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003393 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003394 }
3395 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3396 for (auto dest: { 20, 30, 40, 60, 90 } ) {
3397 canvas->drawImageNine(image, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
3398 canvas->translate(dest + 4, 0);
3399 }
Cary Clark8032b982017-07-28 11:04:54 -04003400}
3401##
3402
Cary Clark2ade9972017-11-02 17:49:34 -04003403#SeeAlso drawImage drawBitmapNine drawImageLattice drawImageRect
Cary Clark8032b982017-07-28 11:04:54 -04003404
3405##
3406
3407# ------------------------------------------------------------------------------
3408
3409#Method void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
Cary Clark73fa9722017-08-29 17:36:51 -04003410 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003411#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003412#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003413#Line # draws Bitmap at (x, y) position ##
Cary Clark09d80c02018-10-31 12:14:03 -04003414#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003415
3416#Example
3417#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003418void draw(SkCanvas* canvas) {
3419 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
3420 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
3421 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
3422 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
3423 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
3424 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
3425 { 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00},
3426 { 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF} };
3427 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003428 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003429 (void*) pixels, sizeof(pixels[0]));
3430 SkPaint paint;
3431 canvas->scale(4, 4);
3432 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
3433 paint.setColor(color);
3434 canvas->drawBitmap(bitmap, 0, 0, &paint);
3435 canvas->translate(12, 0);
3436 }
Cary Clark8032b982017-07-28 11:04:54 -04003437}
3438##
3439
Cary Clark2ade9972017-11-02 17:49:34 -04003440#SeeAlso drawImage drawBitmapLattice drawBitmapNine drawBitmapRect SkBitmap::readPixels SkBitmap::writePixels
Cary Clark8032b982017-07-28 11:04:54 -04003441
3442##
3443
3444# ------------------------------------------------------------------------------
3445
3446#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
3447 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003448#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003449#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003450#Line # draws Bitmap, source Rect to destination Rect ##
Cary Clark09d80c02018-10-31 12:14:03 -04003451#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003452
3453#Example
3454#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003455void draw(SkCanvas* canvas) {
3456 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
3457 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
3458 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
3459 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
3460 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
3461 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
3462 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
3463 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00} };
3464 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003465 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003466 (void*) pixels, sizeof(pixels[0]));
3467 SkPaint paint;
Cary Clark681287e2018-03-16 11:34:15 -04003468 paint.setMaskFilter(SkMaskFilter::MakeBlur(kSolid_SkBlurStyle, 6));
Cary Clarkbad5ad72017-08-03 17:14:08 -04003469 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
3470 paint.setColor(color);
3471 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
3472 canvas->translate(48, 0);
3473 }
Cary Clark8032b982017-07-28 11:04:54 -04003474}
3475##
3476
Cary Clark2ade9972017-11-02 17:49:34 -04003477#SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
Cary Clark8032b982017-07-28 11:04:54 -04003478
3479##
3480
3481# ------------------------------------------------------------------------------
3482
3483#Method void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
3484 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003485#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003486#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003487#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003488
3489#Example
3490#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003491void draw(SkCanvas* canvas) {
3492 uint8_t pixels[][8] = { { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
3493 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
3494 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
3495 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
3496 { 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF},
3497 { 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF},
3498 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
3499 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00} };
3500 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003501 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003502 (void*) pixels, sizeof(pixels[0]));
3503 SkPaint paint;
3504 paint.setFilterQuality(kHigh_SkFilterQuality);
3505 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00, 0xFF7f007f} ) {
3506 paint.setColor(color);
3507 canvas->drawBitmapRect(bitmap, SkIRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
3508 canvas->translate(48.25f, 0);
3509 }
Cary Clark8032b982017-07-28 11:04:54 -04003510}
3511##
3512
Cary Clark2ade9972017-11-02 17:49:34 -04003513#SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
Cary Clark8032b982017-07-28 11:04:54 -04003514
3515##
3516
3517# ------------------------------------------------------------------------------
3518
3519#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
3520 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003521#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003522#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003523#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003524
3525#Example
3526#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003527void draw(SkCanvas* canvas) {
3528 uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
3529 { 0xAAAA0000, 0xFFFF0000} };
3530 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003531 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003532 (void*) pixels, sizeof(pixels[0]));
3533 SkPaint paint;
3534 canvas->scale(4, 4);
3535 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
3536 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
3537 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), &paint);
3538 canvas->translate(8, 0);
3539 }
Cary Clark8032b982017-07-28 11:04:54 -04003540}
3541##
3542
Cary Clark2ade9972017-11-02 17:49:34 -04003543#SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
Cary Clark8032b982017-07-28 11:04:54 -04003544
3545##
3546
3547# ------------------------------------------------------------------------------
3548
Cary Clark682c58d2018-05-16 07:07:07 -04003549#PhraseDef paint_as_used_by_draw_lattice_or_draw_nine(bitmap_or_image)
3550If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
3551Blend_Mode, and Draw_Looper. If #bitmap_or_image# is kAlpha_8_SkColorType, apply Shader.
3552If paint contains Mask_Filter, generate mask from #bitmap_or_image# bounds. If paint
3553Filter_Quality set to kNone_SkFilterQuality, disable pixel filtering. For all
3554other values of paint Filter_Quality, use kLow_SkFilterQuality to filter pixels.
Cary Clark137b8742018-05-30 09:21:49 -04003555Any SkMaskFilter on paint is ignored as is paint Anti_Aliasing state.
Cary Clark682c58d2018-05-16 07:07:07 -04003556##
3557
Cary Clark8032b982017-07-28 11:04:54 -04003558#Method void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
Cary Clark73fa9722017-08-29 17:36:51 -04003559 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003560#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003561#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003562#Line # draws Nine_Patch Bitmap ##
Cary Clark8032b982017-07-28 11:04:54 -04003563
Cary Clark80247e52018-07-11 16:18:41 -04003564Draws Bitmap bitmap stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003565IRect center divides the bitmap into nine sections: four sides, four corners,
Cary Clarkce101242017-09-01 15:51:02 -04003566and the center. Corners are not scaled, or scaled down proportionately if their
Cary Clarkbad5ad72017-08-03 17:14:08 -04003567sides are larger than dst; center and four sides are scaled to fit remaining
3568space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003569
Cary Clarkbad5ad72017-08-03 17:14:08 -04003570Additionally transform draw using Clip, Matrix, and optional Paint paint.
3571
Cary Clark682c58d2018-05-16 07:07:07 -04003572#paint_as_used_by_draw_lattice_or_draw_nine(bitmap)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003573
3574If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
3575just as Shader made from SkShader::MakeBitmapShader with
Cary Clarkbc5697d2017-10-04 14:31:33 -04003576SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
Cary Clarkbad5ad72017-08-03 17:14:08 -04003577outside of its bounds.
3578
3579#Param bitmap Bitmap containing pixels, dimensions, and format ##
3580#Param center IRect edge of image corners and sides ##
3581#Param dst destination Rect of image to draw to ##
3582#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3583 and so on; or nullptr
3584##
Cary Clark8032b982017-07-28 11:04:54 -04003585
3586#Example
3587#Height 128
3588#Description
3589 The two leftmost bitmap draws has four corners and sides to the left and right of center.
3590 The leftmost bitmap draw scales the width of corners proportionately to fit.
Herb Derbyefe39bc2018-05-01 17:06:20 -04003591 The third and fourth draw corners are not scaled; the sides and center are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04003592 fill the remaining space.
3593 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
3594 and below center to fill the remaining space.
3595##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003596void draw(SkCanvas* canvas) {
3597 SkIRect center = { 20, 10, 50, 40 };
3598 SkBitmap bitmap;
3599 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3600 SkCanvas bitCanvas(bitmap);
3601 SkPaint paint;
3602 SkColor gray = 0xFF000000;
3603 int left = 0;
3604 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3605 int top = 0;
3606 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3607 paint.setColor(gray);
3608 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3609 gray += 0x001f1f1f;
3610 top = bottom;
3611 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003612 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003613 }
3614 for (auto dest: { 20, 30, 40, 60, 90 } ) {
3615 canvas->drawBitmapNine(bitmap, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
3616 canvas->translate(dest + 4, 0);
3617 }
Cary Clark8032b982017-07-28 11:04:54 -04003618}
3619##
3620
Cary Clark2ade9972017-11-02 17:49:34 -04003621#SeeAlso drawImageNine drawBitmap drawBitmapLattice drawBitmapRect
Cary Clark8032b982017-07-28 11:04:54 -04003622
3623##
3624
3625# ------------------------------------------------------------------------------
Cary Clark682c58d2018-05-16 07:07:07 -04003626#Subtopic Lattice
3627#Line # divides Bitmap or Image into a rectangular grid ##
3628
Cary Clark8032b982017-07-28 11:04:54 -04003629#Struct Lattice
Cary Clark08895c42018-02-01 09:37:32 -05003630#Line # divides Bitmap or Image into a rectangular grid ##
Cary Clark682c58d2018-05-16 07:07:07 -04003631
Cary Clark8032b982017-07-28 11:04:54 -04003632#Code
Cary Clark61313f32018-10-08 14:57:48 -04003633#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003634##
3635
Cary Clark137b8742018-05-30 09:21:49 -04003636Lattice divides Bitmap or Image into a rectangular grid.
3637Grid entries on even columns and even rows are fixed; these entries are
3638always drawn at their original size if the destination is large enough.
3639If the destination side is too small to hold the fixed entries, all fixed
3640entries are proportionately scaled down to fit.
3641The grid entries not on even columns and rows are scaled to fit the
3642remaining space, if any.
3643
Cary Clark2f466242017-12-11 16:03:17 -05003644 #Enum RectType
Cary Clark682c58d2018-05-16 07:07:07 -04003645 #Line # optional setting per rectangular grid entry ##
Cary Clark8032b982017-07-28 11:04:54 -04003646 #Code
Cary Clark61313f32018-10-08 14:57:48 -04003647 #Populate
Cary Clark8032b982017-07-28 11:04:54 -04003648 ##
3649
Cary Clark2f466242017-12-11 16:03:17 -05003650 Optional setting per rectangular grid entry to make it transparent,
3651 or to fill the grid entry with a color.
Cary Clark8032b982017-07-28 11:04:54 -04003652
Cary Clark2f466242017-12-11 16:03:17 -05003653 #Const kDefault 0
Cary Clark682c58d2018-05-16 07:07:07 -04003654 #Line # draws Bitmap into lattice rectangle ##
Cary Clark2f466242017-12-11 16:03:17 -05003655 ##
3656
3657 #Const kTransparent 1
Cary Clark682c58d2018-05-16 07:07:07 -04003658 #Line # skips lattice rectangle by making it transparent ##
Cary Clark2f466242017-12-11 16:03:17 -05003659 ##
3660
3661 #Const kFixedColor 2
Cary Clark682c58d2018-05-16 07:07:07 -04003662 #Line # draws one of fColors into lattice rectangle ##
Cary Clark8032b982017-07-28 11:04:54 -04003663 ##
3664 ##
3665
Cary Clark61313f32018-10-08 14:57:48 -04003666#Subtopic Members
Cary Clark682c58d2018-05-16 07:07:07 -04003667##
3668
Cary Clark8032b982017-07-28 11:04:54 -04003669 #Member const int* fXDivs
Cary Clark5538c132018-06-14 12:28:14 -04003670 #Line # x-axis values dividing bitmap ##
3671 Array of x-axis values that divide the bitmap vertically.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003672 Array entries must be unique, increasing, greater than or equal to
3673 fBounds left edge, and less than fBounds right edge.
3674 Set the first element to fBounds left to collapse the left column of
3675 fixed grid entries.
Cary Clark8032b982017-07-28 11:04:54 -04003676 ##
3677
3678 #Member const int* fYDivs
Cary Clark5538c132018-06-14 12:28:14 -04003679 #Line # y-axis values dividing bitmap ##
3680 Array of y-axis values that divide the bitmap horizontally.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003681 Array entries must be unique, increasing, greater than or equal to
3682 fBounds top edge, and less than fBounds bottom edge.
3683 Set the first element to fBounds top to collapse the top row of fixed
3684 grid entries.
Cary Clark8032b982017-07-28 11:04:54 -04003685 ##
3686
Cary Clark2f466242017-12-11 16:03:17 -05003687 #Member const RectType* fRectTypes
Cary Clark682c58d2018-05-16 07:07:07 -04003688 #Line # array of fill types ##
Cary Clark2f466242017-12-11 16:03:17 -05003689 Optional array of fill types, one per rectangular grid entry:
Cary Clark2be81cf2018-09-13 12:04:30 -04003690 array length must be #Formula # (fXCount + 1) * (fYCount + 1) ##.
Cary Clark6fc50412017-09-21 12:31:06 -04003691
Cary Clark2f466242017-12-11 16:03:17 -05003692 Each RectType is one of: kDefault, kTransparent, kFixedColor.
3693
Cary Clark8032b982017-07-28 11:04:54 -04003694 Array entries correspond to the rectangular grid entries, ascending
3695 left to right and then top to bottom.
3696 ##
3697
3698 #Member int fXCount
Cary Clark682c58d2018-05-16 07:07:07 -04003699 #Line # number of x-coordinates ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003700 Number of entries in fXDivs array; one less than the number of
3701 horizontal divisions.
Cary Clark8032b982017-07-28 11:04:54 -04003702 ##
3703
3704 #Member int fYCount
Cary Clark682c58d2018-05-16 07:07:07 -04003705 #Line # number of y-coordinates ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003706 Number of entries in fYDivs array; one less than the number of vertical
3707 divisions.
Cary Clark8032b982017-07-28 11:04:54 -04003708 ##
3709
3710 #Member const SkIRect* fBounds
Cary Clark682c58d2018-05-16 07:07:07 -04003711 #Line # source bounds to draw from ##
Cary Clark8032b982017-07-28 11:04:54 -04003712 Optional subset IRect source to draw from.
3713 If nullptr, source bounds is dimensions of Bitmap or Image.
3714 ##
3715
Cary Clark2f466242017-12-11 16:03:17 -05003716 #Member const SkColor* fColors
Cary Clark682c58d2018-05-16 07:07:07 -04003717 #Line # array of colors ##
Cary Clark2f466242017-12-11 16:03:17 -05003718 Optional array of colors, one per rectangular grid entry.
Cary Clark2be81cf2018-09-13 12:04:30 -04003719 Array length must be #Formula # (fXCount + 1) * (fYCount + 1) ##.
Cary Clark2f466242017-12-11 16:03:17 -05003720
3721 Array entries correspond to the rectangular grid entries, ascending
3722 left to right, then top to bottom.
3723 ##
3724
Cary Clark8032b982017-07-28 11:04:54 -04003725#Struct Lattice ##
3726
3727#Method void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
3728 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003729#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003730#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003731#Line # draws proportionally stretched Bitmap ##
Cary Clark8032b982017-07-28 11:04:54 -04003732
Cary Clark80247e52018-07-11 16:18:41 -04003733Draws Bitmap bitmap stretched proportionally to fit into Rect dst.
Cary Clark8032b982017-07-28 11:04:54 -04003734
3735Lattice lattice divides bitmap into a rectangular grid.
3736Each intersection of an even-numbered row and column is fixed; like the corners
Cary Clarkbad5ad72017-08-03 17:14:08 -04003737of drawBitmapNine, fixed lattice elements never scale larger than their initial
Cary Clarkbc5697d2017-10-04 14:31:33 -04003738size and shrink proportionately when all fixed elements exceed the bitmap
Cary Clarkbad5ad72017-08-03 17:14:08 -04003739dimension. All other grid elements scale to fill the available space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003740
3741Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04003742
Cary Clark682c58d2018-05-16 07:07:07 -04003743#paint_as_used_by_draw_lattice_or_draw_nine(bitmap)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003744
3745If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
3746just as Shader made from SkShader::MakeBitmapShader with
Cary Clarkbc5697d2017-10-04 14:31:33 -04003747SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
Cary Clarkbad5ad72017-08-03 17:14:08 -04003748outside of its bounds.
3749
3750#Param bitmap Bitmap containing pixels, dimensions, and format ##
3751#Param lattice division of bitmap into fixed and variable rectangles ##
3752#Param dst destination Rect of image to draw to ##
3753#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3754 and so on; or nullptr
3755##
Cary Clark8032b982017-07-28 11:04:54 -04003756
3757#Example
3758#Height 128
3759#Description
3760 The two leftmost bitmap draws has four corners and sides to the left and right of center.
3761 The leftmost bitmap draw scales the width of corners proportionately to fit.
Herb Derbyefe39bc2018-05-01 17:06:20 -04003762 The third and fourth draw corners are not scaled; the sides are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04003763 fill the remaining space; the center is transparent.
3764 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
3765 and below center to fill the remaining space.
3766##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003767void draw(SkCanvas* canvas) {
3768 SkIRect center = { 20, 10, 50, 40 };
3769 SkBitmap bitmap;
3770 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3771 SkCanvas bitCanvas(bitmap);
3772 SkPaint paint;
3773 SkColor gray = 0xFF000000;
3774 int left = 0;
3775 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3776 int top = 0;
3777 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3778 paint.setColor(gray);
3779 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3780 gray += 0x001f1f1f;
3781 top = bottom;
3782 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003783 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003784 }
3785 const int xDivs[] = { center.fLeft, center.fRight };
3786 const int yDivs[] = { center.fTop, center.fBottom };
Cary Clarkca3ebcd2017-12-12 11:22:38 -05003787 SkCanvas::Lattice::RectType fillTypes[3][3];
3788 memset(fillTypes, 0, sizeof(fillTypes));
3789 fillTypes[1][1] = SkCanvas::Lattice::kTransparent;
3790 SkColor dummy[9]; // temporary pending bug fix
3791 SkCanvas::Lattice lattice = { xDivs, yDivs, fillTypes[0], SK_ARRAY_COUNT(xDivs),
3792 SK_ARRAY_COUNT(yDivs), nullptr, dummy };
Cary Clarkbad5ad72017-08-03 17:14:08 -04003793 for (auto dest: { 20, 30, 40, 60, 90 } ) {
Cary Clarkca3ebcd2017-12-12 11:22:38 -05003794 canvas->drawBitmapLattice(bitmap, lattice, SkRect::MakeWH(dest, 110 - dest), nullptr);
Cary Clarkbad5ad72017-08-03 17:14:08 -04003795 canvas->translate(dest + 4, 0);
3796 }
Cary Clark8032b982017-07-28 11:04:54 -04003797}
3798##
3799
Cary Clark2ade9972017-11-02 17:49:34 -04003800#SeeAlso drawImageLattice drawBitmap drawBitmapNine Lattice
Cary Clark8032b982017-07-28 11:04:54 -04003801
3802##
3803
3804# ------------------------------------------------------------------------------
3805
3806#Method void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
3807 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003808#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003809#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003810#Line # draws proportionally stretched Image ##
Cary Clark8032b982017-07-28 11:04:54 -04003811
Cary Clark80247e52018-07-11 16:18:41 -04003812Draws Image image stretched proportionally to fit into Rect dst.
Cary Clark8032b982017-07-28 11:04:54 -04003813
3814Lattice lattice divides image into a rectangular grid.
3815Each intersection of an even-numbered row and column is fixed; like the corners
Cary Clarkbad5ad72017-08-03 17:14:08 -04003816of drawBitmapNine, fixed lattice elements never scale larger than their initial
Cary Clarkbc5697d2017-10-04 14:31:33 -04003817size and shrink proportionately when all fixed elements exceed the bitmap
Cary Clarkbad5ad72017-08-03 17:14:08 -04003818dimension. All other grid elements scale to fill the available space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003819
3820Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04003821
Cary Clark682c58d2018-05-16 07:07:07 -04003822#paint_as_used_by_draw_lattice_or_draw_nine(image)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003823
3824If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
3825just as Shader made from SkShader::MakeBitmapShader with
Cary Clarkbc5697d2017-10-04 14:31:33 -04003826SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
Cary Clarkbad5ad72017-08-03 17:14:08 -04003827outside of its bounds.
3828
3829#Param image Image containing pixels, dimensions, and format ##
3830#Param lattice division of bitmap into fixed and variable rectangles ##
3831#Param dst destination Rect of image to draw to ##
3832#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3833 and so on; or nullptr
3834##
Cary Clark8032b982017-07-28 11:04:54 -04003835
3836#Example
3837#Height 128
3838#Description
3839 The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
Cary Clarkce101242017-09-01 15:51:02 -04003840 The second image equals the size of center; only corners are drawn without scaling.
3841 The remaining images are larger than center. All corners draw without scaling. The sides
Cary Clark8032b982017-07-28 11:04:54 -04003842 are scaled if needed to take up the remaining space; the center is transparent.
3843##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003844void draw(SkCanvas* canvas) {
3845 SkIRect center = { 20, 10, 50, 40 };
3846 SkBitmap bitmap;
3847 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3848 SkCanvas bitCanvas(bitmap);
3849 SkPaint paint;
3850 SkColor gray = 0xFF000000;
3851 int left = 0;
3852 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3853 int top = 0;
3854 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3855 paint.setColor(gray);
3856 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3857 gray += 0x001f1f1f;
3858 top = bottom;
3859 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003860 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003861 }
Cary Clarkbad5ad72017-08-03 17:14:08 -04003862 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3863 SkImage* imagePtr = image.get();
3864 for (auto dest: { 20, 30, 40, 60, 90 } ) {
3865 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
3866 canvas->translate(dest + 4, 0);
3867 }
Cary Clark8032b982017-07-28 11:04:54 -04003868}
3869##
3870
Cary Clark2ade9972017-11-02 17:49:34 -04003871#SeeAlso drawBitmapLattice drawImage drawImageNine Lattice
Cary Clark8032b982017-07-28 11:04:54 -04003872
3873##
3874
Cary Clark682c58d2018-05-16 07:07:07 -04003875#Subtopic Lattice ##
3876
Cary Clark08895c42018-02-01 09:37:32 -05003877#Subtopic Draw_Image ##
Cary Clark8032b982017-07-28 11:04:54 -04003878
3879# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -05003880#Subtopic Draw_Text
Cary Clark78de7512018-02-07 07:27:09 -05003881#Line # draws text into Canvas ##
3882##
Cary Clark8032b982017-07-28 11:04:54 -04003883
Mike Reedcb268f62019-01-07 12:51:32 -05003884#Method void drawSimpleText(const void* text, size_t byteLength, SkTextEncoding encoding,
3885 SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05003886#In Draw_Text
3887#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003888#Line # draws text at (x, y), using font advance ##
Cary Clark09d80c02018-10-31 12:14:03 -04003889#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003890
3891#Example
3892#Height 200
3893#Description
Mike Reedcb268f62019-01-07 12:51:32 -05003894The same text is drawn varying Paint_Text_Size and varying
3895Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04003896##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003897void draw(SkCanvas* canvas) {
3898 SkPaint paint;
Mike Reedcb268f62019-01-07 12:51:32 -05003899 SkFont font;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003900 float textSizes[] = { 12, 18, 24, 36 };
3901 for (auto size: textSizes ) {
Mike Reedcb268f62019-01-07 12:51:32 -05003902 font.setSize(size);
3903 canvas->drawText("Aa", 2, kUTF8_SkTextEncoding, 10, 20, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04003904 canvas->translate(0, size * 2);
3905 }
Mike Reedcb268f62019-01-07 12:51:32 -05003906 font.setSize(12);
Cary Clarkbad5ad72017-08-03 17:14:08 -04003907 float yPos = 20;
3908 for (auto size: textSizes ) {
3909 float scale = size / 12.f;
3910 canvas->resetMatrix();
3911 canvas->translate(100, 0);
3912 canvas->scale(scale, scale);
Mike Reedcb268f62019-01-07 12:51:32 -05003913 canvas->drawText("Aa", 2, kUTF8_SkTextEncoding, 10 / scale, yPos / scale, font, paint);
Herb Derbyefe39bc2018-05-01 17:06:20 -04003914 yPos += size * 2;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003915 }
3916}
Cary Clark8032b982017-07-28 11:04:54 -04003917##
3918
Mike Reed53a11f52019-01-03 12:18:06 -05003919#SeeAlso drawString drawTextBlob
Cary Clark8032b982017-07-28 11:04:54 -04003920
3921##
3922
Cary Clark8032b982017-07-28 11:04:54 -04003923# ------------------------------------------------------------------------------
3924
3925#Method void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05003926#In Draw_Text
3927#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003928#Line # draws text with arrays of positions and Paint ##
Cary Clark80247e52018-07-11 16:18:41 -04003929Draws Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003930
Cary Clarkce101242017-09-01 15:51:02 -04003931blob contains Glyphs, their positions, and paint attributes specific to text:
Cary Clark3e73dcf2018-12-06 08:41:14 -05003932#font_metrics#.
Cary Clark8032b982017-07-28 11:04:54 -04003933
Mike Reed0f9d33e2018-12-05 10:54:05 -05003934Paint_Text_Encoding must be set to kGlyphID_SkTextEncoding.
Cary Clark3cd22cc2017-12-01 11:49:58 -05003935
Cary Clarkd2ca79c2018-08-10 13:09:13 -04003936Elements of paint: Anti_Alias, Blend_Mode, Color including Color_Alpha,
3937Color_Filter, Paint_Dither, Draw_Looper, Mask_Filter, Path_Effect, Shader, and
Cary Clark61313f32018-10-08 14:57:48 -04003938Paint_Style; apply to blob. If Paint contains SkPaint::kStroke_Style:
Cary Clarkd2ca79c2018-08-10 13:09:13 -04003939Paint_Miter_Limit, Paint_Stroke_Cap, Paint_Stroke_Join, and Paint_Stroke_Width;
3940apply to Path created from blob.
Cary Clark8032b982017-07-28 11:04:54 -04003941
Cary Clarkce101242017-09-01 15:51:02 -04003942#Param blob Glyphs, positions, and their paints' text size, typeface, and so on ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003943#Param x horizontal offset applied to blob ##
3944#Param y vertical offset applied to blob ##
3945#Param paint blend, color, stroking, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003946
3947#Example
3948#Height 120
Cary Clarke80cd442018-07-17 13:19:56 -04003949void draw(SkCanvas* canvas) {
Mike Reed0f9d33e2018-12-05 10:54:05 -05003950 SkTextBlobBuilder textBlobBuilder;
3951 const char bunny[] = "/(^x^)\\";
3952 const int len = sizeof(bunny) - 1;
3953 uint16_t glyphs[len];
Mike Reed0f9d33e2018-12-05 10:54:05 -05003954 SkFont font;
Cary Clark26d173f2019-01-07 15:16:56 -05003955 font.textToGlyphs(bunny, len, SkTextEncoding::kUTF8, glyphs, len);
Mike Reed0f9d33e2018-12-05 10:54:05 -05003956 int runs[] = { 3, 1, 3 };
3957 SkPoint textPos = { 20, 100 };
3958 int glyphIndex = 0;
3959 for (auto runLen : runs) {
3960 font.setSize(1 == runLen ? 20 : 50);
3961 const SkTextBlobBuilder::RunBuffer& run =
3962 textBlobBuilder.allocRun(font, runLen, textPos.fX, textPos.fY);
3963 memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen);
Cary Clark26d173f2019-01-07 15:16:56 -05003964 font.setSize(1 == runLen ? 20 : 50);
3965 textPos.fX += font.measureText(&glyphs[glyphIndex], sizeof(glyphs[0]) * runLen,
3966 SkTextEncoding::kGlyphID);
Mike Reed0f9d33e2018-12-05 10:54:05 -05003967 glyphIndex += runLen;
3968 }
3969 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
Cary Clark26d173f2019-01-07 15:16:56 -05003970 canvas->drawTextBlob(blob.get(), 0, 0, SkPaint());
Cary Clarke80cd442018-07-17 13:19:56 -04003971}
Cary Clark8032b982017-07-28 11:04:54 -04003972##
3973
Mike Reed53a11f52019-01-03 12:18:06 -05003974#SeeAlso drawText
Cary Clark8032b982017-07-28 11:04:54 -04003975
3976##
3977
3978# ------------------------------------------------------------------------------
3979
Herb Derbyefe39bc2018-05-01 17:06:20 -04003980#Method void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint)
Cary Clark8032b982017-07-28 11:04:54 -04003981
Cary Clark80247e52018-07-11 16:18:41 -04003982Draws Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003983
Cary Clarkce101242017-09-01 15:51:02 -04003984blob contains Glyphs, their positions, and paint attributes specific to text:
Cary Clark3e73dcf2018-12-06 08:41:14 -05003985#font_metrics#.
Cary Clark8032b982017-07-28 11:04:54 -04003986
Mike Reed0f9d33e2018-12-05 10:54:05 -05003987Paint_Text_Encoding must be set to kGlyphID_SkTextEncoding.
Cary Clark3cd22cc2017-12-01 11:49:58 -05003988
Herb Derbyefe39bc2018-05-01 17:06:20 -04003989Elements of paint: Path_Effect, Mask_Filter, Shader, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -04003990Image_Filter, and Draw_Looper; apply to blob.
3991
Cary Clarkce101242017-09-01 15:51:02 -04003992#Param blob Glyphs, positions, and their paints' text size, typeface, and so on ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003993#Param x horizontal offset applied to blob ##
3994#Param y vertical offset applied to blob ##
3995#Param paint blend, color, stroking, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04003996
3997#Example
3998#Height 120
3999#Description
Cary Clark8032b982017-07-28 11:04:54 -04004000Paint attributes related to text, like text size, have no effect on paint passed to drawTextBlob.
4001##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004002 void draw(SkCanvas* canvas) {
4003 SkTextBlobBuilder textBlobBuilder;
Cary Clarkfc93eb02018-11-24 22:32:31 -05004004 SkFont font;
4005 font.setSize(50);
Herb Derbyefe39bc2018-05-01 17:06:20 -04004006 const SkTextBlobBuilder::RunBuffer& run =
Cary Clarkfc93eb02018-11-24 22:32:31 -05004007 textBlobBuilder.allocRun(font, 1, 20, 100);
Cary Clarkbad5ad72017-08-03 17:14:08 -04004008 run.glyphs[0] = 20;
4009 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
Cary Clarkfc93eb02018-11-24 22:32:31 -05004010 SkPaint paint;
Cary Clarkbad5ad72017-08-03 17:14:08 -04004011 paint.setTextSize(10);
4012 paint.setColor(SK_ColorBLUE);
4013 canvas->drawTextBlob(blob.get(), 0, 0, paint);
4014 }
Cary Clark8032b982017-07-28 11:04:54 -04004015##
4016
Mike Reed53a11f52019-01-03 12:18:06 -05004017#SeeAlso drawText
Cary Clark8032b982017-07-28 11:04:54 -04004018
4019##
4020
4021# ------------------------------------------------------------------------------
4022
Herb Derbyefe39bc2018-05-01 17:06:20 -04004023#Method void drawPicture(const SkPicture* picture)
Cary Clark78de7512018-02-07 07:27:09 -05004024#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004025#Line # draws Picture using Clip and Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04004026#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004027
4028#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04004029void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04004030 SkPictureRecorder recorder;
4031 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
4032 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
4033 SkPaint paint;
4034 paint.setColor(color);
4035 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
4036 recordingCanvas->translate(10, 10);
4037 recordingCanvas->scale(1.2f, 1.4f);
4038 }
4039 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
Cary Clarkbad5ad72017-08-03 17:14:08 -04004040 canvas->drawPicture(playback);
4041 canvas->scale(2, 2);
4042 canvas->translate(50, 0);
4043 canvas->drawPicture(playback);
Cary Clark8032b982017-07-28 11:04:54 -04004044}
4045##
4046
Cary Clark2ade9972017-11-02 17:49:34 -04004047#SeeAlso drawDrawable SkPicture SkPicture::playback
Cary Clark8032b982017-07-28 11:04:54 -04004048
4049##
4050
4051# ------------------------------------------------------------------------------
4052
Herb Derbyefe39bc2018-05-01 17:06:20 -04004053#Method void drawPicture(const sk_sp<SkPicture>& picture)
Cary Clark09d80c02018-10-31 12:14:03 -04004054#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004055
4056#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04004057void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04004058 SkPictureRecorder recorder;
4059 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
4060 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
4061 SkPaint paint;
4062 paint.setColor(color);
4063 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
4064 recordingCanvas->translate(10, 10);
4065 recordingCanvas->scale(1.2f, 1.4f);
4066 }
4067 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
4068 canvas->drawPicture(playback);
4069 canvas->scale(2, 2);
4070 canvas->translate(50, 0);
4071 canvas->drawPicture(playback);
Cary Clark8032b982017-07-28 11:04:54 -04004072}
4073##
4074
Cary Clark2ade9972017-11-02 17:49:34 -04004075#SeeAlso drawDrawable SkPicture SkPicture::playback
Cary Clark8032b982017-07-28 11:04:54 -04004076
4077##
4078
4079# ------------------------------------------------------------------------------
4080
4081#Method void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004082#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004083
4084#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04004085void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04004086 SkPaint paint;
4087 SkPictureRecorder recorder;
4088 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
4089 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
4090 paint.setColor(color);
4091 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
4092 recordingCanvas->translate(10, 10);
4093 recordingCanvas->scale(1.2f, 1.4f);
4094 }
4095 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
4096 const SkPicture* playbackPtr = playback.get();
4097 SkMatrix matrix;
4098 matrix.reset();
4099 for (auto alpha : { 70, 140, 210 } ) {
4100 paint.setAlpha(alpha);
4101 canvas->drawPicture(playbackPtr, &matrix, &paint);
4102 matrix.preTranslate(70, 70);
4103 }
Cary Clark8032b982017-07-28 11:04:54 -04004104}
4105##
4106
Cary Clark2ade9972017-11-02 17:49:34 -04004107#SeeAlso drawDrawable SkPicture SkPicture::playback
Cary Clark8032b982017-07-28 11:04:54 -04004108
4109##
4110
4111# ------------------------------------------------------------------------------
4112
Herb Derbyefe39bc2018-05-01 17:06:20 -04004113#Method void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004114#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004115
4116#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04004117void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04004118 SkPaint paint;
4119 SkPictureRecorder recorder;
4120 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
4121 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
4122 paint.setColor(color);
4123 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
4124 recordingCanvas->translate(10, 10);
4125 recordingCanvas->scale(1.2f, 1.4f);
4126 }
4127 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
4128 SkMatrix matrix;
4129 matrix.reset();
4130 for (auto alpha : { 70, 140, 210 } ) {
4131 paint.setAlpha(alpha);
4132 canvas->drawPicture(playback, &matrix, &paint);
4133 matrix.preTranslate(70, 70);
4134 }
Cary Clark8032b982017-07-28 11:04:54 -04004135}
4136##
4137
Cary Clark2ade9972017-11-02 17:49:34 -04004138#SeeAlso drawDrawable SkPicture SkPicture::playback
Cary Clark8032b982017-07-28 11:04:54 -04004139
4140##
4141
4142# ------------------------------------------------------------------------------
4143
4144#Method void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05004145#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004146#Line # draws Vertices, a triangle mesh ##
Cary Clark09d80c02018-10-31 12:14:03 -04004147#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004148
4149#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004150void draw(SkCanvas* canvas) {
4151 SkPaint paint;
4152 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
4153 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4154 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
4155 SK_ARRAY_COUNT(points), points, nullptr, colors);
4156 canvas->drawVertices(vertices.get(), SkBlendMode::kSrc, paint);
4157}
Cary Clark8032b982017-07-28 11:04:54 -04004158##
4159
Cary Clark2ade9972017-11-02 17:49:34 -04004160#SeeAlso drawPatch drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004161
4162##
4163
4164# ------------------------------------------------------------------------------
4165
4166#Method void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004167#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004168
4169#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004170void draw(SkCanvas* canvas) {
4171 SkPaint paint;
4172 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
4173 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
4174 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4175 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
4176 SkShader::kClamp_TileMode));
4177 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
4178 SK_ARRAY_COUNT(points), points, texs, colors);
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004179 canvas->drawVertices(vertices, SkBlendMode::kDarken, paint);
4180}
4181##
4182
4183#SeeAlso drawPatch drawPicture
4184
4185##
4186
4187# ------------------------------------------------------------------------------
4188
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004189#Method void drawVertices(const SkVertices* vertices, const SkVertices::Bone bones[],
4190 int boneCount, SkBlendMode mode, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004191#Populate
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004192
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004193#NoExample
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004194void draw(SkCanvas* canvas) {
4195 SkPaint paint;
4196 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
4197 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
4198 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4199 SkVertices::BoneIndices boneIndices[] = { { 0, 0, 0, 0 },
4200 { 1, 0, 0, 0 },
4201 { 2, 0, 0, 0 },
4202 { 3, 0, 0, 0 } };
4203 SkVertices::BoneWeights boneWeights[] = { { 0.0f, 0.0f, 0.0f, 0.0f },
4204 { 1.0f, 0.0f, 0.0f, 0.0f },
4205 { 1.0f, 0.0f, 0.0f, 0.0f },
4206 { 1.0f, 0.0f, 0.0f, 0.0f } };
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004207 SkVertices::Bone bones[] = { {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }},
4208 {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 20.0f }},
4209 {{ 1.0f, 0.0f, 0.0f, 1.0f, 50.0f, 50.0f }},
4210 {{ 1.0f, 0.0f, 0.0f, 1.0f, 20.0f, 0.0f }} };
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004211 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
4212 SkShader::kClamp_TileMode));
4213 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
4214 SK_ARRAY_COUNT(points), points, texs, colors, boneIndices, boneWeights);
4215 canvas->drawVertices(vertices.get(), bones, SK_ARRAY_COUNT(bones), SkBlendMode::kDarken, paint);
4216}
4217##
4218
4219#SeeAlso drawPatch drawPicture
4220
4221##
4222
4223# ------------------------------------------------------------------------------
4224
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004225#Method void drawVertices(const sk_sp<SkVertices>& vertices, const SkVertices::Bone bones[],
4226 int boneCount, SkBlendMode mode, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004227#Populate
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004228
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004229#NoExample
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004230void draw(SkCanvas* canvas) {
4231 SkPaint paint;
4232 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
4233 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
4234 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4235 SkVertices::BoneIndices boneIndices[] = { { 0, 0, 0, 0 },
4236 { 1, 0, 0, 0 },
4237 { 2, 0, 0, 0 },
4238 { 3, 0, 0, 0 } };
4239 SkVertices::BoneWeights boneWeights[] = { { 0.0f, 0.0f, 0.0f, 0.0f },
4240 { 1.0f, 0.0f, 0.0f, 0.0f },
4241 { 1.0f, 0.0f, 0.0f, 0.0f },
4242 { 1.0f, 0.0f, 0.0f, 0.0f } };
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004243 SkVertices::Bone bones[] = { {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }},
4244 {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 20.0f }},
4245 {{ 1.0f, 0.0f, 0.0f, 1.0f, 50.0f, 50.0f }},
4246 {{ 1.0f, 0.0f, 0.0f, 1.0f, 20.0f, 0.0f }} };
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004247 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
4248 SkShader::kClamp_TileMode));
4249 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
4250 SK_ARRAY_COUNT(points), points, texs, colors, boneIndices, boneWeights);
4251 canvas->drawVertices(vertices, bones, SK_ARRAY_COUNT(bones), SkBlendMode::kDarken, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004252}
4253##
4254
Cary Clark2ade9972017-11-02 17:49:34 -04004255#SeeAlso drawPatch drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004256
4257##
4258
4259# ------------------------------------------------------------------------------
4260
4261#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
4262 const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05004263#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004264#Line # draws Coons_Patch ##
Cary Clark09d80c02018-10-31 12:14:03 -04004265#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004266
4267#Example
4268#Image 5
Cary Clarkbad5ad72017-08-03 17:14:08 -04004269void draw(SkCanvas* canvas) {
4270 // SkBitmap source = cmbkygk;
4271 SkPaint paint;
4272 paint.setFilterQuality(kLow_SkFilterQuality);
4273 paint.setAntiAlias(true);
4274 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
4275 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
4276 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
4277 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
4278 SkColor colors[] = { 0xbfff0000, 0xbf0000ff, 0xbfff00ff, 0xbf00ffff };
4279 SkPoint texCoords[] = { { -30, -30 }, { 162, -30}, { 162, 162}, { -30, 162} };
4280 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
4281 SkShader::kClamp_TileMode, nullptr));
4282 canvas->scale(15, 15);
4283 for (auto blend : { SkBlendMode::kSrcOver, SkBlendMode::kModulate, SkBlendMode::kXor } ) {
4284 canvas->drawPatch(cubics, colors, texCoords, blend, paint);
4285 canvas->translate(4, 4);
4286 }
Cary Clark8032b982017-07-28 11:04:54 -04004287}
4288##
4289
Cary Clark2ade9972017-11-02 17:49:34 -04004290#ToDo can patch use image filter? ##
Cary Clark77b3f3a2018-11-07 14:59:03 -05004291#SeeAlso drawVertices drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004292
4293##
4294
4295# ------------------------------------------------------------------------------
4296
4297#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
Herb Derbyefe39bc2018-05-01 17:06:20 -04004298 const SkPoint texCoords[4], const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004299#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004300
4301#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004302void draw(SkCanvas* canvas) {
4303 SkPaint paint;
4304 paint.setAntiAlias(true);
4305 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
4306 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
4307 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
4308 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
4309 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4310 canvas->scale(30, 30);
4311 canvas->drawPatch(cubics, colors, nullptr, paint);
4312 SkPoint text[] = { {3,0.9f}, {4,2.5f}, {5,0.9f}, {7.5f,3.2f}, {5.5f,4.2f},
4313 {7.5f,5.2f}, {5,7.5f}, {4,5.9f}, {3,7.5f}, {0.5f,5.2f}, {2.5f,4.2f},
4314 {0.5f,3.2f} };
Mike Reed33535cb2019-01-09 11:25:18 -05004315
4316 SkFont font(nullptr, 18.f / 30);
Cary Clarkbad5ad72017-08-03 17:14:08 -04004317 for (int i = 0; i< 10; ++i) {
4318 char digit = '0' + i;
Mike Reed33535cb2019-01-09 11:25:18 -05004319 canvas->drawSimpleText(&digit, kUTF8_SkTextEncoding, 1, text[i].fX, text[i].fY, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04004320 }
Mike Reed33535cb2019-01-09 11:25:18 -05004321 canvas->drawString("10", text[10].fX, text[10].fY, font, paint);
4322 canvas->drawString("11", text[11].fX, text[11].fY, font, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04004323 paint.setStyle(SkPaint::kStroke_Style);
4324 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 12, cubics, paint);
4325 canvas->drawLine(cubics[11].fX, cubics[11].fY, cubics[0].fX, cubics[0].fY, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004326}
4327##
4328
4329#Example
4330#Image 6
Cary Clarkbad5ad72017-08-03 17:14:08 -04004331void draw(SkCanvas* canvas) {
4332 // SkBitmap source = checkerboard;
4333 SkPaint paint;
4334 paint.setFilterQuality(kLow_SkFilterQuality);
4335 paint.setAntiAlias(true);
4336 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
4337 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
4338 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
4339 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
4340 SkPoint texCoords[] = { { 0, 0 }, { 0, 62}, { 62, 62}, { 62, 0 } };
4341 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
4342 SkShader::kClamp_TileMode, nullptr));
4343 canvas->scale(30, 30);
4344 canvas->drawPatch(cubics, nullptr, texCoords, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004345}
4346##
4347
Cary Clark2ade9972017-11-02 17:49:34 -04004348#ToDo can patch use image filter? ##
Cary Clark77b3f3a2018-11-07 14:59:03 -05004349#SeeAlso drawVertices drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004350
4351##
4352
4353# ------------------------------------------------------------------------------
4354
4355#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
4356 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
4357 const SkPaint* paint)
Cary Clark78de7512018-02-07 07:27:09 -05004358#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004359#Line # draws sprites using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04004360#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004361
4362#Example
4363#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04004364void draw(SkCanvas* canvas) {
4365 // SkBitmap source = mandrill;
4366 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
4367 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
4368 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
4369 const SkImage* imagePtr = image.get();
4370 canvas->drawAtlas(imagePtr, xforms, tex, colors, 2, SkBlendMode::kSrcOver, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04004371}
4372##
4373
Cary Clark2ade9972017-11-02 17:49:34 -04004374#SeeAlso drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04004375
4376##
4377
4378# ------------------------------------------------------------------------------
4379
4380#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
4381 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
Herb Derbyefe39bc2018-05-01 17:06:20 -04004382 const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004383#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004384
4385#Example
4386#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04004387void draw(SkCanvas* canvas) {
4388 // SkBitmap source = mandrill;
4389 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
4390 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
4391 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
4392 SkPaint paint;
4393 paint.setAlpha(127);
4394 canvas->drawAtlas(image, xforms, tex, colors, 2, SkBlendMode::kPlus, nullptr, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04004395}
4396##
4397
4398#ToDo bug in example on cpu side, gpu looks ok ##
4399
Cary Clark2ade9972017-11-02 17:49:34 -04004400#SeeAlso drawBitmap drawImage
4401
Cary Clark8032b982017-07-28 11:04:54 -04004402##
4403
4404# ------------------------------------------------------------------------------
4405
4406#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
Herb Derbyefe39bc2018-05-01 17:06:20 -04004407 const SkRect* cullRect, const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004408#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004409
4410#Example
4411#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04004412void draw(SkCanvas* canvas) {
4413 // sk_sp<SkImage> image = mandrill;
4414 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
4415 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
4416 const SkImage* imagePtr = image.get();
4417 canvas->drawAtlas(imagePtr, xforms, tex, 2, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04004418}
4419##
4420
Cary Clark2ade9972017-11-02 17:49:34 -04004421#SeeAlso drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04004422
4423##
4424
4425# ------------------------------------------------------------------------------
4426
4427#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
Herb Derbyefe39bc2018-05-01 17:06:20 -04004428 int count, const SkRect* cullRect, const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004429#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004430
4431#Example
4432#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04004433void draw(SkCanvas* canvas) {
4434 // sk_sp<SkImage> image = mandrill;
4435 SkRSXform xforms[] = { { 1, 0, 0, 0 }, {0, 1, 300, 100 } };
4436 SkRect tex[] = { { 0, 0, 200, 200 }, { 200, 0, 400, 200 } };
4437 canvas->drawAtlas(image, xforms, tex, 2, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04004438}
4439##
4440
Cary Clark2ade9972017-11-02 17:49:34 -04004441#SeeAlso drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04004442
4443##
4444
4445# ------------------------------------------------------------------------------
4446
Cary Clark73fa9722017-08-29 17:36:51 -04004447#Method void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr)
Cary Clark78de7512018-02-07 07:27:09 -05004448#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004449#Line # draws Drawable, encapsulated drawing commands ##
Cary Clark09d80c02018-10-31 12:14:03 -04004450#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004451
4452#Example
4453#Height 100
4454#Function
Cary Clarkbad5ad72017-08-03 17:14:08 -04004455struct MyDrawable : public SkDrawable {
4456 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
4457
4458 void onDraw(SkCanvas* canvas) override {
4459 SkPath path;
4460 path.conicTo(10, 90, 50, 90, 0.9f);
4461 SkPaint paint;
4462 paint.setColor(SK_ColorBLUE);
4463 canvas->drawRect(path.getBounds(), paint);
4464 paint.setAntiAlias(true);
4465 paint.setColor(SK_ColorWHITE);
4466 canvas->drawPath(path, paint);
4467 }
4468};
4469
4470#Function ##
4471void draw(SkCanvas* canvas) {
4472 sk_sp<SkDrawable> drawable(new MyDrawable);
4473 SkMatrix matrix;
4474 matrix.setTranslate(10, 10);
4475 canvas->drawDrawable(drawable.get(), &matrix);
Cary Clark8032b982017-07-28 11:04:54 -04004476}
4477##
4478
Cary Clark2ade9972017-11-02 17:49:34 -04004479#SeeAlso SkDrawable drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004480
4481##
4482
4483# ------------------------------------------------------------------------------
4484
4485#Method void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y)
Cary Clark09d80c02018-10-31 12:14:03 -04004486#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004487
4488#Example
4489#Height 100
4490#Function
Cary Clarkbad5ad72017-08-03 17:14:08 -04004491struct MyDrawable : public SkDrawable {
4492 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
4493
4494 void onDraw(SkCanvas* canvas) override {
4495 SkPath path;
4496 path.conicTo(10, 90, 50, 90, 0.9f);
4497 SkPaint paint;
4498 paint.setColor(SK_ColorBLUE);
4499 canvas->drawRect(path.getBounds(), paint);
4500 paint.setAntiAlias(true);
4501 paint.setColor(SK_ColorWHITE);
4502 canvas->drawPath(path, paint);
4503 }
4504};
4505
4506#Function ##
4507void draw(SkCanvas* canvas) {
4508 sk_sp<SkDrawable> drawable(new MyDrawable);
4509 canvas->drawDrawable(drawable.get(), 10, 10);
Cary Clark8032b982017-07-28 11:04:54 -04004510}
4511##
4512
Cary Clark2ade9972017-11-02 17:49:34 -04004513#SeeAlso SkDrawable drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004514
4515##
4516
4517# ------------------------------------------------------------------------------
4518
4519#Method void drawAnnotation(const SkRect& rect, const char key[], SkData* value)
Cary Clark78de7512018-02-07 07:27:09 -05004520#In Draw
4521#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004522#Line # associates a Rect with a key-value pair ##
Cary Clark09d80c02018-10-31 12:14:03 -04004523#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004524
4525#Example
4526 #Height 1
4527 const char text[] = "Click this link!";
4528 SkRect bounds;
4529 SkPaint paint;
Cary Clark26d173f2019-01-07 15:16:56 -05004530 SkFont font(nullptr, 40);
4531 (void)font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
Cary Clark8032b982017-07-28 11:04:54 -04004532 const char url[] = "https://www.google.com/";
4533 sk_sp<SkData> urlData(SkData::MakeWithCString(url));
4534 canvas->drawAnnotation(bounds, "url_key", urlData.get());
4535##
4536
Cary Clark2ade9972017-11-02 17:49:34 -04004537#SeeAlso SkPicture SkDocument
Cary Clark8032b982017-07-28 11:04:54 -04004538
4539##
4540
4541# ------------------------------------------------------------------------------
4542
Herb Derbyefe39bc2018-05-01 17:06:20 -04004543#Method void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value)
Cary Clark09d80c02018-10-31 12:14:03 -04004544#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004545
4546#Example
4547#Height 1
4548 const char text[] = "Click this link!";
4549 SkRect bounds;
4550 SkPaint paint;
Cary Clark26d173f2019-01-07 15:16:56 -05004551 SkFont font(nullptr, 40);
4552 (void)font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
Cary Clark8032b982017-07-28 11:04:54 -04004553 const char url[] = "https://www.google.com/";
4554 sk_sp<SkData> urlData(SkData::MakeWithCString(url));
4555 canvas->drawAnnotation(bounds, "url_key", urlData.get());
4556##
4557
Cary Clark2ade9972017-11-02 17:49:34 -04004558#SeeAlso SkPicture SkDocument
Cary Clark8032b982017-07-28 11:04:54 -04004559
4560##
4561
Cary Clark8032b982017-07-28 11:04:54 -04004562# ------------------------------------------------------------------------------
4563
4564#Method virtual bool isClipEmpty() const
Cary Clark78de7512018-02-07 07:27:09 -05004565#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -05004566#Line # returns if Clip is empty ##
Cary Clark09d80c02018-10-31 12:14:03 -04004567#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004568
4569#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004570 void draw(SkCanvas* canvas) {
4571 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
4572 SkPath path;
4573 canvas->clipPath(path);
4574 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
Cary Clark8032b982017-07-28 11:04:54 -04004575 }
4576 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04004577 clip is not empty
Cary Clark8032b982017-07-28 11:04:54 -04004578 clip is empty
4579 ##
4580##
4581
Cary Clark2ade9972017-11-02 17:49:34 -04004582#SeeAlso isClipRect getLocalClipBounds getDeviceClipBounds
Cary Clark8032b982017-07-28 11:04:54 -04004583
4584##
4585
4586# ------------------------------------------------------------------------------
4587
4588#Method virtual bool isClipRect() const
Cary Clark78de7512018-02-07 07:27:09 -05004589#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -05004590#Line # returns if Clip is Rect and not empty ##
Cary Clark09d80c02018-10-31 12:14:03 -04004591#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004592
4593#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004594 void draw(SkCanvas* canvas) {
4595 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
4596 canvas->clipRect({0, 0, 0, 0});
4597 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
Cary Clark8032b982017-07-28 11:04:54 -04004598 }
4599 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04004600 clip is rect
Cary Clark8032b982017-07-28 11:04:54 -04004601 clip is not rect
4602 ##
4603##
4604
Cary Clark2ade9972017-11-02 17:49:34 -04004605#SeeAlso isClipEmpty getLocalClipBounds getDeviceClipBounds
Cary Clark8032b982017-07-28 11:04:54 -04004606
4607##
4608
4609#Class SkCanvas ##
Cary Clark884dd7d2017-10-11 10:37:52 -04004610
Cary Clark8032b982017-07-28 11:04:54 -04004611#Topic Canvas ##