Documentation: SkCanvas API
authorhalcanary <halcanary@google.com>
Tue, 19 May 2015 17:21:29 +0000 (10:21 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 19 May 2015 17:21:29 +0000 (10:21 -0700)
NOTRY=true
DOCS_PREVIEW= https://skia.org/?cl=1127383010
DOCS_PREVIEW= https://skia.org/user/api?cl=1127383010
DOCS_PREVIEW= https://skia.org/user/api/skcanvas?cl=1127383010
DOCS_PREVIEW= https://skia.org/user/api/skpaint?cl=1127383010
DOCS_PREVIEW= https://skia.org/user/api/skrect?cl=1127383010
DOCS_PREVIEW= https://skia.org/user/api/skregion?cl=1127383010
DOCS_PREVIEW= https://skia.org/user/api/skmatrix?cl=1127383010
DOCS_PREVIEW= https://skia.org/user/api/canvas?cl=1127383010

Review URL: https://codereview.chromium.org/1127383010

Doxyfile
site/user/METADATA
site/user/api.md [deleted file]
site/user/api/METADATA [new file with mode: 0644]
site/user/api/canvas.md [new file with mode: 0644]
site/user/api/index.md [new file with mode: 0644]
site/user/api/skcanvas.md [new file with mode: 0644]
site/user/api/skmatrix.md [new file with mode: 0644]
site/user/api/skpaint.md [new file with mode: 0644]
site/user/api/skrect.md [new file with mode: 0644]
site/user/api/skregion.md [new file with mode: 0644]

index 28dd00e..d5a8682 100644 (file)
--- a/Doxyfile
+++ b/Doxyfile
@@ -4,9 +4,11 @@
 # http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/index.html
 
 
-PROJECT_NAME = skia
+PROJECT_NAME = Skia
 PROJECT_BRIEF = 2D Graphics Library
 
+PROJECT_LOGO = https://skia.org/res/img/logo.png
+
 # These lines are overridden by
 # https://chromium.googlesource.com/chromium/tools/build/+/0f611b202b0e/scripts/slave/recipe_modules/skia/resources/generate_and_upload_doxygen.py
 # but they are needed in case someone wants to generate the doxygen manually
index 5d835d9..1735b80 100644 (file)
@@ -1,4 +1,4 @@
 {
-  "dirOrder": ["sample", "quick", "special"],
-  "fileOrder": ["download", "api"]
+  "dirOrder": ["sample", "quick", "api", "special"],
+  "fileOrder": ["download"]
 }
diff --git a/site/user/api.md b/site/user/api.md
deleted file mode 100644 (file)
index 0b507b9..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-API Overview & Doxygen Docs
-===========================
-
-See navigable API Overview here:
-
-   [http://code.google.com/p/skia/wiki/APIOverview](http://code.google.com/p/skia/wiki/APIOverview)
-
-Autogenerated Doxygen docs are here:
-
-   [http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/index.html](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/index.html)
-
diff --git a/site/user/api/METADATA b/site/user/api/METADATA
new file mode 100644 (file)
index 0000000..27625c5
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  "fileOrder": ["skcanvas", "skpaint", "skrect", "skregion", "skmatrix", "grcontext", "canvas"]
+}
diff --git a/site/user/api/canvas.md b/site/user/api/canvas.md
new file mode 100644 (file)
index 0000000..eacd1cc
--- /dev/null
@@ -0,0 +1,250 @@
+Creating SkCanvas Objects
+=========================
+
+First, read about [the SkCanvas API](skcanvas).
+
+Skia has multiple backends which receive SkCanvas drawing commands,
+including:
+
+-   [Raster](#raster) - CPU-only.
+-   [Ganesh](#ganesh) - Skia's GPU-accelerated backend.
+-   [SkPDF](#skpdf) - PDF document creation.
+-   [SkPicture](#skpicture) - Skia's display list format.
+-   [NullCanvas](#nullcanvas)  - Useful for testing only.
+-   [SkXPS](#skxps) - Experimental XPS backend.
+-   [SkSVG](#sksvg) - Experimental XPS backend.
+
+Each backend has a unique way of creating a SkCanvas.  This page gives
+an example for each:
+
+<span id="raster"></span>
+Raster
+------
+
+The raster backend draws to a block of memory. This memory can be
+managed by Skia or by the client.
+
+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.
+
+<!--?prettify lang=cc?-->
+
+    #include "SkData.h"
+    #include "SkImage.h"
+    #include "SkStream.h"
+    #include "SkSurface.h"
+    void raster(int width, int height,
+                void(*draw)(SkCanvas*),
+                const char* path) {
+        SkAutoTUnref<SkSurface> rasterSurface(
+                SkSurface::NewRasterN32Premul(width, height));
+        SkCanvas* rasterCanvas = rasterSurface->getCanvas();
+        draw(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());
+    }
+
+Alternatively, we could have specified the memory for the surface
+explicitly, instead of asking Skia to manage it.
+
+<!--?prettify lang=cc?-->
+
+    std::vector<char> raster_direct(int width, int height,
+                                    void(*draw)(SkCanvas*)) {
+        SkImageInfo info = SkImageInfo::MakeN32(width, height);
+        size_t rowBytes = info.minRowBytes();
+        size_t size = info.getSafeSize(rowBytes);
+        std::vector<char> pixelMemory(size);  // allocate memory
+        SkAutoTUnref<SkSurface> surface(
+                SkSurface::NewRasterDirect(
+                        info, &pixelMemory[0], rowBytes));
+        SkCanvas* canvas = surface.getCanvas();
+        draw(canvas);
+        return std::move(pixelMemory);
+    }
+
+<span id="ganesh"></span>
+Ganesh
+------
+
+Ganesh Surfaces must have a `GrContext` object which manages the
+GPU context, and related caches for textures and fonts.  In this
+example, we use a `GrContextFactory` to create a context.
+
+<!--?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(*draw)(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();
+        draw(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());
+    }
+
+<span id="skpdf"></span>
+SkPDF
+-----
+
+The SkPDF backend uses `SkDocument` instead of `SkSurface`, since
+a document must include multiple pages.
+
+<!--?prettify lang=cc?-->
+
+    #include "SkDocument.h"
+    #include "SkStream.h"
+    void skpdf(int width, int height,
+               void(*draw)(SkCanvas*),
+               const char* path) {
+        SkFILEWStream pdfStream(path);
+        SkAutoTUnref<SkDocument> pdfDoc(SkDocument::CreatePDF(&pdfStream));
+        SkCanvas* pdfCanvas = pdfDoc->beginPage(SkIntToScalar(width),
+                                                SkIntToScalar(height));
+        draw(pdfCanvas);
+        pdfDoc->close();
+    }
+
+<span id="skpicture"></span>
+SkPicture
+---------
+
+The SkPicture backend uses SkPictureRecorder instead of SkSurface.
+
+<!--?prettify lang=cc?-->
+
+    #include "SkPictureRecorder"
+    #include "SkPicture"
+    #include "SkStream.h"
+    void picture(int width, int height,
+                 void(*draw)(SkCanvas*),
+                 const char* path) {
+        SkPictureRecorder recorder;
+        SkCanvas* recordingCanvas = recorder.beginRecording(SkIntToScalar(width),
+                                                            SkIntToScalar(height));
+        draw(recordingCanvas);
+        SkAutoTUnref<SkPicture> picture(recorder.endRecordingAsPicture());
+        SkFILEWStream skpStream(path);
+        // Open SKP files with `SampleApp --picture SKP_FILE`
+        picture->serialize(&skpStream);
+    }
+
+<span id="nullcanvas"></span>
+NullCanvas
+----------
+
+The null canvas is a canvas that ignores all drawing commands and does
+nothing.
+
+<!--?prettify lang=cc?-->
+
+    #include "SkNullCanvas.h"
+    void picture(int, int, void(*draw)(SkCanvas*), const char*) {
+        SkAutoTDelete<SkCanvas> nullCanvas(SkCreateNullCanvas());
+        draw(nullCanvas);  // NoOp
+    }
+
+<span id="skxps"></span>
+SkXPS
+-----
+
+The (*still experimental*) SkXPS canvas writes into an XPS document.
+
+<!--?prettify lang=cc?-->
+
+    #include "SkDocument.h"
+    #include "SkStream.h"
+    void skxps(int width, int height,
+               void(*draw)(SkCanvas*),
+               const char* path) {
+        SkFILEWStream xpsStream(path);
+        SkAutoTUnref<SkDocument> xpsDoc(SkDocument::CreateXPS(&pdfStream));
+        SkCanvas* xpsCanvas = xpsDoc->beginPage(SkIntToScalar(width),
+                                                SkIntToScalar(height));
+        draw(xpsCanvas);
+        xpsDoc->close();
+    }
+
+<span id="sksvg"></span>
+SkSVG
+-----
+
+The (*still experimental*) SkSVG canvas writes into an SVG document.
+
+<!--?prettify lang=cc?-->
+
+    #include "SkStream.h"
+    #include "SkSVGCanvas.h"
+    #include "SkXMLWriter.h"
+    void sksvg(int width, int height,
+               void(*draw)(SkCanvas*),
+               const char* path) {
+        SkFILEWStream svgStream(path);
+        SkAutoTDelete<SkXMLWriter> xmlWriter(SkNEW_ARGS(SkXMLStreamWriter, (&svgStream)));
+        SkAutoTUnref<SkCanvas> svgCanvas(SkSVGCanvas::Create(
+                SkRect::MakeWH(SkIntToScalar(src.size().width()),
+                               SkIntToScalar(src.size().height())),
+                xmlWriter));
+        draw(svgCanvas);
+    }
+
+<span id="example"></span>
+Example
+-------
+
+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 "SkCanvas.h"
+    #include "SkPath.h"
+    #include "Test.h"
+    void example(SkCanvas* canvas) {
+        const SkScalar scale = 256.0f;
+        const SkScalar R = 0.45f * scale;
+        const SkScalar TAU = 6.2831853f;
+        SkPath path;
+        for (int i = 0; i < 5; ++i) {
+            SkScalar theta = 2 * i * TAU / 5;
+            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->clear(SK_ColorWHITE);
+        canvas->translate(0.5f * scale, 0.5f * scale);
+        canvas->drawPath(path, p);
+    }
+    DEF_TEST(FourBackends, r) {
+        raster( 256, 256, example, "out_raster.png" );
+        ganesh( 256, 256, example, "out_ganesh.png" );
+        skpdf(  256, 256, example, "out_skpdf.pdf"  );
+        picture(256, 256, example, "out_picture.skp");
+    }
diff --git a/site/user/api/index.md b/site/user/api/index.md
new file mode 100644 (file)
index 0000000..8c578b3
--- /dev/null
@@ -0,0 +1,94 @@
+API Overview & Doxygen Docs
+===========================
+
+Skia is organized around the `SkCanvas` object. It is the host for the
+"draw" calls: `drawRect`, `drawPath`, `drawText`, etc. Each of these
+has two components: the primitive being drawn (`SkRect`, `SkPath`, etc.)
+and color/style attributes (`SkPaint`).
+
+<!--?prettify lang=cc?-->
+
+    canvas->drawRect(rect, paint);
+
+The paint holds much of the state describing how the rectangle (in
+this case) is drawn: what color it is, if it is filled or stroked, how
+it should blend with what was previously drawn.
+
+The canvas holds relatively little state. It points to the actual
+pixels being drawn, and it maintains a stack of matrices and
+clips. Thus in the above call, the canvas' current matrix may
+transform the coordinates of the rectangle (translation, rotation,
+skewing, perspective), and the canvas' current clip may restrict where
+on the canvas the rectangle will be drawn, but all other stylistic
+attributes of the drawing are controlled by the paint.
+
+Using the SkCanvas API:
+
+1.  **[SkCanvas](/user/api/skcanvas)** - the drawing context.
+2.  **[SkPaint](/user/api/skpaint)** - color, stroke, font, effects
+3.  **[SkRect](/user/api/skrect)** - rectangles
+4.  **[SkRegion](/user/api/skregion)** - set operations with rectangles and paths
+
+Appendix:
+
+1.  **[Creating SkCanvas Objects](/user/api/canvas)**
+
+Autogenerated Doxygen Documentaion
+----------------------------------
+
+*   [Skia Doxygen](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/index.html)
+
+Here's a partial list of the more important Skia classes:
+
+*   [SkCanvas](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkCanvas.html)
+*   [SkImage](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkImage.html)
+*   [SkSurface](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkSurface.html)
+*   [SkPaint](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkPaint.html)
+*   [SkXfermode](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkXfermode.html)
+    -   [SkLerpXfermode](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkLerpXfermode.html)
+    -   [SkPixelXorXfermode](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkPixelXorXfermode.html)
+*   [SkShader](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkShader.html)
+    -   [SkComposeShader](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkComposeShader.html)
+    -   [SkPerlinNoiseShader](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkPerlinNoiseShader.html)
+    -   [SkGradientShader](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkGradientShader.html)
+    -   [SkTransparentShader](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkTransparentShader.html)
+*   [SkColorFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkColorFilter.html)
+    -   [SkColorCubeFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkColorCubeFilter.html)
+    -   [SkColorMatrixFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkColorMatrixFilter.html)
+    -   [SkLumaColorFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkLumaColorFilter.html)
+    -   [SkModeColorFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkModeColorFilter.html)
+*   [SkPathEffect](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkPathEffect.html)
+    -   [SkPath2DPathEffect](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkPath2DPathEffect.html)
+    -   [SkLine2DPathEffect](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkLine2DPathEffect.html)
+    -   [SkPath1DPathEffect](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkPath1DPathEffect.html)
+    -   [SkArcToPathEffect](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkArcToPathEffect.html)
+    -   [SkCornerPathEffect](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkCornerPathEffect.html)
+    -   [SkDashPathEffect](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkDashPathEffect.html)
+    -   [SkDiscretePathEffect](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkDiscretePathEffect.html)
+    -   [SkComposePathEffect](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkComposePathEffect.html)
+    -   [SkSumPathEffect](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkSumPathEffect.html)
+*   [SkImageFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkImageFilter.html)
+    -   [SkAlphaThresholdFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkAlphaThresholdFilter.html)
+    -   [SkBlurImageFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkBlurImageFilter.html)
+    -   [SkBitmapSource](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkBitmapSource.html)
+    -   [SkColorFilterImageFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkColorFilterImageFilter.html)
+    -   [SkComposeImageFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkComposeImageFilter.html)
+    -   [SkDisplacementMapEffect](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkDisplacementMapEffect.html)
+    -   [SkDownSampleImageFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkDownSampleImageFilter.html)
+    -   [SkDropShadowImageFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkDropShadowImageFilter.html)
+    -   [SkLightingImageFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkLightingImageFilter.html)
+    -   [SkMagnifierImageFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkMagnifierImageFilter.html)
+    -   [SkMatrixConvolutionImageFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkMatrixConvolutionImageFilter.html)
+    -   [SkMergeImageFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkMergeImageFilter.html)
+    -   [SkDilateImageFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkDilateImageFilter.html)
+    -   [SkErodeImageFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkErodeImageFilter.html)
+    -   [SkOffsetImageFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkOffsetImageFilter.html)
+    -   [SkPictureImageFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkPictureImageFilter.html)
+    -   [SkRectShaderImageFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkRectShaderImageFilter.html)
+    -   [SkTileImageFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkTileImageFilter.html)
+    -   [SkXfermodeImageFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkXfermodeImageFilter.html)
+*   [SkMaskFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkMaskFilter.html)
+    -   [SkEmbossMaskFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkEmbossMaskFilter.html)
+    -   [SkTableMaskFilter](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkTableMaskFilter.html)
+*   [SkDrawLooper](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkDrawLooper.html)
+    -   [SkBlurDrawLooper](http://chromium-skia-gm.commondatastorage.googleapis.com/doxygen/doxygen/html/classSkBlurDrawLooper.html)
diff --git a/site/user/api/skcanvas.md b/site/user/api/skcanvas.md
new file mode 100644 (file)
index 0000000..157409d
--- /dev/null
@@ -0,0 +1,132 @@
+SkCanvas
+========
+
+*The drawing context*
+
+<!-- Updated Mar 4, 2011 -->
+
+Preview
+-------
+
+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?-->
+
+    void draw(SkCanvas* canvas) {
+        const SkScalar scale = 256.0f;
+        const SkScalar R = 0.45f * scale;
+        const SkScalar TAU = 6.2831853f;
+        SkPath path;
+        for (int i = 0; i < 7; ++i) {
+            SkScalar 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->clear(SK_ColorWHITE);
+        canvas->translate(0.5f * scale, 0.5f * scale);
+        canvas->drawPath(path, p);
+    }
+
+Details
+-------
+
+SkCanvas is the drawing context for Skia. It knows where to direct the
+drawing (i.e. where the screen of offscreen pixels are), and maintains
+a stack of matrices and clips. Note however, that unlike similar
+contexts in other APIs like postscript, cairo, or awt, Skia does not
+store any other drawing attributes in the context (e.g. color, pen
+size). Rather, these are specified explicitly in each draw call, via a
+SkPaint.
+
+<!--?prettify lang=cc?-->
+
+    void draw(SkCanvas* canvas) {
+        canvas->save();
+        canvas->rotate(SkIntToScalar(45));
+        SkRect rect = SkRect::MakeXYWH(150, -50, 100, 100);
+        SkPaint paint;
+        canvas->drawRect(rect, paint);
+        canvas->restore();
+    }
+
+The code above will draw a rectangle rotated by 45 degrees. Exactly
+what color and style the rect will be drawn in is described by the
+paint, not the canvas.
+
+Check out more detailed info on [creating a SkCanvas object](canvas).
+
+To begin with, we might want to erase the entire canvas. We can do
+this by drawing an enormous rectangle, but there are easier ways to do
+it.
+
+<!--?prettify lang=cc?-->
+
+    void draw(SkCanvas* canvas) {
+        SkPaint paint;
+        paint.setColor(SK_ColorWHITE);
+        canvas->drawPaint(paint);
+    }
+
+This fills the entire canvas (though respecting the current clip of
+course) with whatever color or shader (and xfermode) is specified by
+the paint. If there is a shader in the paint, then it will respect the
+current matrix on the canvas as well (see SkShader). If you just want
+to draw a color (with an optional xfermode), you can just call
+drawColor(), and save yourself having to allocate a paint.
+
+<!--?prettify lang=cc?-->
+
+    void draw(SkCanvas* canvas) {
+        canvas->drawColor(SK_ColorWHITE);
+    }
+
+All of the other draw APIs are similar, each one ending with a paint
+parameter.
+
+<!--?prettify lang=cc?-->
+
+    void draw(SkCanvas* canvas) {
+        SkPaint paint;
+        paint.setStyle(SkPaint::kStroke_Style);
+        paint.setStrokeWidth(2);
+
+        SkRect rect = SkRect::MakeXYWH(50, 50, 40, 60);
+        canvas->drawRect(rect, paint);
+
+        SkRRect oval;
+        oval.setOval(rect);
+        oval.offset(40, 60);
+        canvas->drawRRect(oval, paint);
+
+        canvas->drawCircle(180, 50, 25, paint);
+
+        rect.offset(80, 0);
+        canvas->drawRoundRect(rect, 10, 10, paint);
+
+        SkPath path;
+        path.cubicTo(768, 0, -512, 256, 256, 256);
+        canvas->drawPath(path, paint);
+
+        canvas->drawBitmap(source, 128, 128, &paint);
+
+        SkRect rect2 = SkRect::MakeXYWH(0, 0, 40, 60);
+        canvas->drawBitmapRect(source, rect2);
+
+        SkPaint paint2;
+        const char text[] = "Hello, Skia!";
+        canvas->drawText(text, strlen(text), 50, 25, paint2);
+    }
+
+In some of the calls, we pass a pointer, rather than a reference, to
+the paint. In those instances, the paint parameter may be null. In all
+other cases the paint parameter is required.
+
+Next: [SkPaint](/user/api/skpaint)
diff --git a/site/user/api/skmatrix.md b/site/user/api/skmatrix.md
new file mode 100644 (file)
index 0000000..3048cdc
--- /dev/null
@@ -0,0 +1,12 @@
+SkMatrix
+========
+
+*3x3 transforms*
+
+<!-- Updated Mar 4, 2011 -->
+
+Skia is a 2D graphics engine, but it supports a full 3x3
+transformation matrix. This allow it to draw anything (bitmaps, text,
+rectangles, paths) in perspective. SkCamera is a helper class that
+models a camera in 3D, and can be used to generate the proper matrix
+for a given 3D view of the plane.
diff --git a/site/user/api/skpaint.md b/site/user/api/skpaint.md
new file mode 100644 (file)
index 0000000..fdee783
--- /dev/null
@@ -0,0 +1,102 @@
+SkPaint
+=======
+
+*color, stroke, font, effects*
+
+<!-- Updated Jan 17, 2013 by humper@google.com -->
+
+Anytime you draw something in Skia, and want to specify what color it
+is, or how it blends with the background, or what style or font to
+draw it in, you specify those attributes in a paint.
+
+Unlike `SkCanvas`, paints do not maintain an internal stack of state
+(i.e. there is no save/restore on a paint). However, paints are
+relatively light-weight, so the client may create and maintain any
+number of paint objects, each setup for a particular use. Factoring
+all of these color and stylistic attribute out of the canvas state,
+and into (multiple) paint objects, allows canvas' save/restore to be
+that much more efficient, as all they have to do is maintain the stack
+of matrix and clip settings.
+
+<!--?prettify lang=cc?-->
+
+    SkPaint paint1, paint2, paint3;
+
+    paint1.setColor(0xFFFF0000:
+    paint1.setStyle(SkPaint::kFill_Style);
+
+    paint2.setColor(0x8000FF00);
+    paint2.setStyle(SkPaint::kStroke_Style);
+    paint2.setStrokeWidth(SkIntToScalar(3));
+
+    paint3.setColor(0xFF888888);
+    paint3.setTextSize(SkIntToScalar(24));
+    paint3.setTextScaleX(SkFloatToScalar(0.75f));
+
+
+This shows three different paints, each setup to draw in a different
+style. Now the caller can intermix these paints freely, either using
+them as is, or modifying them as the drawing proceeds.
+
+<!--?prettify lang=cc?-->
+
+    canvas->drawRect(..., paint1);
+    canvas->drawRect(..., paint2);
+
+    paint2.setStrokeWidth(SkIntToScalar(5));
+    canvas->drawOval(..., paint2);
+
+    canvas->drawText(..., paint3);
+    paint3.setColor(0xFF0000FF);
+    canvas->drawText(..., paint3);
+
+
+Beyond simple attributes such as color, strokes, and text values,
+paints support effects. These are subclasses of different aspects of
+the drawing pipeline, that when referenced by a paint (each of them is
+reference-counted), are called to override some part of the drawing
+pipeline.
+
+For example, to draw using a gradient instead of a single color,
+assign a SkShader to the paint.
+
+<!--?prettify lang=cc?-->
+
+    SkShader* shader = SkGradientShader::CreateLinear(...);
+    paint.setShader(shader);
+    shader->unref();
+
+Now, anything drawn with that paint will be drawn with the gradient
+specified in the call to CreateLinear(). The shader object that is
+returned is reference-counted. Whenever any effects object, like a
+shader, is assigned to a paint, its reference-count is increased by
+the paint. To balance this, the caller in the above example calls
+unref() on the shader once it has assigned it to the paint. Now the
+paint is the only "owner" of that shader, and it will automatically
+call unref() on the shader when either the paint goes out of scope, or
+if another shader (or null) is assigned to it.
+
+There are 6 types of effects that can be assigned to a paint:
+
+*   **SkPathEffect** - modifications to the geometry (path) before it
+    generates an alpha mask (e.g. dashing)
+*   **SkRasterizer** - composing custom mask layers (e.g. shadows)
+*   **SkMaskFilter** - modifications to the alpha mask before it is
+    colorized and drawn (e.g. blur, emboss)
+*   **SkShader** - e.g. gradients (linear, radial, sweep), bitmap patterns
+    (clamp, repeat, mirror)
+*   **SkColorFilter** - modify the source color(s) before applying the
+    xfermode (e.g. color matrix)
+*   **SkXfermode** - e.g. porter-duff transfermodes, blend modes
+
+Paints also hold a reference to a SkTypeface. The typeface represents
+a specific font style, to be used for measuring and drawing
+text. Speaking of which, paints are used not only for drawing text,
+but also for measuring it.
+
+<!--?prettify lang=cc?-->
+
+    paint.measureText(...);
+    paint.getTextBounds(...);
+    paint.textToGlyphs(...);
+    paint.getFontMetrics(...);
diff --git a/site/user/api/skrect.md b/site/user/api/skrect.md
new file mode 100644 (file)
index 0000000..c2ebef1
--- /dev/null
@@ -0,0 +1,73 @@
+SkRect
+======
+
+*Rectangles*
+
+<!--Updated Mar 4, 2011-->
+
+SkRect is basic to many drawing and measuring operations. It can be
+drawn using canvas.drawRect(), but it is also used to return the
+bounds of objects like paths and text characters. It is specified
+using SkScalar values.
+
+SkIRect is the integer counter part to SkRect, but is specified using
+32bit integers.
+
+<!--?prettify lang=cc?-->
+
+    struct SkRect {
+       SkScalar fLeft;
+       SkScalar fTop;
+       SkScalar fRight;
+       SkScalar fBottom;
+       // methods
+    };
+
+    SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
+
+SkRect has the usual getters, to return width(), height(), centerX(),
+etc. It also has methods to compute unions and intersections between
+rectangles.
+
+Converting between SkRect and SkIRect is asymetric. Short of overflow
+issues when SkScalar is an int, converting from SkIRect to SkRect is
+straight forward:
+
+<!--?prettify lang=cc?-->
+
+    SkRect::set(const SkIRect&);
+
+However, convert from SkRect to SkIRect needs to know how to go from
+fractional values to integers.
+
+<!--?prettify lang=cc?-->
+
+    SkRect::round(SkIRect*) const;     // Round each coordinate.
+    SkRect::roundOut(SkIRect*) const;  // Apply floor to left/top,
+                                       // and ceil to right/bottom.
+
+In Skia, rectangle coordinates describe the boundary of what is drawn,
+such that an empty rectangle encloses zero pixels:
+
+bool SkRect::isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
+
+<!--?prettify lang=cc?-->
+
+    SkScalar SkRect::width() const { return fRight - fLeft; }
+
+    SkScalar SkRect::height() const { return fBottom - fTop; }
+
+    bool SkRect::contains(SkScalar x, SkScalar y) const {
+        return fLeft <= x && x < fRight && fTop <= y && y < fBottom;
+    }
+
+Thus, to draw a single pixel (assuming no matrix on the canvas), the
+rectangle should be initialized as follows:
+
+<!--?prettify lang=cc?-->
+
+    SkRect r = SkRect::MakeXYWH(x, y, SkIntToScalar(1), SkIntToScalar(1));
+
+The same conventions hold for the integer counterpart: SkIRect. This
+also dovetails with SkRegion, which has the same model for set
+membership, and which uses SkIRect.
diff --git a/site/user/api/skregion.md b/site/user/api/skregion.md
new file mode 100644 (file)
index 0000000..f4f46c9
--- /dev/null
@@ -0,0 +1,111 @@
+SkRegion
+========
+
+*Regions - set operations with rectangles*
+
+<!-- Updated Mar 4, 2011 -->
+
+Regions are a highly compressed way to represent (integer) areas. Skia
+uses them to represent (internally) the current clip on the
+canvas. Regions take their inspiration from the data type with the
+same name on the original Macintosh (thank you Bill).
+
+Regions are opaque structures, but they can be queried via
+iterators. Best of all, they can be combined with other regions and
+with rectangles (which can be thought of as "simple" regions. If you
+remember Set operations from math class (intersection, union,
+difference, etc.), then you're all ready to use regions.
+
+<!--?prettify lang=cc?-->
+
+    bool SkRegion::isEmpty();
+    bool SkRegion::isRect();
+    bool SkRegion::isComplex();
+
+Regions can be classified into one of three types: empty, rectangular,
+or complex.
+
+Empty regions are just that, empty. All empty regions are equal (using
+operator==). Compare this to rectangles (SkRect or SkIRect). Any
+rectangle with fLeft >= fRight or fTop >= fBottom is consider empty,
+but clearly there are different empty rectangles that are not equal.
+
+<!--?prettify lang=cc?-->
+
+    SkRect a = { 0, 0, 0, 0 };
+    SkRect b = { 1, 1, 1, 1 };
+
+Both a and b are empty, but they are definitely not equal to each
+other. However, with regions, all empty regions are equal. If you
+query its bounds, you will always get { 0, 0, 0, 0 }. Even if you
+translate it, it will still be all zeros.
+
+<!--?prettify lang=cc?-->
+
+<!--?prettify lang=cc?-->
+
+    SkRegion a, b;   // regions default to empty
+    assert(a == b);
+    a.offset(10, 20);
+    assert(a == b);
+    assert(a.getBounds() == { 0, 0, 0, 0 });   // not legal C++, but you get the point
+    assert(b.getBounds() == { 0, 0, 0, 0 });
+
+To initialize a region to something more interesting, use one of the
+set() methods
+
+<!--?prettify lang=cc?-->
+
+    SkRegion a, b;
+    a.setRect(10, 10, 50, 50);
+    b.setRect(rect);    // see SkIRect
+    c.setPath(path);   // see SkPath
+
+This is the first step that SkCanvas performs when one of its
+clip...() methods are called. The clip data is first transformed into
+device coordinates (see SkMatrix), and then a region is build from the
+data (either a rect or a path). The final step is to combine this new
+region with the existing clip using the specified operator.
+
+<!--?prettify lang=cc?-->
+
+    enum Op {
+        kUnion_Op,
+        kIntersect_Op,
+        kDifference_Op,
+        kXor_Op,
+        kReverseDifference_Op,
+        kReplace_Op
+    };
+
+By default, intersect op is used when a clip call is made, but the
+other operators are equally valid.
+
+<!--?prettify lang=cc?-->
+
+    // returns true if the resulting clip is non-empty (i.e. drawing can
+    // still occur)
+    bool SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op) {
+        SkRegion rgn;
+    
+        // peek at the CTM (current transformation matrix on the canvas)
+        const SkMatrix& m = this->getTotalMatrix();
+    
+        if (m.rectStaysRect()) {    // check if a transformed rect can be
+                                    // represented as another rect
+
+            SkRect deviceRect;
+            m.mapRect(&deviceRect, rect);
+            SkIRect intRect;
+            deviceRect.round(&intRect);
+            rgn.setRect(intRect);
+        } else {  // matrix rotates or skew (or is perspective)
+            SkPath path;
+            path.addRect(rect);
+            path.transform(m);
+            rgn.setPath(path);
+        }
+    
+        // now combine the new region with the current one, using the specified *op*
+        return fCurrentClip.op(rgn, op);
+    }