aboutsummaryrefslogtreecommitdiffhomepage
path: root/site/user/api/skcanvas.md
blob: 157409da3863f438516d39ad59b76ade36313a32 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
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)