Chromium Code Reviews| Index: site/user/api/canvas.md |
| diff --git a/site/user/api/canvas.md b/site/user/api/canvas.md |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..8e89539f987ea8239bd7c64b5d04b18f14171fb2 |
| --- /dev/null |
| +++ b/site/user/api/canvas.md |
| @@ -0,0 +1,154 @@ |
| +Creating SkCanvas Objects |
| +========================= |
| + |
| +All drawing commands in Skia take place via the `SkCanvas` API. |
| +Here is an example of a set of drawing commands to draw a filled |
| +heptagram. This function can be cut and pasted into |
| +[fiddle.skia.org](https://fiddle.skia.org/). |
| + |
| +<!--?prettify lang=cc?--> |
| + |
| + #include "SkCanvas" |
| + #include "SkPath" |
| + void draw(SkCanvas* canvas) { |
| + float scale = 256.0f; |
|
reed1
2015/05/13 15:44:16
Lets use SkScalar in the dox
hal.canary
2015/05/13 17:58:24
Done.
|
| + canvas->translate(0.5f * scale, 0.5f * scale); |
| + canvas->clear(SK_ColorWHITE); |
|
reed1
2015/05/13 15:44:16
logically, we should probably issue the clear firs
hal.canary
2015/05/13 17:58:24
Done.
|
| + SkPath path; |
| + float R = 0.45f * scale; |
| + float TAU = 6.2831853f; |
| + for (int i = 0; i < 7; ++i) { |
| + float theta = 3 * i * TAU / 7; |
| + if (i == 0) { |
| + path.moveTo(R * cos(theta), R * sin(theta)); |
| + } else { |
| + path.lineTo(R * cos(theta), R * sin(theta)); |
| + } |
| + } |
| + path.close(); |
| + SkPaint p; |
| + p.setAntiAlias(true); |
| + canvas->drawPath(path, p); |
| + } |
| + |
| +Skia has multiple backends which receive SkCanvas drawing commands, |
| +including Raster (CPU-only), Ganesh (Skia's GPU-accelerated |
| +backend), SkPDF (PDF document creation), and Picture (Skia's |
| +display list format). |
| + |
| +Each backend has a unique way of createing a SkCanvas. The |
| +recommended way of creating a canvas for the Raster and Ganesh |
| +backends is to use a SkSurface, which is an object that manages the |
| +memory into which the canvas commands are drawn. The SkPDF and |
| +SkPicture backends uses SkDocument and SkPictureRecorder for the |
| +same purpose. |
| + |
| +1. Raster: |
| + |
| + <!--?prettify lang=cc?--> |
| + |
| + #include "SkData.h" |
| + #include "SkImage.h" |
| + #include "SkStream.h" |
| + #include "SkSurface.h" |
| + void raster(int width, int height, |
| + void(*drawable)(SkCanvas*), |
|
scroggo
2015/05/13 14:51:15
nit: Since this is a function pointer, I'm not sur
hal.canary
2015/05/13 17:58:24
Done.
|
| + const char* path) { |
| + SkAutoTUnref<SkSurface> rasterSurface( |
| + SkSurface::NewRasterN32Premul(width, height)); |
| + SkCanvas* rasterCanvas = rasterSurface->getCanvas(); |
| + |
| + drawable(rasterCanvas); |
| + |
| + SkAutoTUnref<SkImage> img(s->newImageSnapshot()); |
| + if (!img) { return; } |
| + SkAutoTUnref<SkData> png(img->encode()); |
| + if (!png) { return; } |
| + SkFILEWStream out(path); |
| + (void)out.write(png->data(), png->size()); |
| + } |
| + |
| +2. Ganesh: |
| + |
| + <!--?prettify lang=cc?--> |
| + |
| + #include "GrContextFactory.h" |
| + #include "SkData.h" |
| + #include "SkImage.h" |
| + #include "SkStream.h" |
| + #include "SkSurface.h" |
| + void ganesh(int width, int height, |
| + void(*drawable)(SkCanvas*), |
| + const char* path) { |
| + GrContextFactory grFactory; |
| + GrContext* context = grFactory.get(GrContextFactory::kNative_GLContextType); |
| + SkImageInfo info = SkImageInfo:: MakeN32Premul(width, height); |
| + SkAutoTUnref<SkSurface> gpuSurface( |
| + SkSurface::NewRenderTarget(context, SkSurface::kNo_Budgeted, info)); |
| + if (!gpuSurface) { |
| + SkDebugf("SkSurface::NewRenderTarget returned null\n"); |
| + return; |
| + } |
| + SkCanvas* gpuCanvas = gpuSurface->getCanvas(); |
| + |
| + drawable(gpuCanvas); |
| + |
| + SkAutoTUnref<SkImage> img(s->newImageSnapshot()); |
| + if (!img) { return; } |
| + SkAutoTUnref<SkData> png(img->encode()); |
| + if (!png) { return; } |
| + SkFILEWStream out(path); |
| + (void)out.write(png->data(), png->size()); |
| + |
| + } |
| + |
| +3. SkPDF: |
| + |
| + <!--?prettify lang=cc?--> |
| + |
| + #include "SkDocument.h" |
| + #include "SkStream.h" |
| + void skpdf(int width, int height, |
| + void(*drawable)(SkCanvas*), |
| + const char* path) { |
| + SkFILEWStream pdfStream(path); |
| + SkAutoTUnref<SkDocument> pdfDoc(SkDocument::CreatePDF(&pdfStream)); |
| + SkCanvas* pdfCanvas = pdfDoc->beginPage(SkIntToScalar(width), |
| + SkIntToScalar(height)); |
| + drawable(pdfCanvas); |
| + pdfDoc->close(); |
| + } |
| + |
| +3. SkPicture: |
| + |
| + <!--?prettify lang=cc?--> |
| + |
| + #include "SkPictureRecorder" |
| + #include "SkPicture" |
| + #include "SkStream.h" |
| + void picture(int width, int height, |
| + void(*drawable)(SkCanvas*), |
| + const char* path) { |
| + SkPictureRecorder recorder; |
| + SkCanvas* recordingCanvas = recorder.beginRecording(SkIntToScalar(width), |
| + SkIntToScalar(height)); |
| + drawable(recordingCanvas); |
| + SkAutoTUnref<SkPicture> picture(recorder.endRecordingAsPicture()); |
| + SkFILEWStream skpStream(path); |
| + // Open SKP files with `SampleApp --picture SKP_FILE` |
| + picture->serialize(&skpStream); |
| + } |
| + |
| + |
| +To try this code out, make a [new unit test using instructions |
| +here](/dev/testing/tests) and wrap these funtions together: |
| + |
| +<!--?prettify lang=cc?--> |
| + |
| + #include "Test.h" |
| + DEF_TEST(FourBackends, r) { |
|
scroggo
2015/05/13 14:51:15
A danger in telling the user to copy and paste cod
hal.canary
2015/05/13 17:58:24
Acknowledged.
|
| + raster( 256, 256, draw, "out_raster.png" ); |
| + ganesh( 256, 256, draw, "out_ganesh.png" ); |
| + skpdf( 256, 256, draw, "out_skpdf.pdf" ); |
| + picture(256, 256, draw, "out_picture.skp"); |
| + } |