├── .github
└── workflows
│ ├── linux.yml
│ └── macos.yml
├── .gitignore
├── .travis.yml
├── META6.json
├── README.md
├── doc
├── examples
│ ├── README.md
│ ├── arc-negative.raku
│ ├── arc.raku
│ ├── blend.raku
│ ├── camelia.png
│ ├── clip-image.raku
│ ├── clip.raku
│ ├── curve-rectangle.raku
│ ├── curve_to.raku
│ ├── dash.raku
│ ├── fill-and-stroke.raku
│ ├── fill-style.raku
│ ├── fonts
│ │ └── DejaVuSans.ttf
│ ├── freetype.raku
│ ├── gradient.raku
│ ├── image-pattern.raku
│ ├── image.raku
│ ├── multi-page-pdf.raku
│ ├── multi-segment-caps.raku
│ ├── rounded-rectangle.raku
│ ├── set-line-cap.raku
│ ├── set-line-join.raku
│ ├── svg-surface.raku
│ ├── text-align-center.raku
│ ├── text-extents.raku
│ └── text.raku
└── screenshot
│ ├── arc-negative.png
│ ├── arc.png
│ ├── clip-image.png
│ ├── clip.png
│ ├── curve-rectangle.png
│ ├── curve_to.png
│ ├── dash.png
│ ├── fill-and-stroke.png
│ ├── fill-style.png
│ ├── gradient.png
│ ├── image-pattern.png
│ ├── image.png
│ ├── multi-page-pdf.pdf
│ ├── multi-segment-caps.png
│ ├── rounded-rectangle.png
│ ├── set-line-cap.png
│ ├── set-line-join.png
│ ├── svg-surface.svg
│ ├── text-align-center.png
│ ├── text-extents.png
│ └── text.png
├── lib
└── Cairo.pm6
├── sparrow.yaml
└── t
├── matrix.t
├── pattern.t
├── readme.t
├── surface-image.t
├── surface-pdf.t
├── surface-svg.t
└── text.t
/.github/workflows/linux.yml:
--------------------------------------------------------------------------------
1 | name: test linux
2 |
3 | on:
4 | push:
5 | branches:
6 | - '*'
7 | tags-ignore:
8 | - '*'
9 | pull_request:
10 |
11 | jobs:
12 | raku:
13 | strategy:
14 | matrix:
15 | os:
16 | - ubuntu-latest
17 | raku-version:
18 | - 'latest'
19 | - '2021.12'
20 | runs-on: ${{ matrix.os }}
21 | steps:
22 | - uses: actions/checkout@v2
23 | - uses: Raku/setup-raku@v1
24 | with:
25 | raku-version: ${{ matrix.raku-version }}
26 | - name: Install Dependencies
27 | run: |
28 | # install and test if need be (includes [test-depends])
29 | zef install --deps-only .
30 | zef install --/test App::Prove6
31 | - name: Run Tests
32 | run: prove6 -I. t
33 | - name: Install Module
34 | run: zef install --verbose .
35 |
--------------------------------------------------------------------------------
/.github/workflows/macos.yml:
--------------------------------------------------------------------------------
1 | name: test macos
2 |
3 | on:
4 | push:
5 | branches:
6 | - '*'
7 | tags-ignore:
8 | - '*'
9 | pull_request:
10 |
11 | jobs:
12 | raku:
13 | strategy:
14 | matrix:
15 | os:
16 | - macOS-latest
17 | raku-version:
18 | - 'latest'
19 | - '2021.12'
20 | runs-on: ${{ matrix.os }}
21 | steps:
22 | - uses: actions/checkout@v2
23 | - uses: Raku/setup-raku@v1
24 | with:
25 | raku-version: ${{ matrix.raku-version }}
26 | - name: Install Dependencies
27 | run: |
28 | # install and test if need be (includes [test-depends])
29 | brew update
30 | brew install cairo
31 | zef install --deps-only .
32 | zef install --/test App::Prove6
33 | - name: Run Tests
34 | run: prove6 -I. t
35 | - name: Install Module
36 | run: zef install --verbose .
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | .*
3 | *#*
4 | #.png
5 | #*.svg
6 | #*.pdf
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: perl6
2 | perl6:
3 | - latest
4 | - '2018.12'
5 | addons:
6 | apt:
7 | packages:
8 | - libcairo2
9 | install:
10 | - rakudobrew build-zef
11 | - zef install --depsonly .
12 | script:
13 | - zef test .
14 | sudo: false
15 |
--------------------------------------------------------------------------------
/META6.json:
--------------------------------------------------------------------------------
1 | {
2 | "perl" : "v6",
3 | "name" : "Cairo",
4 | "description" : "Cairo 2D graphics library",
5 | "version" : "0.3.7",
6 | "depends" : [ "MacOS::NativeLib" ],
7 | "source-url" : "https://github.com/timo/cairo-p6.git",
8 | "tags" : [ "png", "pdf", "svg", "cairo" ],
9 | "provides" : {
10 | "Cairo" : "lib/Cairo.pm6"
11 | },
12 | "support" : {
13 | "source" : "https://github.com/timo/cairo-p6.git"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Cairo 2D Graphics library binding for Raku
2 | ==========================================
3 |
4 | Synopsis
5 | --------
6 |
7 | ```raku
8 | use Cairo;
9 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 128, 128) {
10 | given Cairo::Context.new($_) {
11 | .rgb(0, 0.7, 0.9);
12 | .rectangle(10, 10, 50, 50);
13 | .fill :preserve; .rgb(1, 1, 1);
14 | .stroke
15 | };
16 | .write_png("foobar.png")
17 | }
18 | ```
19 |
20 |
21 | Native Cairo library
22 | --------------
23 |
24 | In order to use this module, native `Cairo` library is needed. See instructions at https://cairographics.org/download/.
25 |
26 | ### Examples
27 |
28 | doc/screenshot/arc-negative.png
29 | 
30 |
31 | doc/screenshot/arc.png
32 | 
33 |
34 | doc/screenshot/clip-image.png
35 | 
36 |
37 | doc/screenshot/clip.png
38 | 
39 |
40 | doc/screenshot/curve-rectangle.png
41 | 
42 |
43 |
44 |
45 | doc/screenshot/curve_to.png
46 | 
47 |
48 | doc/screenshot/dash.png
49 | 
50 |
51 | doc/screenshot/fill-and-stroke.png
52 | 
53 |
54 | doc/screenshot/fill-style.png
55 | 
56 |
57 | doc/screenshot/gradient.png
58 | 
59 |
60 | doc/screenshot/image-pattern.png
61 | 
62 |
63 | doc/screenshot/image.png
64 | 
65 |
66 | doc/screenshot/multi-page-pdf.pdf
67 | 
68 |
69 | doc/screenshot/multi-segment-caps.png
70 | 
71 |
72 | doc/screenshot/rounded-rectangle.png
73 | 
74 |
75 | doc/screenshot/set-line-cap.png
76 | 
77 |
78 | doc/screenshot/set-line-join.png
79 | 
80 |
81 | doc/screenshot/svg-surface.svg
82 | 
83 |
84 | doc/screenshot/text-align-center.png
85 | 
86 |
87 | doc/screenshot/text-extents.png
88 | 
89 |
90 | doc/screenshot/text.png
91 | 
92 |
--------------------------------------------------------------------------------
/doc/examples/README.md:
--------------------------------------------------------------------------------
1 | - `multi-page-pdf.p6` demonstrates the creation of a two page PDF.
2 | - `svg-surface.p6` demonstrates creation of a SVG graphic.
3 | - all other examples produce PNG images.
4 |
5 | Please see https://cairographics.org/samples for expected output and equivalent C programs.
6 |
--------------------------------------------------------------------------------
/doc/examples/arc-negative.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | constant xc = 128.0;
5 | constant yc = 128.0;
6 | constant radius = 100.0;
7 | constant angle1 = 45.0 * (pi/180.0); # angles are specified
8 | constant angle2 = 180.0 * (pi/180.0); # in radians
9 |
10 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
11 | given Cairo::Context.new($_) {
12 | .line_width = 10.0;
13 | .arc(xc, yc, radius, angle1, angle2, :negative);
14 | .stroke;
15 |
16 | # draw helping lines
17 | .rgba(1, 0.2, 0.2, 0.6);
18 | .line_width = 6.0;
19 |
20 | .arc(xc, yc, 10.0, 0, 2*pi);
21 | .fill;
22 |
23 | .arc(xc, yc, radius, angle1, angle1);
24 | .line_to(xc, yc);
25 | .arc(xc, yc, radius, angle2, angle2);
26 | .line_to(xc, yc);
27 | .stroke;
28 | };
29 | .write_png("arc-negative.png");
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/doc/examples/arc.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | constant xc = 128.0;
5 | constant yc = 128.0;
6 | constant radius = 100.0;
7 | constant angle1 = 45.0 * (pi/180.0); # angles are specified
8 | constant angle2 = 180.0 * (pi/180.0); # in radians
9 |
10 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
11 | given Cairo::Context.new($_) {
12 | .line_width = 10.0;
13 | .arc(xc, yc, radius, angle1, angle2);
14 | .stroke;
15 |
16 | # draw helping lines
17 | .rgba(1, 0.2, 0.2, 0.6);
18 | .line_width = 6.0;
19 |
20 | .arc(xc, yc, 10.0, 0, 2*pi);
21 | .fill;
22 |
23 | .arc(xc, yc, radius, angle1, angle1);
24 | .line_to(xc, yc);
25 | .arc(xc, yc, radius, angle2, angle2);
26 | .line_to(xc, yc);
27 | .stroke;
28 | };
29 | .write_png("arc.png");
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/doc/examples/blend.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | # adapted from https://zetcode.com/gfx/cairo/compositing/
5 |
6 | sub do-drawing(Cairo::Context $ctx, Int $x, Int $w, Int $h, Int $op) {
7 |
8 | my Cairo::Image $blended-image .= create(Cairo::FORMAT_ARGB32, $w, $h);
9 | given Cairo::Context.new($blended-image) {
10 | .rgb(.5, .5, 0);
11 | .rectangle($x+10, 40, 50, 50);
12 | .fill;
13 | }
14 | my Cairo::Image $image .= create(Cairo::FORMAT_ARGB32, $w, $h);
15 | given Cairo::Context.new($image) {
16 | .rgb(0, 0, 0.4);
17 | .rectangle($x, 20, 50, 50);
18 | .fill;
19 | .operator = $op;
20 | .set_source_surface($blended-image, 0, 0);
21 | .paint;
22 | }
23 | $ctx.set_source_surface($image, 0, 0);
24 | $ctx.paint;
25 |
26 | }
27 |
28 | constant Width = 510;
29 | constant Height = 120;
30 |
31 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, Width, Height) {
32 | given Cairo::Context.new($_) {
33 | my @ops = (CAIRO_OPERATOR_DEST_OVER,
34 | CAIRO_OPERATOR_DEST_IN,
35 | CAIRO_OPERATOR_OUT,
36 | CAIRO_OPERATOR_ADD,
37 | CAIRO_OPERATOR_ATOP,
38 | CAIRO_OPERATOR_DEST_ATOP,
39 | );
40 |
41 | my $x = 20;
42 | for @ops -> $op {
43 | do-drawing($_, $x, Width, Height, $op );
44 | $x += 80;
45 | }
46 | }
47 | .write_png("blend.png");
48 | }
49 |
--------------------------------------------------------------------------------
/doc/examples/camelia.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/examples/camelia.png
--------------------------------------------------------------------------------
/doc/examples/clip-image.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
5 | given Cairo::Context.new($_) {
6 | .arc(128.0, 128.0, 76.8, 0, 2*pi);
7 | .clip;
8 | .new_path; # path not consumed by .clip
9 |
10 | my \image = Cairo::Image.open("examples/camelia.png" );
11 | my \w = image.width;
12 | my \h = image.height;
13 |
14 | .scale(256.0/w, 256.0/h);
15 |
16 | .set_source_surface(image, 0, 0);
17 | .paint;
18 |
19 | image.destroy;
20 | };
21 | .write_png("clip-image.png");
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/doc/examples/clip.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | constant xc = 128.0;
5 | constant yc = 128.0;
6 | constant radius = 100.0;
7 | constant angle1 = 45.0 * (pi/180.0); # angles are specified
8 | constant angle2 = 180.0 * (pi/180.0); # in radians
9 |
10 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
11 | given Cairo::Context.new($_) {
12 | .arc(128.0, 128.0, 76.8, 0, 2 * pi);
13 | .clip();
14 |
15 | .new_path(); # current path is not
16 | # consumed by .clip
17 | .rectangle(0, 0, 256, 256);
18 | .fill();
19 | .rgb(0, 1, 0);
20 | .move_to(0, 0);
21 | .line_to(256, 256);
22 | .move_to(256, 0);
23 | .line_to(0, 256);
24 | .line_width = 10.0;
25 | .stroke();
26 | };
27 | .write_png("clip.png");
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/doc/examples/curve-rectangle.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
5 | given Cairo::Context.new($_) {
6 | # a custom shape that could be wrapped in a function
7 | constant x0 = 25.6; # parameters like cairo_rectangle
8 | constant y0 = 25.6;
9 | constant rect_width = 204.8;
10 | constant rect_height = 204.8;
11 | constant radius = 102.4 * 2; # and an approximate curvature radius
12 |
13 | constant x1 = x0 + rect_width;
14 | constant y1 = y0 + rect_height;
15 |
16 | if (!rect_width || !rect_height) {
17 | return;
18 | }
19 | if (rect_width/2 < radius) {
20 | if (rect_height/2 < radius) {
21 | .move_to(x0, (y0 + y1)/2);
22 | .curve_to(x0 ,y0, x0, y0, (x0 + x1)/2, y0);
23 | .curve_to(x1, y0, x1, y0, x1, (y0 + y1)/2);
24 | .curve_to(x1, y1, x1, y1, (x1 + x0)/2, y1);
25 | .curve_to(x0, y1, x0, y1, x0, (y0 + y1)/2);
26 | } else {
27 | .move_to(x0, y0 + radius);
28 | .curve_to(x0 ,y0, x0, y0, (x0 + x1)/2, y0);
29 | .curve_to(x1, y0, x1, y0, x1, y0 + radius);
30 | .line_to(x1 , y1 - radius);
31 | .curve_to(x1, y1, x1, y1, (x1 + x0)/2, y1);
32 | .curve_to(x0, y1, x0, y1, x0, y1- radius);
33 | }
34 | } else {
35 | if (rect_height/2 < radius) {
36 | .move_to(x0, (y0 + y1)/2);
37 | .curve_to(x0 , y0, x0 , y0, x0 + radius, y0);
38 | .line_to(x1 - radius, y0);
39 | .curve_to(x1, y0, x1, y0, x1, (y0 + y1)/2);
40 | .curve_to(x1, y1, x1, y1, x1 - radius, y1);
41 | .line_to(x0 + radius, y1);
42 | .curve_to(x0, y1, x0, y1, x0, (y0 + y1)/2);
43 | } else {
44 | .move_to(x0, y0 + radius);
45 | .curve_to(x0 , y0, x0 , y0, x0 + radius, y0);
46 | .line_to(x1 - radius, y0);
47 | .curve_to(x1, y0, x1, y0, x1, y0 + radius);
48 | .line_to(x1 , y1 - radius);
49 | .curve_to(x1, y1, x1, y1, x1 - radius, y1);
50 | .line_to(x0 + radius, y1);
51 | .curve_to(x0, y1, x0, y1, x0, y1- radius);
52 | }
53 | }
54 |
55 | .rgb(0.5, 0.5, 1);
56 | .fill(:preserve);
57 | .rgba(0.5, 0, 0, 0.5);
58 | .line_width = 10.0;
59 | .stroke;
60 | };
61 | .write_png("curve-rectangle.png");
62 | }
63 |
64 |
--------------------------------------------------------------------------------
/doc/examples/curve_to.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
5 | given Cairo::Context.new($_) {
6 |
7 | constant x=25.6;
8 | constant y=128.0;
9 | constant x1=102.4;
10 | constant y1=230.4;
11 | constant x2=153.6;
12 | constant y2=25.6;
13 | constant x3=230.4;
14 | constant y3=128.0;
15 |
16 | .move_to(x, y);
17 | .curve_to(x1, y1, x2, y2, x3, y3);
18 |
19 | .line_width = 10.0;
20 | .stroke;
21 |
22 | .rgba(1, 0.2, 0.2, 0.6);
23 | .line_width = 6.0;
24 | .move_to(x,y); .line_to(x1,y1);
25 | .move_to(x2,y2); .line_to(x3,y3);
26 | .stroke;
27 |
28 | };
29 | .write_png("curve_to.png");
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/doc/examples/dash.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
5 | given Cairo::Context.new($_) {
6 |
7 | my \dashes = (50.0, # ink
8 | 10.0, # skip
9 | 10.0, # ink
10 | 10.0 # skip
11 | );
12 | my \ndash = +dashes;
13 | my \offset = -50.0;
14 |
15 | .set_dash(dashes, ndash, offset);
16 | .line_width = 10.0;
17 |
18 | .move_to(128.0, 25.6);
19 | .line_to(230.4, 230.4);
20 | .line_to(-102.4, 0.0, :relative);
21 | .curve_to(51.2, 230.4, 51.2, 128.0, 128.0, 128.0);
22 |
23 | .stroke;
24 | };
25 | .write_png("dash.png");
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/doc/examples/fill-and-stroke.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
5 | given Cairo::Context.new($_) {
6 | .move_to(128.0, 25.6);
7 | .line_to(230.4, 230.4);
8 | .line_to(-102.4, 0.0, :relative);
9 | .curve_to(51.2, 230.4, 51.2, 128.0, 128.0, 128.0);
10 | .close_path;
11 |
12 | .move_to(64.0, 25.6);
13 | .line_to(51.2, 51.2, :relative);
14 | .line_to(-51.2, 51.2, :relative);
15 | .line_to(-51.2, -51.2, :relative);
16 | .close_path;
17 |
18 | .line_width = 10.0;
19 | .rgb(0, 0, 1);
20 | .fill(:preserve);
21 | .rgb(0, 0, 0);
22 | .stroke;
23 | };
24 | .write_png("fill-and-stroke.png");
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/doc/examples/fill-style.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
5 | given Cairo::Context.new($_) {
6 |
7 | .line_width = 6;
8 |
9 | .rectangle(12, 12, 232, 70);
10 | .sub_path; .arc(64, 64, 40, 0, 2*pi);
11 | .sub_path; .arc(192, 64, 40, 0, -2*pi, :negative);
12 |
13 | .fill_rule = Cairo::FILL_RULE_EVEN_ODD;
14 | .rgb(0, 0.7, 0); .fill(:preserve);
15 | .rgb(0, 0, 0); .stroke;
16 |
17 | .translate(0, 128);
18 | .rectangle(12, 12, 232, 70);
19 | .sub_path; .arc(64, 64, 40, 0, 2*pi);
20 | .sub_path; .arc(192, 64, 40, 0, -2*pi, :negative);
21 |
22 | .fill_rule = Cairo::FILL_RULE_WINDING;
23 | .rgb(0, 0, 0.9); .fill(:preserve);
24 | .rgb(0, 0, 0); .stroke;
25 | };
26 | .write_png("fill-style.png");
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/doc/examples/fonts/DejaVuSans.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/examples/fonts/DejaVuSans.ttf
--------------------------------------------------------------------------------
/doc/examples/freetype.raku:
--------------------------------------------------------------------------------
1 | # This example requires the Font::FreeType module
2 | use Cairo;
3 | use Font::FreeType:ver<0.3.0+>;
4 | use Font::FreeType::Face;
5 | use Font::FreeType::Raw;
6 |
7 | my Font::FreeType $freetype .= new;
8 |
9 | sub MAIN(
10 | :$font-file = '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf',
11 | :$png = 'freetype.png',
12 | ) {
13 | my Font::FreeType::Face $face = $freetype.face($font-file);
14 | # get the underlying FreeType Face native C-struct
15 | my FT_Face $ft-face = $face.raw;
16 | my Cairo::Font $font .= create(
17 | $ft-face, :free-type,
18 | );
19 |
20 | freetype-demo($font, $png);
21 |
22 | $font.destroy;
23 | }
24 |
25 | sub freetype-demo(Cairo::Font:D $font, Str:D $png-file) {
26 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
27 |
28 | given Cairo::Context.new($_) {
29 |
30 | .set_font_size(90.0);
31 | .set_font_face($font);
32 | .move_to(10.0, 135.0);
33 | .show_text("Hello");
34 |
35 | .move_to(70.0, 165.0);
36 | .text_path("font");
37 | .rgb(0.5, 0.5, 1);
38 | .fill(:preserve);
39 | .rgb(0, 0, 0);
40 | .line_width = 2.56;
41 | .stroke;
42 |
43 | # draw helping lines
44 | .rgba(1, 0.2, 0.2, 0.6);
45 | .arc(10.0, 135.0, 5.12, 0, 2*pi);
46 | .close_path;
47 | .arc(70.0, 165.0, 5.12, 0, 2*pi);
48 | .fill;
49 | }
50 | .write_png($png-file);
51 |
52 | .destroy;
53 | }
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/doc/examples/gradient.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
5 | given Cairo::Context.new($_) {
6 |
7 | my Cairo::Pattern::Gradient::Linear $lpat .= create(0.0, 0.0, 0.0, 256.0);
8 | $lpat.add_color_stop_rgba(1, 0, 0, 0, 1);
9 | $lpat.add_color_stop_rgba(0, 1, 1, 1, 1);
10 | .rectangle(0, 0, 256, 256);
11 | .pattern($lpat);
12 | .fill;
13 | $lpat.destroy;
14 |
15 | my Cairo::Pattern::Gradient::Radial $rpat .= create(115.2, 102.4, 25.6,
16 | 102.4, 102.4, 128.0);
17 | $rpat.add_color_stop_rgba(0, 1, 1, 1, 1);
18 | $rpat.add_color_stop_rgba(1, 0, 0, 0, 1);
19 | .pattern($rpat);
20 | .arc(128.0, 128.0, 76.8, 0, 2 * pi);
21 | .fill;
22 | $rpat.destroy;
23 |
24 | };
25 | .write_png("gradient.png");
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/doc/examples/image-pattern.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
5 | given Cairo::Context.new($_) {
6 |
7 | my $image = Cairo::Image.open("examples/camelia.png" );
8 | my \w = $image.width;
9 | my \h = $image.height;
10 |
11 | my Cairo::Pattern::Surface $pattern .= create($image.surface);
12 | $pattern.extend = Cairo::EXTEND_REPEAT;
13 |
14 | .translate(128.0, 128.0);
15 | .rotate(pi / 4);
16 | .scale(1 / sqrt(2), 1 / sqrt(2));
17 | .translate(-128.0, -128.0);
18 |
19 | my Cairo::Matrix $matrix .= new.scale(w/256.0 * 5.0, h/256.0 * 5.0);
20 | $pattern.matrix = $matrix;
21 | .pattern($pattern);
22 |
23 | .rectangle(0, 0, 256.0, 256.0);
24 | .fill;
25 |
26 | $pattern.destroy;
27 | $image.destroy;
28 |
29 | };
30 | .write_png("image-pattern.png");
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/doc/examples/image.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
5 | given Cairo::Context.new($_) {
6 |
7 | my \image = Cairo::Image.open("camelia.png" );
8 | my \w = image.width;
9 | my \h = image.height;
10 |
11 | .translate(128.0, 128.0);
12 | .rotate(30 * pi/180);
13 | .scale(256/w, 256/h);
14 | .translate(-0.5*w, -0.5*h);
15 |
16 | .set_source_surface(image, 0, 0);
17 | .paint;
18 | image.destroy;
19 |
20 | };
21 | .write_png("image.png");
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/doc/examples/multi-page-pdf.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Surface::PDF.create("multi-page-pdf.pdf", 256, 256) -> $s {
5 | given Cairo::Context.new($s) {
6 | # Tag for accessibility
7 | .tag: "Document", {
8 | for 1..2 -> $page {
9 | .set_font_size(10);
10 | .tag: "Figure", {
11 | .save;
12 | .rgb(0, 0.7, 0.9);
13 | .rectangle(10, 10, 50, 50);
14 | .fill :preserve;
15 | .rgb(1, 1, 1);
16 | .stroke;
17 | .restore;
18 | };
19 | .tag: "P", {
20 | .select_font_face("courier", Cairo::FONT_SLANT_ITALIC, Cairo::FONT_WEIGHT_BOLD);
21 | .move_to(10, 10);
22 | .show_text("Page $page/2");
23 | }
24 | $s.show_page;
25 | }
26 | $s.finish;
27 | }
28 | }
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/doc/examples/multi-segment-caps.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
5 | given Cairo::Context.new($_) {
6 |
7 | .move_to(50.0, 75.0);
8 | .line_to(200.0, 75.0);
9 |
10 | .move_to(50.0, 125.0);
11 | .line_to(200.0, 125.0);
12 |
13 | .move_to(50.0, 175.0);
14 | .line_to(200.0, 175.0);
15 |
16 | .line_width = 30.0;
17 | .line_cap = Cairo::LINE_CAP_ROUND;
18 | .stroke;
19 |
20 | };
21 | .write_png("multi-segment-caps.png");
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/doc/examples/rounded-rectangle.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
5 | given Cairo::Context.new($_) {
6 |
7 | constant x = 25.6; # parameters like cairo_rectangle
8 | constant y = 25.6;
9 | constant width = 204.8;
10 | constant height = 204.8;
11 | constant aspect = 1.0; # aspect ratio
12 | constant corner_radius = height / 10.0; # and corner curvature radius
13 | constant radius = corner_radius / aspect;
14 | constant degrees = pi / 180.0;
15 |
16 | .sub_path;
17 | .arc(x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees);
18 | .arc(x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees);
19 | .arc(x + radius, y + height - radius, radius, 90 * degrees, 180 * degrees);
20 | .arc(x + radius, y + radius, radius, 180 * degrees, 270 * degrees);
21 | .close_path;
22 |
23 | .rgb(0.5, 0.5, 1);
24 | .fill(:preserve);
25 | .rgba(0.5, 0, 0, 0.5);
26 | .line_width = 10;
27 | .stroke;
28 |
29 | };
30 | .write_png("rounded-rectangle.png");
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/doc/examples/set-line-cap.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
5 | given Cairo::Context.new($_) {
6 |
7 | .line_width = 30.0;
8 | .line_cap = Cairo::LINE_CAP_BUTT; # default
9 | .move_to(64.0, 50.0); .line_to(64.0, 200.0);
10 | .stroke;
11 | .line_cap = Cairo::LINE_CAP_ROUND;
12 | .move_to(128.0, 50.0); .line_to(128.0, 200.0);
13 | .stroke;
14 | .line_cap = Cairo::LINE_CAP_SQUARE;
15 | .move_to(192.0, 50.0); .line_to(192.0, 200.0);
16 | .stroke;
17 |
18 | # draw helping lines */
19 | .rgb(1, 0.2, 0.2);
20 | .line_width = 2.56;
21 | .move_to(64.0, 50.0); .line_to(64.0, 200.0);
22 | .move_to(128.0, 50.0); .line_to(128.0, 200.0);
23 | .move_to(192.0, 50.0); .line_to(192.0, 200.0);
24 | .stroke;
25 |
26 | };
27 | .write_png("set-line-cap.png");
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/doc/examples/set-line-join.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
5 | given Cairo::Context.new($_) {
6 |
7 | .line_width = 40.96;
8 | .move_to(76.8, 84.48);
9 | .line_to(51.2, -51.2, :relative);
10 | .line_to(51.2, 51.2, :relative);
11 | .line_join = Cairo::LINE_JOIN_MITER; # default
12 | .stroke;
13 |
14 | .move_to(76.8, 161.28);
15 | .line_to(51.2, -51.2, :relative);
16 | .line_to(51.2, 51.2, :relative);
17 | .line_join = Cairo::LINE_JOIN_BEVEL;
18 | .stroke;
19 |
20 | .move_to(76.8, 238.08);
21 | .line_to(51.2, -51.2, :relative);
22 | .line_to(51.2, 51.2, :relative);
23 | .line_join = Cairo::LINE_JOIN_ROUND;
24 | .stroke;
25 |
26 | };
27 | .write_png("set-line-join.png");
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/doc/examples/svg-surface.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Surface::SVG.create("svg-surface.svg", 256, 256) {
5 | given Cairo::Context.new($_) {
6 |
7 | .select_font_face("courier", Cairo::FONT_SLANT_ITALIC, Cairo::FONT_WEIGHT_BOLD);
8 | .set_font_size(10);
9 | .save;
10 | do {
11 | .rgb(0, 0.7, 0.9);
12 | .rectangle(10, 10, 50, 50);
13 | .fill :preserve;
14 | .rgb(1, 1, 1);
15 | .stroke;
16 | };
17 | .restore;
18 | .move_to(10, 10);
19 | .show_text("SVG Example");
20 | }
21 | .finish;
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/doc/examples/text-align-center.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
5 | given Cairo::Context.new($_) {
6 |
7 | .select_font_face("Sans",
8 | Cairo::FONT_SLANT_NORMAL,
9 | Cairo::FONT_WEIGHT_BOLD);
10 | .set_font_size(52.0);
11 |
12 | my \text = "cairo";
13 | my Cairo::cairo_text_extents_t \extents = .text_extents(text);
14 | my \x = 128.0-(extents.width/2 + extents.x_bearing);
15 | my \y = 128.0-(extents.height/2 + extents.y_bearing);
16 |
17 | .move_to(x, y);
18 | .show_text(text);
19 |
20 | # draw helping lines
21 | .rgba(1, 0.2, 0.2, 0.6);
22 | .line_width = 6.0;
23 | .arc(x, y, 10.0, 0, 2*pi);
24 | .fill;
25 | .move_to(128.0, 0);
26 | .line_to(0, 256, :relative);
27 | .move_to(0, 128.0);
28 | .line_to(256, 0, :relative);
29 | .stroke;
30 | };
31 | .write_png("text-align-center.png");
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/doc/examples/text-extents.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
5 | given Cairo::Context.new($_) {
6 |
7 | .select_font_face("Sans",
8 | Cairo::FONT_SLANT_NORMAL,
9 | Cairo::FONT_WEIGHT_NORMAL);
10 | .set_font_size(100.0);
11 |
12 | my \text = "cairo";
13 | my Cairo::cairo_text_extents_t \extents = .text_extents(text);
14 | constant x=25.0;
15 | constant y=150.0;
16 |
17 | .move_to(x,y);
18 | .show_text(text);
19 |
20 | # draw helping lines
21 | .rgba(1, 0.2, 0.2, 0.6);
22 | .line_width = 6.0;
23 | .arc(x, y, 10.0, 0, 2*pi);
24 | .fill;
25 | .move_to(x,y);
26 | .line_to(0, -extents.height, :relative);
27 | .line_to(extents.width, 0, :relative);
28 | .line_to(extents.x_bearing, -extents.y_bearing, :relative);
29 | .stroke;
30 | };
31 | .write_png("text-extents.png");
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/doc/examples/text.raku:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 |
4 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 256, 256) {
5 | given Cairo::Context.new($_) {
6 |
7 | .select_font_face("Sans",
8 | Cairo::FONT_SLANT_NORMAL,
9 | Cairo::FONT_WEIGHT_BOLD);
10 | .set_font_size(90.0);
11 |
12 | .move_to(10.0, 135.0);
13 | .show_text("Hello");
14 |
15 | .move_to(70.0, 165.0);
16 | .text_path("void");
17 | .rgb(0.5, 0.5, 1);
18 | .fill(:preserve);
19 | .rgb(0, 0, 0);
20 | .line_width = 2.56;
21 | .stroke;
22 |
23 | # draw helping lines
24 | .rgba(1, 0.2, 0.2, 0.6);
25 | .arc(10.0, 135.0, 5.12, 0, 2*pi);
26 | .close_path;
27 | .arc(70.0, 165.0, 5.12, 0, 2*pi);
28 | .fill;
29 |
30 | };
31 | .write_png("text.png");
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/doc/screenshot/arc-negative.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/arc-negative.png
--------------------------------------------------------------------------------
/doc/screenshot/arc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/arc.png
--------------------------------------------------------------------------------
/doc/screenshot/clip-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/clip-image.png
--------------------------------------------------------------------------------
/doc/screenshot/clip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/clip.png
--------------------------------------------------------------------------------
/doc/screenshot/curve-rectangle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/curve-rectangle.png
--------------------------------------------------------------------------------
/doc/screenshot/curve_to.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/curve_to.png
--------------------------------------------------------------------------------
/doc/screenshot/dash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/dash.png
--------------------------------------------------------------------------------
/doc/screenshot/fill-and-stroke.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/fill-and-stroke.png
--------------------------------------------------------------------------------
/doc/screenshot/fill-style.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/fill-style.png
--------------------------------------------------------------------------------
/doc/screenshot/gradient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/gradient.png
--------------------------------------------------------------------------------
/doc/screenshot/image-pattern.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/image-pattern.png
--------------------------------------------------------------------------------
/doc/screenshot/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/image.png
--------------------------------------------------------------------------------
/doc/screenshot/multi-page-pdf.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/multi-page-pdf.pdf
--------------------------------------------------------------------------------
/doc/screenshot/multi-segment-caps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/multi-segment-caps.png
--------------------------------------------------------------------------------
/doc/screenshot/rounded-rectangle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/rounded-rectangle.png
--------------------------------------------------------------------------------
/doc/screenshot/set-line-cap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/set-line-cap.png
--------------------------------------------------------------------------------
/doc/screenshot/set-line-join.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/set-line-join.png
--------------------------------------------------------------------------------
/doc/screenshot/svg-surface.svg:
--------------------------------------------------------------------------------
1 |
2 |
61 |
--------------------------------------------------------------------------------
/doc/screenshot/text-align-center.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/text-align-center.png
--------------------------------------------------------------------------------
/doc/screenshot/text-extents.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/text-extents.png
--------------------------------------------------------------------------------
/doc/screenshot/text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/timo/cairo-p6/b946950165f75b0db4ade60dd9f81e16cc399ca6/doc/screenshot/text.png
--------------------------------------------------------------------------------
/lib/Cairo.pm6:
--------------------------------------------------------------------------------
1 | unit module Cairo:ver<0.3.7>;
2 |
3 | use MacOS::NativeLib 'cairo';
4 |
5 | our $cairolib;
6 | BEGIN {
7 | if $*VM.config ~~ /dll/ {
8 | $cairolib = 'libcairo-2';
9 | } else {
10 | $cairolib = ('cairo', v2);
11 | }
12 | }
13 |
14 | use NativeCall;
15 |
16 | our enum cairo_status_t is export <
17 | CAIRO_STATUS_SUCCESS
18 |
19 | CAIRO_STATUS_NO_MEMORY
20 | CAIRO_STATUS_INVALID_RESTORE
21 | CAIRO_STATUS_INVALID_POP_GROUP
22 | CAIRO_STATUS_NO_CURRENT_POINT
23 | CAIRO_STATUS_INVALID_MATRIX
24 | CAIRO_STATUS_INVALID_STATUS
25 | CAIRO_STATUS_NULL_POINTER
26 | CAIRO_STATUS_INVALID_STRING
27 | CAIRO_STATUS_INVALID_PATH_DATA
28 | CAIRO_STATUS_READ_ERROR
29 | CAIRO_STATUS_WRITE_ERROR
30 | CAIRO_STATUS_SURFACE_FINISHED
31 | CAIRO_STATUS_SURFACE_TYPE_MISMATCH
32 | CAIRO_STATUS_PATTERN_TYPE_MISMATCH
33 | CAIRO_STATUS_INVALID_CONTENT
34 | CAIRO_STATUS_INVALID_FORMAT
35 | CAIRO_STATUS_INVALID_VISUAL
36 | CAIRO_STATUS_FILE_NOT_FOUND
37 | CAIRO_STATUS_INVALID_DASH
38 | CAIRO_STATUS_INVALID_DSC_COMMENT
39 | CAIRO_STATUS_INVALID_INDEX
40 | CAIRO_STATUS_CLIP_NOT_REPRESENTABLE
41 | CAIRO_STATUS_TEMP_FILE_ERROR
42 | CAIRO_STATUS_INVALID_STRIDE
43 | CAIRO_STATUS_FONT_TYPE_MISMATCH
44 | CAIRO_STATUS_USER_FONT_IMMUTABLE
45 | CAIRO_STATUS_USER_FONT_ERROR
46 | CAIRO_STATUS_NEGATIVE_COUNT
47 | CAIRO_STATUS_INVALID_CLUSTERS
48 | CAIRO_STATUS_INVALID_SLANT
49 | CAIRO_STATUS_INVALID_WEIGHT
50 | CAIRO_STATUS_INVALID_SIZE
51 | CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED
52 | CAIRO_STATUS_DEVICE_TYPE_MISMATCH
53 | CAIRO_STATUS_DEVICE_ERROR
54 | CAIRO_STATUS_INVALID_MESH_CONSTRUCTION
55 | CAIRO_STATUS_DEVICE_FINISHED
56 |
57 | CAIRO_STATUS_LAST_STATUS
58 | >;
59 |
60 | our enum CairoStatus is export <
61 | STATUS_SUCCESS
62 |
63 | STATUS_NO_MEMORY
64 | STATUS_INVALID_RESTORE
65 | STATUS_INVALID_POP_GROUP
66 | STATUS_NO_CURRENT_POINT
67 | STATUS_INVALID_MATRIX
68 | STATUS_INVALID_STATUS
69 | STATUS_NULL_POINTER
70 | STATUS_INVALID_STRING
71 | STATUS_INVALID_PATH_DATA
72 | STATUS_READ_ERROR
73 | STATUS_WRITE_ERROR
74 | STATUS_SURFACE_FINISHED
75 | STATUS_SURFACE_TYPE_MISMATCH
76 | STATUS_PATTERN_TYPE_MISMATCH
77 | STATUS_INVALID_CONTENT
78 | STATUS_INVALID_FORMAT
79 | STATUS_INVALID_VISUAL
80 | STATUS_FILE_NOT_FOUND
81 | STATUS_INVALID_DASH
82 | STATUS_INVALID_DSC_COMMENT
83 | STATUS_INVALID_INDEX
84 | STATUS_CLIP_NOT_REPRESENTABLE
85 | STATUS_TEMP_FILE_ERROR
86 | STATUS_INVALID_STRIDE
87 | STATUS_FONT_TYPE_MISMATCH
88 | STATUS_USER_FONT_IMMUTABLE
89 | STATUS_USER_FONT_ERROR
90 | STATUS_NEGATIVE_COUNT
91 | STATUS_INVALID_CLUSTERS
92 | STATUS_INVALID_SLANT
93 | STATUS_INVALID_WEIGHT
94 | STATUS_INVALID_SIZE
95 | STATUS_USER_FONT_NOT_IMPLEMENTED
96 | STATUS_DEVICE_TYPE_MISMATCH
97 | STATUS_DEVICE_ERROR
98 | STATUS_INVALID_MESH_CONSTRUCTION
99 | STATUS_DEVICE_FINISHED
100 |
101 | STATUS_LAST_STATUS
102 | >;
103 |
104 | our enum cairo_path_data_type_t is export <
105 | CAIRO_PATH_MOVE_TO
106 | CAIRO_PATH_LINE_TO
107 | CAIRO_PATH_CURVE_TO
108 | CAIRO_PATH_CLOSE_PATH
109 | >;
110 |
111 | our enum PathDataTypes is export <
112 | PATH_MOVE_TO
113 | PATH_LINE_TO
114 | PATH_CURVE_TO
115 | PATH_CLOSE_PATH
116 | >;
117 |
118 | our enum cairo_tag_t is export (
119 | :CAIRO_TAG_DEST,
120 | :CAIRO_TAG_LINK,
121 | );
122 |
123 | our enum cairo_pdf_outline_flags_t is export (
124 | :CAIRO_PDF_OUTLINE_FLAG_OPEN(0x1),
125 | :CAIRO_PDF_OUTLINE_FLAG_BOLD(0x2),
126 | :CAIRO_PDF_OUTLINE_FLAG_ITALIC(0x4),
127 | );
128 |
129 | our enum cairo_pdf_metadata_t is export <
130 | CAIRO_PDF_METADATA_TITLE
131 | CAIRO_PDF_METADATA_AUTHOR
132 | CAIRO_PDF_METADATA_SUBJECT
133 | CAIRO_PDF_METADATA_KEYWORDS
134 | CAIRO_PDF_METADATA_CREATOR
135 | CAIRO_PDF_METADATA_CREATE_DATE
136 | CAIRO_PDF_METADATA_MOD_DATE
137 | >;
138 |
139 | sub cairo_version_string
140 | returns Str
141 | is native($cairolib)
142 | {*}
143 |
144 | our sub version {
145 | Version.new: cairo_version_string()
146 | }
147 |
148 | my class StreamClosure is repr('CStruct') is rw {
149 |
150 | sub memcpy(Pointer[uint8] $dest, Pointer[uint8] $src, size_t $n)
151 | is native
152 | {*}
153 |
154 | has CArray[uint8] $!buf;
155 | has size_t $.buf-len;
156 | has size_t $.n-read;
157 | has size_t $.size;
158 | submethod TWEAK(CArray :$buf!) { $!buf := $buf }
159 | method buf-pointer( --> Pointer[uint8]) {
160 | nativecast(Pointer[uint8], $!buf);
161 | }
162 | method read-pointer(--> Pointer) {
163 | Pointer[uint8].new: +$.buf-pointer + $!n-read;
164 | }
165 | method write-pointer(--> Pointer) {
166 | Pointer[uint8].new: +$.buf-pointer + $!buf-len;
167 | }
168 | our method read(Pointer $out, uint32 $len --> int32) {
169 | return STATUS_READ_ERROR
170 | if $len > self.buf-len - self.n-read;
171 |
172 | memcpy($out, self.read-pointer, $len);
173 | self.n-read += $len;
174 | return STATUS_SUCCESS;
175 | }
176 | our method write(Pointer $in, uint32 $len --> int32) {
177 | return STATUS_WRITE_ERROR
178 | if $len > self.size - self.buf-len;
179 | memcpy(self.write-pointer, $in, $len);
180 | self.buf-len += $len;
181 | return STATUS_SUCCESS;
182 | }
183 | }
184 |
185 | module Attrs {
186 | sub attr-value($_) {
187 | when List { '[' ~ .map(&attr-value).join(' ') ~ ']' }
188 | when Bool { $_ ?? 'true' !! 'false'}
189 | when Int { .Str }
190 | when Numeric {
191 | my Str $num = .fmt('%.5f');
192 | $num ~~ s/(\.\d*?)0+$/$0/;
193 | $num .= chop if $num.ends-with('.');
194 | $num
195 | }
196 | when Str {
197 | q{'} ~ .trans("\\" => "\\\\", "'" => "\\'") ~ q{'};
198 | }
199 | default {
200 | warn "unsupported attribute value: {.raku}";
201 | ''
202 | }
203 | }
204 |
205 | our sub serialize(%attrs) {
206 | join ' ', %attrs.sort.map: {
207 | .value.defined
208 | ?? .key ~ '=' ~ attr-value(.value)
209 | !! Empty
210 | }
211 | }
212 | }
213 |
214 | our class cairo_surface_t is repr('CPointer') {
215 |
216 | method status
217 | returns uint32
218 | is native($cairolib)
219 | is symbol('cairo_surface_status')
220 | {*}
221 |
222 | method write_to_png(Str $filename)
223 | returns int32
224 | is native($cairolib)
225 | is symbol('cairo_surface_write_to_png')
226 | {*}
227 |
228 | method write_to_png_stream(
229 | &write-func (StreamClosure, Pointer[uint8], uint32 --> int32),
230 | StreamClosure)
231 | returns int32
232 | is native($cairolib)
233 | is symbol('cairo_surface_write_to_png_stream')
234 | {*}
235 |
236 | method reference
237 | returns cairo_surface_t
238 | is native($cairolib)
239 | is symbol('cairo_surface_reference')
240 | {*}
241 |
242 | method show_page
243 | is native($cairolib)
244 | is symbol('cairo_surface_show_page')
245 | {*}
246 |
247 | method flush
248 | is native($cairolib)
249 | is symbol('cairo_surface_flush')
250 | {*}
251 |
252 | method finish
253 | is native($cairolib)
254 | is symbol('cairo_surface_finish')
255 | {*}
256 |
257 | method destroy
258 | is native($cairolib)
259 | is symbol('cairo_surface_destroy')
260 | {*}
261 |
262 | method get_image_data
263 | returns OpaquePointer
264 | is native($cairolib)
265 | is symbol('cairo_image_surface_get_data')
266 | {*}
267 | method get_image_stride
268 | returns int32
269 | is native($cairolib)
270 | is symbol('cairo_image_surface_get_stride')
271 | {*}
272 | method get_image_width
273 | returns int32
274 | is native($cairolib)
275 | is symbol('cairo_image_surface_get_width')
276 | {*}
277 | method get_image_height
278 | returns int32
279 | is native($cairolib)
280 | is symbol('cairo_image_surface_get_height')
281 | {*}
282 |
283 | }
284 |
285 | class cairo_pdf_surface_t is cairo_surface_t is repr('CPointer') {
286 |
287 | our sub create(str $filename, num64 $width, num64 $height)
288 | returns cairo_pdf_surface_t
289 | is native($cairolib)
290 | is symbol('cairo_pdf_surface_create')
291 | {*}
292 |
293 |
294 | method add_outline(int32 $parent-id, Str $name, Str $link-attrs, int32 $flags --> int32)
295 | is native($cairolib)
296 | is symbol('cairo_pdf_surface_add_outline')
297 | {*}
298 |
299 | method set_metadata(int32 $type, Str $value)
300 | is native($cairolib)
301 | is symbol('cairo_pdf_surface_set_metadata')
302 | {*}
303 |
304 | method new(Str:D :$filename!, Num:D() :$width!, Num:D() :$height! --> cairo_pdf_surface_t:D) {
305 | create($filename, $width, $height);
306 | }
307 | }
308 |
309 | class cairo_svg_surface_t is cairo_surface_t is repr('CPointer') {
310 | our sub create(str $filename, num64 $width, num64 $height)
311 | returns cairo_svg_surface_t
312 | is native($cairolib)
313 | is symbol('cairo_svg_surface_create')
314 | {*}
315 |
316 | method new(Str:D :$filename!, Num:D() :$width!, Num:D() :$height! --> cairo_svg_surface_t) {
317 | create($filename, $width, $height);
318 | }
319 | }
320 |
321 | our class cairo_rectangle_t is repr('CPointer') { }
322 |
323 | our class cairo_path_data_header_t is repr('CStruct') {
324 | has uint32 $.type;
325 | has int32 $.length;
326 | }
327 | our class cairo_path_data_point_t is repr('CStruct') {
328 | has num64 $.x is rw;
329 | has num64 $.y is rw;
330 | }
331 | our class cairo_path_data_t is repr('CUnion') is export {
332 | HAS cairo_path_data_header_t $.header;
333 | HAS cairo_path_data_point_t $.point;
334 |
335 | method data-type { PathDataTypes( self.header.type ) }
336 | method length { self.header.length }
337 | method x is rw { self.point.x }
338 | method y is rw { self.point.y }
339 | }
340 |
341 | our class cairo_path_t is repr('CStruct') is export {
342 | has uint32 $.status; # cairo_path_data_type_t
343 | has Pointer[cairo_path_data_t] $.data;
344 | has int32 $.num_data;
345 |
346 | sub path_destroy(cairo_path_t)
347 | is symbol('cairo_path_destroy')
348 | is native($cairolib)
349 | {*}
350 |
351 | method destroy {
352 | path_destroy(self);
353 | }
354 | }
355 |
356 | our class cairo_text_extents_t is repr('CStruct') {
357 | has num64 $.x_bearing is rw;
358 | has num64 $.y_bearing is rw;
359 | has num64 $.width is rw;
360 | has num64 $.height is rw;
361 | has num64 $.x_advance is rw;
362 | has num64 $.y_advance is rw;
363 | }
364 |
365 | our class cairo_font_extents_t is repr('CStruct') {
366 | has num64 $.ascent is rw;
367 | has num64 $.descent is rw;
368 | has num64 $.height is rw;
369 | has num64 $.max_x_advance is rw;
370 | has num64 $.max_y_advance is rw;
371 | }
372 |
373 | our class cairo_rectangle_int_t is repr('CStruct') {
374 | has int32 $.x is rw;
375 | has int32 $.y is rw;
376 | has int32 $.width is rw;
377 | has int32 $.height is rw;
378 | }
379 |
380 | our class cairo_font_face_t is repr('CPointer') {
381 |
382 | method reference
383 | is native($cairolib)
384 | is symbol('cairo_font_face_reference')
385 | {*}
386 | method destroy
387 | is native($cairolib)
388 | is symbol('cairo_font_face_destroy')
389 | {*}
390 | }
391 |
392 | our class cairo_scaled_font_t is repr('CPointer') {
393 |
394 | method reference
395 | is native($cairolib)
396 | is symbol('cairo_scaled_font_reference')
397 | {*}
398 | method destroy
399 | is native($cairolib)
400 | is symbol('cairo_scaled_font_destroy')
401 | {*}
402 | }
403 |
404 | our class cairo_glyph_t is repr('CStruct') {
405 | has ulong $.index is rw;
406 | has num64 $.x is rw ;
407 | has num64 $.y is rw;
408 |
409 | sub cairo_glyph_allocate(int32 $num_glyphs)
410 | returns cairo_glyph_t
411 | is native($cairolib)
412 | {*}
413 |
414 | method allocate(UInt $num_glyphs) {
415 | cairo_glyph_allocate($num_glyphs);
416 | }
417 |
418 | method free
419 | is native($cairolib)
420 | is symbol('cairo_glyph_free')
421 | {*}
422 | }
423 |
424 | our class cairo_matrix_t is repr('CStruct') {
425 | has num64 $.xx; has num64 $.yx;
426 | has num64 $.xy; has num64 $.yy;
427 | has num64 $.x0; has num64 $.y0;
428 |
429 | method init(num64 $xx, num64 $yx, num64 $xy, num64 $yy, num64 $x0, num64 $y0)
430 | is native($cairolib)
431 | is symbol('cairo_matrix_init')
432 | {*}
433 |
434 | method scale(num64 $sx, num64 $sy)
435 | is native($cairolib)
436 | is symbol('cairo_matrix_scale')
437 | {*}
438 |
439 | method translate(num64 $tx, num64 $ty)
440 | is native($cairolib)
441 | is symbol('cairo_matrix_translate')
442 | {*}
443 |
444 | method rotate(cairo_matrix_t $b)
445 | is native($cairolib)
446 | is symbol('cairo_matrix_rotate')
447 | {*}
448 |
449 | method invert
450 | is native($cairolib)
451 | is symbol('cairo_matrix_invert')
452 | {*}
453 |
454 | method multiply(cairo_matrix_t $a, cairo_matrix_t $b)
455 | is native($cairolib)
456 | is symbol('cairo_matrix_multiply')
457 | {*}
458 |
459 | }
460 |
461 | our class cairo_pattern_t is repr('CPointer') {
462 |
463 | method destroy
464 | is native($cairolib)
465 | is symbol('cairo_pattern_destroy')
466 | {*}
467 |
468 | method get_extend
469 | returns int32
470 | is native($cairolib)
471 | is symbol('cairo_pattern_get_extend')
472 | {*}
473 |
474 | method set_extend(uint32 $extend)
475 | is native($cairolib)
476 | is symbol('cairo_pattern_set_extend')
477 | {*}
478 |
479 | method set_matrix(cairo_matrix_t $matrix)
480 | is native($cairolib)
481 | is symbol('cairo_pattern_set_matrix')
482 | {*}
483 |
484 | method get_matrix(cairo_matrix_t $matrix)
485 | is native($cairolib)
486 | is symbol('cairo_pattern_get_matrix')
487 | {*}
488 |
489 | method get_color_stop_count(int32 $count is rw)
490 | returns int32
491 | is native($cairolib)
492 | is symbol('cairo_pattern_get_color_stop_count')
493 | {*}
494 |
495 | method get_color_stop_rgba(
496 | int32 $index,
497 | num64 $o is rw,
498 | num64 $r is rw,
499 | num64 $g is rw,
500 | num64 $b is rw
501 | )
502 | returns int32
503 | is native($cairolib)
504 | is symbol('cairo_pattern_get_color_stop_rgba')
505 | {*}
506 |
507 | method add_color_stop_rgb(num64 $offset, num64 $r, num64 $g, num64 $b)
508 | returns int32
509 | is native($cairolib)
510 | is symbol('cairo_pattern_add_color_stop_rgb')
511 | {*}
512 |
513 | method add_color_stop_rgba(num64 $offset, num64 $r, num64 $g, num64 $b, num64 $a)
514 | returns int32
515 | is native($cairolib)
516 | is symbol('cairo_pattern_add_color_stop_rgba')
517 | {*}
518 |
519 | }
520 |
521 | class cairo_font_options_t is repr('CPointer') {
522 |
523 | method copy
524 | returns cairo_font_options_t
525 | is native($cairolib)
526 | is symbol('cairo_font_options_create')
527 | {*}
528 |
529 | method destroy
530 | is native($cairolib)
531 | is symbol('cairo_font_options_destroy')
532 | {*}
533 |
534 | method status
535 | returns uint32
536 | is native($cairolib)
537 | is symbol('cairo_font_options_status')
538 | {*}
539 |
540 | method merge(cairo_font_options_t $other)
541 | is native($cairolib)
542 | is symbol('cairo_font_options_merge')
543 | {*}
544 |
545 | method hash
546 | returns uint64
547 | is native($cairolib)
548 | is symbol('cairo_font_options_hash')
549 | {*}
550 |
551 | method equal(cairo_font_options_t $opts)
552 | returns uint32
553 | is native($cairolib)
554 | is symbol('cairo_font_options_equal')
555 | {*}
556 |
557 | method set_antialias(uint32 $aa)
558 | is native($cairolib)
559 | is symbol('cairo_font_options_set_antialias')
560 | {*}
561 |
562 | method get_antialias
563 | returns uint32
564 | is native($cairolib)
565 | is symbol('cairo_font_options_get_antialias')
566 | {*}
567 |
568 | method set_subpixel_order(uint32 $order)
569 | is native($cairolib)
570 | is symbol('cairo_font_options_create_subpixel_order')
571 | {*}
572 |
573 | method get_subpixel_order
574 | returns uint32
575 | is native($cairolib)
576 | is symbol('cairo_font_options_create_get_subpixel_order')
577 | {*}
578 |
579 | method set_hint_style(uint32 $style)
580 | is native($cairolib)
581 | is symbol('cairo_font_options_set_hint_style')
582 | {*}
583 |
584 | method get_hint_style
585 | returns uint32
586 | is native($cairolib)
587 | is symbol('cairo_font_options_get_hint_style')
588 | {*}
589 |
590 | method set_hint_metrics(uint32 $metrics)
591 | is native($cairolib)
592 | is symbol('cairo_font_options_set_hint_metrics')
593 | {*}
594 |
595 | method get_hint_metrics
596 | returns uint32
597 | is native($cairolib)
598 | is symbol('cairo_font_options_get_hint_metrics')
599 | {*}
600 |
601 | }
602 |
603 | our class cairo_t is repr('CPointer') {
604 |
605 | method destroy
606 | is native($cairolib)
607 | is symbol('cairo_destroy')
608 | {*}
609 |
610 | method sub_path
611 | returns cairo_path_t
612 | is native($cairolib)
613 | is symbol('cairo_new_sub_path')
614 | {*}
615 |
616 | method copy_path
617 | returns cairo_path_t
618 | is native($cairolib)
619 | is symbol('cairo_copy_path')
620 | {*}
621 |
622 | method copy_path_flat
623 | returns cairo_path_t
624 | is native($cairolib)
625 | is symbol('cairo_copy_path_flat')
626 | {*}
627 |
628 | method append_path(cairo_path_t $path)
629 | returns cairo_path_t
630 | is native($cairolib)
631 | is symbol('cairo_append_path')
632 | {*}
633 |
634 |
635 | method push_group
636 | is native($cairolib)
637 | is symbol('cairo_push_group')
638 | {*}
639 |
640 | method pop_group
641 | returns cairo_pattern_t
642 | is native($cairolib)
643 | is symbol('cairo_pop_group')
644 | {*}
645 |
646 | method pop_group_to_source
647 | is native($cairolib)
648 | is symbol('cairo_pop_group_to_source')
649 | {*}
650 |
651 |
652 | method get_current_point(num64 $x is rw, num64 $y is rw)
653 | is native($cairolib)
654 | is symbol('cairo_get_current_point')
655 | {*}
656 | method line_to(num64 $x, num64 $y)
657 | is native($cairolib)
658 | is symbol('cairo_line_to')
659 | {*}
660 |
661 | method move_to(num64 $x, num64 $y)
662 | is native($cairolib)
663 | is symbol('cairo_move_to')
664 | {*}
665 |
666 | method curve_to(num64 $x1, num64 $y1, num64 $x2, num64 $y2, num64 $x3, num64 $y3)
667 | is native($cairolib)
668 | is symbol('cairo_curve_to')
669 | {*}
670 |
671 | method rel_line_to(num64 $x, num64 $y)
672 | is native($cairolib)
673 | is symbol('cairo_rel_line_to')
674 | {*}
675 |
676 | method rel_move_to(num64 $x, num64 $y)
677 | is native($cairolib)
678 | is symbol('cairo_rel_move_to')
679 | {*}
680 |
681 | method rel_curve_to(num64 $x1, num64 $y1, num64 $x2, num64 $y2, num64 $x3, num64 $y3)
682 | is native($cairolib)
683 | is symbol('cairo_rel_curve_to')
684 | {*}
685 |
686 | method arc(num64 $xc, num64 $yc, num64 $radius, num64 $angle1, num64 $angle2)
687 | is native($cairolib)
688 | is symbol('cairo_arc')
689 | {*}
690 | method arc_negative(num64 $xc, num64 $yc, num64 $radius, num64 $angle1, num64 $angle2)
691 | is native($cairolib)
692 | is symbol('cairo_arc_negative')
693 | {*}
694 |
695 | method close_path
696 | is native($cairolib)
697 | is symbol('cairo_close_path')
698 | {*}
699 |
700 | method new_path
701 | is native($cairolib)
702 | is symbol('cairo_new_path')
703 | {*}
704 |
705 | method rectangle(num64 $x, num64 $y, num64 $w, num64 $h)
706 | is native($cairolib)
707 | is symbol('cairo_rectangle')
708 | {*}
709 |
710 |
711 | method set_source_rgb(num64 $r, num64 $g, num64 $b)
712 | is native($cairolib)
713 | is symbol('cairo_set_source_rgb')
714 | {*}
715 |
716 | method set_source_rgba(num64 $r, num64 $g, num64 $b, num64 $a)
717 | is native($cairolib)
718 | is symbol('cairo_set_source_rgba')
719 | {*}
720 |
721 | method set_source(cairo_pattern_t $pat)
722 | is native($cairolib)
723 | is symbol('cairo_set_source')
724 | {*}
725 |
726 | method set_line_cap(int32 $cap)
727 | is native($cairolib)
728 | is symbol('cairo_set_line_cap')
729 | {*}
730 |
731 | method get_line_cap
732 | returns int32
733 | is native($cairolib)
734 | is symbol('cairo_get_line_cap')
735 | {*}
736 |
737 | method set_line_join(int32 $join)
738 | is native($cairolib)
739 | is symbol('cairo_set_line_join')
740 | {*}
741 |
742 | method get_line_join
743 | returns int32
744 | is native($cairolib)
745 | is symbol('cairo_get_line_join')
746 | {*}
747 |
748 | method set_fill_rule(int32 $cap)
749 | is native($cairolib)
750 | is symbol('cairo_set_fill_rule')
751 | {*}
752 |
753 | method get_fill_rule
754 | returns int32
755 | is native($cairolib)
756 | is symbol('cairo_get_fill_rule')
757 | {*}
758 |
759 | method set_line_width(num64 $width)
760 | is native($cairolib)
761 | is symbol('cairo_set_line_width')
762 | {*}
763 | method get_line_width
764 | returns num64
765 | is native($cairolib)
766 | is symbol('cairo_get_line_width')
767 | {*}
768 |
769 | method set_miter_limit(num64 $width)
770 | is native($cairolib)
771 | is symbol('cairo_set_miter_limit')
772 | {*}
773 | method get_miter_limit
774 | returns num64
775 | is native($cairolib)
776 | is symbol('cairo_get_miter_limit')
777 | {*}
778 |
779 | method set_dash(CArray[num64] $dashes, int32 $len, num64 $offset)
780 | is native($cairolib)
781 | is symbol('cairo_set_dash')
782 | {*}
783 |
784 | method get_operator
785 | returns int32
786 | is native($cairolib)
787 | is symbol('cairo_get_operator')
788 | {*}
789 | method set_operator(int32 $op)
790 | is native($cairolib)
791 | is symbol('cairo_set_operator')
792 | {*}
793 |
794 | method get_antialias
795 | returns int32
796 | is native($cairolib)
797 | is symbol('cairo_get_antialias')
798 | {*}
799 | method set_antialias(int32 $op)
800 | is native($cairolib)
801 | is symbol('cairo_set_antialias')
802 | {*}
803 |
804 | method set_source_surface(cairo_surface_t $surface, num64 $x, num64 $y)
805 | is native($cairolib)
806 | is symbol('cairo_set_source_surface')
807 | {*}
808 |
809 | method mask(cairo_pattern_t $pattern)
810 | is native($cairolib)
811 | is symbol('cairo_mask')
812 | {*}
813 | method mask_surface(cairo_surface_t $surface, num64 $sx, num64 $sy)
814 | is native($cairolib)
815 | is symbol('cairo_mask_surface')
816 | {*}
817 |
818 | method clip
819 | is native($cairolib)
820 | is symbol('cairo_clip')
821 | {*}
822 | method clip_preserve
823 | is native($cairolib)
824 | is symbol('cairo_clip_preserve')
825 | {*}
826 |
827 | method fill
828 | is native($cairolib)
829 | is symbol('cairo_fill')
830 | {*}
831 |
832 | method stroke
833 | is native($cairolib)
834 | is symbol('cairo_stroke')
835 | {*}
836 |
837 | method fill_preserve
838 | is native($cairolib)
839 | is symbol('cairo_fill_preserve')
840 | {*}
841 |
842 | method stroke_preserve
843 | is native($cairolib)
844 | is symbol('cairo_stroke_preserve')
845 | {*}
846 |
847 | method paint
848 | is native($cairolib)
849 | is symbol('cairo_paint')
850 | {*}
851 | method paint_with_alpha(num64 $alpha)
852 | is native($cairolib)
853 | is symbol('cairo_paint_with_alpha')
854 | {*}
855 |
856 | method translate(num64 $tx, num64 $ty)
857 | is native($cairolib)
858 | is symbol('cairo_translate')
859 | {*}
860 | method scale(num64 $sx, num64 $sy)
861 | is native($cairolib)
862 | is symbol('cairo_scale')
863 | {*}
864 | method rotate(num64 $angle)
865 | is native($cairolib)
866 | is symbol('cairo_rotate')
867 | {*}
868 | method transform(cairo_matrix_t $matrix)
869 | is native($cairolib)
870 | is symbol('cairo_transform')
871 | {*}
872 | method identity_matrix
873 | is native($cairolib)
874 | is symbol('cairo_identity_matrix')
875 | {*}
876 | method set_matrix(cairo_matrix_t $matrix)
877 | is native($cairolib)
878 | is symbol('cairo_set_matrix')
879 | {*}
880 | method get_matrix(cairo_matrix_t $matrix)
881 | is native($cairolib)
882 | is symbol('cairo_get_matrix')
883 | {*}
884 |
885 | method save
886 | is native($cairolib)
887 | is symbol('cairo_save')
888 | {*}
889 | method restore
890 | is native($cairolib)
891 | is symbol('cairo_restore')
892 | {*}
893 |
894 | method status
895 | returns int32
896 | is native($cairolib)
897 | is symbol('cairo_status')
898 | {*}
899 |
900 |
901 | method select_font_face(Str $family, int32 $slant, int32 $weight)
902 | is native($cairolib)
903 | is symbol('cairo_select_font_face')
904 | {*}
905 |
906 | method set_font_face(cairo_font_face_t $font)
907 | is native($cairolib)
908 | is symbol('cairo_set_font_face')
909 | {*}
910 |
911 | method get_font_face
912 | returns cairo_font_face_t
913 | is native($cairolib)
914 | is symbol('cairo_get_font_face')
915 | {*}
916 |
917 | method set_font_size(num64 $size)
918 | is native($cairolib)
919 | is symbol('cairo_set_font_size')
920 | {*}
921 |
922 | method set_scaled_font(cairo_scaled_font_t $font)
923 | is native($cairolib)
924 | is symbol('cairo_set_scaled_font')
925 | {*}
926 |
927 | method get_scaled_font
928 | returns cairo_scaled_font_t
929 | is native($cairolib)
930 | is symbol('cairo_get_scaled_font')
931 | {*}
932 |
933 | method show_text(Str $utf8)
934 | is native($cairolib)
935 | is symbol('cairo_show_text')
936 | {*}
937 |
938 | method text_path(Str $utf8)
939 | is native($cairolib)
940 | is symbol('cairo_text_path')
941 | {*}
942 |
943 | method show_glyphs(cairo_glyph_t $glyphs, int32 $len)
944 | is native($cairolib)
945 | is symbol('cairo_show_glyphs')
946 | {*}
947 |
948 | method glyph_path(cairo_glyph_t $glyphs, int32 $len)
949 | is native($cairolib)
950 | is symbol('cairo_glyph_path')
951 | {*}
952 |
953 | method text_extents(Str $utf8, cairo_text_extents_t $extents)
954 | is native($cairolib)
955 | is symbol('cairo_text_extents')
956 | {*}
957 |
958 | method font_extents(cairo_font_extents_t $extents)
959 | is native($cairolib)
960 | is symbol('cairo_font_extents')
961 | {*}
962 |
963 | method set_tolerance(num64 $tolerance)
964 | is native($cairolib)
965 | is symbol('cairo_set_tolerance')
966 | {*}
967 |
968 | method get_tolerance()
969 | returns num64
970 | is native($cairolib)
971 | is symbol('cairo_get_tolerance')
972 | {*}
973 |
974 | method set_font_options(cairo_font_options_t $options)
975 | is native($cairolib)
976 | is symbol('cairo_set_font_options')
977 | {*}
978 | method get_font_options()
979 | is native($cairolib)
980 | is symbol('cairo_get_font_options')
981 | {*}
982 |
983 | method tag_begin(Str $tag, Str $attrs)
984 | is native($cairolib)
985 | is symbol('cairo_tag_begin')
986 | {*}
987 |
988 | method tag_end(Str $tag)
989 | is native($cairolib)
990 | is symbol('cairo_tag_end')
991 | {*}
992 |
993 | }
994 |
995 | # Backwards compatibility
996 | our enum cairo_subpixel_order_t is export <
997 | CAIRO_SUBPIXEL_ORDER_DEFAULT,
998 | CAIRO_SUBPIXEL_ORDER_RGB,
999 | CAIRO_SUBPIXEL_ORDER_BGR,
1000 | CAIRO_SUBPIXEL_ORDER_VRGB,
1001 | CAIRO_SUBPIXEL_ORDER_VBGR
1002 | >;
1003 |
1004 | our enum SubpixelOrder is export <
1005 | SUBPIXEL_ORDER_DEFAULT
1006 | SUBPIXEL_ORDER_RGB
1007 | SUBPIXEL_ORDER_BGR
1008 | SUBPIXEL_ORDER_VRGB
1009 | SUBPIXEL_ORDER_VBGR
1010 | >;
1011 |
1012 | our enum cairo_hint_style_t is export <
1013 | CAIRO_HINT_STYLE_DEFAULT
1014 | CAIRO_HINT_STYLE_NONE
1015 | CAIRO_HINT_STYLE_SLIGHT
1016 | CAIRO_HINT_STYLE_MEDIUM
1017 | CAIRO_HINT_STYLE_FULL
1018 | >;
1019 |
1020 | our enum HintStyle is export <
1021 | HINT_STYLE_DEFAULT
1022 | HINT_STYLE_NONE
1023 | HINT_STYLE_SLIGHT
1024 | HINT_STYLE_MEDIUM
1025 | HINT_STYLE_FULL
1026 | >;
1027 |
1028 | our enum cairo_hint_metrics_t is export <
1029 | CAIRO_HINT_METRICS_DEFAULT
1030 | CAIRO_HINT_METRICS_OFF
1031 | CAIRO_HINT_METRICS_ON
1032 | >;
1033 |
1034 | our enum HintMetrics is export <
1035 | HINT_METRICS_DEFAULT
1036 | HINT_METRICS_OFF
1037 | HINT_METRICS_ON
1038 | >;
1039 |
1040 | our enum cairo_antialias_t is export <
1041 | CAIRO_ANTIALIAS_DEFAULT
1042 | CAIRO_ANTIALIAS_NONE
1043 | CAIRO_ANTIALIAS_GRAY
1044 | CAIRO_ANTIALIAS_SUBPIXEL
1045 | CAIRO_ANTIALIAS_FAST
1046 | CAIRO_ANTIALIAS_GOOD
1047 | CAIRO_ANTIALIAS_BEST
1048 | >;
1049 |
1050 | our class Matrix { ... }
1051 | our class Surface { ... }
1052 | our class Image { ... }
1053 | our class Pattern { ... }
1054 | our class Context { ... }
1055 | our class Font { ... }
1056 | our class FontOptions { ... }
1057 | our class ScaledFont { ... }
1058 |
1059 | # Backwards compatibility
1060 | our enum cairo_format_t is export (
1061 | CAIRO_FORMAT_INVALID => -1,
1062 | CAIRO_FORMAT_ARGB32 => 0,
1063 | CAIRO_FORMAT_RGB24 => 1,
1064 | CAIRO_FORMAT_A8 => 2,
1065 | CAIRO_FORMAT_A1 => 3,
1066 | CAIRO_FORMAT_RGB16_565 => 4,
1067 | CAIRO_FORMAT_RGB30 => 5
1068 | );
1069 |
1070 | our enum Format is export (
1071 | FORMAT_INVALID => -1,
1072 | "FORMAT_ARGB32" ,
1073 | "FORMAT_RGB24" ,
1074 | "FORMAT_A8" ,
1075 | "FORMAT_A1" ,
1076 | "FORMAT_RGB16_565",
1077 | "FORMAT_RGB30" ,
1078 | );
1079 |
1080 | # Backwards compatibility
1081 | our enum cairo_operator_t is export <
1082 | CAIRO_OPERATOR_CLEAR
1083 | CAIRO_OPERATOR_SOURCE
1084 | CAIRO_OPERATOR_OVER
1085 | CAIRO_OPERATOR_IN
1086 | CAIRO_OPERATOR_OUT
1087 | CAIRO_OPERATOR_ATOP
1088 | CAIRO_OPERATOR_DEST
1089 | CAIRO_OPERATOR_DEST_OVER
1090 | CAIRO_OPERATOR_DEST_IN
1091 | CAIRO_OPERATOR_DEST_OUT
1092 | CAIRO_OPERATOR_DEST_ATOP
1093 | CAIRO_OPERATOR_XOR
1094 | CAIRO_OPERATOR_ADD
1095 | CAIRO_OPERATOR_SATURATE
1096 | CAIRO_OPERATOR_MULTIPLY
1097 | CAIRO_OPERATOR_SCREEN
1098 | CAIRO_OPERATOR_OVERLAY
1099 | CAIRO_OPERATOR_DARKEN
1100 | CAIRO_OPERATOR_LIGHTEN
1101 | CAIRO_OPERATOR_COLOR_DODGE
1102 | CAIRO_OPERATOR_COLOR_BURN
1103 | CAIRO_OPERATOR_HARD_LIGHT
1104 | CAIRO_OPERATOR_SOFT_LIGHT
1105 | CAIRO_OPERATOR_DIFFERENCE
1106 | CAIRO_OPERATOR_EXCLUSION
1107 | CAIRO_OPERATOR_HSL_HUE
1108 | CAIRO_OPERATOR_HSL_SATURATION
1109 | CAIRO_OPERATOR_HSL_COLOR
1110 | CAIRO_OPERATOR_HSL_LUMINOSITY
1111 | >;
1112 |
1113 | our enum CairoOperator is export <
1114 | OPERATOR_CLEAR
1115 |
1116 | OPERATOR_SOURCE
1117 | OPERATOR_OVER
1118 | OPERATOR_IN
1119 | OPERATOR_OUT
1120 | OPERATOR_ATOP
1121 |
1122 | OPERATOR_DEST
1123 | OPERATOR_DEST_OVER
1124 | OPERATOR_DEST_IN
1125 | OPERATOR_DEST_OUT
1126 | OPERATOR_DEST_ATOP
1127 |
1128 | OPERATOR_XOR
1129 | OPERATOR_ADD
1130 | OPERATOR_SATURATE
1131 |
1132 | OPERATOR_MULTIPLY
1133 | OPERATOR_SCREEN
1134 | OPERATOR_OVERLAY
1135 | OPERATOR_DARKEN
1136 | OPERATOR_LIGHTEN
1137 | OPERATOR_COLOR_DODGE
1138 | OPERATOR_COLOR_BURN
1139 | OPERATOR_HARD_LIGHT
1140 | OPERATOR_SOFT_LIGHT
1141 | OPERATOR_DIFFERENCE
1142 | OPERATOR_EXCLUSION
1143 | OPERATOR_HSL_HUE
1144 | OPERATOR_HSL_SATURATION
1145 | OPERATOR_HSL_COLOR
1146 | OPERATOR_HSL_LUMINOSITY
1147 | >;
1148 |
1149 | our enum cairo_line_cap is export <
1150 | CAIRO_LINE_CAP_BUTT
1151 | CAIRO_LINE_CAP_ROUND
1152 | CAIRO_LINE_CAP_SQUARE
1153 | >;
1154 |
1155 | our enum LineCap is export <
1156 | LINE_CAP_BUTT
1157 | LINE_CAP_ROUND
1158 | LINE_CAP_SQUARE
1159 | >;
1160 |
1161 | our enum cairo_line_join is export <
1162 | CAIRO_LINE_JOIN_MITER
1163 | CAIRO_LINE_JOIN_ROUND
1164 | CAIRO_LINE_JOIN_BEVEL
1165 | >;
1166 |
1167 | our enum LineJoin is export <
1168 | LINE_JOIN_MITER
1169 | LINE_JOIN_ROUND
1170 | LINE_JOIN_BEVEL
1171 | >;
1172 |
1173 | our enum Content is export (
1174 | CONTENT_COLOR => 0x1000,
1175 | CONTENT_ALPHA => 0x2000,
1176 | CONTENT_COLOR_ALPHA => 0x3000,
1177 | );
1178 |
1179 | our enum Antialias is export <
1180 | ANTIALIAS_DEFAULT
1181 | ANTIALIAS_NONE
1182 | ANTIALIAS_GRAY
1183 | ANTIALIAS_SUBPIXEL
1184 | ANTIALIAS_FAST
1185 | ANTIALIAS_GOOD
1186 | ANTIALIAS_BEST
1187 | >;
1188 |
1189 | our enum FontWeight is export <
1190 | FONT_WEIGHT_NORMAL
1191 | FONT_WEIGHT_BOLD
1192 | >;
1193 |
1194 | our enum FontSlant is export <
1195 | FONT_SLANT_NORMAL
1196 | FONT_SLANT_ITALIC
1197 | FONT_SLANT_OBLIQUE
1198 | >;
1199 |
1200 | our enum Extend is export <
1201 | EXTEND_NONE
1202 | EXTEND_REPEAT
1203 | EXTEND_REFLECT
1204 | CAIRO_EXTEND_PAD
1205 | >;
1206 |
1207 | our enum FillRule is export <
1208 | FILL_RULE_WINDING
1209 | FILL_RULE_EVEN_ODD
1210 | >;
1211 |
1212 | class Matrix {
1213 | has cairo_matrix_t $.matrix handles <
1214 | xx yx xy yy x0 y0
1215 | > .= new: :xx(1e0), :yy(1e0);
1216 |
1217 | multi method init(Num(Cool) :$xx = 1e0, Num(Cool) :$yx = 0e0, Num(Cool) :$xy = 0e0, Num(Cool) :$yy = 1e0, Num(Cool) :$x0 = 0e0, Num(Cool) :$y0 = 0e0) {
1218 | $!matrix.init( $xx, $yx, $xy, $yy, $x0, $y0 );
1219 | self;
1220 | }
1221 |
1222 | multi method init(Num(Cool) $xx, Num(Cool) $yx = 0e0,
1223 | Num(Cool) $xy = 0e0, Num(Cool) $yy = 1e0,
1224 | Num(Cool) $x0 = 0e0, Num(Cool) $y0 = 0e0) {
1225 | $!matrix.init( $xx, $yx, $xy, $yy, $x0, $y0 );
1226 | self;
1227 | }
1228 |
1229 | method scale(Num(Cool) $sx, Num(Cool) $sy) {
1230 | $!matrix.scale($sx, $sy);
1231 | self;
1232 | }
1233 |
1234 | method translate(Num(Cool) $tx, Num(Cool) $ty) {
1235 | $!matrix.translate($tx, $ty);
1236 | self;
1237 | }
1238 |
1239 | method rotate(Num(Cool) $rad) {
1240 | $!matrix.rotate($rad);
1241 | self;
1242 | }
1243 |
1244 | method invert {
1245 | $!matrix.invert;
1246 | self;
1247 | }
1248 |
1249 | method multiply(Matrix $b) {
1250 | my cairo_matrix_t $a-matrix = $!matrix;
1251 | $!matrix = cairo_matrix_t.new;
1252 | $!matrix.multiply($a-matrix, $b.matrix);
1253 | self;
1254 | }
1255 |
1256 | }
1257 |
1258 | class Surface {
1259 | has cairo_surface_t $.surface handles ;
1260 | method set-surface($!surface) {}
1261 |
1262 | method write_png(Str $filename) {
1263 | my $result = CairoStatus( $.surface.write_to_png($filename) );
1264 | fail $result if $result != STATUS_SUCCESS;
1265 | $result;
1266 | }
1267 |
1268 | method Blob(UInt :$size = 64_000 --> Blob) {
1269 | my $buf = CArray[uint8].new;
1270 | $buf[$size] = 0;
1271 | my $closure = StreamClosure.new: :$buf, :buf-len(0), :n-read(0), :$size;
1272 | $.surface.write_to_png_stream(&StreamClosure::write, $closure);
1273 | return Blob[uint8].new: $buf[0 ..^ $closure.buf-len];
1274 | }
1275 |
1276 | method record(&things) {
1277 | my $ctx = Context.new(self);
1278 | &things($ctx);
1279 | $ctx.destroy();
1280 | return self;
1281 | }
1282 |
1283 | }
1284 |
1285 | class Surface::PDF is Surface {
1286 | has Num:D() $.width is required;
1287 | has Num:D() $.height is required;
1288 |
1289 | submethod BUILD(Str:D() :$filename!, :$!width!, :$!height!) is hidden-from-backtrace {
1290 | my $s = cairo_pdf_surface_t::create($filename, $!width, $!height);
1291 | self.set-surface: $s;
1292 | }
1293 |
1294 | method create(Str:D() $filename, Str:D() $width, Str:D() $height) {
1295 | return self.new( :$filename, :$width, :$height );
1296 | }
1297 |
1298 | method add_outline(Int :$parent-id, Str:D :$name = '', :$flags = 0, *%attrs) {
1299 | $.surface.add_outline: $parent-id, $name, Attrs::serialize(%attrs), $flags;
1300 | }
1301 |
1302 | method surface returns cairo_pdf_surface_t handles { callsame() }
1303 | }
1304 |
1305 | class Surface::SVG is Surface {
1306 | has Num:D() $.width is required;
1307 | has Num:D() $.height is required;
1308 |
1309 | submethod BUILD(Str:D() :$filename!, :$!width!, :$!height!) is hidden-from-backtrace {
1310 | self.set-surface: cairo_svg_surface_t::create $filename, $!width, $!height;
1311 | }
1312 |
1313 | method create(Str:D() $filename, Int:D() $width, Int:D() $height) {
1314 | return self.new(:$filename, :$width, :$height);
1315 | }
1316 |
1317 | method surface returns cairo_svg_surface_t { callsame }
1318 |
1319 | }
1320 |
1321 | class RecordingSurface {
1322 | sub cairo_recording_surface_create(int32 $content, cairo_rectangle_t $extents)
1323 | returns cairo_surface_t
1324 | is native($cairolib)
1325 | {*}
1326 |
1327 | method new(Content $content = CONTENT_COLOR_ALPHA) {
1328 | my cairo_surface_t $surface = cairo_recording_surface_create($content.Int, OpaquePointer);
1329 | my RecordingSurface $rsurf = self.bless: :$surface;
1330 | $rsurf.reference;
1331 | $rsurf;
1332 | }
1333 |
1334 | method record(&things, Content :$content = CONTENT_COLOR_ALPHA) {
1335 | my Context $ctx .= new(my $surface = self.new($content));
1336 | &things($ctx);
1337 | $ctx.destroy();
1338 | return $surface;
1339 | }
1340 | }
1341 |
1342 | class Image is Surface {
1343 | sub cairo_image_surface_create(int32 $format, int32 $width, int32 $height)
1344 | returns cairo_surface_t
1345 | is native($cairolib)
1346 | {*}
1347 |
1348 | sub cairo_image_surface_create_for_data_ca(CArray[uint8] $data, int32 $format, int32 $width, int32 $height, int32 $stride)
1349 | returns cairo_surface_t
1350 | is native($cairolib)
1351 | {*}
1352 | sub cairo_image_surface_create_for_data_b(Blob[uint8] $data, int32 $format, int32 $width, int32 $height, int32 $stride)
1353 | returns cairo_surface_t
1354 | is native($cairolib)
1355 | {*}
1356 | sub cairo_image_surface_create_for_data(Pointer $data, int32 $format, int32 $width, int32 $height, int32 $stride)
1357 | returns cairo_surface_t
1358 | is native($cairolib)
1359 | {*}
1360 |
1361 | sub cairo_image_surface_create_from_png(Str $filename)
1362 | returns cairo_surface_t
1363 | is native($cairolib)
1364 | {*}
1365 |
1366 | sub cairo_image_surface_create_from_png_stream(
1367 | &read-func (StreamClosure, Pointer[uint8], uint32 --> int32),
1368 | StreamClosure)
1369 | returns cairo_surface_t
1370 | is native($cairolib)
1371 | {*}
1372 |
1373 | sub cairo_format_stride_for_width(int32 $format, int32 $width)
1374 | returns int32
1375 | is native($cairolib)
1376 | {*}
1377 |
1378 | multi submethod BUILD(cairo_surface_t:D :$surface) is hidden-from-backtrace { self.set-surface: $surface}
1379 | multi submethod BUILD(Str:D :$filename!) is hidden-from-backtrace {
1380 | self.set-surface: cairo_image_surface_create_from_png($filename)
1381 | }
1382 | multi submethod BUILD(Int:D() :$width!, Int:D() :$height!, Int:D() :$format = Cairo::FORMAT_ARGB32) is hidden-from-backtrace {
1383 | self.set-surface: cairo_image_surface_create($format, $width, $height);
1384 | }
1385 |
1386 | multi method create(Int() $format, Cool $width, Cool $height) {
1387 | return self.new(surface => cairo_image_surface_create($format.Int, $width.Int, $height.Int));
1388 | }
1389 |
1390 | multi method create(Int() $format, Cool $width, Cool $height, $data, Cool $stride? is copy) {
1391 | if $stride eqv False {
1392 | $stride = $width.Int;
1393 | } elsif $stride eqv True {
1394 | $stride = cairo_format_stride_for_width($format.Int, $width.Int);
1395 | }
1396 | my $d = do given $data {
1397 | when Array[uint8] { my $tmp = CArray[uint8].new($_);
1398 | $_ = $tmp;
1399 | proceed; }
1400 | when Buf[uint8] { my $tmp = nativecast(Blob[uint8], $_);
1401 | $_ = $tmp;
1402 | proceed; }
1403 | when CArray[uint8] |
1404 | Blob[uint8] |
1405 | Pointer { $_ }
1406 |
1407 | default {
1408 | die qq:to/D/;
1409 | Invalid type: { .^name }
1410 | Cairo::Image.create only supports variables of type: {
1411 | '' }Array[uint8], CArray[uint8], Blob[uint8] and Pointer.
1412 | D
1413 | }
1414 | }
1415 | return self.new(surface => do given $d {
1416 | when CArray { cairo_image_surface_create_for_data_ca($d, $format.Int, $width.Int, $height.Int, $stride) }
1417 | when Blob { cairo_image_surface_create_for_data_b($d, $format.Int, $width.Int, $height.Int, $stride) }
1418 | when Pointer { cairo_image_surface_create_for_data($d, $format.Int, $width.Int, $height.Int, $stride) }
1419 | });
1420 | }
1421 |
1422 | multi method create(Blob[uint8] $data, Int(Cool) $buf-len = $data.elems) {
1423 | my $buf = CArray[uint8].new: $data;
1424 | my $closure = StreamClosure.new: :$buf, :$buf-len, :n-read(0);
1425 | return self.new(surface => cairo_image_surface_create_from_png_stream(&StreamClosure::read, $closure));
1426 | }
1427 |
1428 | multi method open(str $filename) {
1429 | return self.new(surface => cairo_image_surface_create_from_png($filename));
1430 | }
1431 | multi method open(Str(Cool) $filename) {
1432 | return self.new(surface => cairo_image_surface_create_from_png($filename));
1433 | }
1434 |
1435 | method record(&things, Cool $width?, Cool $height?, Format $format = FORMAT_ARGB32) {
1436 | if defined $width and defined $height {
1437 | my $surface = self.create($format, $width, $height);
1438 | my $ctx = Context.new($surface);
1439 | &things($ctx);
1440 | return $surface;
1441 | } else {
1442 | die "recording surfaces are currently NYI. please specify a width and height for your Cairo::Image.";
1443 | }
1444 | }
1445 |
1446 | method data() { $.surface.get_image_data }
1447 | method stride() { $.surface.get_image_stride }
1448 | method width() { $.surface.get_image_width }
1449 | method height() { $.surface.get_image_height }
1450 | }
1451 |
1452 | class Pattern::Solid { ... }
1453 | class Pattern::Surface { ... }
1454 | class Pattern::Gradient { ... }
1455 | class Pattern::Gradient::Linear { ... }
1456 | class Pattern::Gradient::Radial { ... }
1457 | class Glyphs {...}
1458 |
1459 | class Pattern {
1460 |
1461 | has cairo_pattern_t $.pattern handles ;
1462 |
1463 | method Cairo::cairo_pattern_t { $!pattern }
1464 |
1465 | multi method new(cairo_pattern_t $pattern) {
1466 | self.bless(:$pattern)
1467 | }
1468 |
1469 | method extend() is rw {
1470 | Proxy.new:
1471 | FETCH => { Extend($!pattern.get_extend) },
1472 | STORE => -> \c, \value { $!pattern.set_extend(value.Int) }
1473 | }
1474 |
1475 | method matrix() is rw {
1476 | Proxy.new:
1477 | FETCH => {
1478 | my cairo_matrix_t $matrix .= new;
1479 | $!pattern.get_matrix($matrix);
1480 | Cairo::Matrix.new: :$matrix;
1481 | },
1482 | STORE => -> \c, Cairo::Matrix \matrix { $!pattern.set_matrix(matrix.matrix) }
1483 | }
1484 |
1485 | }
1486 |
1487 | class Pattern::Solid is Pattern {
1488 |
1489 | sub cairo_pattern_create_rgb(num64 $r, num64 $g, num64 $b)
1490 | returns cairo_pattern_t
1491 | is native($cairolib)
1492 | {*}
1493 |
1494 | sub cairo_pattern_create_rgba(num64 $r, num64 $g, num64 $b, num64 $a)
1495 | returns cairo_pattern_t
1496 | is native($cairolib)
1497 | {*}
1498 |
1499 | multi method create(Num(Cool) $r, Num(Cool) $g, Num(Cool) $b) {
1500 | self.new: cairo_pattern_create_rgb($r, $g, $b);
1501 | }
1502 |
1503 | multi method create(Num(Cool) $r, Num(Cool) $g, Num(Cool) $b, Num(Cool) $a) {
1504 | self.new: cairo_pattern_create_rgba($r, $g, $b, $a);
1505 | }
1506 |
1507 | }
1508 |
1509 | class Pattern::Surface is Pattern {
1510 | sub cairo_pattern_create_for_surface(cairo_surface_t $surface)
1511 | returns cairo_pattern_t
1512 | is native($cairolib)
1513 | {*}
1514 |
1515 | method create(cairo_surface_t $surface) {
1516 | self.new: cairo_pattern_create_for_surface($surface);
1517 | }
1518 |
1519 | }
1520 |
1521 | class Pattern::Gradient is Pattern {
1522 |
1523 | method add_color_stop_rgb(Num(Cool) $offset, Num(Cool) $red, Num(Cool) $green, Num(Cool) $blue) {
1524 | my num64 ($o, $r, $g, $b) = ($offset, $red, $green, $blue);
1525 | say "o = $offset / r = $r / g = $g / b = $b";
1526 | $.pattern.add_color_stop_rgb($o, $r, $g, $b);
1527 | }
1528 |
1529 | method add_color_stop_rgba(Num(Cool) $offset, Num(Cool) $r, Num(Cool) $g, Num(Cool) $b, Num(Cool) $a) {
1530 | say "o = $offset / r = $r / g = $g / b = $b / a = $a";
1531 | $.pattern.add_color_stop_rgba($offset, $r, $g, $b, $a);
1532 | }
1533 |
1534 | multi method get_color_stop_count {
1535 | samewith($);
1536 | }
1537 | multi method get_color_stop_count ($count is rw) {
1538 | my int32 $c = 0;
1539 | $.pattern.get_color_stop_count($c);
1540 | $count = $c;
1541 | }
1542 | method elems {
1543 | self.get_color_stop_count;
1544 | }
1545 |
1546 | multi method get_color_stop_rgba (Int() $index) {
1547 | samewith($index, $, $, $, $);
1548 | }
1549 | multi method get_color_stop_rgba (
1550 | Int() $index,
1551 | $offset is rw,
1552 | $red is rw,
1553 | $green is rw,
1554 | $blue is rw
1555 | ) {
1556 | my int32 $i = $index;
1557 | my num64 ($o, $r, $g, $b) = 0e0 xx 4;
1558 |
1559 | $.pattern.get_color_stop_rgba($i, $o, $r, $g, $b);
1560 | ($offset, $red, $green, $blue) = ($o, $r, $g, $b);
1561 | }
1562 |
1563 | method gist {
1564 | my @stops;
1565 |
1566 | for ^self.get_color_stop_count {
1567 | my @s = self.get_color_stop_rgba($_);
1568 | say "Stop #{ $_ } = { @s.join(', ') }";
1569 | @stops.push: @s;
1570 | }
1571 |
1572 | say "Cario::Pattern::Gradient.new(stops => { @stops.join(', ') }) ";
1573 | }
1574 |
1575 |
1576 | }
1577 |
1578 | class Pattern::Gradient::Linear is Pattern::Gradient {
1579 |
1580 | sub cairo_pattern_create_linear(num64 $x0, num64 $y0, num64 $x1, num64 $y1)
1581 | returns cairo_pattern_t
1582 | is native($cairolib)
1583 | {*}
1584 |
1585 | method create(Num(Cool) $x0, Num(Cool) $y0, Num(Cool) $x1, Num(Cool) $y1) {
1586 | self.new: cairo_pattern_create_linear($x0, $y0, $x1, $y1);
1587 | }
1588 |
1589 | }
1590 |
1591 | class Pattern::Gradient::Radial is Pattern::Gradient {
1592 | sub cairo_pattern_create_radial(num64 $cx0, num64 $cy0, num64 $r0, num64 $cx1, num64 $cy1, num64 $r1)
1593 | returns cairo_pattern_t
1594 | is native($cairolib)
1595 | {*}
1596 |
1597 | method create(Num(Cool) $cx0, Num(Cool) $cy0, Num(Cool) $r0,
1598 | Num(Cool) $cx1, Num(Cool) $cy1, Num(Cool) $r1) {
1599 | self.new: cairo_pattern_create_radial($cx0, $cy0, $r0, $cx1, $cy1, $r1);
1600 | }
1601 |
1602 | }
1603 |
1604 | class Path { ... }
1605 |
1606 | class Context {
1607 | sub cairo_create(cairo_surface_t $surface)
1608 | returns cairo_t
1609 | is native($cairolib)
1610 | {*}
1611 |
1612 | has cairo_t $.context handles <
1613 | status destroy push_group pop_group_to_source sub_path
1614 | save restore paint close_path new_path identity_matrix
1615 | tag_end
1616 | >;
1617 |
1618 | method Cairo::cairo_t {
1619 | $.context
1620 | }
1621 |
1622 | multi method new(cairo_t $context) {
1623 | self.bless(:$context);
1624 | }
1625 |
1626 | multi method new(Surface $surface) {
1627 | my $context = cairo_create($surface.surface);
1628 | self.bless(:$context);
1629 | }
1630 |
1631 | submethod BUILD(:$!context) { }
1632 |
1633 | method pop_group() returns Pattern {
1634 | Pattern.new($!context.pop_group);
1635 | }
1636 |
1637 | method append_path(cairo_path_t() $path) {
1638 | $!context.append_path($path);
1639 | }
1640 |
1641 | multi method copy_path() {
1642 | Path.new($!context.copy_path);
1643 | }
1644 | multi method copy_path(:$flat! where .so) {
1645 | Path.new($!context.copy_path_flat)
1646 | }
1647 |
1648 | method memoize_path($storage is rw, &creator, :$flat?) {
1649 | if defined $storage {
1650 | self.append_path($storage);
1651 | } else {
1652 | &creator();
1653 | $storage = self.copy_path(:$flat);
1654 | }
1655 | }
1656 |
1657 | multi method rgb(Num(Cool) $r, Num(Cool) $g, Num(Cool) $b) {
1658 | $!context.set_source_rgb($r, $g, $b);
1659 | }
1660 | multi method rgb(num $r, num $g, num $b) {
1661 | $!context.set_source_rgb($r, $g, $b);
1662 | }
1663 |
1664 | multi method rgba(Num(Cool) $r, Num(Cool) $g, Num(Cool) $b, Num(Cool) $a) {
1665 | $!context.set_source_rgba($r, $g, $b, $a);
1666 | }
1667 | multi method rgb(num $r, num $g, num $b, num $a) {
1668 | $!context.set_source_rgba($r, $g, $b, $a);
1669 | }
1670 |
1671 | method pattern(Pattern $pat) {
1672 | $!context.set_source($pat.pattern);
1673 | }
1674 |
1675 | method set_source_surface(Surface $surface, Num(Cool) $x = 0, Num(Cool) $y = 0) {
1676 | $!context.set_source_surface($surface.surface, $x, $y)
1677 | }
1678 |
1679 | multi method mask(Pattern $pat, Num(Cool) $sx = 0, Num(Cool) $sy = 0) {
1680 | $!context.mask($pat.pattern, $sx, $sy)
1681 | }
1682 | multi method mask(Pattern $pat, num $sx = 0e0, num $sy = 0e0) {
1683 | $!context.mask($pat.pattern, $sx, $sy)
1684 | }
1685 | multi method mask(Surface $surface, Num(Cool) $sx = 0, Num(Cool) $sy = 0) {
1686 | $!context.mask_surface($surface.surface, $sx, $sy)
1687 | }
1688 | multi method mask(Surface $surface, num $sx = 0e0, num $sy = 0e0) {
1689 | $!context.mask_surface($surface.surface, $sx, $sy)
1690 | }
1691 |
1692 | multi method fill {
1693 | $!context.fill
1694 | }
1695 | multi method stroke {
1696 | $!context.stroke
1697 | }
1698 | multi method fill(:$preserve! where .so) {
1699 | $!context.fill_preserve
1700 | }
1701 | multi method stroke(:$preserve! where .so) {
1702 | $!context.stroke_preserve
1703 | }
1704 | multi method clip {
1705 | $!context.clip
1706 | }
1707 | multi method clip(:$preserve! where .so) {
1708 | $!context.clip_preserve
1709 | }
1710 |
1711 | multi method paint_with_alpha( num64 $alpha) {
1712 | $!context.paint_with_alpha($alpha)
1713 | }
1714 | multi method paint_with_alpha( Num(Cool) $alpha) {
1715 | $!context.paint_with_alpha($alpha)
1716 | }
1717 |
1718 | multi method move_to(Num(Cool) $x, Num(Cool) $y) {
1719 | $!context.move_to($x, $y);
1720 | }
1721 | multi method line_to(Num(Cool) $x, Num(Cool) $y) {
1722 | $!context.line_to($x, $y);
1723 | }
1724 |
1725 | multi method move_to(Num(Cool) $x, Num(Cool) $y, :$relative! where .so) {
1726 | $!context.rel_move_to($x, $y);
1727 | }
1728 | multi method line_to(Num(Cool) $x, Num(Cool) $y, :$relative! where .so) {
1729 | $!context.rel_line_to($x, $y);
1730 | }
1731 |
1732 | multi method get_current_point {
1733 | my Num ($x, $y);
1734 | samewith($x, $y);
1735 | }
1736 | multi method get_current_point(Num $x is rw, Num $y is rw) {
1737 | my num64 ($xx, $yy) = (0.Num, 0.Num);
1738 | $!context.get_current_point($xx, $yy);
1739 | ($x, $y) = ($xx, $yy);
1740 | }
1741 |
1742 | multi method curve_to(Num(Cool) $x1, Num(Cool) $y1, Num(Cool) $x2, Num(Cool) $y2, Num(Cool) $x3, Num(Cool) $y3) {
1743 | $!context.curve_to($x1, $y1, $x2, $y2, $x3, $y3);
1744 | }
1745 | multi method curve_to(Num(Cool) $x1, Num(Cool) $y1, Num(Cool) $x2, Num(Cool) $y2, Num(Cool) $x3, Num(Cool) $y3, :$relative! where .so) {
1746 | $!context.rel_curve_to($x1, $y1, $x2, $y2, $x3, $y3);
1747 | }
1748 |
1749 | multi method arc(Num(Cool) $xc, Num(Cool) $yc, Num(Cool) $radius, Num(Cool) $angle1, Num(Cool) $angle2, :$negative! where .so) {
1750 | $!context.arc_negative($xc, $yc, $radius, $angle1, $angle2);
1751 | }
1752 | multi method arc(num $xc, num $yc, num $radius, num $angle1, num $angle2, :$negative! where .so) {
1753 | $!context.arc_negative($xc, $yc, $radius, $angle1, $angle2);
1754 | }
1755 |
1756 | multi method arc(Num(Cool) $xc, Num(Cool) $yc, Num(Cool) $radius, Num(Cool) $angle1, Num(Cool) $angle2) {
1757 | $!context.arc($xc, $yc, $radius, $angle1, $angle2);
1758 | }
1759 | multi method arc(num $xc, num $yc, num $radius, num $angle1, num $angle2) {
1760 | $!context.arc($xc, $yc, $radius, $angle1, $angle2);
1761 | }
1762 |
1763 | multi method rectangle(Num(Cool) $x, Num(Cool) $y, Num(Cool) $w, Num(Cool) $h) {
1764 | $!context.rectangle($x, $y, $w, $h);
1765 | }
1766 | multi method rectangle(num $x, num $y, num $w, num $h) {
1767 | $!context.rectangle($x, $y, $w, $h);
1768 | }
1769 |
1770 | multi method translate(num $tx, num $ty) {
1771 | $!context.translate($tx, $ty)
1772 | }
1773 | multi method translate(Num(Cool) $tx, Num(Cool) $ty) {
1774 | $!context.translate($tx, $ty)
1775 | }
1776 |
1777 | multi method scale(num $sx, num $sy) {
1778 | $!context.scale($sx, $sy)
1779 | }
1780 | multi method scale(Num(Cool) $sx, Num(Cool) $sy) {
1781 | $!context.scale($sx, $sy)
1782 | }
1783 |
1784 | multi method rotate(num $angle) {
1785 | $!context.rotate($angle)
1786 | }
1787 | multi method rotate(Num(Cool) $angle) {
1788 | $!context.rotate($angle)
1789 | }
1790 |
1791 | method transform(Matrix $matrix) {
1792 | $!context.transform($matrix.matrix)
1793 | }
1794 |
1795 | multi method select_font_face(str $family, int32 $slant, int32 $weight) {
1796 | $!context.select_font_face($family, $slant, $weight);
1797 | }
1798 | multi method select_font_face(Str(Cool) $family, Int(Cool) $slant, Int(Cool) $weight) {
1799 | $!context.select_font_face($family, $slant, $weight);
1800 | }
1801 | method set_font_face(Cairo::Font $font) {
1802 | $!context.set_font_face($font.face);
1803 | }
1804 | method get_font_face {
1805 | my $face = $!context.get_font_face;
1806 | $face.reference;
1807 | Cairo::Face.new: :$face;
1808 | }
1809 |
1810 | multi method set_font_size(num $size) {
1811 | $!context.set_font_size($size);
1812 | }
1813 | multi method set_font_size(Num(Cool) $size) {
1814 | $!context.set_font_size($size);
1815 | }
1816 |
1817 | method set_scaled_font(Cairo::ScaledFont $font) {
1818 | $!context.set_scaled_font($font.font);
1819 | }
1820 | method get_scaled_font {
1821 | my $font = $!context.get_scaled_font;
1822 | $font.reference;
1823 | Cairo::Face.new: :$font;
1824 | }
1825 |
1826 | multi method show_text(str $text) {
1827 | $!context.show_text($text);
1828 | }
1829 | multi method show_text(Str(Cool) $text) {
1830 | $!context.show_text($text);
1831 | }
1832 |
1833 | method show_glyphs(Glyphs $glyph_array, $n = $glyph_array.elems) {
1834 | $!context.show_glyphs($glyph_array.glyphs, $n);
1835 | }
1836 |
1837 | method glyph_path(Glyphs $glyph_array, $n = $glyph_array.elems) {
1838 | $!context.glyph_path($glyph_array.glyphs, $n);
1839 | }
1840 |
1841 | multi method text_path(str $text) {
1842 | $!context.text_path($text);
1843 | }
1844 | multi method text_path(Str(Cool) $text) {
1845 | $!context.text_path($text);
1846 | }
1847 |
1848 | multi method text_extents(str $text --> cairo_text_extents_t) {
1849 | my cairo_text_extents_t $extents .= new;
1850 | $!context.text_extents($text, $extents);
1851 | $extents;
1852 | }
1853 | multi method text_extents(Str(Cool) $text --> cairo_text_extents_t) {
1854 | my cairo_text_extents_t $extents .= new;
1855 | $!context.text_extents($text, $extents);
1856 | $extents;
1857 | }
1858 |
1859 | method font_extents {
1860 | my cairo_font_extents_t $extents .= new;
1861 | $!context.font_extents($extents);
1862 | $extents;
1863 | }
1864 |
1865 | multi method set_dash(CArray[num64] $dashes, int32 $len, num64 $offset) {
1866 | $!context.set_dash($dashes, $len, $offset);
1867 | }
1868 | multi method set_dash(@dashes, Num(Cool) $offset = 0) {
1869 | samewith(@dashes.List, @dashes.elems, $offset);
1870 | }
1871 | multi method set_dash(List $dashes, Int(Cool) $len, Num(Cool) $offset) {
1872 | my $d = CArray[num64].new;
1873 | $d[$_] = $dashes[$_].Num
1874 | for 0 ..^ $len;
1875 | $!context.set_dash($d, $len, $offset);
1876 | }
1877 |
1878 | method line_cap() is rw {
1879 | Proxy.new:
1880 | FETCH => { LineCap($!context.get_line_cap) },
1881 | STORE => -> \c, \value { $!context.set_line_cap(value.Int) }
1882 | }
1883 |
1884 | method fill_rule() is rw {
1885 | Proxy.new:
1886 | FETCH => { LineCap($!context.get_fill_rule) },
1887 | STORE => -> \c, \value { $!context.set_fill_rule(value.Int) }
1888 | }
1889 |
1890 | method line_join() is rw {
1891 | Proxy.new:
1892 | FETCH => { LineJoin($!context.get_line_join) },
1893 | STORE => -> \c, \value { $!context.set_line_join(value.Int) }
1894 | }
1895 |
1896 | method operator() is rw {
1897 | Proxy.new:
1898 | FETCH => { CairoOperator($!context.get_operator) },
1899 | STORE => -> \c, \value { $!context.set_operator(value.Int) }
1900 | }
1901 |
1902 | method antialias() is rw {
1903 | Proxy.new:
1904 | FETCH => { Antialias($!context.get_antialias) },
1905 | STORE => -> \c, \value { $!context.set_antialias(value.Int) }
1906 | }
1907 |
1908 | method line_width() is rw {
1909 | Proxy.new:
1910 | FETCH => { $!context.get_line_width},
1911 | STORE => -> \c, \value { $!context.set_line_width(value.Num) }
1912 | }
1913 |
1914 | method miter_limit() is rw {
1915 | Proxy.new:
1916 | FETCH => { $!context.get_miter_limit},
1917 | STORE => -> \c, \value { $!context.set_miter_limit(value.Num) }
1918 | }
1919 |
1920 | method tolerance() is rw {
1921 | Proxy.new:
1922 | FETCH => { $!context.get_tolerance},
1923 | STORE => -> \c, \value { $!context.set_tolerance(value.Num) }
1924 | }
1925 | method font_options() is rw {
1926 | Proxy.new:
1927 | FETCH => { $!context.get_font_options},
1928 | STORE => -> \c, cairo_font_options_t() \value { $!context.set_font_options(value) }
1929 | }
1930 | method font_face() is rw {
1931 | Proxy.new:
1932 | FETCH => { self.get_font_face},
1933 | STORE => -> \c, Cairo::Font() \value { self.set_font_face(value) }
1934 | }
1935 |
1936 | method tag_begin(Str:D $tag, *%attrs) {
1937 | $!context.tag_begin($tag, Attrs::serialize(%attrs));
1938 | }
1939 |
1940 | # tags links, destinations; primarily for PDF backend
1941 | method tag(Str:D $tag, &block) {
1942 | $.tag_begin: $tag, |%_;
1943 | &block(self);
1944 | $.tag_end($tag);
1945 | }
1946 |
1947 | # URI link
1948 | multi method link_begin(Str:D :$uri!, List :$rect) {
1949 | $.tag_begin: CAIRO_TAG_LINK, :$uri, :$rect;
1950 | }
1951 | # link to a named destination, in this or another PDF file
1952 | multi method link_begin(Str:D :$dest!, Str :$file) {
1953 | $.tag_begin: CAIRO_TAG_LINK, :$dest, :$file;
1954 | }
1955 | # link to a page, in this or another PDF file
1956 | multi method link_begin(Int:D :$page!, List :$pos, Str :$file) {
1957 | $.tag_begin: CAIRO_TAG_LINK, :$page, :$pos, :$file;
1958 | }
1959 | method link_end { $.tag_end(CAIRO_TAG_LINK) }
1960 | method link(&block, |c) {
1961 | $.link_begin: |c;
1962 | &block();
1963 | $.link_end;
1964 | }
1965 |
1966 | # creates a named destination
1967 | method destination(&block, Str:D :$name!, Numeric :$x, Numeric :$y, Bool :$internal) {
1968 | $.tag: CAIRO_TAG_DEST, &block, :$name, :$x, :$y, :$internal;
1969 | }
1970 |
1971 | method matrix() is rw {
1972 | Proxy.new:
1973 | FETCH => {
1974 | my cairo_matrix_t $matrix .= new;
1975 | $!context.get_matrix($matrix);
1976 | Matrix.new: :$matrix;
1977 | },
1978 | STORE => -> \c, Matrix \matrix { $!context.set_matrix(matrix.matrix) }
1979 | }
1980 |
1981 | }
1982 |
1983 | class Path {
1984 | has cairo_path_t $.path handles ;
1985 |
1986 | submethod BUILD (:$!path) { }
1987 |
1988 | method Cairo::cairo_path_t { $.path }
1989 |
1990 | method AT-POS(|) {
1991 | die 'Sorry! Cairo::Path is an iterated list, not an array.'
1992 | }
1993 |
1994 | method get_data(Int $i) {
1995 | my $a = [];
1996 | $a[$_] := $!path.data[$i + $_] for ^$!path.data[$i].length;
1997 | $a;
1998 | }
1999 |
2000 | method iterator {
2001 | my $oc = self;
2002 | my $path = $!path;
2003 |
2004 | class :: does Iterator {
2005 | has $.index is rw = 0;
2006 |
2007 | method pull-one {
2008 | my $r;
2009 | if $path.num_data > $.index {
2010 | $r = $oc.get_data($.index);
2011 | $.index += $r.elems;
2012 | } else {
2013 | $r := IterationEnd;
2014 | }
2015 | $r;
2016 | }
2017 | }.new;
2018 | }
2019 |
2020 | method new (cairo_path_t $path) {
2021 | self.bless(:$path);
2022 | }
2023 |
2024 | method destroy {
2025 | $!path.destroy;
2026 | }
2027 | }
2028 |
2029 |
2030 | class Font {
2031 | sub cairo_ft_font_face_create_for_ft_face(Pointer $ft-face, int32 $flags)
2032 | returns cairo_font_face_t
2033 | is native($cairolib)
2034 | {*}
2035 |
2036 | sub cairo_ft_font_face_create_for_pattern(Pointer $fontconfig-patt)
2037 | returns cairo_font_face_t
2038 | is native($cairolib)
2039 | {*}
2040 |
2041 | has cairo_font_face_t $.face handles ;
2042 | multi method create($font-face, :free-type($)! where .so, Int :$flags = 0) {
2043 | return self.new(
2044 | face => cairo_ft_font_face_create_for_ft_face(
2045 | nativecast(Pointer, $font-face),
2046 | $flags )
2047 | )
2048 | }
2049 | multi method create($pattern, :fontconfig($)! where .so) {
2050 | return self.new(
2051 | face => cairo_ft_font_face_create_for_pattern(
2052 | nativecast(Pointer, $pattern),
2053 | )
2054 | )
2055 | }
2056 | }
2057 |
2058 | class ScaledFont {
2059 | sub cairo_scaled_font_create(cairo_font_face_t, cairo_matrix_t, cairo_matrix_t, cairo_font_options_t)
2060 | returns cairo_scaled_font_t
2061 | is native($cairolib)
2062 | {*}
2063 |
2064 | has cairo_scaled_font_t $.font handles ;
2065 | has Matrix:D $.ctm is required;
2066 | has Matrix:D $.scale is required;
2067 | multi method create(Font:D $font, Matrix:D $scale, Matrix:D $ctm, Cairo::FontOptions $opts = Cairo::FontOptions.new) {
2068 | return self.new(
2069 | :$ctm,
2070 | :$scale,
2071 | font => cairo_scaled_font_create(
2072 | $font.face,
2073 | $scale.matrix,
2074 | $ctm.matrix,
2075 | $opts.font_options,
2076 | )
2077 | )
2078 | }
2079 | }
2080 |
2081 | class FontOptions {
2082 |
2083 | sub font_options_create()
2084 | returns cairo_font_options_t
2085 | is native($cairolib)
2086 | is symbol('cairo_font_options_create')
2087 | {*}
2088 |
2089 | has cairo_font_options_t $.font_options handles ;
2090 |
2091 | submethod BUILD(:$!font_options) { }
2092 |
2093 | method Cairo::cairo_font_options_t {
2094 | $.font_options;
2095 | }
2096 |
2097 | multi method new {
2098 | my $font_options = font_options_create();
2099 | self.bless(:$font_options);
2100 | }
2101 | multi method new (cairo_font_options_t $font_options) {
2102 | self.bless(:$font_options);
2103 | }
2104 |
2105 | method status {
2106 | CairoStatus( $.font_options.status );
2107 | }
2108 |
2109 | method merge($other) {
2110 | $.font_options.merge($other);
2111 | }
2112 |
2113 | method equal(cairo_font_options_t $b) {
2114 | so $.font_options.equals($b);
2115 | }
2116 |
2117 | method antialias() is rw {
2118 | Proxy.new:
2119 | FETCH => { Antialias( $.font_options.get_antialias ) },
2120 | STORE => -> \c, \value { $.font_options.set_antialias(value.Int) }
2121 | }
2122 | method subpixel_order() is rw {
2123 | Proxy.new:
2124 | FETCH => { SubpixelOrder( $.font_options.get_subpixel_order ) },
2125 | STORE => -> \c, \value { $.font_options.set_subpixel_order(value.Int) }
2126 | }
2127 | method hint_style() is rw {
2128 | Proxy.new:
2129 | FETCH => { HintStyle( $.font_options.get_hint_style ) },
2130 | STORE => -> \c, \value { $.font_options.set_hint_style(value.Int) }
2131 | }
2132 | method hint_metrics() is rw {
2133 | Proxy.new:
2134 | FETCH => { HintMetrics( $.font_options.get_hint_metrics ) },
2135 | STORE => -> \c, \value { $.font_options.set_hint_metrics(value.Int) }
2136 | }
2137 |
2138 | }
2139 |
2140 | class Glyphs {
2141 | has UInt:D $.elems is required;
2142 | has cairo_glyph_t $!glyphs; # a contiguous array of $!elems glyphs
2143 | has Numeric ($.x-advance, $.y-advance) is rw;
2144 | constant RecSize = nativesizeof(cairo_glyph_t);
2145 | submethod TWEAK {
2146 | $!glyphs = cairo_glyph_t.allocate($!elems);
2147 | }
2148 | method glyphs { $!glyphs }
2149 | method AT-POS(Int:D $idx where 0 <= * < $!elems) {
2150 | my Pointer $base-addr := nativecast(Pointer, $!glyphs);
2151 | my Pointer $rec-addr := Pointer.new(+$base-addr + RecSize * $idx);
2152 | nativecast(cairo_glyph_t, $rec-addr);
2153 | }
2154 | submethod DESTROY {
2155 | $!glyphs.free;
2156 | }
2157 | }
2158 |
--------------------------------------------------------------------------------
/sparrow.yaml:
--------------------------------------------------------------------------------
1 | image:
2 | - melezhik/sparrow:debian_arm
3 | tasks:
4 | -
5 | name: zef-build
6 | language: Bash
7 | default: true
8 | code: |
9 | set -e
10 | cd source/
11 | zef install --deps-only --/test .
12 | zef test .
13 | depends:
14 | -
15 | name: deps
16 | -
17 | name: deps
18 | language: Bash
19 | code: |
20 | set -e
21 | sudo apt-get update
22 | sudo apt-get install -y libcairo2 libcairo2-dev
23 |
--------------------------------------------------------------------------------
/t/matrix.t:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 | use Test;
4 |
5 | plan 14;
6 |
7 | constant Matrix = Cairo::Matrix;
8 | constant matrix_t = Cairo::cairo_matrix_t;
9 |
10 | my $version = Cairo::version();
11 | diag "Running cairo version: $version (module {Cairo.^ver}, Raku {$*RAKU.compiler.version})";
12 |
13 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 128, 128) {
14 | given Cairo::Context.new($_) {
15 |
16 | my Matrix $identity-matrix .= new;
17 | is-deeply .matrix, Matrix.new.init(:xx(1e0), :yx(0e0), :xy(0e0), :yy(1e0), :x0(0e0), :y0(0e0)), 'identity';
18 |
19 | .translate(10,20);
20 | is-deeply .matrix, Matrix.new.init( :xx(1e0), :yy(1e0), :x0(10e0), :y0(20e0) ), 'translate';
21 | .save; {
22 | .scale(2, 3);
23 | is-deeply .matrix, Matrix.new.init( :xx(2e0), :yy(3e0), :x0(10e0), :y0(20e0) ), 'translate + scale';
24 |
25 | # http://zetcode.com/gfx/cairo/transformations/
26 | my Matrix $transform-matrix .= new.init( :xx(1), :yx(0.5),
27 | :xy(0), :yy(1),
28 | :x0(0), :y0(0) );
29 | .transform( $transform-matrix);
30 | is-deeply .matrix, Matrix.new.init( :xx(2e0), :yx(1.5e0), :yy(3e0), :x0(10e0), :y0(20e0) ), 'transform';
31 | };
32 | .restore;
33 |
34 | is-deeply .matrix, Matrix.new.init( :xx(1e0), :yy(1e0), :x0(10e0), :y0(20e0) ), 'save/restore';
35 |
36 | .identity_matrix;
37 | is-deeply .matrix, $identity-matrix, 'identity';
38 |
39 | my $prev-matrix = .matrix;
40 | .rotate(pi/2);
41 | my $rot-matrix = .matrix;
42 | is-deeply $prev-matrix, $identity-matrix, 'previous';
43 | is-approx $rot-matrix.yx, 1, 'rotated yx';
44 | is-approx $rot-matrix.xy, -1, 'rotated xy';
45 |
46 | my $matrix = Matrix.new.translate(10,20);
47 | is-deeply $matrix, Matrix.new.init( :xx(1e0), :yy(1e0), :x0(10e0), :y0(20e0) ), 'translate';
48 |
49 | $matrix.multiply: Matrix.new.scale(2,3);
50 | is-deeply $matrix, Matrix.new.init( :xx(2e0), :yy(3e0), :x0(20e0), :y0(60e0) ), 'multiply';
51 |
52 | $matrix.invert;
53 | is-approx $matrix.xx, 0.5, 'invert xx';
54 | is-approx $matrix.yy, 1/3, 'invert yy';
55 | is-approx $matrix.x0, -10, 'invert x0';
56 | };
57 | };
58 |
59 | done-testing;
60 |
--------------------------------------------------------------------------------
/t/pattern.t:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 | use Test;
4 |
5 | plan 7;
6 |
7 | {
8 | my $pattern-rgb = Cairo::Pattern::Solid.create(.7, .5, .3);
9 | isa-ok $pattern-rgb, Cairo::Pattern::Solid;
10 | }
11 |
12 | {
13 | my $pattern-rgba = Cairo::Pattern::Solid.create(.7, .5, .3, .5);
14 | isa-ok $pattern-rgba, Cairo::Pattern::Solid;
15 | }
16 |
17 | {
18 | my $image = Cairo::Image.create(Cairo::FORMAT_ARGB32, 128, 128);
19 | my $pattern = Cairo::Pattern::Surface.create($image.surface);
20 | isa-ok $pattern, Cairo::Pattern::Surface;
21 | }
22 |
23 | {
24 | my $pattern = Cairo::Pattern::Gradient::Linear.create(0,0,170,120);
25 | isa-ok $pattern, Cairo::Pattern::Gradient::Linear;
26 | lives-ok {$pattern.add_color_stop_rgb(0.5, .8, .1, .1);}, 'linear color stop';
27 | }
28 |
29 | {
30 | my $pattern = Cairo::Pattern::Gradient::Radial.create(75,50,5,90,60,100);
31 | isa-ok $pattern, Cairo::Pattern::Gradient::Radial;
32 | lives-ok {$pattern.add_color_stop_rgb(0.5, .8, .1, .1);}, 'radial color stop';
33 | }
34 |
35 | done-testing;
36 |
--------------------------------------------------------------------------------
/t/readme.t:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 | use Test;
4 |
5 | plan 1;
6 |
7 | lives-ok {
8 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 128, 128) {
9 | given Cairo::Context.new($_) {
10 | .rgb(0, 0.7, 0.9);
11 | .rectangle(10, 10, 50, 50);
12 | .fill :preserve; .rgb(1, 1, 1);
13 | .stroke
14 | };
15 | .write_png("foobar.png")
16 | }
17 | };
18 |
19 | unlink "foobar.png"; # don't care if failed
20 |
21 | done-testing;
22 |
--------------------------------------------------------------------------------
/t/surface-image.t:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 | use Test;
4 | plan 2;
5 |
6 | lives-ok {
7 | given Cairo::Image.new(:width(256), :height(256)) {
8 | given Cairo::Context.new($_) {
9 | .arc(128.0, 128.0, 76.8, 0, 2*pi);
10 | .clip;
11 | .new_path; # path not consumed by .clip
12 |
13 | my \image = Cairo::Image.new(:filename );
14 | my \w = image.width;
15 | my \h = image.height;
16 |
17 | .scale(256.0/w, 256.0/h);
18 |
19 | .set_source_surface(image, 0, 0);
20 | .paint;
21 |
22 | image.destroy;
23 | };
24 | .write_png("clip-image.png");
25 | }
26 | };
27 |
28 | ok "clip-image.png".IO.e, "png created from new";
29 |
30 | unlink "clip-image.png"; # don't care if failed
31 |
32 | done-testing;
33 |
--------------------------------------------------------------------------------
/t/surface-pdf.t:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 | use Test;
4 |
5 | plan 6;
6 |
7 | lives-ok {
8 | given Cairo::Surface::PDF.create("foobar.pdf", 128, 128) {
9 | is .width, 128, 'width';
10 | is .height, 128, 'height';
11 | given Cairo::Context.new($_) {
12 | .rgb(0, 0.7, 0.9);
13 | .rectangle(10, 10, 50, 50);
14 | .fill :preserve; .rgb(1, 1, 1);
15 | .stroke
16 | };
17 | .show_page;
18 | .finish;
19 | ok "foobar.pdf".IO.e, "pdf created";
20 | }
21 | };
22 |
23 | lives-ok {
24 | my Cairo::Surface::PDF $pdf .= new: :filename, :width(128), :height(64);
25 | $pdf.finish;
26 | }
27 | ok "foo2.pdf".IO.e, "pdf created from new";
28 |
29 | unlink "foobar.pdf"; # don't care if failed
30 | unlink "foo2.pdf"; # don't care if failed
31 |
32 | done-testing;
33 |
--------------------------------------------------------------------------------
/t/surface-svg.t:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 | use Test;
4 |
5 | plan 6;
6 |
7 | lives-ok {
8 | given Cairo::Surface::SVG.create("foobar.svg", 128, 128) {
9 | is .width, 128, 'width';
10 | is .height, 128, 'height';
11 | given Cairo::Context.new($_) {
12 | .rgb(0, 0.7, 0.9);
13 | .rectangle(10, 10, 50, 50);
14 | .fill :preserve; .rgb(1, 1, 1);
15 | .stroke
16 | };
17 | .finish;
18 | ok "foobar.svg".IO.e, "svg created";
19 | }
20 | };
21 |
22 | lives-ok {
23 | my Cairo::Surface::SVG $svg .= new: :filename, :width(128), :height(64);
24 | $svg.finish;
25 | }
26 | ok "foo2.svg".IO.e, "svg created from new";
27 |
28 | unlink "foobar.svg"; # don't care if failed
29 | unlink "foo2.svg"; # don't care if failed
30 |
31 | done-testing;
32 |
--------------------------------------------------------------------------------
/t/text.t:
--------------------------------------------------------------------------------
1 | use v6;
2 | use Cairo;
3 | use Test;
4 |
5 | plan 10;
6 |
7 | given Cairo::Image.create(Cairo::FORMAT_ARGB32, 128, 128) {
8 | given Cairo::Context.new($_) {
9 | lives-ok {
10 | .move_to(10, 10);
11 | .select_font_face("courier", Cairo::FontSlant::FONT_SLANT_ITALIC, Cairo::FontWeight::FONT_WEIGHT_BOLD);
12 | .set_font_size(10);
13 | .show_text("Hello World");
14 | }
15 | # issue #11 actual chosen font is system dependant
16 | my $font-extents = .font_extents;
17 | isa-ok $font-extents, Cairo::cairo_font_extents_t;
18 | ok 7 < $font-extents.ascent < 12, 'font extents ascent'
19 | or diag "got ascent: {$font-extents.ascent}";
20 |
21 | my $text-extents = .text_extents("Hello World");
22 | isa-ok $text-extents, Cairo::cairo_text_extents_t;
23 | ok 30 < $text-extents.width < 75, 'text extents width'
24 | or diag "got width: {$text-extents.width}";
25 | ok 5 < $text-extents.height < 9, 'text extents height'
26 | or diag "got height: {$text-extents.height}";
27 | };
28 | my Blob $data;
29 | my Cairo::Image $image;
30 | lives-ok {$data = .Blob}, '.Blob';
31 | ok $data.elems, 'data has length';
32 | lives-ok {$image = Cairo::Image.create($data, $data.elems)}, 'create image from data';
33 | is $image.width, 128, 'created image width';
34 | };
35 |
36 | done-testing;
37 |
--------------------------------------------------------------------------------