blob: dbce6a8b18d40d363e5114f0bf645c3cc36bda63 [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
213 canvas.drawString("!", 1, 10, paint); // 1 char at baseline (1, 10)
214 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
263 canvas.drawString("!", 1, 10, paint); // 1 char at baseline (1, 10)
264 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;
310 paint.setTextSize(100);
311 offscreen.drawString("ABC", 20, 160, paint);
312 SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192);
313 offscreen.saveLayerAlpha(&layerBounds, 128);
314 offscreen.clear(SK_ColorWHITE);
315 offscreen.drawString("DEF", 20, 160, paint);
316 }
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;
532 paint.setTextSize(100);
533 canvas->drawString("ABC", 20, 160, paint);
534 SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192);
535 canvas->saveLayerAlpha(&layerBounds, 128);
536 canvas->clear(SK_ColorWHITE);
537 canvas->drawString("DEF", 20, 160, paint);
538 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
1009save(), saveLayer, saveLayerPreserveLCDTextRequests, and saveLayerAlpha
1010save 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
Cary Clarka90ea222018-10-16 10:30:28 -04001065#SeeAlso save saveLayer saveLayerPreserveLCDTextRequests 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
Cary Clarka90ea222018-10-16 10:30:28 -04001093#SeeAlso saveLayer saveLayerPreserveLCDTextRequests 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
Cary Clarka90ea222018-10-16 10:30:28 -04001114#SeeAlso save saveLayer saveLayerPreserveLCDTextRequests 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
Cary Clarka90ea222018-10-16 10:30:28 -04001226#SeeAlso save restore saveLayer saveLayerPreserveLCDTextRequests 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
Cary Clarka90ea222018-10-16 10:30:28 -04001261#SeeAlso save restore saveLayerPreserveLCDTextRequests saveLayerAlpha SaveLayerRec
Cary Clarkce101242017-09-01 15:51:02 -04001262
1263##
1264
1265#Method int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint)
1266
Cary Clarkab2621d2018-01-30 10:08:57 -05001267#In Layer
1268#Line # saves Clip and Matrix on stack; creates Layer for LCD text ##
Cary Clark09d80c02018-10-31 12:14:03 -04001269#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001270
1271#Example
1272 SkPaint paint;
1273 paint.setAntiAlias(true);
1274 paint.setLCDRenderText(true);
1275 paint.setTextSize(20);
1276 for (auto preserve : { false, true } ) {
1277 preserve ? canvas->saveLayerPreserveLCDTextRequests(nullptr, nullptr)
1278 : canvas->saveLayer(nullptr, nullptr);
1279 SkPaint p;
1280 p.setColor(SK_ColorWHITE);
1281 // Comment out the next line to draw on a non-opaque background.
1282 canvas->drawRect(SkRect::MakeLTRB(25, 40, 200, 70), p);
1283 canvas->drawString("Hamburgefons", 30, 60, paint);
1284
1285 p.setColor(0xFFCCCCCC);
1286 canvas->drawRect(SkRect::MakeLTRB(25, 70, 200, 100), p);
1287 canvas->drawString("Hamburgefons", 30, 90, paint);
1288
1289 canvas->restore();
1290 canvas->translate(0, 80);
1291 }
1292 ##
1293
Cary Clarka90ea222018-10-16 10:30:28 -04001294#SeeAlso save restore saveLayer saveLayerAlpha SaveLayerRec
Cary Clarkce101242017-09-01 15:51:02 -04001295
1296##
1297
1298#Method int saveLayerAlpha(const SkRect* bounds, U8CPU alpha)
1299
Cary Clarkab2621d2018-01-30 10:08:57 -05001300#In Layer
1301#Line # saves Clip and Matrix on stack; creates Layer; sets opacity ##
Cary Clark09d80c02018-10-31 12:14:03 -04001302#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001303
1304#Example
1305 SkPaint paint;
1306 paint.setColor(SK_ColorRED);
1307 canvas->drawCircle(50, 50, 50, paint);
1308 canvas->saveLayerAlpha(nullptr, 128);
1309 paint.setColor(SK_ColorBLUE);
1310 canvas->drawCircle(100, 50, 50, paint);
1311 paint.setColor(SK_ColorGREEN);
1312 paint.setAlpha(128);
1313 canvas->drawCircle(75, 90, 50, paint);
1314 canvas->restore();
1315##
1316
Cary Clarka90ea222018-10-16 10:30:28 -04001317#SeeAlso save restore saveLayer saveLayerPreserveLCDTextRequests SaveLayerRec
Cary Clarkce101242017-09-01 15:51:02 -04001318
1319##
1320
Cary Clarkd98f78c2018-04-26 08:32:37 -04001321#Enum SaveLayerFlagsSet
Cary Clark08895c42018-02-01 09:37:32 -05001322#Line # sets SaveLayerRec options ##
Cary Clarkce101242017-09-01 15:51:02 -04001323#Code
Cary Clark61313f32018-10-08 14:57:48 -04001324#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001325##
1326
Cary Clark682c58d2018-05-16 07:07:07 -04001327
1328#Typedef uint32_t SaveLayerFlags
1329#Line # options for SaveLayerRec ##
Cary Clark137b8742018-05-30 09:21:49 -04001330##
Cary Clark682c58d2018-05-16 07:07:07 -04001331
Cary Clarkce101242017-09-01 15:51:02 -04001332SaveLayerFlags provides options that may be used in any combination in SaveLayerRec,
Cary Clark682c58d2018-05-16 07:07:07 -04001333defining how Layer allocated by saveLayer operates. It may be set to zero,
1334kPreserveLCDText_SaveLayerFlag, kInitWithPrevious_SaveLayerFlag, or both flags.
1335
Cary Clarkce101242017-09-01 15:51:02 -04001336#Const kPreserveLCDText_SaveLayerFlag 2
Cary Clark682c58d2018-05-16 07:07:07 -04001337#Line # creates Layer for LCD text ##
Cary Clarkce101242017-09-01 15:51:02 -04001338 Creates Layer for LCD text. Flag is ignored if Layer Paint contains
1339 Image_Filter or Color_Filter.
1340##
1341
1342#Const kInitWithPrevious_SaveLayerFlag 4
Cary Clark682c58d2018-05-16 07:07:07 -04001343#Line # initializes with previous contents ##
Cary Clarkce101242017-09-01 15:51:02 -04001344 Initializes Layer with the contents of the previous Layer.
1345##
1346
Cary Clarkce101242017-09-01 15:51:02 -04001347#Example
1348#Height 160
1349#Description
1350Canvas Layer captures red and blue circles scaled up by four.
Herb Derbyefe39bc2018-05-01 17:06:20 -04001351scalePaint blends Layer back with transparency.
Cary Clarkce101242017-09-01 15:51:02 -04001352##
1353void draw(SkCanvas* canvas) {
1354 SkPaint redPaint, bluePaint, scalePaint;
1355 redPaint.setColor(SK_ColorRED);
1356 canvas->drawCircle(21, 21, 8, redPaint);
1357 bluePaint.setColor(SK_ColorBLUE);
1358 canvas->drawCircle(31, 21, 8, bluePaint);
1359 SkMatrix matrix;
1360 matrix.setScale(4, 4);
1361 scalePaint.setAlpha(0x40);
1362 scalePaint.setImageFilter(
1363 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
1364 SkCanvas::SaveLayerRec saveLayerRec(nullptr, &scalePaint,
Herb Derbyefe39bc2018-05-01 17:06:20 -04001365 SkCanvas::kInitWithPrevious_SaveLayerFlag);
Cary Clarkce101242017-09-01 15:51:02 -04001366 canvas->saveLayer(saveLayerRec);
1367 canvas->restore();
1368}
1369##
1370
Cary Clarka90ea222018-10-16 10:30:28 -04001371#SeeAlso save restore saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha SaveLayerRec
Cary Clarkce101242017-09-01 15:51:02 -04001372
1373#Enum ##
1374
Cary Clark682c58d2018-05-16 07:07:07 -04001375#Subtopic SaveLayerRec
1376#Line # contains the state used to create the Layer ##
Cary Clarka560c472017-11-27 10:44:06 -05001377
Cary Clarkce101242017-09-01 15:51:02 -04001378#Struct SaveLayerRec
Cary Clark08895c42018-02-01 09:37:32 -05001379#Line # contains the state used to create the Layer ##
Cary Clark682c58d2018-05-16 07:07:07 -04001380
Cary Clarkce101242017-09-01 15:51:02 -04001381#Code
Cary Clark61313f32018-10-08 14:57:48 -04001382#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001383##
1384
Cary Clark137b8742018-05-30 09:21:49 -04001385SaveLayerRec contains the state used to create the Layer.
1386
Cary Clarkce101242017-09-01 15:51:02 -04001387#Member const SkRect* fBounds
Cary Clark682c58d2018-05-16 07:07:07 -04001388#Line # hints at Layer size limit ##
Cary Clarkce101242017-09-01 15:51:02 -04001389 fBounds is used as a hint to limit the size of Layer; may be nullptr.
1390 fBounds suggests but does not define Layer size. To clip drawing to
1391 a specific rectangle, use clipRect.
1392##
1393
1394#Member const SkPaint* fPaint
Cary Clark682c58d2018-05-16 07:07:07 -04001395#Line # modifies overlay ##
Cary Clarkce101242017-09-01 15:51:02 -04001396 fPaint modifies how Layer overlays the prior Layer; may be nullptr.
1397 Color_Alpha, Blend_Mode, Color_Filter, Draw_Looper, Image_Filter, and
1398 Mask_Filter affect Layer draw.
1399##
1400
1401#Member const SkImageFilter* fBackdrop
Cary Clark682c58d2018-05-16 07:07:07 -04001402#Line # applies Image_Filter to prior Layer ##
Cary Clarkce101242017-09-01 15:51:02 -04001403 fBackdrop applies Image_Filter to the prior Layer when copying to the Layer;
1404 may be nullptr. Use kInitWithPrevious_SaveLayerFlag to copy the
1405 prior Layer without an Image_Filter.
1406##
1407
1408#Member const SkImage* fClipMask
Cary Clark682c58d2018-05-16 07:07:07 -04001409#Line # clips Layer with Mask_Alpha ##
Cary Clarkce101242017-09-01 15:51:02 -04001410 restore() clips Layer by the Color_Alpha channel of fClipMask when
1411 Layer is copied to Device. fClipMask may be nullptr. .
1412##
1413
1414#Member const SkMatrix* fClipMatrix
Cary Clark682c58d2018-05-16 07:07:07 -04001415#Line # transforms Mask_Alpha used to clip ##
Herb Derbyefe39bc2018-05-01 17:06:20 -04001416 fClipMatrix transforms fClipMask before it clips Layer. If
Cary Clarkce101242017-09-01 15:51:02 -04001417 fClipMask describes a translucent gradient, it may be scaled and rotated
1418 without introducing artifacts. fClipMatrix may be nullptr.
1419##
1420
1421#Member SaveLayerFlags fSaveLayerFlags
Cary Clark682c58d2018-05-16 07:07:07 -04001422#Line # preserves LCD Text, creates with prior Layer contents ##
Cary Clarkce101242017-09-01 15:51:02 -04001423 fSaveLayerFlags are used to create Layer without transparency,
1424 create Layer for LCD text, and to create Layer with the
1425 contents of the previous Layer.
1426##
1427
1428#Example
1429#Height 160
1430#Description
Cary Clarkffb3d682018-05-17 12:17:28 -04001431Canvas Layer captures a red Anti_Aliased circle and a blue Aliased circle scaled
Cary Clarkce101242017-09-01 15:51:02 -04001432up by four. After drawing another red circle without scaling on top, the Layer is
Herb Derbyefe39bc2018-05-01 17:06:20 -04001433transferred to the main canvas.
Cary Clarkce101242017-09-01 15:51:02 -04001434##
1435void draw(SkCanvas* canvas) {
1436 SkPaint redPaint, bluePaint;
1437 redPaint.setAntiAlias(true);
1438 redPaint.setColor(SK_ColorRED);
1439 canvas->drawCircle(21, 21, 8, redPaint);
1440 bluePaint.setColor(SK_ColorBLUE);
1441 canvas->drawCircle(31, 21, 8, bluePaint);
1442 SkMatrix matrix;
1443 matrix.setScale(4, 4);
1444 auto scaler = SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr);
Herb Derbyefe39bc2018-05-01 17:06:20 -04001445 SkCanvas::SaveLayerRec saveLayerRec(nullptr, nullptr, scaler.get(), 0);
Cary Clarkce101242017-09-01 15:51:02 -04001446 canvas->saveLayer(saveLayerRec);
1447 canvas->drawCircle(125, 85, 8, redPaint);
1448 canvas->restore();
1449}
1450##
1451
Cary Clark61313f32018-10-08 14:57:48 -04001452#Subtopic Constructors
Cary Clark682c58d2018-05-16 07:07:07 -04001453##
Cary Clarkce101242017-09-01 15:51:02 -04001454
Cary Clark682c58d2018-05-16 07:07:07 -04001455#Method SaveLayerRec()
1456#Line # constructs SaveLayerRec ##
Cary Clark09d80c02018-10-31 12:14:03 -04001457#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001458
1459#Example
1460 SkCanvas::SaveLayerRec rec1;
Mike Kleine083f7c2018-02-07 12:54:27 -05001461 rec1.fSaveLayerFlags = SkCanvas::kPreserveLCDText_SaveLayerFlag;
1462 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, SkCanvas::kPreserveLCDText_SaveLayerFlag);
Cary Clarkce101242017-09-01 15:51:02 -04001463 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1464 && rec1.fPaint == rec2.fPaint
1465 && rec1.fBackdrop == rec2.fBackdrop
1466 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1467 #StdOut
1468 rec1 == rec2
1469 ##
1470##
1471
Cary Clarka90ea222018-10-16 10:30:28 -04001472#SeeAlso save restore saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha
Cary Clark2ade9972017-11-02 17:49:34 -04001473
Cary Clarkce101242017-09-01 15:51:02 -04001474##
1475
Cary Clark224c7002018-06-27 11:00:21 -04001476#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
Cary Clark09d80c02018-10-31 12:14:03 -04001477#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001478
1479#Example
1480 SkCanvas::SaveLayerRec rec1;
1481 SkCanvas::SaveLayerRec rec2(nullptr, nullptr);
1482 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1483 && rec1.fPaint == rec2.fPaint
1484 && rec1.fBackdrop == rec2.fBackdrop
1485 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1486 #StdOut
1487 rec1 == rec2
1488 ##
1489##
1490
Cary Clarka90ea222018-10-16 10:30:28 -04001491#SeeAlso save restore saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha
Cary Clark2ade9972017-11-02 17:49:34 -04001492
Cary Clarkce101242017-09-01 15:51:02 -04001493##
1494
1495#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
1496 SaveLayerFlags saveLayerFlags)
Cary Clark09d80c02018-10-31 12:14:03 -04001497#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001498
1499#Example
1500 SkCanvas::SaveLayerRec rec1;
1501 SkCanvas::SaveLayerRec rec2(nullptr, nullptr, nullptr, 0);
1502 SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
1503 && rec1.fPaint == rec2.fPaint
1504 && rec1.fBackdrop == rec2.fBackdrop
1505 && rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
1506 #StdOut
1507 rec1 == rec2
1508 ##
1509##
1510
Cary Clarka90ea222018-10-16 10:30:28 -04001511#SeeAlso save restore saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha
Cary Clark2ade9972017-11-02 17:49:34 -04001512
Cary Clarkce101242017-09-01 15:51:02 -04001513##
1514
Cary Clarkce101242017-09-01 15:51:02 -04001515#Struct ##
1516
Cary Clark682c58d2018-05-16 07:07:07 -04001517#Subtopic ##
1518
Cary Clarkce101242017-09-01 15:51:02 -04001519#Method int saveLayer(const SaveLayerRec& layerRec)
1520
Cary Clarkab2621d2018-01-30 10:08:57 -05001521#In Layer
Cary Clark09d80c02018-10-31 12:14:03 -04001522#Populate
Cary Clarkce101242017-09-01 15:51:02 -04001523
1524#Example
1525#Description
1526The example draws an image, and saves it into a Layer with kInitWithPrevious_SaveLayerFlag.
1527Next it punches a hole in Layer and restore with SkBlendMode::kPlus.
1528Where Layer was cleared, the original image will draw unchanged.
1529Outside of the circle the mandrill is brightened.
1530##
1531 #Image 3
Hal Canaryc465d132017-12-08 10:21:31 -05001532 // sk_sp<SkImage> image = GetResourceAsImage("images/mandrill_256.png");
Cary Clarkce101242017-09-01 15:51:02 -04001533 canvas->drawImage(image, 0, 0, nullptr);
1534 SkCanvas::SaveLayerRec rec;
1535 SkPaint paint;
1536 paint.setBlendMode(SkBlendMode::kPlus);
1537 rec.fSaveLayerFlags = SkCanvas::kInitWithPrevious_SaveLayerFlag;
1538 rec.fPaint = &paint;
1539 canvas->saveLayer(rec);
1540 paint.setBlendMode(SkBlendMode::kClear);
1541 canvas->drawCircle(128, 128, 96, paint);
1542 canvas->restore();
1543##
1544
1545#ToDo above example needs to replace GetResourceAsImage with way to select image in fiddle ##
1546
Cary Clarka90ea222018-10-16 10:30:28 -04001547#SeeAlso save restore saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha
Cary Clark2ade9972017-11-02 17:49:34 -04001548
Cary Clarkce101242017-09-01 15:51:02 -04001549##
1550
Cary Clark08895c42018-02-01 09:37:32 -05001551#Subtopic Layer ##
Cary Clarkce101242017-09-01 15:51:02 -04001552
1553# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001554#Subtopic Matrix
1555#Line # coordinate transformation ##
Cary Clark8032b982017-07-28 11:04:54 -04001556
1557#Method void translate(SkScalar dx, SkScalar dy)
1558
Cary Clarkab2621d2018-01-30 10:08:57 -05001559#In Matrix
1560#Line # translates Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001561#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001562
1563#Example
1564#Height 128
1565#Description
1566scale() followed by translate() produces different results from translate() followed
Herb Derbyefe39bc2018-05-01 17:06:20 -04001567by scale().
Cary Clark8032b982017-07-28 11:04:54 -04001568
1569The blue stroke follows translate of (50, 50); a black
Herb Derbyefe39bc2018-05-01 17:06:20 -04001570fill follows scale of (2, 1/2.f). After restoring the clip, which resets
Cary Clark8032b982017-07-28 11:04:54 -04001571Matrix, a red frame follows the same scale of (2, 1/2.f); a gray fill
1572follows translate of (50, 50).
1573##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001574void draw(SkCanvas* canvas) {
1575 SkPaint filledPaint;
1576 SkPaint outlinePaint;
1577 outlinePaint.setStyle(SkPaint::kStroke_Style);
1578 outlinePaint.setColor(SK_ColorBLUE);
1579 canvas->save();
1580 canvas->translate(50, 50);
1581 canvas->drawCircle(28, 28, 15, outlinePaint); // blue center: (50+28, 50+28)
1582 canvas->scale(2, 1/2.f);
1583 canvas->drawCircle(28, 28, 15, filledPaint); // black center: (50+(28*2), 50+(28/2))
1584 canvas->restore();
1585 filledPaint.setColor(SK_ColorGRAY);
1586 outlinePaint.setColor(SK_ColorRED);
1587 canvas->scale(2, 1/2.f);
1588 canvas->drawCircle(28, 28, 15, outlinePaint); // red center: (28*2, 28/2)
1589 canvas->translate(50, 50);
1590 canvas->drawCircle(28, 28, 15, filledPaint); // gray center: ((50+28)*2, (50+28)/2)
Cary Clark8032b982017-07-28 11:04:54 -04001591}
1592##
1593
Cary Clark2ade9972017-11-02 17:49:34 -04001594#SeeAlso concat() scale() skew() rotate() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001595
1596##
1597
1598# ------------------------------------------------------------------------------
1599
1600#Method void scale(SkScalar sx, SkScalar sy)
1601
Cary Clarkab2621d2018-01-30 10:08:57 -05001602#In Matrix
1603#Line # scales Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001604#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001605
1606#Example
1607#Height 160
Cary Clarkbad5ad72017-08-03 17:14:08 -04001608void draw(SkCanvas* canvas) {
1609 SkPaint paint;
1610 SkRect rect = { 10, 20, 60, 120 };
1611 canvas->translate(20, 20);
1612 canvas->drawRect(rect, paint);
1613 canvas->scale(2, .5f);
1614 paint.setColor(SK_ColorGRAY);
1615 canvas->drawRect(rect, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001616}
1617##
1618
Cary Clark2ade9972017-11-02 17:49:34 -04001619#SeeAlso concat() translate() skew() rotate() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001620
1621##
1622
1623# ------------------------------------------------------------------------------
1624
1625#Method void rotate(SkScalar degrees)
1626
Cary Clarkab2621d2018-01-30 10:08:57 -05001627#In Matrix
1628#Line # rotates Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001629#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001630
1631#Example
1632#Description
1633Draw clock hands at time 5:10. The hour hand and minute hand point up and
1634are rotated clockwise.
1635##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001636void draw(SkCanvas* canvas) {
1637 SkPaint paint;
1638 paint.setStyle(SkPaint::kStroke_Style);
1639 canvas->translate(128, 128);
1640 canvas->drawCircle(0, 0, 60, paint);
1641 canvas->save();
1642 canvas->rotate(10 * 360 / 60); // 10 minutes of 60 scaled to 360 degrees
Herb Derbyefe39bc2018-05-01 17:06:20 -04001643 canvas->drawLine(0, 0, 0, -50, paint);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001644 canvas->restore();
1645 canvas->rotate((5 + 10.f/60) * 360 / 12); // 5 and 10/60 hours of 12 scaled to 360 degrees
1646 canvas->drawLine(0, 0, 0, -30, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001647}
1648##
1649
Cary Clark2ade9972017-11-02 17:49:34 -04001650#SeeAlso concat() translate() skew() scale() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001651
1652##
1653
1654# ------------------------------------------------------------------------------
1655
1656#Method void rotate(SkScalar degrees, SkScalar px, SkScalar py)
1657
Cary Clarkab2621d2018-01-30 10:08:57 -05001658#In Matrix
Cary Clark09d80c02018-10-31 12:14:03 -04001659#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001660
1661#Example
1662#Height 192
Cary Clarkbad5ad72017-08-03 17:14:08 -04001663void draw(SkCanvas* canvas) {
1664 SkPaint paint;
1665 paint.setTextSize(96);
1666 canvas->drawString("A1", 130, 100, paint);
1667 canvas->rotate(180, 130, 100);
1668 canvas->drawString("A1", 130, 100, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001669}
1670##
1671
Cary Clark2ade9972017-11-02 17:49:34 -04001672#SeeAlso concat() translate() skew() scale() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001673
1674##
1675
1676# ------------------------------------------------------------------------------
1677
1678#Method void skew(SkScalar sx, SkScalar sy)
1679
Cary Clarkab2621d2018-01-30 10:08:57 -05001680#In Matrix
1681#Line # skews Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001682#Populate
Cary Clarkbad5ad72017-08-03 17:14:08 -04001683
Cary Clark8032b982017-07-28 11:04:54 -04001684#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04001685 #Description
Cary Clark5538c132018-06-14 12:28:14 -04001686 Black text mimics an oblique text style by using a negative skew on x-axis
1687 that shifts the geometry to the right as the y-axis values decrease.
1688 Red text uses a positive skew on y-axis to shift the geometry down
1689 as the x-axis values increase.
1690 Blue text combines sx and sy skew to rotate and scale.
Cary Clark8032b982017-07-28 11:04:54 -04001691 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001692 SkPaint paint;
1693 paint.setTextSize(128);
1694 canvas->translate(30, 130);
1695 canvas->save();
1696 canvas->skew(-.5, 0);
1697 canvas->drawString("A1", 0, 0, paint);
1698 canvas->restore();
1699 canvas->save();
1700 canvas->skew(0, .5);
1701 paint.setColor(SK_ColorRED);
1702 canvas->drawString("A1", 0, 0, paint);
1703 canvas->restore();
1704 canvas->skew(-.5, .5);
1705 paint.setColor(SK_ColorBLUE);
Cary Clark8032b982017-07-28 11:04:54 -04001706 canvas->drawString("A1", 0, 0, paint);
1707##
1708
Cary Clark2ade9972017-11-02 17:49:34 -04001709#SeeAlso concat() translate() rotate() scale() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001710
1711##
1712
1713# ------------------------------------------------------------------------------
1714
1715#Method void concat(const SkMatrix& matrix)
1716
Cary Clarkab2621d2018-01-30 10:08:57 -05001717#In Matrix
1718#Line # multiplies Matrix by Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001719#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001720
1721#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001722void draw(SkCanvas* canvas) {
1723 SkPaint paint;
1724 paint.setTextSize(80);
1725 paint.setTextScaleX(.3);
1726 SkMatrix matrix;
1727 SkRect rect[2] = {{ 10, 20, 90, 110 }, { 40, 130, 140, 180 }};
1728 matrix.setRectToRect(rect[0], rect[1], SkMatrix::kFill_ScaleToFit);
1729 canvas->drawRect(rect[0], paint);
1730 canvas->drawRect(rect[1], paint);
1731 paint.setColor(SK_ColorWHITE);
1732 canvas->drawString("Here", rect[0].fLeft + 10, rect[0].fBottom - 10, paint);
1733 canvas->concat(matrix);
1734 canvas->drawString("There", rect[0].fLeft + 10, rect[0].fBottom - 10, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001735}
1736##
1737
Cary Clark2ade9972017-11-02 17:49:34 -04001738#SeeAlso translate() rotate() scale() skew() setMatrix
Cary Clark8032b982017-07-28 11:04:54 -04001739
1740##
1741
1742# ------------------------------------------------------------------------------
1743
1744#Method void setMatrix(const SkMatrix& matrix)
1745
Cary Clarkab2621d2018-01-30 10:08:57 -05001746#In Matrix
1747#Line # sets Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001748#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001749
1750#Example
1751#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001752void draw(SkCanvas* canvas) {
1753 SkPaint paint;
1754 canvas->scale(4, 6);
1755 canvas->drawString("truth", 2, 10, paint);
1756 SkMatrix matrix;
1757 matrix.setScale(2.8f, 6);
1758 canvas->setMatrix(matrix);
1759 canvas->drawString("consequences", 2, 20, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001760}
1761##
1762
Cary Clark2ade9972017-11-02 17:49:34 -04001763#SeeAlso resetMatrix concat() translate() rotate() scale() skew()
Cary Clark8032b982017-07-28 11:04:54 -04001764
1765##
1766
1767# ------------------------------------------------------------------------------
1768
1769#Method void resetMatrix()
1770
Cary Clarkab2621d2018-01-30 10:08:57 -05001771#In Matrix
1772#Line # resets Matrix to identity ##
Cary Clark09d80c02018-10-31 12:14:03 -04001773#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001774
1775#Example
1776#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001777void draw(SkCanvas* canvas) {
1778 SkPaint paint;
1779 canvas->scale(4, 6);
1780 canvas->drawString("truth", 2, 10, paint);
1781 canvas->resetMatrix();
1782 canvas->scale(2.8f, 6);
1783 canvas->drawString("consequences", 2, 20, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001784}
1785##
1786
Cary Clark2ade9972017-11-02 17:49:34 -04001787#SeeAlso setMatrix concat() translate() rotate() scale() skew()
Cary Clark8032b982017-07-28 11:04:54 -04001788
1789##
1790
1791# ------------------------------------------------------------------------------
1792
1793#Method const SkMatrix& getTotalMatrix() const
1794
Cary Clarkab2621d2018-01-30 10:08:57 -05001795#In Matrix
1796#Line # returns Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04001797#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001798
1799#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04001800 SkDebugf("isIdentity %s\n", canvas->getTotalMatrix().isIdentity() ? "true" : "false");
1801 #StdOut
1802 isIdentity true
1803 ##
Cary Clark8032b982017-07-28 11:04:54 -04001804##
1805
Cary Clark2ade9972017-11-02 17:49:34 -04001806#SeeAlso setMatrix resetMatrix concat()
Cary Clark8032b982017-07-28 11:04:54 -04001807
1808##
1809
Cary Clark08895c42018-02-01 09:37:32 -05001810#Subtopic Matrix ##
Cary Clark8032b982017-07-28 11:04:54 -04001811
1812# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05001813#Subtopic Clip
1814#Line # stack of clipping Paths ##
Cary Clark8032b982017-07-28 11:04:54 -04001815
1816Clip is built from a stack of clipping paths. Each Path in the
Herb Derbyefe39bc2018-05-01 17:06:20 -04001817stack can be constructed from one or more Path_Contour elements. The
Cary Clark8032b982017-07-28 11:04:54 -04001818Path_Contour may be composed of any number of Path_Verb segments. Each
1819Path_Contour forms a closed area; Path_Fill_Type defines the area enclosed
1820by Path_Contour.
1821
1822Clip stack of Path elements successfully restrict the Path area. Each
Herb Derbyefe39bc2018-05-01 17:06:20 -04001823Path is transformed by Matrix, then intersected with or subtracted from the
Cary Clark8032b982017-07-28 11:04:54 -04001824prior Clip to form the replacement Clip. Use SkClipOp::kDifference
1825to subtract Path from Clip; use SkClipOp::kIntersect to intersect Path
1826with Clip.
1827
Cary Clarkffb3d682018-05-17 12:17:28 -04001828A clipping Path may be Anti_Aliased; if Path, after transformation, is
1829composed of horizontal and vertical lines, clearing Anti_Alias allows whole pixels
Cary Clarkce101242017-09-01 15:51:02 -04001830to either be inside or outside the clip. The fastest drawing has a Aliased,
1831rectangular clip.
Cary Clark8032b982017-07-28 11:04:54 -04001832
Cary Clarkffb3d682018-05-17 12:17:28 -04001833If clipping Path has Anti_Alias set, clip may partially clip a pixel, requiring
Herb Derbyefe39bc2018-05-01 17:06:20 -04001834that drawing blend partially with the destination along the edge. A rotated
Cary Clarkffb3d682018-05-17 12:17:28 -04001835rectangular Anti_Aliased clip looks smoother but draws slower.
Cary Clark8032b982017-07-28 11:04:54 -04001836
1837Clip can combine with Rect and Round_Rect primitives; like
1838Path, these are transformed by Matrix before they are combined with Clip.
1839
1840Clip can combine with Region. Region is assumed to be in Device coordinates
1841and is unaffected by Matrix.
1842
1843#Example
1844#Height 90
1845 #Description
Cary Clarkffb3d682018-05-17 12:17:28 -04001846 Draw a red circle with an Aliased clip and an Anti_Aliased clip.
Cary Clark8032b982017-07-28 11:04:54 -04001847 Use an image filter to zoom into the pixels drawn.
Cary Clarkce101242017-09-01 15:51:02 -04001848 The edge of the Aliased clip fully draws pixels in the red circle.
Cary Clarkffb3d682018-05-17 12:17:28 -04001849 The edge of the Anti_Aliased clip partially draws pixels in the red circle.
Cary Clark8032b982017-07-28 11:04:54 -04001850 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001851 SkPaint redPaint, scalePaint;
1852 redPaint.setAntiAlias(true);
1853 redPaint.setColor(SK_ColorRED);
1854 canvas->save();
1855 for (bool antialias : { false, true } ) {
1856 canvas->save();
1857 canvas->clipRect(SkRect::MakeWH(19.5f, 11.5f), antialias);
1858 canvas->drawCircle(17, 11, 8, redPaint);
1859 canvas->restore();
1860 canvas->translate(16, 0);
1861 }
1862 canvas->restore();
1863 SkMatrix matrix;
1864 matrix.setScale(6, 6);
1865 scalePaint.setImageFilter(
1866 SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
1867 SkCanvas::SaveLayerRec saveLayerRec(
Herb Derbyefe39bc2018-05-01 17:06:20 -04001868 nullptr, &scalePaint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
Cary Clarkbad5ad72017-08-03 17:14:08 -04001869 canvas->saveLayer(saveLayerRec);
Cary Clark8032b982017-07-28 11:04:54 -04001870 canvas->restore();
1871##
1872
1873#Method void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias)
1874
Cary Clarkab2621d2018-01-30 10:08:57 -05001875#In Clip
1876#Line # combines Clip with Rect ##
Cary Clark09d80c02018-10-31 12:14:03 -04001877#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001878
1879#Example
1880#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001881void draw(SkCanvas* canvas) {
1882 canvas->rotate(10);
1883 SkPaint paint;
1884 paint.setAntiAlias(true);
1885 for (auto alias: { false, true } ) {
1886 canvas->save();
1887 canvas->clipRect(SkRect::MakeWH(90, 80), SkClipOp::kIntersect, alias);
1888 canvas->drawCircle(100, 60, 60, paint);
1889 canvas->restore();
1890 canvas->translate(80, 0);
1891 }
Cary Clark8032b982017-07-28 11:04:54 -04001892}
1893##
1894
Cary Clark2ade9972017-11-02 17:49:34 -04001895#SeeAlso clipRRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001896
1897##
1898
Herb Derbyefe39bc2018-05-01 17:06:20 -04001899#Method void clipRect(const SkRect& rect, SkClipOp op)
Cary Clark8032b982017-07-28 11:04:54 -04001900
Cary Clarkab2621d2018-01-30 10:08:57 -05001901#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04001902#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001903
1904#Example
1905#Height 192
1906#Width 280
Cary Clarkbad5ad72017-08-03 17:14:08 -04001907void draw(SkCanvas* canvas) {
1908 SkPaint paint;
1909 for (SkClipOp op: { SkClipOp::kIntersect, SkClipOp::kDifference } ) {
1910 canvas->save();
1911 canvas->clipRect(SkRect::MakeWH(90, 120), op, false);
1912 canvas->drawCircle(100, 100, 60, paint);
1913 canvas->restore();
1914 canvas->translate(80, 0);
1915 }
Cary Clark8032b982017-07-28 11:04:54 -04001916}
1917##
1918
Cary Clark2ade9972017-11-02 17:49:34 -04001919#SeeAlso clipRRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001920
1921##
1922
Herb Derbyefe39bc2018-05-01 17:06:20 -04001923#Method void clipRect(const SkRect& rect, bool doAntiAlias = false)
Cary Clark8032b982017-07-28 11:04:54 -04001924
Cary Clarkab2621d2018-01-30 10:08:57 -05001925#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04001926#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001927
1928#Example
1929#Height 133
1930 #Description
Cary Clarkce101242017-09-01 15:51:02 -04001931 A circle drawn in pieces looks uniform when drawn Aliased.
Cary Clarkffb3d682018-05-17 12:17:28 -04001932 The same circle pieces blend with pixels more than once when Anti_Aliased,
Cary Clark8032b982017-07-28 11:04:54 -04001933 visible as a thin pair of lines through the right circle.
1934 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04001935void draw(SkCanvas* canvas) {
1936 canvas->clear(SK_ColorWHITE);
1937 SkPaint paint;
1938 paint.setAntiAlias(true);
1939 paint.setColor(0x8055aaff);
1940 SkRect clipRect = { 0, 0, 87.4f, 87.4f };
1941 for (auto alias: { false, true } ) {
1942 canvas->save();
1943 canvas->clipRect(clipRect, SkClipOp::kIntersect, alias);
1944 canvas->drawCircle(67, 67, 60, paint);
1945 canvas->restore();
1946 canvas->save();
1947 canvas->clipRect(clipRect, SkClipOp::kDifference, alias);
1948 canvas->drawCircle(67, 67, 60, paint);
1949 canvas->restore();
1950 canvas->translate(120, 0);
1951 }
Cary Clark8032b982017-07-28 11:04:54 -04001952}
1953##
1954
Cary Clark2ade9972017-11-02 17:49:34 -04001955#SeeAlso clipRRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001956
1957##
1958
Cary Clark8032b982017-07-28 11:04:54 -04001959#Method void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias)
1960
Cary Clarkab2621d2018-01-30 10:08:57 -05001961#In Clip
1962#Line # combines Clip with Round_Rect ##
Cary Clark09d80c02018-10-31 12:14:03 -04001963#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001964
1965#Example
1966#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001967void draw(SkCanvas* canvas) {
1968 canvas->clear(SK_ColorWHITE);
1969 SkPaint paint;
1970 paint.setAntiAlias(true);
1971 paint.setColor(0x8055aaff);
1972 SkRRect oval;
1973 oval.setOval({10, 20, 90, 100});
1974 canvas->clipRRect(oval, SkClipOp::kIntersect, true);
1975 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001976}
1977##
1978
Cary Clark2ade9972017-11-02 17:49:34 -04001979#SeeAlso clipRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04001980
1981##
1982
Herb Derbyefe39bc2018-05-01 17:06:20 -04001983#Method void clipRRect(const SkRRect& rrect, SkClipOp op)
Cary Clark8032b982017-07-28 11:04:54 -04001984
Cary Clarkab2621d2018-01-30 10:08:57 -05001985#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04001986#Populate
Cary Clark8032b982017-07-28 11:04:54 -04001987
1988#Example
1989#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04001990void draw(SkCanvas* canvas) {
1991 SkPaint paint;
1992 paint.setColor(0x8055aaff);
1993 auto oval = SkRRect::MakeOval({10, 20, 90, 100});
1994 canvas->clipRRect(oval, SkClipOp::kIntersect);
1995 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04001996}
1997##
1998
Cary Clark2ade9972017-11-02 17:49:34 -04001999#SeeAlso clipRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04002000
2001##
2002
Herb Derbyefe39bc2018-05-01 17:06:20 -04002003#Method void clipRRect(const SkRRect& rrect, bool doAntiAlias = false)
Cary Clark8032b982017-07-28 11:04:54 -04002004
Cary Clarkab2621d2018-01-30 10:08:57 -05002005#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002006#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002007
2008#Example
2009#Height 128
Cary Clarkbad5ad72017-08-03 17:14:08 -04002010void draw(SkCanvas* canvas) {
2011 SkPaint paint;
2012 paint.setAntiAlias(true);
2013 auto oval = SkRRect::MakeRectXY({10, 20, 90, 100}, 9, 13);
2014 canvas->clipRRect(oval, true);
2015 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002016}
2017##
2018
Cary Clark2ade9972017-11-02 17:49:34 -04002019#SeeAlso clipRect clipPath clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04002020
2021##
2022
2023#Method void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias)
2024
Cary Clarkab2621d2018-01-30 10:08:57 -05002025#In Clip
2026#Line # combines Clip with Path ##
Cary Clark09d80c02018-10-31 12:14:03 -04002027#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002028
2029#Example
2030#Description
2031Top figure uses SkPath::kInverseWinding_FillType and SkClipOp::kDifference;
2032area outside clip is subtracted from circle.
2033
2034Bottom figure uses SkPath::kWinding_FillType and SkClipOp::kIntersect;
2035area inside clip is intersected with circle.
2036##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002037void draw(SkCanvas* canvas) {
2038 SkPaint paint;
2039 paint.setAntiAlias(true);
2040 SkPath path;
2041 path.addRect({20, 30, 100, 110});
2042 path.setFillType(SkPath::kInverseWinding_FillType);
2043 canvas->save();
2044 canvas->clipPath(path, SkClipOp::kDifference, false);
2045 canvas->drawCircle(70, 100, 60, paint);
2046 canvas->restore();
2047 canvas->translate(100, 100);
2048 path.setFillType(SkPath::kWinding_FillType);
2049 canvas->clipPath(path, SkClipOp::kIntersect, false);
2050 canvas->drawCircle(70, 100, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002051}
2052##
2053
Cary Clark2ade9972017-11-02 17:49:34 -04002054#SeeAlso clipRect clipRRect clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04002055
2056##
2057
Herb Derbyefe39bc2018-05-01 17:06:20 -04002058#Method void clipPath(const SkPath& path, SkClipOp op)
Cary Clark8032b982017-07-28 11:04:54 -04002059
Cary Clarkab2621d2018-01-30 10:08:57 -05002060#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002061#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002062
2063#Example
2064#Description
Cary Clarkbc5697d2017-10-04 14:31:33 -04002065Overlapping Rects form a clip. When clip Path_Fill_Type is set to
Herb Derbyefe39bc2018-05-01 17:06:20 -04002066SkPath::kWinding_FillType, the overlap is included. Set to
Cary Clark8032b982017-07-28 11:04:54 -04002067SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
2068##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002069void draw(SkCanvas* canvas) {
2070 SkPaint paint;
2071 paint.setAntiAlias(true);
2072 SkPath path;
2073 path.addRect({20, 15, 100, 95});
2074 path.addRect({50, 65, 130, 135});
2075 path.setFillType(SkPath::kWinding_FillType);
2076 canvas->save();
2077 canvas->clipPath(path, SkClipOp::kIntersect);
2078 canvas->drawCircle(70, 85, 60, paint);
2079 canvas->restore();
2080 canvas->translate(100, 100);
2081 path.setFillType(SkPath::kEvenOdd_FillType);
2082 canvas->clipPath(path, SkClipOp::kIntersect);
2083 canvas->drawCircle(70, 85, 60, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002084}
2085##
2086
Cary Clark2ade9972017-11-02 17:49:34 -04002087#SeeAlso clipRect clipRRect clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04002088
2089##
2090
Herb Derbyefe39bc2018-05-01 17:06:20 -04002091#Method void clipPath(const SkPath& path, bool doAntiAlias = false)
Cary Clark8032b982017-07-28 11:04:54 -04002092
Cary Clarkab2621d2018-01-30 10:08:57 -05002093#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002094#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002095
2096#Example
2097#Height 212
2098#Description
Herb Derbyefe39bc2018-05-01 17:06:20 -04002099Clip loops over itself covering its center twice. When clip Path_Fill_Type
2100is set to SkPath::kWinding_FillType, the overlap is included. Set to
Cary Clark8032b982017-07-28 11:04:54 -04002101SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
2102##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002103void draw(SkCanvas* canvas) {
2104 SkPaint paint;
2105 paint.setAntiAlias(true);
2106 SkPath path;
2107 SkPoint poly[] = {{20, 20}, { 80, 20}, { 80, 80}, {40, 80},
2108 {40, 40}, {100, 40}, {100, 100}, {20, 100}};
2109 path.addPoly(poly, SK_ARRAY_COUNT(poly), true);
2110 path.setFillType(SkPath::kWinding_FillType);
2111 canvas->save();
2112 canvas->clipPath(path, SkClipOp::kIntersect);
2113 canvas->drawCircle(50, 50, 45, paint);
2114 canvas->restore();
2115 canvas->translate(100, 100);
2116 path.setFillType(SkPath::kEvenOdd_FillType);
2117 canvas->clipPath(path, SkClipOp::kIntersect);
2118 canvas->drawCircle(50, 50, 45, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002119}
2120##
2121
Cary Clark2ade9972017-11-02 17:49:34 -04002122#SeeAlso clipRect clipRRect clipRegion
Cary Clark8032b982017-07-28 11:04:54 -04002123
2124##
2125
2126# ------------------------------------------------------------------------------
2127
Cary Clark8032b982017-07-28 11:04:54 -04002128#Method void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect)
2129
Cary Clarkab2621d2018-01-30 10:08:57 -05002130#In Clip
2131#Line # combines Clip with Region ##
Cary Clark09d80c02018-10-31 12:14:03 -04002132#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002133
2134#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002135#Description
Cary Clarkce101242017-09-01 15:51:02 -04002136 region is unaffected by canvas rotation; iRect is affected by canvas rotation.
2137 Both clips are Aliased; this is not noticeable on Region clip because it
Cary Clarkbad5ad72017-08-03 17:14:08 -04002138 aligns to pixel boundaries.
2139##
2140void draw(SkCanvas* canvas) {
2141 SkPaint paint;
2142 paint.setAntiAlias(true);
2143 SkIRect iRect = {30, 40, 120, 130 };
2144 SkRegion region(iRect);
2145 canvas->rotate(10);
2146 canvas->save();
2147 canvas->clipRegion(region, SkClipOp::kIntersect);
2148 canvas->drawCircle(50, 50, 45, paint);
2149 canvas->restore();
2150 canvas->translate(100, 100);
2151 canvas->clipRect(SkRect::Make(iRect), SkClipOp::kIntersect);
2152 canvas->drawCircle(50, 50, 45, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002153}
2154##
2155
Cary Clark2ade9972017-11-02 17:49:34 -04002156#SeeAlso clipRect clipRRect clipPath
Cary Clark8032b982017-07-28 11:04:54 -04002157
2158##
2159
2160#Method bool quickReject(const SkRect& rect) const
2161
Cary Clarkab2621d2018-01-30 10:08:57 -05002162#In Clip
2163#Line # returns if Rect is outside Clip ##
Cary Clark09d80c02018-10-31 12:14:03 -04002164#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002165
2166#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002167void draw(SkCanvas* canvas) {
Herb Derbyefe39bc2018-05-01 17:06:20 -04002168 SkRect testRect = {30, 30, 120, 129 };
2169 SkRect clipRect = {30, 130, 120, 230 };
Cary Clarkbad5ad72017-08-03 17:14:08 -04002170 canvas->save();
2171 canvas->clipRect(clipRect);
2172 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
2173 canvas->restore();
2174 canvas->rotate(10);
2175 canvas->clipRect(clipRect);
2176 SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
Cary Clark8032b982017-07-28 11:04:54 -04002177}
2178 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002179 quickReject true
Cary Clark8032b982017-07-28 11:04:54 -04002180 quickReject false
2181 ##
2182##
2183
Cary Clark2ade9972017-11-02 17:49:34 -04002184#SeeAlso getLocalClipBounds getTotalMatrix SkBitmap::drawsNothing
Cary Clark8032b982017-07-28 11:04:54 -04002185
2186##
2187
2188#Method bool quickReject(const SkPath& path) const
2189
Cary Clarkab2621d2018-01-30 10:08:57 -05002190#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002191#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002192
2193#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002194void draw(SkCanvas* canvas) {
Herb Derbyefe39bc2018-05-01 17:06:20 -04002195 SkPoint testPoints[] = {{30, 30}, {120, 30}, {120, 129} };
2196 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
Cary Clarkbad5ad72017-08-03 17:14:08 -04002197 SkPath testPath, clipPath;
2198 testPath.addPoly(testPoints, SK_ARRAY_COUNT(testPoints), true);
2199 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2200 canvas->save();
2201 canvas->clipPath(clipPath);
2202 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
2203 canvas->restore();
2204 canvas->rotate(10);
2205 canvas->clipPath(clipPath);
2206 SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
Cary Clark8032b982017-07-28 11:04:54 -04002207 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002208 quickReject true
Cary Clark8032b982017-07-28 11:04:54 -04002209 quickReject false
2210 ##
2211}
2212##
2213
Cary Clark2ade9972017-11-02 17:49:34 -04002214#SeeAlso getLocalClipBounds getTotalMatrix SkBitmap::drawsNothing
Cary Clark8032b982017-07-28 11:04:54 -04002215
2216##
2217
Herb Derbyefe39bc2018-05-01 17:06:20 -04002218#Method SkRect getLocalClipBounds() const
Cary Clark8032b982017-07-28 11:04:54 -04002219
Cary Clarkab2621d2018-01-30 10:08:57 -05002220#In Clip
2221#Line # returns Clip bounds in source coordinates ##
Cary Clark09d80c02018-10-31 12:14:03 -04002222#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002223
2224#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04002225 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002226 Initial bounds is device bounds outset by 1 on all sides.
2227 Clipped bounds is clipPath bounds outset by 1 on all sides.
Cary Clark5538c132018-06-14 12:28:14 -04002228 Scaling the canvas by two on both axes scales the local bounds by 1/2
2229 on both axes.
Cary Clark8032b982017-07-28 11:04:54 -04002230 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002231 SkCanvas local(256, 256);
2232 canvas = &local;
2233 SkRect bounds = canvas->getLocalClipBounds();
2234 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2235 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002236 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
Cary Clarkbad5ad72017-08-03 17:14:08 -04002237 SkPath clipPath;
2238 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2239 canvas->clipPath(clipPath);
2240 bounds = canvas->getLocalClipBounds();
2241 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2242 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2243 canvas->scale(2, 2);
2244 bounds = canvas->getLocalClipBounds();
2245 SkDebugf("left:%g top:%g right:%g bottom:%g\n",
2246 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2247 #StdOut
2248 left:-1 top:-1 right:257 bottom:257
2249 left:29 top:129 right:121 bottom:231
2250 left:14.5 top:64.5 right:60.5 bottom:115.5
2251 ##
Cary Clark8032b982017-07-28 11:04:54 -04002252##
2253
2254# local canvas in example works around bug in fiddle ##
Cary Clark4855f782018-02-06 09:41:53 -05002255#Bug 6524
Cary Clark2ade9972017-11-02 17:49:34 -04002256#SeeAlso getDeviceClipBounds getBaseLayerSize quickReject
Cary Clark8032b982017-07-28 11:04:54 -04002257
2258##
2259
Herb Derbyefe39bc2018-05-01 17:06:20 -04002260#Method bool getLocalClipBounds(SkRect* bounds) const
Cary Clark8032b982017-07-28 11:04:54 -04002261
Cary Clarkab2621d2018-01-30 10:08:57 -05002262#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002263#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002264
2265#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002266 void draw(SkCanvas* canvas) {
2267 SkCanvas local(256, 256);
2268 canvas = &local;
2269 SkRect bounds;
2270 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
2271 ? "false" : "true");
2272 SkPath path;
2273 canvas->clipPath(path);
2274 SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
2275 ? "false" : "true");
Cary Clark8032b982017-07-28 11:04:54 -04002276 }
2277 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002278 local bounds empty = false
Cary Clark8032b982017-07-28 11:04:54 -04002279 local bounds empty = true
2280 ##
2281##
2282
2283# local canvas in example works around bug in fiddle ##
Cary Clark4855f782018-02-06 09:41:53 -05002284#Bug 6524
Cary Clark2ade9972017-11-02 17:49:34 -04002285#SeeAlso getDeviceClipBounds getBaseLayerSize quickReject
Cary Clark8032b982017-07-28 11:04:54 -04002286
2287##
2288
Herb Derbyefe39bc2018-05-01 17:06:20 -04002289#Method SkIRect getDeviceClipBounds() const
Cary Clark8032b982017-07-28 11:04:54 -04002290
Cary Clarkab2621d2018-01-30 10:08:57 -05002291#In Clip
2292#Line # returns IRect bounds of Clip ##
Cary Clark09d80c02018-10-31 12:14:03 -04002293#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002294
2295#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002296void draw(SkCanvas* canvas) {
2297 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002298 Initial bounds is device bounds, not outset.
2299 Clipped bounds is clipPath bounds, not outset.
Cary Clark5538c132018-06-14 12:28:14 -04002300 Scaling the canvas by 1/2 on both axes scales the device bounds by 1/2
2301 on both axes.
Cary Clarkbad5ad72017-08-03 17:14:08 -04002302 ##
2303 SkCanvas device(256, 256);
2304 canvas = &device;
2305 SkIRect bounds = canvas->getDeviceClipBounds();
2306 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2307 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002308 SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
Cary Clarkbad5ad72017-08-03 17:14:08 -04002309 SkPath clipPath;
2310 clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
2311 canvas->save();
2312 canvas->clipPath(clipPath);
2313 bounds = canvas->getDeviceClipBounds();
2314 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2315 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
2316 canvas->restore();
2317 canvas->scale(1.f/2, 1.f/2);
2318 canvas->clipPath(clipPath);
2319 bounds = canvas->getDeviceClipBounds();
2320 SkDebugf("left:%d top:%d right:%d bottom:%d\n",
2321 bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
Cary Clark8032b982017-07-28 11:04:54 -04002322 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002323 left:0 top:0 right:256 bottom:256
2324 left:30 top:130 right:120 bottom:230
Cary Clark8032b982017-07-28 11:04:54 -04002325 left:15 top:65 right:60 bottom:115
2326 ##
2327}
2328##
2329
2330#ToDo some confusion on why with an identity Matrix local and device are different ##
Cary Clark2ade9972017-11-02 17:49:34 -04002331#SeeAlso getLocalClipBounds getBaseLayerSize quickReject
Cary Clark8032b982017-07-28 11:04:54 -04002332
2333# device canvas in example works around bug in fiddle ##
Cary Clark4855f782018-02-06 09:41:53 -05002334#Bug 6524
Cary Clark8032b982017-07-28 11:04:54 -04002335
2336##
2337
Herb Derbyefe39bc2018-05-01 17:06:20 -04002338#Method bool getDeviceClipBounds(SkIRect* bounds) const
Cary Clark8032b982017-07-28 11:04:54 -04002339
Cary Clarkab2621d2018-01-30 10:08:57 -05002340#In Clip
Cary Clark09d80c02018-10-31 12:14:03 -04002341#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002342
2343#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002344 void draw(SkCanvas* canvas) {
2345 SkIRect bounds;
2346 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
2347 ? "false" : "true");
2348 SkPath path;
2349 canvas->clipPath(path);
2350 SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
2351 ? "false" : "true");
Cary Clark8032b982017-07-28 11:04:54 -04002352 }
2353 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04002354 device bounds empty = false
Cary Clark8032b982017-07-28 11:04:54 -04002355 device bounds empty = true
2356 ##
2357##
2358
Cary Clark2ade9972017-11-02 17:49:34 -04002359#SeeAlso getLocalClipBounds getBaseLayerSize quickReject
Cary Clark8032b982017-07-28 11:04:54 -04002360
2361##
2362
Cary Clark08895c42018-02-01 09:37:32 -05002363#Subtopic Clip ##
Cary Clark8032b982017-07-28 11:04:54 -04002364
2365# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -05002366#Subtopic Draw
Cary Clark78de7512018-02-07 07:27:09 -05002367#Line # draws into Canvas ##
2368##
Cary Clark8032b982017-07-28 11:04:54 -04002369
2370#Method void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver)
Cary Clark78de7512018-02-07 07:27:09 -05002371#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002372#Line # fills Clip with Color and Blend_Mode ##
Cary Clark09d80c02018-10-31 12:14:03 -04002373#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002374
2375#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002376 canvas->drawColor(SK_ColorRED);
2377 canvas->clipRect(SkRect::MakeWH(150, 150));
2378 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00), SkBlendMode::kPlus);
2379 canvas->clipRect(SkRect::MakeWH(75, 75));
2380 canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF), SkBlendMode::kPlus);
Cary Clark8032b982017-07-28 11:04:54 -04002381##
2382
Cary Clark2ade9972017-11-02 17:49:34 -04002383#SeeAlso clear SkBitmap::erase drawPaint
Cary Clark8032b982017-07-28 11:04:54 -04002384
2385##
2386
2387# ------------------------------------------------------------------------------
2388
Herb Derbyefe39bc2018-05-01 17:06:20 -04002389#Method void clear(SkColor color)
Cary Clark78de7512018-02-07 07:27:09 -05002390#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002391#Line # fills Clip with Color ##
Cary Clark09d80c02018-10-31 12:14:03 -04002392#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002393
2394#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002395void draw(SkCanvas* canvas) {
2396 canvas->save();
2397 canvas->clipRect(SkRect::MakeWH(256, 128));
Herb Derbyefe39bc2018-05-01 17:06:20 -04002398 canvas->clear(SkColorSetARGB(0x80, 0xFF, 0x00, 0x00));
Cary Clarkbad5ad72017-08-03 17:14:08 -04002399 canvas->restore();
2400 canvas->save();
2401 canvas->clipRect(SkRect::MakeWH(150, 192));
2402 canvas->clear(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00));
2403 canvas->restore();
2404 canvas->clipRect(SkRect::MakeWH(75, 256));
2405 canvas->clear(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF));
Cary Clark8032b982017-07-28 11:04:54 -04002406}
2407##
2408
Cary Clark2ade9972017-11-02 17:49:34 -04002409#SeeAlso drawColor SkBitmap::erase drawPaint
Cary Clark8032b982017-07-28 11:04:54 -04002410
2411##
2412
2413# ------------------------------------------------------------------------------
2414
Herb Derbyefe39bc2018-05-01 17:06:20 -04002415#Method void discard()
Cary Clark78de7512018-02-07 07:27:09 -05002416#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05002417#Line # makes Canvas contents undefined ##
Cary Clark09d80c02018-10-31 12:14:03 -04002418#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002419
Herb Derbyefe39bc2018-05-01 17:06:20 -04002420#NoExample
Cary Clark8032b982017-07-28 11:04:54 -04002421##
2422
Cary Clarkabaffd82018-11-15 08:25:12 -05002423#SeeAlso flush() GrContext::abandonContext
Cary Clark09d80c02018-10-31 12:14:03 -04002424
Cary Clark8032b982017-07-28 11:04:54 -04002425##
2426
2427# ------------------------------------------------------------------------------
2428
2429#Method void drawPaint(const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002430#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002431#Line # fills Clip with Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002432#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002433
2434#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002435void draw(SkCanvas* canvas) {
2436 SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
2437 SkScalar pos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
2438 SkPaint paint;
2439 paint.setShader(SkGradientShader::MakeSweep(256, 256, colors, pos, SK_ARRAY_COUNT(colors)));
2440 canvas->drawPaint(paint);
Cary Clark8032b982017-07-28 11:04:54 -04002441}
2442##
2443
Cary Clark2ade9972017-11-02 17:49:34 -04002444#SeeAlso clear drawColor SkBitmap::erase
Cary Clark8032b982017-07-28 11:04:54 -04002445
2446##
2447
2448# ------------------------------------------------------------------------------
2449
2450#Enum PointMode
Cary Clark08895c42018-02-01 09:37:32 -05002451#Line # sets drawPoints options ##
Cary Clark8032b982017-07-28 11:04:54 -04002452
2453#Code
Cary Clark61313f32018-10-08 14:57:48 -04002454#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002455##
2456
2457Selects if an array of points are drawn as discrete points, as lines, or as
2458an open polygon.
2459
2460#Const kPoints_PointMode 0
Cary Clark682c58d2018-05-16 07:07:07 -04002461#Line # draw each point separately ##
Cary Clark8032b982017-07-28 11:04:54 -04002462##
2463
2464#Const kLines_PointMode 1
Cary Clark682c58d2018-05-16 07:07:07 -04002465#Line # draw each pair of points as a line segment ##
Cary Clark8032b982017-07-28 11:04:54 -04002466##
2467
2468#Const kPolygon_PointMode 2
Cary Clark682c58d2018-05-16 07:07:07 -04002469#Line # draw the array of points as a open polygon ##
Cary Clark8032b982017-07-28 11:04:54 -04002470##
2471
2472#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04002473 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002474 The upper left corner shows three squares when drawn as points.
2475 The upper right corner shows one line; when drawn as lines, two points are required per line.
2476 The lower right corner shows two lines; when draw as polygon, no miter is drawn at the corner.
2477 The lower left corner shows two lines with a miter when path contains polygon.
2478 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002479void draw(SkCanvas* canvas) {
2480 SkPaint paint;
2481 paint.setStyle(SkPaint::kStroke_Style);
2482 paint.setStrokeWidth(10);
2483 SkPoint points[] = {{64, 32}, {96, 96}, {32, 96}};
2484 canvas->drawPoints(SkCanvas::kPoints_PointMode, 3, points, paint);
2485 canvas->translate(128, 0);
2486 canvas->drawPoints(SkCanvas::kLines_PointMode, 3, points, paint);
2487 canvas->translate(0, 128);
2488 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, points, paint);
2489 SkPath path;
2490 path.addPoly(points, 3, false);
2491 canvas->translate(-128, 0);
2492 canvas->drawPath(path, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002493}
2494##
2495
Cary Clark2ade9972017-11-02 17:49:34 -04002496#SeeAlso drawLine drawPoint drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002497
2498##
2499
2500# ------------------------------------------------------------------------------
2501
2502#Method void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002503#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002504#Line # draws array as points, lines, polygon ##
Cary Clark09d80c02018-10-31 12:14:03 -04002505#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002506
2507#Example
2508#Height 200
Herb Derbyefe39bc2018-05-01 17:06:20 -04002509 #Description
Cary Clark8032b982017-07-28 11:04:54 -04002510 #List
2511 # The first column draws points. ##
2512 # The second column draws points as lines. ##
2513 # The third column draws points as a polygon. ##
2514 # The fourth column draws points as a polygonal path. ##
2515 # The first row uses a round cap and round join. ##
2516 # The second row uses a square cap and a miter join. ##
2517 # The third row uses a butt cap and a bevel join. ##
2518 ##
2519 The transparent color makes multiple line draws visible;
2520 the path is drawn all at once.
2521 ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002522void draw(SkCanvas* canvas) {
2523 SkPaint paint;
2524 paint.setAntiAlias(true);
2525 paint.setStyle(SkPaint::kStroke_Style);
2526 paint.setStrokeWidth(10);
2527 paint.setColor(0x80349a45);
2528 const SkPoint points[] = {{32, 16}, {48, 48}, {16, 32}};
Herb Derbyefe39bc2018-05-01 17:06:20 -04002529 const SkPaint::Join join[] = { SkPaint::kRound_Join,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002530 SkPaint::kMiter_Join,
2531 SkPaint::kBevel_Join };
2532 int joinIndex = 0;
2533 SkPath path;
2534 path.addPoly(points, 3, false);
2535 for (const auto cap : { SkPaint::kRound_Cap, SkPaint::kSquare_Cap, SkPaint::kButt_Cap } ) {
2536 paint.setStrokeCap(cap);
2537 paint.setStrokeJoin(join[joinIndex++]);
2538 for (const auto mode : { SkCanvas::kPoints_PointMode,
2539 SkCanvas::kLines_PointMode,
2540 SkCanvas::kPolygon_PointMode } ) {
2541 canvas->drawPoints(mode, 3, points, paint);
2542 canvas->translate(64, 0);
2543 }
2544 canvas->drawPath(path, paint);
2545 canvas->translate(-192, 64);
2546 }
Cary Clark8032b982017-07-28 11:04:54 -04002547}
2548##
2549
Cary Clark2ade9972017-11-02 17:49:34 -04002550#SeeAlso drawLine drawPoint drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002551
2552##
2553
2554# ------------------------------------------------------------------------------
2555
2556#Method void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002557#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002558#Line # draws point at (x, y) position ##
Cary Clark09d80c02018-10-31 12:14:03 -04002559#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002560
2561#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002562void draw(SkCanvas* canvas) {
2563 SkPaint paint;
2564 paint.setAntiAlias(true);
2565 paint.setColor(0x80349a45);
2566 paint.setStyle(SkPaint::kStroke_Style);
2567 paint.setStrokeWidth(100);
2568 paint.setStrokeCap(SkPaint::kRound_Cap);
2569 canvas->scale(1, 1.2f);
2570 canvas->drawPoint(64, 96, paint);
2571 canvas->scale(.6f, .8f);
2572 paint.setColor(SK_ColorWHITE);
2573 canvas->drawPoint(106, 120, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002574}
2575##
2576
Cary Clark2ade9972017-11-02 17:49:34 -04002577#SeeAlso drawPoints drawCircle drawRect drawLine drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002578
2579##
2580
Cary Clarkbad5ad72017-08-03 17:14:08 -04002581#Method void drawPoint(SkPoint p, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04002582#Populate
Cary Clarkbad5ad72017-08-03 17:14:08 -04002583
2584#Example
2585void draw(SkCanvas* canvas) {
2586 SkPaint paint;
2587 paint.setAntiAlias(true);
2588 paint.setColor(0x80349a45);
2589 paint.setStyle(SkPaint::kStroke_Style);
2590 paint.setStrokeWidth(100);
2591 paint.setStrokeCap(SkPaint::kSquare_Cap);
2592 canvas->scale(1, 1.2f);
2593 canvas->drawPoint({64, 96}, paint);
2594 canvas->scale(.6f, .8f);
2595 paint.setColor(SK_ColorWHITE);
2596 canvas->drawPoint(106, 120, paint);
2597}
2598##
2599
Cary Clark2ade9972017-11-02 17:49:34 -04002600#SeeAlso drawPoints drawCircle drawRect drawLine drawPath
Cary Clarkbad5ad72017-08-03 17:14:08 -04002601
2602##
2603
Cary Clark8032b982017-07-28 11:04:54 -04002604# ------------------------------------------------------------------------------
2605
2606#Method void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002607#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002608#Line # draws line segment between two points ##
Cary Clark09d80c02018-10-31 12:14:03 -04002609#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002610
2611#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002612 SkPaint paint;
2613 paint.setAntiAlias(true);
2614 paint.setColor(0xFF9a67be);
2615 paint.setStrokeWidth(20);
2616 canvas->skew(1, 0);
2617 canvas->drawLine(32, 96, 32, 160, paint);
2618 canvas->skew(-2, 0);
2619 canvas->drawLine(288, 96, 288, 160, paint);
2620##
2621
Cary Clark2ade9972017-11-02 17:49:34 -04002622#SeeAlso drawPoint drawCircle drawRect drawPath
Cary Clarkbad5ad72017-08-03 17:14:08 -04002623
2624##
2625
2626#Method void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04002627#Populate
Cary Clarkbad5ad72017-08-03 17:14:08 -04002628
2629#Example
2630 SkPaint paint;
2631 paint.setAntiAlias(true);
2632 paint.setColor(0xFF9a67be);
2633 paint.setStrokeWidth(20);
2634 canvas->skew(1, 0);
2635 canvas->drawLine({32, 96}, {32, 160}, paint);
2636 canvas->skew(-2, 0);
2637 canvas->drawLine({288, 96}, {288, 160}, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002638##
2639
Cary Clark2ade9972017-11-02 17:49:34 -04002640#SeeAlso drawPoint drawCircle drawRect drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002641
2642##
2643
2644# ------------------------------------------------------------------------------
2645
2646#Method void drawRect(const SkRect& rect, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002647#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002648#Line # draws Rect using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002649#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002650
2651#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002652void draw(SkCanvas* canvas) {
2653 SkPoint rectPts[] = { {64, 48}, {192, 160} };
2654 SkPaint paint;
2655 paint.setAntiAlias(true);
2656 paint.setStyle(SkPaint::kStroke_Style);
2657 paint.setStrokeWidth(20);
2658 paint.setStrokeJoin(SkPaint::kRound_Join);
2659 SkMatrix rotator;
2660 rotator.setRotate(30, 128, 128);
2661 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
2662 paint.setColor(color);
2663 SkRect rect;
2664 rect.set(rectPts[0], rectPts[1]);
2665 canvas->drawRect(rect, paint);
2666 rotator.mapPoints(rectPts, 2);
2667 }
Cary Clark8032b982017-07-28 11:04:54 -04002668}
2669##
2670
Herb Derbyefe39bc2018-05-01 17:06:20 -04002671#SeeAlso drawIRect drawRRect drawRoundRect drawRegion drawPath drawLine
Cary Clark8032b982017-07-28 11:04:54 -04002672
2673##
2674
2675# ------------------------------------------------------------------------------
2676
Herb Derbyefe39bc2018-05-01 17:06:20 -04002677#Method void drawIRect(const SkIRect& rect, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002678#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002679#Line # draws IRect using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002680#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002681
2682#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002683 SkIRect rect = { 64, 48, 192, 160 };
2684 SkPaint paint;
2685 paint.setAntiAlias(true);
2686 paint.setStyle(SkPaint::kStroke_Style);
2687 paint.setStrokeWidth(20);
2688 paint.setStrokeJoin(SkPaint::kRound_Join);
2689 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
2690 paint.setColor(color);
2691 canvas->drawIRect(rect, paint);
2692 canvas->rotate(30, 128, 128);
2693 }
Cary Clark8032b982017-07-28 11:04:54 -04002694##
2695
Cary Clark2ade9972017-11-02 17:49:34 -04002696#SeeAlso drawRect drawRRect drawRoundRect drawRegion drawPath drawLine
Cary Clark8032b982017-07-28 11:04:54 -04002697
2698##
2699
2700# ------------------------------------------------------------------------------
2701
2702#Method void drawRegion(const SkRegion& region, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002703#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002704#Line # draws Region using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002705#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002706
2707#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002708void draw(SkCanvas* canvas) {
2709 SkRegion region;
2710 region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
2711 region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
2712 SkPaint paint;
2713 paint.setAntiAlias(true);
2714 paint.setStyle(SkPaint::kStroke_Style);
2715 paint.setStrokeWidth(20);
2716 paint.setStrokeJoin(SkPaint::kRound_Join);
2717 canvas->drawRegion(region, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002718}
2719##
2720
Cary Clark2ade9972017-11-02 17:49:34 -04002721#SeeAlso drawRect drawIRect drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002722
2723##
2724
2725# ------------------------------------------------------------------------------
2726
2727#Method void drawOval(const SkRect& oval, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002728#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002729#Line # draws Oval using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002730#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002731
2732#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002733void draw(SkCanvas* canvas) {
2734 canvas->clear(0xFF3f5f9f);
2735 SkColor kColor1 = SkColorSetARGB(0xff, 0xff, 0x7f, 0);
2736 SkColor g1Colors[] = { kColor1, SkColorSetA(kColor1, 0x20) };
2737 SkPoint g1Points[] = { { 0, 0 }, { 0, 100 } };
2738 SkScalar pos[] = { 0.2f, 1.0f };
2739 SkRect bounds = SkRect::MakeWH(80, 70);
2740 SkPaint paint;
2741 paint.setAntiAlias(true);
2742 paint.setShader(SkGradientShader::MakeLinear(g1Points, g1Colors, pos, SK_ARRAY_COUNT(g1Colors),
2743 SkShader::kClamp_TileMode));
2744 canvas->drawOval(bounds , paint);
Cary Clark8032b982017-07-28 11:04:54 -04002745}
2746##
2747
Cary Clark2ade9972017-11-02 17:49:34 -04002748#SeeAlso drawCircle drawPoint drawPath drawRRect drawRoundRect
Cary Clark8032b982017-07-28 11:04:54 -04002749
2750##
2751
2752# ------------------------------------------------------------------------------
2753
2754#Method void drawRRect(const SkRRect& rrect, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002755#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002756#Line # draws Round_Rect using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002757#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002758
2759#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002760void draw(SkCanvas* canvas) {
2761 SkPaint paint;
2762 paint.setAntiAlias(true);
2763 SkRect outer = {30, 40, 210, 220};
2764 SkRect radii = {30, 50, 70, 90 };
2765 SkRRect rRect;
2766 rRect.setNinePatch(outer, radii.fLeft, radii.fTop, radii.fRight, radii.fBottom);
2767 canvas->drawRRect(rRect, paint);
2768 paint.setColor(SK_ColorWHITE);
2769 canvas->drawLine(outer.fLeft + radii.fLeft, outer.fTop,
2770 outer.fLeft + radii.fLeft, outer.fBottom, paint);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002771 canvas->drawLine(outer.fRight - radii.fRight, outer.fTop,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002772 outer.fRight - radii.fRight, outer.fBottom, paint);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002773 canvas->drawLine(outer.fLeft, outer.fTop + radii.fTop,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002774 outer.fRight, outer.fTop + radii.fTop, paint);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002775 canvas->drawLine(outer.fLeft, outer.fBottom - radii.fBottom,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002776 outer.fRight, outer.fBottom - radii.fBottom, paint);
2777}
Cary Clark8032b982017-07-28 11:04:54 -04002778##
2779
Cary Clark2ade9972017-11-02 17:49:34 -04002780#SeeAlso drawRect drawRoundRect drawDRRect drawCircle drawOval drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002781
2782##
2783
2784# ------------------------------------------------------------------------------
2785
2786#Method void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002787#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002788#Line # draws double Round_Rect stroked or filled ##
Cary Clark09d80c02018-10-31 12:14:03 -04002789#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002790
2791#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002792void draw(SkCanvas* canvas) {
2793 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
2794 SkRRect inner = SkRRect::MakeOval({60, 70, 170, 160});
2795 SkPaint paint;
2796 canvas->drawDRRect(outer, inner, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002797}
2798##
2799
2800#Example
2801#Description
2802 Outer Rect has no corner radii, but stroke join is rounded.
2803 Inner Round_Rect has corner radii; outset stroke increases radii of corners.
2804 Stroke join does not affect inner Round_Rect since it has no sharp corners.
2805##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002806void draw(SkCanvas* canvas) {
2807 SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
2808 SkRRect inner = SkRRect::MakeRectXY({60, 70, 170, 160}, 10, 10);
2809 SkPaint paint;
2810 paint.setAntiAlias(true);
2811 paint.setStyle(SkPaint::kStroke_Style);
2812 paint.setStrokeWidth(20);
2813 paint.setStrokeJoin(SkPaint::kRound_Join);
2814 canvas->drawDRRect(outer, inner, paint);
2815 paint.setStrokeWidth(1);
2816 paint.setColor(SK_ColorWHITE);
2817 canvas->drawDRRect(outer, inner, paint);
Cary Clark8032b982017-07-28 11:04:54 -04002818}
2819##
2820
Cary Clark2ade9972017-11-02 17:49:34 -04002821#SeeAlso drawRect drawRoundRect drawRRect drawCircle drawOval drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002822
2823##
2824
2825# ------------------------------------------------------------------------------
2826
2827#Method void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002828#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002829#Line # draws Circle using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002830#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002831
2832#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002833 void draw(SkCanvas* canvas) {
2834 SkPaint paint;
2835 paint.setAntiAlias(true);
2836 canvas->drawCircle(128, 128, 90, paint);
2837 paint.setColor(SK_ColorWHITE);
2838 canvas->drawCircle(86, 86, 20, paint);
2839 canvas->drawCircle(160, 76, 20, paint);
2840 canvas->drawCircle(140, 150, 35, paint);
2841 }
2842##
2843
Cary Clark2ade9972017-11-02 17:49:34 -04002844#SeeAlso drawOval drawRRect drawRoundRect drawPath drawArc drawPoint drawLine
Cary Clarkbad5ad72017-08-03 17:14:08 -04002845
2846##
2847
2848#Method void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04002849#Populate
Cary Clarkbad5ad72017-08-03 17:14:08 -04002850
2851#Example
2852 void draw(SkCanvas* canvas) {
2853 SkPaint paint;
2854 paint.setAntiAlias(true);
2855 canvas->drawCircle(128, 128, 90, paint);
2856 paint.setColor(SK_ColorWHITE);
2857 canvas->drawCircle({86, 86}, 20, paint);
2858 canvas->drawCircle({160, 76}, 20, paint);
2859 canvas->drawCircle({140, 150}, 35, paint);
2860 }
Cary Clark8032b982017-07-28 11:04:54 -04002861##
2862
Cary Clark2ade9972017-11-02 17:49:34 -04002863#SeeAlso drawOval drawRRect drawRoundRect drawPath drawArc drawPoint drawLine
Cary Clark8032b982017-07-28 11:04:54 -04002864
2865##
2866
2867# ------------------------------------------------------------------------------
2868
2869#Method void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
2870 bool useCenter, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002871#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002872#Line # draws Arc using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002873#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002874
2875#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04002876 void draw(SkCanvas* canvas) {
2877 SkPaint paint;
2878 paint.setAntiAlias(true);
2879 SkRect oval = { 4, 4, 60, 60};
2880 for (auto useCenter : { false, true } ) {
2881 for (auto style : { SkPaint::kFill_Style, SkPaint::kStroke_Style } ) {
2882 paint.setStyle(style);
2883 for (auto degrees : { 45, 90, 180, 360} ) {
2884 canvas->drawArc(oval, 0, degrees , useCenter, paint);
2885 canvas->translate(64, 0);
2886 }
2887 canvas->translate(-256, 64);
2888 }
2889 }
Cary Clark8032b982017-07-28 11:04:54 -04002890 }
2891##
2892
2893#Example
2894#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04002895 void draw(SkCanvas* canvas) {
2896 SkPaint paint;
2897 paint.setAntiAlias(true);
2898 paint.setStyle(SkPaint::kStroke_Style);
2899 paint.setStrokeWidth(4);
2900 SkRect oval = { 4, 4, 60, 60};
2901 float intervals[] = { 5, 5 };
2902 paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
2903 for (auto degrees : { 270, 360, 540, 720 } ) {
2904 canvas->drawArc(oval, 0, degrees, false, paint);
2905 canvas->translate(64, 0);
2906 }
Cary Clark8032b982017-07-28 11:04:54 -04002907 }
2908##
2909
Cary Clark2ade9972017-11-02 17:49:34 -04002910#SeeAlso SkPath::arcTo drawCircle drawOval drawPath
Cary Clark8032b982017-07-28 11:04:54 -04002911
2912##
2913
2914# ------------------------------------------------------------------------------
2915
2916#Method void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002917#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002918#Line # draws Round_Rect using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002919#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002920
2921#Example
2922#Description
2923 Top row has a zero radius a generates a rectangle.
2924 Second row radii sum to less than sides.
2925 Third row radii sum equals sides.
2926 Fourth row radii sum exceeds sides; radii are scaled to fit.
2927##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002928 void draw(SkCanvas* canvas) {
2929 SkVector radii[] = { {0, 20}, {10, 10}, {10, 20}, {10, 40} };
2930 SkPaint paint;
2931 paint.setStrokeWidth(15);
2932 paint.setStrokeJoin(SkPaint::kRound_Join);
2933 paint.setAntiAlias(true);
2934 for (auto style : { SkPaint::kStroke_Style, SkPaint::kFill_Style } ) {
2935 paint.setStyle(style );
2936 for (size_t i = 0; i < SK_ARRAY_COUNT(radii); ++i) {
2937 canvas->drawRoundRect({10, 10, 60, 40}, radii[i].fX, radii[i].fY, paint);
2938 canvas->translate(0, 60);
2939 }
2940 canvas->translate(80, -240);
2941 }
Cary Clark8032b982017-07-28 11:04:54 -04002942 }
2943##
2944
Cary Clark77b3f3a2018-11-07 14:59:03 -05002945#SeeAlso drawRRect drawRect drawDRRect drawPath drawCircle drawOval drawPoint
Cary Clark8032b982017-07-28 11:04:54 -04002946
2947##
2948
2949# ------------------------------------------------------------------------------
2950
2951#Method void drawPath(const SkPath& path, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05002952#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05002953#Line # draws Path using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04002954#Populate
Cary Clark8032b982017-07-28 11:04:54 -04002955
2956#Example
2957#Description
2958 Top rows draw stroked path with combinations of joins and caps. The open contour
2959 is affected by caps; the closed contour is affected by joins.
Herb Derbyefe39bc2018-05-01 17:06:20 -04002960 Bottom row draws fill the same for open and closed contour.
Cary Clark8032b982017-07-28 11:04:54 -04002961 First bottom column shows winding fills overlap.
2962 Second bottom column shows even odd fills exclude overlap.
2963 Third bottom column shows inverse winding fills area outside both contours.
2964##
Cary Clarkbad5ad72017-08-03 17:14:08 -04002965void draw(SkCanvas* canvas) {
2966 SkPath path;
2967 path.moveTo(20, 20);
2968 path.quadTo(60, 20, 60, 60);
2969 path.close();
2970 path.moveTo(60, 20);
2971 path.quadTo(60, 60, 20, 60);
2972 SkPaint paint;
2973 paint.setStrokeWidth(10);
2974 paint.setAntiAlias(true);
2975 paint.setStyle(SkPaint::kStroke_Style);
2976 for (auto join: { SkPaint::kBevel_Join, SkPaint::kRound_Join, SkPaint::kMiter_Join } ) {
2977 paint.setStrokeJoin(join);
2978 for (auto cap: { SkPaint::kButt_Cap, SkPaint::kSquare_Cap, SkPaint::kRound_Cap } ) {
2979 paint.setStrokeCap(cap);
2980 canvas->drawPath(path, paint);
2981 canvas->translate(80, 0);
2982 }
2983 canvas->translate(-240, 60);
2984 }
2985 paint.setStyle(SkPaint::kFill_Style);
Herb Derbyefe39bc2018-05-01 17:06:20 -04002986 for (auto fill : { SkPath::kWinding_FillType,
2987 SkPath::kEvenOdd_FillType,
Cary Clarkbad5ad72017-08-03 17:14:08 -04002988 SkPath::kInverseWinding_FillType } ) {
2989 path.setFillType(fill);
2990 canvas->save();
2991 canvas->clipRect({0, 10, 80, 70});
2992 canvas->drawPath(path, paint);
2993 canvas->restore();
2994 canvas->translate(80, 0);
2995 }
Cary Clark8032b982017-07-28 11:04:54 -04002996}
2997##
2998
Cary Clark2ade9972017-11-02 17:49:34 -04002999#SeeAlso SkPath drawLine drawArc drawRect drawPoints
Cary Clark8032b982017-07-28 11:04:54 -04003000
3001##
3002
3003# ------------------------------------------------------------------------------
Cary Clark08895c42018-02-01 09:37:32 -05003004#Subtopic Draw_Image
3005#Line # draws Image to Canvas ##
Cary Clark8032b982017-07-28 11:04:54 -04003006
Cary Clarkbad5ad72017-08-03 17:14:08 -04003007drawImage, drawImageRect, and drawImageNine can be called with a bare pointer or
3008a smart pointer as a convenience. The pairs of calls are otherwise identical.
Cary Clark8032b982017-07-28 11:04:54 -04003009
Cary Clark73fa9722017-08-29 17:36:51 -04003010#Method void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003011#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003012#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003013#Line # draws Image at (x, y) position ##
Cary Clark09d80c02018-10-31 12:14:03 -04003014#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003015
3016#Example
3017#Height 64
3018#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003019void draw(SkCanvas* canvas) {
3020 // sk_sp<SkImage> image;
3021 SkImage* imagePtr = image.get();
3022 canvas->drawImage(imagePtr, 0, 0);
3023 SkPaint paint;
3024 canvas->drawImage(imagePtr, 80, 0, &paint);
3025 paint.setAlpha(0x80);
3026 canvas->drawImage(imagePtr, 160, 0, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04003027}
3028##
3029
Cary Clark2ade9972017-11-02 17:49:34 -04003030#SeeAlso drawBitmap drawImageLattice drawImageNine drawImageRect SkPaint::setImageFilter
Cary Clark8032b982017-07-28 11:04:54 -04003031
3032##
3033
3034# ------------------------------------------------------------------------------
3035
3036#Method void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
Herb Derbyefe39bc2018-05-01 17:06:20 -04003037 const SkPaint* paint = nullptr)
Cary Clark09d80c02018-10-31 12:14:03 -04003038#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003039
3040#Example
3041#Height 64
3042#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003043void draw(SkCanvas* canvas) {
3044 // sk_sp<SkImage> image;
3045 canvas->drawImage(image, 0, 0);
3046 SkPaint paint;
3047 canvas->drawImage(image, 80, 0, &paint);
3048 paint.setAlpha(0x80);
3049 canvas->drawImage(image, 160, 0, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04003050}
3051##
3052
Cary Clark2ade9972017-11-02 17:49:34 -04003053#SeeAlso drawBitmap drawImageLattice drawImageNine drawImageRect SkPaint::setImageFilter
Cary Clark8032b982017-07-28 11:04:54 -04003054
3055##
3056
3057# ------------------------------------------------------------------------------
3058
3059#Enum SrcRectConstraint
Cary Clark08895c42018-02-01 09:37:32 -05003060#Line # sets drawImageRect options ##
Cary Clark8032b982017-07-28 11:04:54 -04003061
3062#Code
Cary Clark61313f32018-10-08 14:57:48 -04003063#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003064##
3065
Cary Clarkce101242017-09-01 15:51:02 -04003066SrcRectConstraint controls the behavior at the edge of source Rect,
3067provided to drawImageRect, trading off speed for precision.
Cary Clark8032b982017-07-28 11:04:54 -04003068
Cary Clarkce101242017-09-01 15:51:02 -04003069Image_Filter in Paint may sample multiple pixels in the image. Source Rect
Cary Clarkbad5ad72017-08-03 17:14:08 -04003070restricts the bounds of pixels that may be read. Image_Filter may slow down if
Herb Derbyefe39bc2018-05-01 17:06:20 -04003071it cannot read outside the bounds, when sampling near the edge of source Rect.
Cary Clark8032b982017-07-28 11:04:54 -04003072SrcRectConstraint specifies whether an Image_Filter is allowed to read pixels
Cary Clarkce101242017-09-01 15:51:02 -04003073outside source Rect.
Cary Clark8032b982017-07-28 11:04:54 -04003074
Cary Clark682c58d2018-05-16 07:07:07 -04003075#Const kStrict_SrcRectConstraint 0
3076#Line # sample only inside bounds; slower ##
Cary Clarkce101242017-09-01 15:51:02 -04003077 Requires Image_Filter to respect source Rect,
Cary Clark8032b982017-07-28 11:04:54 -04003078 sampling only inside of its bounds, possibly with a performance penalty.
3079##
3080
Cary Clark682c58d2018-05-16 07:07:07 -04003081#Const kFast_SrcRectConstraint 1
3082#Line # sample outside bounds; faster ##
Cary Clarkce101242017-09-01 15:51:02 -04003083 Permits Image_Filter to sample outside of source Rect
Cary Clark8032b982017-07-28 11:04:54 -04003084 by half the width of Image_Filter, permitting it to run faster but with
3085 error at the image edges.
3086##
3087
3088#Example
3089#Height 64
3090#Description
3091 redBorder contains a black and white checkerboard bordered by red.
3092 redBorder is drawn scaled by 16 on the left.
Cary Clarkce101242017-09-01 15:51:02 -04003093 The middle and right bitmaps are filtered checkerboards.
Cary Clark8032b982017-07-28 11:04:54 -04003094 Drawing the checkerboard with kStrict_SrcRectConstraint shows only a blur of black and white.
3095 Drawing the checkerboard with kFast_SrcRectConstraint allows red to bleed in the corners.
3096##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003097void draw(SkCanvas* canvas) {
3098 SkBitmap redBorder;
3099 redBorder.allocPixels(SkImageInfo::MakeN32Premul(4, 4));
3100 SkCanvas checkRed(redBorder);
3101 checkRed.clear(SK_ColorRED);
3102 uint32_t checkers[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
3103 { SK_ColorWHITE, SK_ColorBLACK } };
3104 checkRed.writePixels(
3105 SkImageInfo::MakeN32Premul(2, 2), (void*) checkers, sizeof(checkers[0]), 1, 1);
3106 canvas->scale(16, 16);
3107 canvas->drawBitmap(redBorder, 0, 0, nullptr);
3108 canvas->resetMatrix();
3109 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
3110 SkPaint lowPaint;
3111 lowPaint.setFilterQuality(kLow_SkFilterQuality);
3112 for (auto constraint : { SkCanvas::kStrict_SrcRectConstraint,
3113 SkCanvas::kFast_SrcRectConstraint } ) {
3114 canvas->translate(80, 0);
3115 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
3116 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
3117 }
Cary Clark8032b982017-07-28 11:04:54 -04003118}
3119##
3120
Cary Clark2ade9972017-11-02 17:49:34 -04003121#SeeAlso drawImageRect drawImage SkPaint::setImageFilter
Cary Clark8032b982017-07-28 11:04:54 -04003122
3123##
3124
3125# ------------------------------------------------------------------------------
3126
3127#Method void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
3128 const SkPaint* paint,
3129 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003130#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003131#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003132#Line # draws Image, source Rect to destination Rect ##
Cary Clark09d80c02018-10-31 12:14:03 -04003133#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003134
3135#Example
3136#Height 64
3137#Description
3138 The left bitmap draws with Paint default kNone_SkFilterQuality, and stays within
Cary Clarkbc5697d2017-10-04 14:31:33 -04003139 its bounds; there is no bleeding with kFast_SrcRectConstraint.
Cary Clark8032b982017-07-28 11:04:54 -04003140 the middle and right bitmaps draw with kLow_SkFilterQuality; with
3141 kStrict_SrcRectConstraint, the filter remains within the checkerboard, and
3142 with kFast_SrcRectConstraint red bleeds on the edges.
3143##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003144void draw(SkCanvas* canvas) {
Herb Derbyefe39bc2018-05-01 17:06:20 -04003145 uint32_t pixels[][4] = {
Cary Clarkbad5ad72017-08-03 17:14:08 -04003146 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 },
3147 { 0xFFFF0000, 0xFF000000, 0xFFFFFFFF, 0xFFFF0000 },
3148 { 0xFFFF0000, 0xFFFFFFFF, 0xFF000000, 0xFFFF0000 },
3149 { 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 } };
3150 SkBitmap redBorder;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003151 redBorder.installPixels(SkImageInfo::MakeN32Premul(4, 4),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003152 (void*) pixels, sizeof(pixels[0]));
3153 sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
3154 SkPaint lowPaint;
3155 for (auto constraint : {
3156 SkCanvas::kFast_SrcRectConstraint,
3157 SkCanvas::kStrict_SrcRectConstraint,
3158 SkCanvas::kFast_SrcRectConstraint } ) {
3159 canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
3160 SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
3161 lowPaint.setFilterQuality(kLow_SkFilterQuality);
3162 canvas->translate(80, 0);
3163 }
3164}
Cary Clark8032b982017-07-28 11:04:54 -04003165##
3166
Cary Clark2ade9972017-11-02 17:49:34 -04003167#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003168
3169##
3170
3171# ------------------------------------------------------------------------------
3172
3173#Method void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
3174 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003175#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003176#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003177#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003178
3179#Example
3180#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003181void draw(SkCanvas* canvas) {
3182 // sk_sp<SkImage> image;
3183 for (auto i : { 1, 2, 4, 8 } ) {
Herb Derbyefe39bc2018-05-01 17:06:20 -04003184 canvas->drawImageRect(image.get(), SkIRect::MakeLTRB(0, 0, 100, 100),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003185 SkRect::MakeXYWH(i * 20, i * 20, i * 20, i * 20), nullptr);
3186 }
Cary Clark8032b982017-07-28 11:04:54 -04003187}
3188##
3189
Cary Clark2ade9972017-11-02 17:49:34 -04003190#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003191
3192##
3193
3194# ------------------------------------------------------------------------------
3195
Cary Clark0ac0edd2018-10-29 11:28:43 -04003196#Method void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003197#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003198#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003199#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003200
3201#Example
3202#Image 4
Cary Clarkbad5ad72017-08-03 17:14:08 -04003203void draw(SkCanvas* canvas) {
3204 // sk_sp<SkImage> image;
3205 for (auto i : { 20, 40, 80, 160 } ) {
3206 canvas->drawImageRect(image.get(), SkRect::MakeXYWH(i, i, i, i), nullptr);
3207 }
Cary Clark8032b982017-07-28 11:04:54 -04003208}
3209##
3210
Cary Clark2ade9972017-11-02 17:49:34 -04003211#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003212
3213##
3214
3215# ------------------------------------------------------------------------------
3216
3217#Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
3218 const SkPaint* paint,
Herb Derbyefe39bc2018-05-01 17:06:20 -04003219 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003220#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003221#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003222#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003223
3224#Example
3225#Height 64
3226#Description
3227 Canvas scales and translates; transformation from src to dst also scales.
3228 The two matrices are concatenated to create the final transformation.
3229##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003230void draw(SkCanvas* canvas) {
3231 uint32_t pixels[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
3232 { SK_ColorWHITE, SK_ColorBLACK } };
3233 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003234 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003235 (void*) pixels, sizeof(pixels[0]));
3236 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3237 SkPaint paint;
3238 canvas->scale(4, 4);
3239 for (auto alpha : { 50, 100, 150, 255 } ) {
3240 paint.setAlpha(alpha);
3241 canvas->drawImageRect(image, SkRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
3242 canvas->translate(8, 0);
3243 }
3244}
Cary Clark8032b982017-07-28 11:04:54 -04003245##
3246
Cary Clark2ade9972017-11-02 17:49:34 -04003247#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003248
3249##
3250
3251# ------------------------------------------------------------------------------
3252
3253#Method void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst,
Herb Derbyefe39bc2018-05-01 17:06:20 -04003254 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003255#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003256#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003257#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003258
3259#Example
3260#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003261void draw(SkCanvas* canvas) {
3262 uint32_t pixels[][2] = { { 0x00000000, 0x55555555},
3263 { 0xAAAAAAAA, 0xFFFFFFFF} };
3264 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003265 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003266 (void*) pixels, sizeof(pixels[0]));
3267 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3268 SkPaint paint;
3269 canvas->scale(4, 4);
3270 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
3271 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
3272 canvas->drawImageRect(image, SkIRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
3273 canvas->translate(8, 0);
3274 }
Cary Clark8032b982017-07-28 11:04:54 -04003275}
3276##
3277
Cary Clark2ade9972017-11-02 17:49:34 -04003278#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
3279
Cary Clark8032b982017-07-28 11:04:54 -04003280##
3281
3282# ------------------------------------------------------------------------------
3283
Cary Clark0ac0edd2018-10-29 11:28:43 -04003284#Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003285#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003286#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003287#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003288
3289#Example
3290#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003291void draw(SkCanvas* canvas) {
3292 uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
3293 { 0xAAAA0000, 0xFFFF0000} };
3294 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003295 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003296 (void*) pixels, sizeof(pixels[0]));
3297 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3298 SkPaint paint;
3299 canvas->scale(4, 4);
3300 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
3301 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
3302 canvas->drawImageRect(image, SkRect::MakeWH(8, 8), &paint);
3303 canvas->translate(8, 0);
3304 }
Cary Clark8032b982017-07-28 11:04:54 -04003305}
3306##
3307
Cary Clark2ade9972017-11-02 17:49:34 -04003308#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
Cary Clark8032b982017-07-28 11:04:54 -04003309
3310##
3311
3312# ------------------------------------------------------------------------------
3313
3314#Method void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
3315 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003316#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003317#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003318#Line # draws Nine_Patch Image ##
Cary Clark8032b982017-07-28 11:04:54 -04003319
Cary Clark80247e52018-07-11 16:18:41 -04003320Draws Image image stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003321IRect center divides the image into nine sections: four sides, four corners, and
Cary Clarkce101242017-09-01 15:51:02 -04003322the center. Corners are unmodified or scaled down proportionately if their sides
Cary Clarkbad5ad72017-08-03 17:14:08 -04003323are larger than dst; center and four sides are scaled to fit remaining space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003324
Cary Clarkbad5ad72017-08-03 17:14:08 -04003325Additionally transform draw using Clip, Matrix, and optional Paint paint.
3326
Cary Clark682c58d2018-05-16 07:07:07 -04003327#paint_as_used_by_draw_lattice_or_draw_nine(image)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003328
3329If generated mask extends beyond image bounds, replicate image edge colors, just
3330as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
Cary Clarkbc5697d2017-10-04 14:31:33 -04003331replicates the image edge color when it samples outside of its bounds.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003332
3333#Param image Image containing pixels, dimensions, and format ##
3334#Param center IRect edge of image corners and sides ##
3335#Param dst destination Rect of image to draw to ##
3336#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3337 and so on; or nullptr
3338##
Cary Clark8032b982017-07-28 11:04:54 -04003339
3340#Example
3341#Height 128
3342#Description
3343 The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
Cary Clarkce101242017-09-01 15:51:02 -04003344 The second image equals the size of center; only corners are drawn without scaling.
3345 The remaining images are larger than center. All corners draw without scaling.
3346 The sides and center are scaled if needed to take up the remaining space.
Cary Clark8032b982017-07-28 11:04:54 -04003347##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003348void draw(SkCanvas* canvas) {
3349 SkIRect center = { 20, 10, 50, 40 };
3350 SkBitmap bitmap;
3351 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3352 SkCanvas bitCanvas(bitmap);
3353 SkPaint paint;
3354 SkColor gray = 0xFF000000;
3355 int left = 0;
3356 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3357 int top = 0;
3358 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3359 paint.setColor(gray);
3360 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3361 gray += 0x001f1f1f;
3362 top = bottom;
3363 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003364 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003365 }
3366 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3367 SkImage* imagePtr = image.get();
3368 for (auto dest: { 20, 30, 40, 60, 90 } ) {
3369 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
3370 canvas->translate(dest + 4, 0);
3371 }
Cary Clark8032b982017-07-28 11:04:54 -04003372}
3373##
3374
Cary Clark2ade9972017-11-02 17:49:34 -04003375#SeeAlso drawImage drawBitmapNine drawImageLattice drawImageRect
Cary Clark8032b982017-07-28 11:04:54 -04003376
3377##
3378
3379# ------------------------------------------------------------------------------
3380
3381#Method void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst,
Herb Derbyefe39bc2018-05-01 17:06:20 -04003382 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003383#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003384#In Draw
Cary Clark80247e52018-07-11 16:18:41 -04003385Draws Image image stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003386IRect center divides the image into nine sections: four sides, four corners, and
Cary Clarkce101242017-09-01 15:51:02 -04003387the center. Corners are not scaled, or scaled down proportionately if their sides
Cary Clarkbad5ad72017-08-03 17:14:08 -04003388are larger than dst; center and four sides are scaled to fit remaining space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003389
Cary Clarkbad5ad72017-08-03 17:14:08 -04003390Additionally transform draw using Clip, Matrix, and optional Paint paint.
3391
Cary Clark137b8742018-05-30 09:21:49 -04003392#paint_as_used_by_draw_lattice_or_draw_nine(image)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003393
3394If generated mask extends beyond image bounds, replicate image edge colors, just
3395as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
Cary Clarkbc5697d2017-10-04 14:31:33 -04003396replicates the image edge color when it samples outside of its bounds.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003397
3398#Param image Image containing pixels, dimensions, and format ##
3399#Param center IRect edge of image corners and sides ##
3400#Param dst destination Rect of image to draw to ##
3401#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3402 and so on; or nullptr
3403##
Cary Clark8032b982017-07-28 11:04:54 -04003404
3405#Example
3406#Height 128
3407#Description
3408 The two leftmost images has four corners and sides to the left and right of center.
3409 The leftmost image scales the width of corners proportionately to fit.
Herb Derbyefe39bc2018-05-01 17:06:20 -04003410 The third and fourth image corners are not scaled; the sides and center are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04003411 fill the remaining space.
3412 The rightmost image has four corners scaled vertically to fit, and uses sides above
3413 and below center to fill the remaining space.
3414##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003415void draw(SkCanvas* canvas) {
3416 SkIRect center = { 20, 10, 50, 40 };
3417 SkBitmap bitmap;
3418 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3419 SkCanvas bitCanvas(bitmap);
3420 SkPaint paint;
3421 SkColor gray = 0xFF000000;
3422 int left = 0;
3423 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3424 int top = 0;
3425 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3426 paint.setColor(gray);
3427 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3428 gray += 0x001f1f1f;
3429 top = bottom;
3430 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003431 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003432 }
3433 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3434 for (auto dest: { 20, 30, 40, 60, 90 } ) {
3435 canvas->drawImageNine(image, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
3436 canvas->translate(dest + 4, 0);
3437 }
Cary Clark8032b982017-07-28 11:04:54 -04003438}
3439##
3440
Cary Clark2ade9972017-11-02 17:49:34 -04003441#SeeAlso drawImage drawBitmapNine drawImageLattice drawImageRect
Cary Clark8032b982017-07-28 11:04:54 -04003442
3443##
3444
3445# ------------------------------------------------------------------------------
3446
3447#Method void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
Cary Clark73fa9722017-08-29 17:36:51 -04003448 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003449#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003450#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003451#Line # draws Bitmap at (x, y) position ##
Cary Clark09d80c02018-10-31 12:14:03 -04003452#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003453
3454#Example
3455#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003456void draw(SkCanvas* canvas) {
3457 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
3458 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
3459 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
3460 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
3461 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
3462 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
3463 { 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00},
3464 { 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF} };
3465 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003466 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003467 (void*) pixels, sizeof(pixels[0]));
3468 SkPaint paint;
3469 canvas->scale(4, 4);
3470 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
3471 paint.setColor(color);
3472 canvas->drawBitmap(bitmap, 0, 0, &paint);
3473 canvas->translate(12, 0);
3474 }
Cary Clark8032b982017-07-28 11:04:54 -04003475}
3476##
3477
Cary Clark2ade9972017-11-02 17:49:34 -04003478#SeeAlso drawImage drawBitmapLattice drawBitmapNine drawBitmapRect SkBitmap::readPixels SkBitmap::writePixels
Cary Clark8032b982017-07-28 11:04:54 -04003479
3480##
3481
3482# ------------------------------------------------------------------------------
3483
3484#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
3485 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003486#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003487#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003488#Line # draws Bitmap, source Rect to destination Rect ##
Cary Clark09d80c02018-10-31 12:14:03 -04003489#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003490
3491#Example
3492#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003493void draw(SkCanvas* canvas) {
3494 uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
3495 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
3496 { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
3497 { 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
3498 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
3499 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
3500 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
3501 { 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00} };
3502 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003503 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003504 (void*) pixels, sizeof(pixels[0]));
3505 SkPaint paint;
Cary Clark681287e2018-03-16 11:34:15 -04003506 paint.setMaskFilter(SkMaskFilter::MakeBlur(kSolid_SkBlurStyle, 6));
Cary Clarkbad5ad72017-08-03 17:14:08 -04003507 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
3508 paint.setColor(color);
3509 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
3510 canvas->translate(48, 0);
3511 }
Cary Clark8032b982017-07-28 11:04:54 -04003512}
3513##
3514
Cary Clark2ade9972017-11-02 17:49:34 -04003515#SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
Cary Clark8032b982017-07-28 11:04:54 -04003516
3517##
3518
3519# ------------------------------------------------------------------------------
3520
3521#Method void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
3522 const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003523#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003524#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003525#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003526
3527#Example
3528#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003529void draw(SkCanvas* canvas) {
3530 uint8_t pixels[][8] = { { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
3531 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
3532 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
3533 { 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
3534 { 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF},
3535 { 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF},
3536 { 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
3537 { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00} };
3538 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003539 bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003540 (void*) pixels, sizeof(pixels[0]));
3541 SkPaint paint;
3542 paint.setFilterQuality(kHigh_SkFilterQuality);
3543 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00, 0xFF7f007f} ) {
3544 paint.setColor(color);
3545 canvas->drawBitmapRect(bitmap, SkIRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
3546 canvas->translate(48.25f, 0);
3547 }
Cary Clark8032b982017-07-28 11:04:54 -04003548}
3549##
3550
Cary Clark2ade9972017-11-02 17:49:34 -04003551#SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
Cary Clark8032b982017-07-28 11:04:54 -04003552
3553##
3554
3555# ------------------------------------------------------------------------------
3556
3557#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
3558 SrcRectConstraint constraint = kStrict_SrcRectConstraint)
Cary Clarkab2621d2018-01-30 10:08:57 -05003559#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003560#In Draw
Cary Clark09d80c02018-10-31 12:14:03 -04003561#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003562
3563#Example
3564#Height 64
Cary Clarkbad5ad72017-08-03 17:14:08 -04003565void draw(SkCanvas* canvas) {
3566 uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
3567 { 0xAAAA0000, 0xFFFF0000} };
3568 SkBitmap bitmap;
Herb Derbyefe39bc2018-05-01 17:06:20 -04003569 bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
Cary Clarkbad5ad72017-08-03 17:14:08 -04003570 (void*) pixels, sizeof(pixels[0]));
3571 SkPaint paint;
3572 canvas->scale(4, 4);
3573 for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
3574 paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
3575 canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), &paint);
3576 canvas->translate(8, 0);
3577 }
Cary Clark8032b982017-07-28 11:04:54 -04003578}
3579##
3580
Cary Clark2ade9972017-11-02 17:49:34 -04003581#SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
Cary Clark8032b982017-07-28 11:04:54 -04003582
3583##
3584
3585# ------------------------------------------------------------------------------
3586
Cary Clark682c58d2018-05-16 07:07:07 -04003587#PhraseDef paint_as_used_by_draw_lattice_or_draw_nine(bitmap_or_image)
3588If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
3589Blend_Mode, and Draw_Looper. If #bitmap_or_image# is kAlpha_8_SkColorType, apply Shader.
3590If paint contains Mask_Filter, generate mask from #bitmap_or_image# bounds. If paint
3591Filter_Quality set to kNone_SkFilterQuality, disable pixel filtering. For all
3592other values of paint Filter_Quality, use kLow_SkFilterQuality to filter pixels.
Cary Clark137b8742018-05-30 09:21:49 -04003593Any SkMaskFilter on paint is ignored as is paint Anti_Aliasing state.
Cary Clark682c58d2018-05-16 07:07:07 -04003594##
3595
Cary Clark8032b982017-07-28 11:04:54 -04003596#Method void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
Cary Clark73fa9722017-08-29 17:36:51 -04003597 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003598#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003599#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003600#Line # draws Nine_Patch Bitmap ##
Cary Clark8032b982017-07-28 11:04:54 -04003601
Cary Clark80247e52018-07-11 16:18:41 -04003602Draws Bitmap bitmap stretched proportionally to fit into Rect dst.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003603IRect center divides the bitmap into nine sections: four sides, four corners,
Cary Clarkce101242017-09-01 15:51:02 -04003604and the center. Corners are not scaled, or scaled down proportionately if their
Cary Clarkbad5ad72017-08-03 17:14:08 -04003605sides are larger than dst; center and four sides are scaled to fit remaining
3606space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003607
Cary Clarkbad5ad72017-08-03 17:14:08 -04003608Additionally transform draw using Clip, Matrix, and optional Paint paint.
3609
Cary Clark682c58d2018-05-16 07:07:07 -04003610#paint_as_used_by_draw_lattice_or_draw_nine(bitmap)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003611
3612If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
3613just as Shader made from SkShader::MakeBitmapShader with
Cary Clarkbc5697d2017-10-04 14:31:33 -04003614SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
Cary Clarkbad5ad72017-08-03 17:14:08 -04003615outside of its bounds.
3616
3617#Param bitmap Bitmap containing pixels, dimensions, and format ##
3618#Param center IRect edge of image corners and sides ##
3619#Param dst destination Rect of image to draw to ##
3620#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3621 and so on; or nullptr
3622##
Cary Clark8032b982017-07-28 11:04:54 -04003623
3624#Example
3625#Height 128
3626#Description
3627 The two leftmost bitmap draws has four corners and sides to the left and right of center.
3628 The leftmost bitmap draw scales the width of corners proportionately to fit.
Herb Derbyefe39bc2018-05-01 17:06:20 -04003629 The third and fourth draw corners are not scaled; the sides and center are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04003630 fill the remaining space.
3631 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
3632 and below center to fill the remaining space.
3633##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003634void draw(SkCanvas* canvas) {
3635 SkIRect center = { 20, 10, 50, 40 };
3636 SkBitmap bitmap;
3637 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3638 SkCanvas bitCanvas(bitmap);
3639 SkPaint paint;
3640 SkColor gray = 0xFF000000;
3641 int left = 0;
3642 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3643 int top = 0;
3644 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3645 paint.setColor(gray);
3646 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3647 gray += 0x001f1f1f;
3648 top = bottom;
3649 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003650 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003651 }
3652 for (auto dest: { 20, 30, 40, 60, 90 } ) {
3653 canvas->drawBitmapNine(bitmap, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
3654 canvas->translate(dest + 4, 0);
3655 }
Cary Clark8032b982017-07-28 11:04:54 -04003656}
3657##
3658
Cary Clark2ade9972017-11-02 17:49:34 -04003659#SeeAlso drawImageNine drawBitmap drawBitmapLattice drawBitmapRect
Cary Clark8032b982017-07-28 11:04:54 -04003660
3661##
3662
3663# ------------------------------------------------------------------------------
Cary Clark682c58d2018-05-16 07:07:07 -04003664#Subtopic Lattice
3665#Line # divides Bitmap or Image into a rectangular grid ##
3666
Cary Clark8032b982017-07-28 11:04:54 -04003667#Struct Lattice
Cary Clark08895c42018-02-01 09:37:32 -05003668#Line # divides Bitmap or Image into a rectangular grid ##
Cary Clark682c58d2018-05-16 07:07:07 -04003669
Cary Clark8032b982017-07-28 11:04:54 -04003670#Code
Cary Clark61313f32018-10-08 14:57:48 -04003671#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003672##
3673
Cary Clark137b8742018-05-30 09:21:49 -04003674Lattice divides Bitmap or Image into a rectangular grid.
3675Grid entries on even columns and even rows are fixed; these entries are
3676always drawn at their original size if the destination is large enough.
3677If the destination side is too small to hold the fixed entries, all fixed
3678entries are proportionately scaled down to fit.
3679The grid entries not on even columns and rows are scaled to fit the
3680remaining space, if any.
3681
Cary Clark2f466242017-12-11 16:03:17 -05003682 #Enum RectType
Cary Clark682c58d2018-05-16 07:07:07 -04003683 #Line # optional setting per rectangular grid entry ##
Cary Clark8032b982017-07-28 11:04:54 -04003684 #Code
Cary Clark61313f32018-10-08 14:57:48 -04003685 #Populate
Cary Clark8032b982017-07-28 11:04:54 -04003686 ##
3687
Cary Clark2f466242017-12-11 16:03:17 -05003688 Optional setting per rectangular grid entry to make it transparent,
3689 or to fill the grid entry with a color.
Cary Clark8032b982017-07-28 11:04:54 -04003690
Cary Clark2f466242017-12-11 16:03:17 -05003691 #Const kDefault 0
Cary Clark682c58d2018-05-16 07:07:07 -04003692 #Line # draws Bitmap into lattice rectangle ##
Cary Clark2f466242017-12-11 16:03:17 -05003693 ##
3694
3695 #Const kTransparent 1
Cary Clark682c58d2018-05-16 07:07:07 -04003696 #Line # skips lattice rectangle by making it transparent ##
Cary Clark2f466242017-12-11 16:03:17 -05003697 ##
3698
3699 #Const kFixedColor 2
Cary Clark682c58d2018-05-16 07:07:07 -04003700 #Line # draws one of fColors into lattice rectangle ##
Cary Clark8032b982017-07-28 11:04:54 -04003701 ##
3702 ##
3703
Cary Clark61313f32018-10-08 14:57:48 -04003704#Subtopic Members
Cary Clark682c58d2018-05-16 07:07:07 -04003705##
3706
Cary Clark8032b982017-07-28 11:04:54 -04003707 #Member const int* fXDivs
Cary Clark5538c132018-06-14 12:28:14 -04003708 #Line # x-axis values dividing bitmap ##
3709 Array of x-axis values that divide the bitmap vertically.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003710 Array entries must be unique, increasing, greater than or equal to
3711 fBounds left edge, and less than fBounds right edge.
3712 Set the first element to fBounds left to collapse the left column of
3713 fixed grid entries.
Cary Clark8032b982017-07-28 11:04:54 -04003714 ##
3715
3716 #Member const int* fYDivs
Cary Clark5538c132018-06-14 12:28:14 -04003717 #Line # y-axis values dividing bitmap ##
3718 Array of y-axis values that divide the bitmap horizontally.
Cary Clarkbad5ad72017-08-03 17:14:08 -04003719 Array entries must be unique, increasing, greater than or equal to
3720 fBounds top edge, and less than fBounds bottom edge.
3721 Set the first element to fBounds top to collapse the top row of fixed
3722 grid entries.
Cary Clark8032b982017-07-28 11:04:54 -04003723 ##
3724
Cary Clark2f466242017-12-11 16:03:17 -05003725 #Member const RectType* fRectTypes
Cary Clark682c58d2018-05-16 07:07:07 -04003726 #Line # array of fill types ##
Cary Clark2f466242017-12-11 16:03:17 -05003727 Optional array of fill types, one per rectangular grid entry:
Cary Clark2be81cf2018-09-13 12:04:30 -04003728 array length must be #Formula # (fXCount + 1) * (fYCount + 1) ##.
Cary Clark6fc50412017-09-21 12:31:06 -04003729
Cary Clark2f466242017-12-11 16:03:17 -05003730 Each RectType is one of: kDefault, kTransparent, kFixedColor.
3731
Cary Clark8032b982017-07-28 11:04:54 -04003732 Array entries correspond to the rectangular grid entries, ascending
3733 left to right and then top to bottom.
3734 ##
3735
3736 #Member int fXCount
Cary Clark682c58d2018-05-16 07:07:07 -04003737 #Line # number of x-coordinates ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003738 Number of entries in fXDivs array; one less than the number of
3739 horizontal divisions.
Cary Clark8032b982017-07-28 11:04:54 -04003740 ##
3741
3742 #Member int fYCount
Cary Clark682c58d2018-05-16 07:07:07 -04003743 #Line # number of y-coordinates ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003744 Number of entries in fYDivs array; one less than the number of vertical
3745 divisions.
Cary Clark8032b982017-07-28 11:04:54 -04003746 ##
3747
3748 #Member const SkIRect* fBounds
Cary Clark682c58d2018-05-16 07:07:07 -04003749 #Line # source bounds to draw from ##
Cary Clark8032b982017-07-28 11:04:54 -04003750 Optional subset IRect source to draw from.
3751 If nullptr, source bounds is dimensions of Bitmap or Image.
3752 ##
3753
Cary Clark2f466242017-12-11 16:03:17 -05003754 #Member const SkColor* fColors
Cary Clark682c58d2018-05-16 07:07:07 -04003755 #Line # array of colors ##
Cary Clark2f466242017-12-11 16:03:17 -05003756 Optional array of colors, one per rectangular grid entry.
Cary Clark2be81cf2018-09-13 12:04:30 -04003757 Array length must be #Formula # (fXCount + 1) * (fYCount + 1) ##.
Cary Clark2f466242017-12-11 16:03:17 -05003758
3759 Array entries correspond to the rectangular grid entries, ascending
3760 left to right, then top to bottom.
3761 ##
3762
Cary Clark8032b982017-07-28 11:04:54 -04003763#Struct Lattice ##
3764
3765#Method void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
3766 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003767#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003768#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003769#Line # draws proportionally stretched Bitmap ##
Cary Clark8032b982017-07-28 11:04:54 -04003770
Cary Clark80247e52018-07-11 16:18:41 -04003771Draws Bitmap bitmap stretched proportionally to fit into Rect dst.
Cary Clark8032b982017-07-28 11:04:54 -04003772
3773Lattice lattice divides bitmap into a rectangular grid.
3774Each intersection of an even-numbered row and column is fixed; like the corners
Cary Clarkbad5ad72017-08-03 17:14:08 -04003775of drawBitmapNine, fixed lattice elements never scale larger than their initial
Cary Clarkbc5697d2017-10-04 14:31:33 -04003776size and shrink proportionately when all fixed elements exceed the bitmap
Cary Clarkbad5ad72017-08-03 17:14:08 -04003777dimension. All other grid elements scale to fill the available space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003778
3779Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04003780
Cary Clark682c58d2018-05-16 07:07:07 -04003781#paint_as_used_by_draw_lattice_or_draw_nine(bitmap)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003782
3783If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
3784just as Shader made from SkShader::MakeBitmapShader with
Cary Clarkbc5697d2017-10-04 14:31:33 -04003785SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
Cary Clarkbad5ad72017-08-03 17:14:08 -04003786outside of its bounds.
3787
3788#Param bitmap Bitmap containing pixels, dimensions, and format ##
3789#Param lattice division of bitmap into fixed and variable rectangles ##
3790#Param dst destination Rect of image to draw to ##
3791#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3792 and so on; or nullptr
3793##
Cary Clark8032b982017-07-28 11:04:54 -04003794
3795#Example
3796#Height 128
3797#Description
3798 The two leftmost bitmap draws has four corners and sides to the left and right of center.
3799 The leftmost bitmap draw scales the width of corners proportionately to fit.
Herb Derbyefe39bc2018-05-01 17:06:20 -04003800 The third and fourth draw corners are not scaled; the sides are scaled to
Cary Clark8032b982017-07-28 11:04:54 -04003801 fill the remaining space; the center is transparent.
3802 The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
3803 and below center to fill the remaining space.
3804##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003805void draw(SkCanvas* canvas) {
3806 SkIRect center = { 20, 10, 50, 40 };
3807 SkBitmap bitmap;
3808 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3809 SkCanvas bitCanvas(bitmap);
3810 SkPaint paint;
3811 SkColor gray = 0xFF000000;
3812 int left = 0;
3813 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3814 int top = 0;
3815 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3816 paint.setColor(gray);
3817 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3818 gray += 0x001f1f1f;
3819 top = bottom;
3820 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003821 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003822 }
3823 const int xDivs[] = { center.fLeft, center.fRight };
3824 const int yDivs[] = { center.fTop, center.fBottom };
Cary Clarkca3ebcd2017-12-12 11:22:38 -05003825 SkCanvas::Lattice::RectType fillTypes[3][3];
3826 memset(fillTypes, 0, sizeof(fillTypes));
3827 fillTypes[1][1] = SkCanvas::Lattice::kTransparent;
3828 SkColor dummy[9]; // temporary pending bug fix
3829 SkCanvas::Lattice lattice = { xDivs, yDivs, fillTypes[0], SK_ARRAY_COUNT(xDivs),
3830 SK_ARRAY_COUNT(yDivs), nullptr, dummy };
Cary Clarkbad5ad72017-08-03 17:14:08 -04003831 for (auto dest: { 20, 30, 40, 60, 90 } ) {
Cary Clarkca3ebcd2017-12-12 11:22:38 -05003832 canvas->drawBitmapLattice(bitmap, lattice, SkRect::MakeWH(dest, 110 - dest), nullptr);
Cary Clarkbad5ad72017-08-03 17:14:08 -04003833 canvas->translate(dest + 4, 0);
3834 }
Cary Clark8032b982017-07-28 11:04:54 -04003835}
3836##
3837
Cary Clark2ade9972017-11-02 17:49:34 -04003838#SeeAlso drawImageLattice drawBitmap drawBitmapNine Lattice
Cary Clark8032b982017-07-28 11:04:54 -04003839
3840##
3841
3842# ------------------------------------------------------------------------------
3843
3844#Method void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
3845 const SkPaint* paint = nullptr)
Cary Clarkab2621d2018-01-30 10:08:57 -05003846#In Draw_Image
Cary Clark78de7512018-02-07 07:27:09 -05003847#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003848#Line # draws proportionally stretched Image ##
Cary Clark8032b982017-07-28 11:04:54 -04003849
Cary Clark80247e52018-07-11 16:18:41 -04003850Draws Image image stretched proportionally to fit into Rect dst.
Cary Clark8032b982017-07-28 11:04:54 -04003851
3852Lattice lattice divides image into a rectangular grid.
3853Each intersection of an even-numbered row and column is fixed; like the corners
Cary Clarkbad5ad72017-08-03 17:14:08 -04003854of drawBitmapNine, fixed lattice elements never scale larger than their initial
Cary Clarkbc5697d2017-10-04 14:31:33 -04003855size and shrink proportionately when all fixed elements exceed the bitmap
Cary Clarkbad5ad72017-08-03 17:14:08 -04003856dimension. All other grid elements scale to fill the available space, if any.
Cary Clark8032b982017-07-28 11:04:54 -04003857
3858Additionally transform draw using Clip, Matrix, and optional Paint paint.
Cary Clark8032b982017-07-28 11:04:54 -04003859
Cary Clark682c58d2018-05-16 07:07:07 -04003860#paint_as_used_by_draw_lattice_or_draw_nine(image)#
Cary Clarkbad5ad72017-08-03 17:14:08 -04003861
3862If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
3863just as Shader made from SkShader::MakeBitmapShader with
Cary Clarkbc5697d2017-10-04 14:31:33 -04003864SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
Cary Clarkbad5ad72017-08-03 17:14:08 -04003865outside of its bounds.
3866
3867#Param image Image containing pixels, dimensions, and format ##
3868#Param lattice division of bitmap into fixed and variable rectangles ##
3869#Param dst destination Rect of image to draw to ##
3870#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
3871 and so on; or nullptr
3872##
Cary Clark8032b982017-07-28 11:04:54 -04003873
3874#Example
3875#Height 128
3876#Description
3877 The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
Cary Clarkce101242017-09-01 15:51:02 -04003878 The second image equals the size of center; only corners are drawn without scaling.
3879 The remaining images are larger than center. All corners draw without scaling. The sides
Cary Clark8032b982017-07-28 11:04:54 -04003880 are scaled if needed to take up the remaining space; the center is transparent.
3881##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003882void draw(SkCanvas* canvas) {
3883 SkIRect center = { 20, 10, 50, 40 };
3884 SkBitmap bitmap;
3885 bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
3886 SkCanvas bitCanvas(bitmap);
3887 SkPaint paint;
3888 SkColor gray = 0xFF000000;
3889 int left = 0;
3890 for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
3891 int top = 0;
3892 for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
3893 paint.setColor(gray);
3894 bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
3895 gray += 0x001f1f1f;
3896 top = bottom;
3897 }
Herb Derbyefe39bc2018-05-01 17:06:20 -04003898 left = right;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003899 }
Cary Clarkbad5ad72017-08-03 17:14:08 -04003900 sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
3901 SkImage* imagePtr = image.get();
3902 for (auto dest: { 20, 30, 40, 60, 90 } ) {
3903 canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
3904 canvas->translate(dest + 4, 0);
3905 }
Cary Clark8032b982017-07-28 11:04:54 -04003906}
3907##
3908
Cary Clark2ade9972017-11-02 17:49:34 -04003909#SeeAlso drawBitmapLattice drawImage drawImageNine Lattice
Cary Clark8032b982017-07-28 11:04:54 -04003910
3911##
3912
Cary Clark682c58d2018-05-16 07:07:07 -04003913#Subtopic Lattice ##
3914
Cary Clark08895c42018-02-01 09:37:32 -05003915#Subtopic Draw_Image ##
Cary Clark8032b982017-07-28 11:04:54 -04003916
3917# ------------------------------------------------------------------------------
Cary Clark78de7512018-02-07 07:27:09 -05003918#Subtopic Draw_Text
Cary Clark78de7512018-02-07 07:27:09 -05003919#Line # draws text into Canvas ##
3920##
Cary Clark8032b982017-07-28 11:04:54 -04003921
3922#Method void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
3923 const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05003924#In Draw_Text
3925#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003926#Line # draws text at (x, y), using font advance ##
Cary Clark09d80c02018-10-31 12:14:03 -04003927#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003928
3929#Example
3930#Height 200
3931#Description
3932 The same text is drawn varying Paint_Text_Size and varying
Herb Derbyefe39bc2018-05-01 17:06:20 -04003933 Matrix.
Cary Clark8032b982017-07-28 11:04:54 -04003934##
Cary Clarkbad5ad72017-08-03 17:14:08 -04003935void draw(SkCanvas* canvas) {
3936 SkPaint paint;
3937 paint.setAntiAlias(true);
3938 float textSizes[] = { 12, 18, 24, 36 };
3939 for (auto size: textSizes ) {
3940 paint.setTextSize(size);
3941 canvas->drawText("Aa", 2, 10, 20, paint);
3942 canvas->translate(0, size * 2);
3943 }
3944 paint.reset();
3945 paint.setAntiAlias(true);
3946 float yPos = 20;
3947 for (auto size: textSizes ) {
3948 float scale = size / 12.f;
3949 canvas->resetMatrix();
3950 canvas->translate(100, 0);
3951 canvas->scale(scale, scale);
3952 canvas->drawText("Aa", 2, 10 / scale, yPos / scale, paint);
Herb Derbyefe39bc2018-05-01 17:06:20 -04003953 yPos += size * 2;
Cary Clarkbad5ad72017-08-03 17:14:08 -04003954 }
3955}
Cary Clark8032b982017-07-28 11:04:54 -04003956##
3957
Cary Clark153e76d2018-08-28 11:48:28 -04003958#SeeAlso drawString drawPosText drawPosTextH drawTextBlob drawTextRSXform
Cary Clark8032b982017-07-28 11:04:54 -04003959
3960##
3961
3962#Method void drawString(const char* string, SkScalar x, SkScalar y, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05003963#In Draw_Text
3964#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003965#Line # draws null terminated string at (x, y) using font advance ##
Cary Clark09d80c02018-10-31 12:14:03 -04003966#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003967
3968#Example
Cary Clarkffb3d682018-05-17 12:17:28 -04003969#Height 48
Cary Clark8032b982017-07-28 11:04:54 -04003970 SkPaint paint;
3971 canvas->drawString("a small hello", 20, 20, paint);
3972##
3973
Cary Clark153e76d2018-08-28 11:48:28 -04003974#SeeAlso drawText drawPosText drawPosTextH drawTextBlob drawTextRSXform
Cary Clark8032b982017-07-28 11:04:54 -04003975
3976##
3977
3978#Method void drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04003979#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003980
3981#Example
3982 SkPaint paint;
3983 SkString string("a small hello");
3984 canvas->drawString(string, 20, 20, paint);
3985##
3986
Cary Clark153e76d2018-08-28 11:48:28 -04003987#SeeAlso drawText drawPosText drawPosTextH drawTextBlob drawTextRSXform
Cary Clark8032b982017-07-28 11:04:54 -04003988
3989##
3990
3991# ------------------------------------------------------------------------------
3992
3993#Method void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
3994 const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05003995#In Draw_Text
3996#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05003997#Line # draws text at array of (x, y) positions ##
Cary Clark09d80c02018-10-31 12:14:03 -04003998#Populate
Cary Clark8032b982017-07-28 11:04:54 -04003999
4000#Example
4001#Height 120
Cary Clarkbad5ad72017-08-03 17:14:08 -04004002void draw(SkCanvas* canvas) {
4003 const char hello[] = "HeLLo!";
4004 const SkPoint pos[] = { {40, 100}, {82, 95}, {115, 110}, {130, 95}, {145, 85},
4005 {172, 100} };
4006 SkPaint paint;
4007 paint.setTextSize(60);
4008 canvas->drawPosText(hello, strlen(hello), pos, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004009}
4010##
4011
Cary Clark153e76d2018-08-28 11:48:28 -04004012#SeeAlso drawText drawPosTextH drawTextBlob drawTextRSXform
Cary Clark8032b982017-07-28 11:04:54 -04004013
4014##
4015
4016# ------------------------------------------------------------------------------
4017
4018#Method void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
4019 const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05004020#In Draw_Text
4021#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004022#Line # draws text at x positions with common baseline ##
Cary Clark09d80c02018-10-31 12:14:03 -04004023#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004024
4025#Example
4026#Height 40
Cary Clarkbad5ad72017-08-03 17:14:08 -04004027 void draw(SkCanvas* canvas) {
4028 SkScalar xpos[] = { 20, 40, 80, 160 };
4029 SkPaint paint;
4030 canvas->drawPosTextH("XXXX", 4, xpos, 20, paint);
4031 }
Cary Clark8032b982017-07-28 11:04:54 -04004032##
4033
Cary Clark153e76d2018-08-28 11:48:28 -04004034#SeeAlso drawText drawPosText drawTextBlob drawTextRSXform
Cary Clark8032b982017-07-28 11:04:54 -04004035
4036##
4037
4038# ------------------------------------------------------------------------------
4039
Cary Clark8032b982017-07-28 11:04:54 -04004040#Method void drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
4041 const SkRect* cullRect, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05004042#In Draw_Text
4043#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004044#Line # draws text with array of RSXform ##
Cary Clark09d80c02018-10-31 12:14:03 -04004045#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004046
4047#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04004048void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04004049 const int iterations = 26;
4050 SkRSXform transforms[iterations];
4051 char alphabet[iterations];
4052 SkScalar angle = 0;
4053 SkScalar scale = 1;
4054 for (size_t i = 0; i < SK_ARRAY_COUNT(transforms); ++i) {
4055 const SkScalar s = SkScalarSin(angle) * scale;
4056 const SkScalar c = SkScalarCos(angle) * scale;
4057 transforms[i] = SkRSXform::Make(-c, -s, -s * 16, c * 16);
4058 angle += .45;
4059 scale += .2;
4060 alphabet[i] = 'A' + i;
4061 }
4062 SkPaint paint;
Cary Clarkbad5ad72017-08-03 17:14:08 -04004063 canvas->translate(110, 138);
4064 canvas->drawTextRSXform(alphabet, sizeof(alphabet), transforms, nullptr, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004065}
4066##
4067
Cary Clark153e76d2018-08-28 11:48:28 -04004068#SeeAlso drawText drawPosText drawTextBlob
Cary Clark8032b982017-07-28 11:04:54 -04004069
4070##
4071
4072# ------------------------------------------------------------------------------
4073
4074#Method void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05004075#In Draw_Text
4076#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004077#Line # draws text with arrays of positions and Paint ##
Cary Clark80247e52018-07-11 16:18:41 -04004078Draws Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004079
Cary Clarkce101242017-09-01 15:51:02 -04004080blob contains Glyphs, their positions, and paint attributes specific to text:
Cary Clark3e73dcf2018-12-06 08:41:14 -05004081#font_metrics#.
Cary Clark8032b982017-07-28 11:04:54 -04004082
Mike Reed0f9d33e2018-12-05 10:54:05 -05004083Paint_Text_Encoding must be set to kGlyphID_SkTextEncoding.
Cary Clark3cd22cc2017-12-01 11:49:58 -05004084
Cary Clarkd2ca79c2018-08-10 13:09:13 -04004085Elements of paint: Anti_Alias, Blend_Mode, Color including Color_Alpha,
4086Color_Filter, Paint_Dither, Draw_Looper, Mask_Filter, Path_Effect, Shader, and
Cary Clark61313f32018-10-08 14:57:48 -04004087Paint_Style; apply to blob. If Paint contains SkPaint::kStroke_Style:
Cary Clarkd2ca79c2018-08-10 13:09:13 -04004088Paint_Miter_Limit, Paint_Stroke_Cap, Paint_Stroke_Join, and Paint_Stroke_Width;
4089apply to Path created from blob.
Cary Clark8032b982017-07-28 11:04:54 -04004090
Cary Clarkce101242017-09-01 15:51:02 -04004091#Param blob Glyphs, positions, and their paints' text size, typeface, and so on ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004092#Param x horizontal offset applied to blob ##
4093#Param y vertical offset applied to blob ##
4094#Param paint blend, color, stroking, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04004095
4096#Example
4097#Height 120
Cary Clarke80cd442018-07-17 13:19:56 -04004098void draw(SkCanvas* canvas) {
Mike Reed0f9d33e2018-12-05 10:54:05 -05004099 SkTextBlobBuilder textBlobBuilder;
4100 const char bunny[] = "/(^x^)\\";
4101 const int len = sizeof(bunny) - 1;
4102 uint16_t glyphs[len];
4103 SkPaint paint;
4104 paint.textToGlyphs(bunny, len, glyphs);
4105 paint.setTextEncoding(kGlyphID_SkTextEncoding);
4106 SkFont font;
4107 int runs[] = { 3, 1, 3 };
4108 SkPoint textPos = { 20, 100 };
4109 int glyphIndex = 0;
4110 for (auto runLen : runs) {
4111 font.setSize(1 == runLen ? 20 : 50);
4112 const SkTextBlobBuilder::RunBuffer& run =
4113 textBlobBuilder.allocRun(font, runLen, textPos.fX, textPos.fY);
4114 memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen);
4115 paint.setTextSize(1 == runLen ? 20 : 50);
4116 textPos.fX += paint.measureText(&glyphs[glyphIndex], sizeof(glyphs[0]) * runLen, nullptr);
4117 glyphIndex += runLen;
4118 }
4119 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
4120 paint.reset();
4121 canvas->drawTextBlob(blob.get(), 0, 0, paint);
Cary Clarke80cd442018-07-17 13:19:56 -04004122}
Cary Clark8032b982017-07-28 11:04:54 -04004123##
4124
Cary Clark2ade9972017-11-02 17:49:34 -04004125#SeeAlso drawText drawPosText drawPosTextH
Cary Clark8032b982017-07-28 11:04:54 -04004126
4127##
4128
4129# ------------------------------------------------------------------------------
4130
Herb Derbyefe39bc2018-05-01 17:06:20 -04004131#Method void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint)
Cary Clark8032b982017-07-28 11:04:54 -04004132
Cary Clark80247e52018-07-11 16:18:41 -04004133Draws Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
Cary Clarkbad5ad72017-08-03 17:14:08 -04004134
Cary Clarkce101242017-09-01 15:51:02 -04004135blob contains Glyphs, their positions, and paint attributes specific to text:
Cary Clark3e73dcf2018-12-06 08:41:14 -05004136#font_metrics#.
Cary Clark8032b982017-07-28 11:04:54 -04004137
Mike Reed0f9d33e2018-12-05 10:54:05 -05004138Paint_Text_Encoding must be set to kGlyphID_SkTextEncoding.
Cary Clark3cd22cc2017-12-01 11:49:58 -05004139
Herb Derbyefe39bc2018-05-01 17:06:20 -04004140Elements of paint: Path_Effect, Mask_Filter, Shader, Color_Filter,
Cary Clark8032b982017-07-28 11:04:54 -04004141Image_Filter, and Draw_Looper; apply to blob.
4142
Cary Clarkce101242017-09-01 15:51:02 -04004143#Param blob Glyphs, positions, and their paints' text size, typeface, and so on ##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004144#Param x horizontal offset applied to blob ##
4145#Param y vertical offset applied to blob ##
4146#Param paint blend, color, stroking, and so on, used to draw ##
Cary Clark8032b982017-07-28 11:04:54 -04004147
4148#Example
4149#Height 120
4150#Description
Cary Clark8032b982017-07-28 11:04:54 -04004151Paint attributes related to text, like text size, have no effect on paint passed to drawTextBlob.
4152##
Cary Clarkbad5ad72017-08-03 17:14:08 -04004153 void draw(SkCanvas* canvas) {
4154 SkTextBlobBuilder textBlobBuilder;
Cary Clarkfc93eb02018-11-24 22:32:31 -05004155 SkFont font;
4156 font.setSize(50);
Herb Derbyefe39bc2018-05-01 17:06:20 -04004157 const SkTextBlobBuilder::RunBuffer& run =
Cary Clarkfc93eb02018-11-24 22:32:31 -05004158 textBlobBuilder.allocRun(font, 1, 20, 100);
Cary Clarkbad5ad72017-08-03 17:14:08 -04004159 run.glyphs[0] = 20;
4160 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
Cary Clarkfc93eb02018-11-24 22:32:31 -05004161 SkPaint paint;
Cary Clarkbad5ad72017-08-03 17:14:08 -04004162 paint.setTextSize(10);
4163 paint.setColor(SK_ColorBLUE);
4164 canvas->drawTextBlob(blob.get(), 0, 0, paint);
4165 }
Cary Clark8032b982017-07-28 11:04:54 -04004166##
4167
Cary Clark2ade9972017-11-02 17:49:34 -04004168#SeeAlso drawText drawPosText drawPosTextH
Cary Clark8032b982017-07-28 11:04:54 -04004169
4170##
4171
4172# ------------------------------------------------------------------------------
4173
Herb Derbyefe39bc2018-05-01 17:06:20 -04004174#Method void drawPicture(const SkPicture* picture)
Cary Clark78de7512018-02-07 07:27:09 -05004175#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004176#Line # draws Picture using Clip and Matrix ##
Cary Clark09d80c02018-10-31 12:14:03 -04004177#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004178
4179#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04004180void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04004181 SkPictureRecorder recorder;
4182 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
4183 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
4184 SkPaint paint;
4185 paint.setColor(color);
4186 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
4187 recordingCanvas->translate(10, 10);
4188 recordingCanvas->scale(1.2f, 1.4f);
4189 }
4190 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
Cary Clarkbad5ad72017-08-03 17:14:08 -04004191 canvas->drawPicture(playback);
4192 canvas->scale(2, 2);
4193 canvas->translate(50, 0);
4194 canvas->drawPicture(playback);
Cary Clark8032b982017-07-28 11:04:54 -04004195}
4196##
4197
Cary Clark2ade9972017-11-02 17:49:34 -04004198#SeeAlso drawDrawable SkPicture SkPicture::playback
Cary Clark8032b982017-07-28 11:04:54 -04004199
4200##
4201
4202# ------------------------------------------------------------------------------
4203
Herb Derbyefe39bc2018-05-01 17:06:20 -04004204#Method void drawPicture(const sk_sp<SkPicture>& picture)
Cary Clark09d80c02018-10-31 12:14:03 -04004205#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004206
4207#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04004208void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04004209 SkPictureRecorder recorder;
4210 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
4211 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
4212 SkPaint paint;
4213 paint.setColor(color);
4214 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
4215 recordingCanvas->translate(10, 10);
4216 recordingCanvas->scale(1.2f, 1.4f);
4217 }
4218 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
4219 canvas->drawPicture(playback);
4220 canvas->scale(2, 2);
4221 canvas->translate(50, 0);
4222 canvas->drawPicture(playback);
Cary Clark8032b982017-07-28 11:04:54 -04004223}
4224##
4225
Cary Clark2ade9972017-11-02 17:49:34 -04004226#SeeAlso drawDrawable SkPicture SkPicture::playback
Cary Clark8032b982017-07-28 11:04:54 -04004227
4228##
4229
4230# ------------------------------------------------------------------------------
4231
4232#Method void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004233#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004234
4235#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04004236void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04004237 SkPaint paint;
4238 SkPictureRecorder recorder;
4239 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
4240 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
4241 paint.setColor(color);
4242 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
4243 recordingCanvas->translate(10, 10);
4244 recordingCanvas->scale(1.2f, 1.4f);
4245 }
4246 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
4247 const SkPicture* playbackPtr = playback.get();
4248 SkMatrix matrix;
4249 matrix.reset();
4250 for (auto alpha : { 70, 140, 210 } ) {
4251 paint.setAlpha(alpha);
4252 canvas->drawPicture(playbackPtr, &matrix, &paint);
4253 matrix.preTranslate(70, 70);
4254 }
Cary Clark8032b982017-07-28 11:04:54 -04004255}
4256##
4257
Cary Clark2ade9972017-11-02 17:49:34 -04004258#SeeAlso drawDrawable SkPicture SkPicture::playback
Cary Clark8032b982017-07-28 11:04:54 -04004259
4260##
4261
4262# ------------------------------------------------------------------------------
4263
Herb Derbyefe39bc2018-05-01 17:06:20 -04004264#Method void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004265#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004266
4267#Example
Herb Derbyefe39bc2018-05-01 17:06:20 -04004268void draw(SkCanvas* canvas) {
Cary Clarkbad5ad72017-08-03 17:14:08 -04004269 SkPaint paint;
4270 SkPictureRecorder recorder;
4271 SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
4272 for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
4273 paint.setColor(color);
4274 recordingCanvas->drawRect({10, 10, 30, 40}, paint);
4275 recordingCanvas->translate(10, 10);
4276 recordingCanvas->scale(1.2f, 1.4f);
4277 }
4278 sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
4279 SkMatrix matrix;
4280 matrix.reset();
4281 for (auto alpha : { 70, 140, 210 } ) {
4282 paint.setAlpha(alpha);
4283 canvas->drawPicture(playback, &matrix, &paint);
4284 matrix.preTranslate(70, 70);
4285 }
Cary Clark8032b982017-07-28 11:04:54 -04004286}
4287##
4288
Cary Clark2ade9972017-11-02 17:49:34 -04004289#SeeAlso drawDrawable SkPicture SkPicture::playback
Cary Clark8032b982017-07-28 11:04:54 -04004290
4291##
4292
4293# ------------------------------------------------------------------------------
4294
4295#Method void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05004296#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004297#Line # draws Vertices, a triangle mesh ##
Cary Clark09d80c02018-10-31 12:14:03 -04004298#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004299
4300#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004301void draw(SkCanvas* canvas) {
4302 SkPaint paint;
4303 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
4304 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4305 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
4306 SK_ARRAY_COUNT(points), points, nullptr, colors);
4307 canvas->drawVertices(vertices.get(), SkBlendMode::kSrc, paint);
4308}
Cary Clark8032b982017-07-28 11:04:54 -04004309##
4310
Cary Clark2ade9972017-11-02 17:49:34 -04004311#SeeAlso drawPatch drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004312
4313##
4314
4315# ------------------------------------------------------------------------------
4316
4317#Method void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004318#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004319
4320#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004321void draw(SkCanvas* canvas) {
4322 SkPaint paint;
4323 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
4324 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
4325 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4326 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
4327 SkShader::kClamp_TileMode));
4328 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
4329 SK_ARRAY_COUNT(points), points, texs, colors);
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004330 canvas->drawVertices(vertices, SkBlendMode::kDarken, paint);
4331}
4332##
4333
4334#SeeAlso drawPatch drawPicture
4335
4336##
4337
4338# ------------------------------------------------------------------------------
4339
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004340#Method void drawVertices(const SkVertices* vertices, const SkVertices::Bone bones[],
4341 int boneCount, SkBlendMode mode, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004342#Populate
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004343
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004344#NoExample
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004345void draw(SkCanvas* canvas) {
4346 SkPaint paint;
4347 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
4348 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
4349 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4350 SkVertices::BoneIndices boneIndices[] = { { 0, 0, 0, 0 },
4351 { 1, 0, 0, 0 },
4352 { 2, 0, 0, 0 },
4353 { 3, 0, 0, 0 } };
4354 SkVertices::BoneWeights boneWeights[] = { { 0.0f, 0.0f, 0.0f, 0.0f },
4355 { 1.0f, 0.0f, 0.0f, 0.0f },
4356 { 1.0f, 0.0f, 0.0f, 0.0f },
4357 { 1.0f, 0.0f, 0.0f, 0.0f } };
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004358 SkVertices::Bone bones[] = { {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }},
4359 {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 20.0f }},
4360 {{ 1.0f, 0.0f, 0.0f, 1.0f, 50.0f, 50.0f }},
4361 {{ 1.0f, 0.0f, 0.0f, 1.0f, 20.0f, 0.0f }} };
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004362 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
4363 SkShader::kClamp_TileMode));
4364 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
4365 SK_ARRAY_COUNT(points), points, texs, colors, boneIndices, boneWeights);
4366 canvas->drawVertices(vertices.get(), bones, SK_ARRAY_COUNT(bones), SkBlendMode::kDarken, paint);
4367}
4368##
4369
4370#SeeAlso drawPatch drawPicture
4371
4372##
4373
4374# ------------------------------------------------------------------------------
4375
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004376#Method void drawVertices(const sk_sp<SkVertices>& vertices, const SkVertices::Bone bones[],
4377 int boneCount, SkBlendMode mode, const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004378#Populate
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004379
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004380#NoExample
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004381void draw(SkCanvas* canvas) {
4382 SkPaint paint;
4383 SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
4384 SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
4385 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4386 SkVertices::BoneIndices boneIndices[] = { { 0, 0, 0, 0 },
4387 { 1, 0, 0, 0 },
4388 { 2, 0, 0, 0 },
4389 { 3, 0, 0, 0 } };
4390 SkVertices::BoneWeights boneWeights[] = { { 0.0f, 0.0f, 0.0f, 0.0f },
4391 { 1.0f, 0.0f, 0.0f, 0.0f },
4392 { 1.0f, 0.0f, 0.0f, 0.0f },
4393 { 1.0f, 0.0f, 0.0f, 0.0f } };
Ruiqi Maoc97a3392018-08-15 10:44:19 -04004394 SkVertices::Bone bones[] = { {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }},
4395 {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 20.0f }},
4396 {{ 1.0f, 0.0f, 0.0f, 1.0f, 50.0f, 50.0f }},
4397 {{ 1.0f, 0.0f, 0.0f, 1.0f, 20.0f, 0.0f }} };
Ruiqi Mao94d57c42018-07-02 15:20:10 -04004398 paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
4399 SkShader::kClamp_TileMode));
4400 auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
4401 SK_ARRAY_COUNT(points), points, texs, colors, boneIndices, boneWeights);
4402 canvas->drawVertices(vertices, bones, SK_ARRAY_COUNT(bones), SkBlendMode::kDarken, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004403}
4404##
4405
Cary Clark2ade9972017-11-02 17:49:34 -04004406#SeeAlso drawPatch drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004407
4408##
4409
4410# ------------------------------------------------------------------------------
4411
4412#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
4413 const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint)
Cary Clark78de7512018-02-07 07:27:09 -05004414#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004415#Line # draws Coons_Patch ##
Cary Clark09d80c02018-10-31 12:14:03 -04004416#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004417
4418#Example
4419#Image 5
Cary Clarkbad5ad72017-08-03 17:14:08 -04004420void draw(SkCanvas* canvas) {
4421 // SkBitmap source = cmbkygk;
4422 SkPaint paint;
4423 paint.setFilterQuality(kLow_SkFilterQuality);
4424 paint.setAntiAlias(true);
4425 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
4426 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
4427 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
4428 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
4429 SkColor colors[] = { 0xbfff0000, 0xbf0000ff, 0xbfff00ff, 0xbf00ffff };
4430 SkPoint texCoords[] = { { -30, -30 }, { 162, -30}, { 162, 162}, { -30, 162} };
4431 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
4432 SkShader::kClamp_TileMode, nullptr));
4433 canvas->scale(15, 15);
4434 for (auto blend : { SkBlendMode::kSrcOver, SkBlendMode::kModulate, SkBlendMode::kXor } ) {
4435 canvas->drawPatch(cubics, colors, texCoords, blend, paint);
4436 canvas->translate(4, 4);
4437 }
Cary Clark8032b982017-07-28 11:04:54 -04004438}
4439##
4440
Cary Clark2ade9972017-11-02 17:49:34 -04004441#ToDo can patch use image filter? ##
Cary Clark77b3f3a2018-11-07 14:59:03 -05004442#SeeAlso drawVertices drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004443
4444##
4445
4446# ------------------------------------------------------------------------------
4447
4448#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
Herb Derbyefe39bc2018-05-01 17:06:20 -04004449 const SkPoint texCoords[4], const SkPaint& paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004450#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004451
4452#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004453void draw(SkCanvas* canvas) {
4454 SkPaint paint;
4455 paint.setAntiAlias(true);
4456 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
4457 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
4458 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
4459 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
4460 SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
4461 canvas->scale(30, 30);
4462 canvas->drawPatch(cubics, colors, nullptr, paint);
4463 SkPoint text[] = { {3,0.9f}, {4,2.5f}, {5,0.9f}, {7.5f,3.2f}, {5.5f,4.2f},
4464 {7.5f,5.2f}, {5,7.5f}, {4,5.9f}, {3,7.5f}, {0.5f,5.2f}, {2.5f,4.2f},
4465 {0.5f,3.2f} };
4466 paint.setTextSize(18.f / 30);
Cary Clarkbad5ad72017-08-03 17:14:08 -04004467 for (int i = 0; i< 10; ++i) {
4468 char digit = '0' + i;
4469 canvas->drawText(&digit, 1, text[i].fX, text[i].fY, paint);
4470 }
4471 canvas->drawString("10", text[10].fX, text[10].fY, paint);
4472 canvas->drawString("11", text[11].fX, text[11].fY, paint);
4473 paint.setStyle(SkPaint::kStroke_Style);
4474 canvas->drawPoints(SkCanvas::kPolygon_PointMode, 12, cubics, paint);
4475 canvas->drawLine(cubics[11].fX, cubics[11].fY, cubics[0].fX, cubics[0].fY, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004476}
4477##
4478
4479#Example
4480#Image 6
Cary Clarkbad5ad72017-08-03 17:14:08 -04004481void draw(SkCanvas* canvas) {
4482 // SkBitmap source = checkerboard;
4483 SkPaint paint;
4484 paint.setFilterQuality(kLow_SkFilterQuality);
4485 paint.setAntiAlias(true);
4486 SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
4487 /* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
4488 /* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
4489 /* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
4490 SkPoint texCoords[] = { { 0, 0 }, { 0, 62}, { 62, 62}, { 62, 0 } };
4491 paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
4492 SkShader::kClamp_TileMode, nullptr));
4493 canvas->scale(30, 30);
4494 canvas->drawPatch(cubics, nullptr, texCoords, paint);
Cary Clark8032b982017-07-28 11:04:54 -04004495}
4496##
4497
Cary Clark2ade9972017-11-02 17:49:34 -04004498#ToDo can patch use image filter? ##
Cary Clark77b3f3a2018-11-07 14:59:03 -05004499#SeeAlso drawVertices drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004500
4501##
4502
4503# ------------------------------------------------------------------------------
4504
4505#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
4506 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
4507 const SkPaint* paint)
Cary Clark78de7512018-02-07 07:27:09 -05004508#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004509#Line # draws sprites using Clip, Matrix, and Paint ##
Cary Clark09d80c02018-10-31 12:14:03 -04004510#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004511
4512#Example
4513#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04004514void draw(SkCanvas* canvas) {
4515 // SkBitmap source = mandrill;
4516 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
4517 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
4518 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
4519 const SkImage* imagePtr = image.get();
4520 canvas->drawAtlas(imagePtr, xforms, tex, colors, 2, SkBlendMode::kSrcOver, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04004521}
4522##
4523
Cary Clark2ade9972017-11-02 17:49:34 -04004524#SeeAlso drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04004525
4526##
4527
4528# ------------------------------------------------------------------------------
4529
4530#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
4531 const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
Herb Derbyefe39bc2018-05-01 17:06:20 -04004532 const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004533#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004534
4535#Example
4536#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04004537void draw(SkCanvas* canvas) {
4538 // SkBitmap source = mandrill;
4539 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
4540 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
4541 SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
4542 SkPaint paint;
4543 paint.setAlpha(127);
4544 canvas->drawAtlas(image, xforms, tex, colors, 2, SkBlendMode::kPlus, nullptr, &paint);
Cary Clark8032b982017-07-28 11:04:54 -04004545}
4546##
4547
4548#ToDo bug in example on cpu side, gpu looks ok ##
4549
Cary Clark2ade9972017-11-02 17:49:34 -04004550#SeeAlso drawBitmap drawImage
4551
Cary Clark8032b982017-07-28 11:04:54 -04004552##
4553
4554# ------------------------------------------------------------------------------
4555
4556#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
Herb Derbyefe39bc2018-05-01 17:06:20 -04004557 const SkRect* cullRect, const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004558#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004559
4560#Example
4561#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04004562void draw(SkCanvas* canvas) {
4563 // sk_sp<SkImage> image = mandrill;
4564 SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
4565 SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
4566 const SkImage* imagePtr = image.get();
4567 canvas->drawAtlas(imagePtr, xforms, tex, 2, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04004568}
4569##
4570
Cary Clark2ade9972017-11-02 17:49:34 -04004571#SeeAlso drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04004572
4573##
4574
4575# ------------------------------------------------------------------------------
4576
4577#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
Herb Derbyefe39bc2018-05-01 17:06:20 -04004578 int count, const SkRect* cullRect, const SkPaint* paint)
Cary Clark09d80c02018-10-31 12:14:03 -04004579#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004580
4581#Example
4582#Image 3
Cary Clarkbad5ad72017-08-03 17:14:08 -04004583void draw(SkCanvas* canvas) {
4584 // sk_sp<SkImage> image = mandrill;
4585 SkRSXform xforms[] = { { 1, 0, 0, 0 }, {0, 1, 300, 100 } };
4586 SkRect tex[] = { { 0, 0, 200, 200 }, { 200, 0, 400, 200 } };
4587 canvas->drawAtlas(image, xforms, tex, 2, nullptr, nullptr);
Cary Clark8032b982017-07-28 11:04:54 -04004588}
4589##
4590
Cary Clark2ade9972017-11-02 17:49:34 -04004591#SeeAlso drawBitmap drawImage
Cary Clark8032b982017-07-28 11:04:54 -04004592
4593##
4594
4595# ------------------------------------------------------------------------------
4596
Cary Clark73fa9722017-08-29 17:36:51 -04004597#Method void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr)
Cary Clark78de7512018-02-07 07:27:09 -05004598#In Draw
Cary Clarkab2621d2018-01-30 10:08:57 -05004599#Line # draws Drawable, encapsulated drawing commands ##
Cary Clark09d80c02018-10-31 12:14:03 -04004600#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004601
4602#Example
4603#Height 100
4604#Function
Cary Clarkbad5ad72017-08-03 17:14:08 -04004605struct MyDrawable : public SkDrawable {
4606 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
4607
4608 void onDraw(SkCanvas* canvas) override {
4609 SkPath path;
4610 path.conicTo(10, 90, 50, 90, 0.9f);
4611 SkPaint paint;
4612 paint.setColor(SK_ColorBLUE);
4613 canvas->drawRect(path.getBounds(), paint);
4614 paint.setAntiAlias(true);
4615 paint.setColor(SK_ColorWHITE);
4616 canvas->drawPath(path, paint);
4617 }
4618};
4619
4620#Function ##
4621void draw(SkCanvas* canvas) {
4622 sk_sp<SkDrawable> drawable(new MyDrawable);
4623 SkMatrix matrix;
4624 matrix.setTranslate(10, 10);
4625 canvas->drawDrawable(drawable.get(), &matrix);
Cary Clark8032b982017-07-28 11:04:54 -04004626}
4627##
4628
Cary Clark2ade9972017-11-02 17:49:34 -04004629#SeeAlso SkDrawable drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004630
4631##
4632
4633# ------------------------------------------------------------------------------
4634
4635#Method void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y)
Cary Clark09d80c02018-10-31 12:14:03 -04004636#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004637
4638#Example
4639#Height 100
4640#Function
Cary Clarkbad5ad72017-08-03 17:14:08 -04004641struct MyDrawable : public SkDrawable {
4642 SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
4643
4644 void onDraw(SkCanvas* canvas) override {
4645 SkPath path;
4646 path.conicTo(10, 90, 50, 90, 0.9f);
4647 SkPaint paint;
4648 paint.setColor(SK_ColorBLUE);
4649 canvas->drawRect(path.getBounds(), paint);
4650 paint.setAntiAlias(true);
4651 paint.setColor(SK_ColorWHITE);
4652 canvas->drawPath(path, paint);
4653 }
4654};
4655
4656#Function ##
4657void draw(SkCanvas* canvas) {
4658 sk_sp<SkDrawable> drawable(new MyDrawable);
4659 canvas->drawDrawable(drawable.get(), 10, 10);
Cary Clark8032b982017-07-28 11:04:54 -04004660}
4661##
4662
Cary Clark2ade9972017-11-02 17:49:34 -04004663#SeeAlso SkDrawable drawPicture
Cary Clark8032b982017-07-28 11:04:54 -04004664
4665##
4666
4667# ------------------------------------------------------------------------------
4668
4669#Method void drawAnnotation(const SkRect& rect, const char key[], SkData* value)
Cary Clark78de7512018-02-07 07:27:09 -05004670#In Draw
4671#In Utility
Cary Clarkab2621d2018-01-30 10:08:57 -05004672#Line # associates a Rect with a key-value pair ##
Cary Clark09d80c02018-10-31 12:14:03 -04004673#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004674
4675#Example
4676 #Height 1
4677 const char text[] = "Click this link!";
4678 SkRect bounds;
4679 SkPaint paint;
4680 paint.setTextSize(40);
4681 (void)paint.measureText(text, strlen(text), &bounds);
4682 const char url[] = "https://www.google.com/";
4683 sk_sp<SkData> urlData(SkData::MakeWithCString(url));
4684 canvas->drawAnnotation(bounds, "url_key", urlData.get());
4685##
4686
Cary Clark2ade9972017-11-02 17:49:34 -04004687#SeeAlso SkPicture SkDocument
Cary Clark8032b982017-07-28 11:04:54 -04004688
4689##
4690
4691# ------------------------------------------------------------------------------
4692
Herb Derbyefe39bc2018-05-01 17:06:20 -04004693#Method void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value)
Cary Clark09d80c02018-10-31 12:14:03 -04004694#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004695
4696#Example
4697#Height 1
4698 const char text[] = "Click this link!";
4699 SkRect bounds;
4700 SkPaint paint;
4701 paint.setTextSize(40);
4702 (void)paint.measureText(text, strlen(text), &bounds);
4703 const char url[] = "https://www.google.com/";
4704 sk_sp<SkData> urlData(SkData::MakeWithCString(url));
4705 canvas->drawAnnotation(bounds, "url_key", urlData.get());
4706##
4707
Cary Clark2ade9972017-11-02 17:49:34 -04004708#SeeAlso SkPicture SkDocument
Cary Clark8032b982017-07-28 11:04:54 -04004709
4710##
4711
Cary Clark8032b982017-07-28 11:04:54 -04004712# ------------------------------------------------------------------------------
4713
4714#Method virtual bool isClipEmpty() const
Cary Clark78de7512018-02-07 07:27:09 -05004715#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -05004716#Line # returns if Clip is empty ##
Cary Clark09d80c02018-10-31 12:14:03 -04004717#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004718
4719#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004720 void draw(SkCanvas* canvas) {
4721 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
4722 SkPath path;
4723 canvas->clipPath(path);
4724 SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
Cary Clark8032b982017-07-28 11:04:54 -04004725 }
4726 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04004727 clip is not empty
Cary Clark8032b982017-07-28 11:04:54 -04004728 clip is empty
4729 ##
4730##
4731
Cary Clark2ade9972017-11-02 17:49:34 -04004732#SeeAlso isClipRect getLocalClipBounds getDeviceClipBounds
Cary Clark8032b982017-07-28 11:04:54 -04004733
4734##
4735
4736# ------------------------------------------------------------------------------
4737
4738#Method virtual bool isClipRect() const
Cary Clark78de7512018-02-07 07:27:09 -05004739#In Property
Cary Clarkab2621d2018-01-30 10:08:57 -05004740#Line # returns if Clip is Rect and not empty ##
Cary Clark09d80c02018-10-31 12:14:03 -04004741#Populate
Cary Clark8032b982017-07-28 11:04:54 -04004742
4743#Example
Cary Clarkbad5ad72017-08-03 17:14:08 -04004744 void draw(SkCanvas* canvas) {
4745 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
4746 canvas->clipRect({0, 0, 0, 0});
4747 SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
Cary Clark8032b982017-07-28 11:04:54 -04004748 }
4749 #StdOut
Cary Clarkbad5ad72017-08-03 17:14:08 -04004750 clip is rect
Cary Clark8032b982017-07-28 11:04:54 -04004751 clip is not rect
4752 ##
4753##
4754
Cary Clark2ade9972017-11-02 17:49:34 -04004755#SeeAlso isClipEmpty getLocalClipBounds getDeviceClipBounds
Cary Clark8032b982017-07-28 11:04:54 -04004756
4757##
4758
4759#Class SkCanvas ##
Cary Clark884dd7d2017-10-11 10:37:52 -04004760
Cary Clark8032b982017-07-28 11:04:54 -04004761#Topic Canvas ##