halcanary 2015-05-19 10:21:29 -07:00 committed by Commit bot
parent 4b91f768b3
commit ee2a8eede9
11 changed files with 782 additions and 14 deletions

View File

@ -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

View File

@ -1,4 +1,4 @@
{
"dirOrder": ["sample", "quick", "special"],
"fileOrder": ["download", "api"]
"dirOrder": ["sample", "quick", "api", "special"],
"fileOrder": ["download"]
}

View File

@ -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)

3
site/user/api/METADATA Normal file
View File

@ -0,0 +1,3 @@
{
"fileOrder": ["skcanvas", "skpaint", "skrect", "skregion", "skmatrix", "grcontext", "canvas"]
}

250
site/user/api/canvas.md Normal file
View File

@ -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");
}

94
site/user/api/index.md Normal file
View File

@ -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)

132
site/user/api/skcanvas.md Normal file
View File

@ -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)

12
site/user/api/skmatrix.md Normal file
View File

@ -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.

102
site/user/api/skpaint.md Normal file
View File

@ -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(...);

73
site/user/api/skrect.md Normal file
View File

@ -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.

111
site/user/api/skregion.md Normal file
View File

@ -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);
}