├── .gitignore ├── samples ├── sample_arc.png ├── sample_clip.png ├── sample_dash.png ├── sample_image.png ├── sample_text.png ├── data │ └── mulberry.png ├── sample_curve_to.png ├── sample_gradient.png ├── sample_record0.png ├── sample_record1.png ├── sample_script0.png ├── sample_set_dash.png ├── sample_clip_image.png ├── sample_copy_path.png ├── sample_fill_style.png ├── sample_image_copy.png ├── sample_operators.png ├── sample_pango_text.png ├── sample_alpha_paint.png ├── sample_arc_negative.png ├── sample_current_point.png ├── sample_imagepattern.png ├── sample_imagestream.png ├── sample_meshpattern.png ├── sample_set_line_cap.png ├── sample_set_line_join.png ├── sample_text_extents.png ├── sample_copy_path_flat.png ├── sample_curve_rectangle.png ├── sample_fill_and_stroke2.png ├── sample_multi_segment_caps.png ├── sample_rounded_rectangle.png ├── sample_text_align_center.png ├── sample_image.jl ├── sample_multi_segment_caps.jl ├── sample_clip.jl ├── sample_clip_image.jl ├── sample_curve_to.jl ├── sample_set_dash.jl ├── sample_pango_text1.jl ├── sample_dash.jl ├── sample_fill_and_stroke2.jl ├── sample_arc.jl ├── sample_arc_negative.jl ├── sample_image_copy.jl ├── sample_set_line_join.jl ├── sample_imagepattern.jl ├── sample_pango_text.jl ├── sample_text.jl ├── sample_gradient.jl ├── sample_record0.jl ├── sample_set_line_cap.jl ├── sample_fill_style.jl ├── sample_record1.jl ├── sample_text_extents.jl ├── sample_text_align_center.jl ├── sample_script0.jl ├── sample_rounded_rectangle.jl ├── sample_current_point.jl ├── sample_imagestream.jl ├── sample_alpha_paint.jl ├── sample_copy_path.jl ├── sample_copy_path_flat.jl ├── sample_meshpattern.jl ├── sample_operators.jl ├── sample_curve_rectangle.jl └── Samples.md ├── test ├── tex.jl ├── test_stream.jl ├── test_speed.jl ├── test_painting.jl ├── runtests.jl └── shape_functions.jl ├── .github └── workflows │ ├── TagBot.yml │ └── CompatHelper.yml ├── .drone.yml ├── README.md ├── .travis.yml ├── Project.toml ├── appveyor.yml ├── LICENSE.md └── src ├── constants.jl └── Cairo.jl /.gitignore: -------------------------------------------------------------------------------- 1 | test/test_results 2 | .DS_Store 3 | *~ 4 | .vscode 5 | -------------------------------------------------------------------------------- /samples/sample_arc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_arc.png -------------------------------------------------------------------------------- /samples/sample_clip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_clip.png -------------------------------------------------------------------------------- /samples/sample_dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_dash.png -------------------------------------------------------------------------------- /samples/sample_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_image.png -------------------------------------------------------------------------------- /samples/sample_text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_text.png -------------------------------------------------------------------------------- /samples/data/mulberry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/data/mulberry.png -------------------------------------------------------------------------------- /samples/sample_curve_to.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_curve_to.png -------------------------------------------------------------------------------- /samples/sample_gradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_gradient.png -------------------------------------------------------------------------------- /samples/sample_record0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_record0.png -------------------------------------------------------------------------------- /samples/sample_record1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_record1.png -------------------------------------------------------------------------------- /samples/sample_script0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_script0.png -------------------------------------------------------------------------------- /samples/sample_set_dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_set_dash.png -------------------------------------------------------------------------------- /samples/sample_clip_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_clip_image.png -------------------------------------------------------------------------------- /samples/sample_copy_path.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_copy_path.png -------------------------------------------------------------------------------- /samples/sample_fill_style.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_fill_style.png -------------------------------------------------------------------------------- /samples/sample_image_copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_image_copy.png -------------------------------------------------------------------------------- /samples/sample_operators.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_operators.png -------------------------------------------------------------------------------- /samples/sample_pango_text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_pango_text.png -------------------------------------------------------------------------------- /samples/sample_alpha_paint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_alpha_paint.png -------------------------------------------------------------------------------- /samples/sample_arc_negative.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_arc_negative.png -------------------------------------------------------------------------------- /samples/sample_current_point.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_current_point.png -------------------------------------------------------------------------------- /samples/sample_imagepattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_imagepattern.png -------------------------------------------------------------------------------- /samples/sample_imagestream.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_imagestream.png -------------------------------------------------------------------------------- /samples/sample_meshpattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_meshpattern.png -------------------------------------------------------------------------------- /samples/sample_set_line_cap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_set_line_cap.png -------------------------------------------------------------------------------- /samples/sample_set_line_join.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_set_line_join.png -------------------------------------------------------------------------------- /samples/sample_text_extents.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_text_extents.png -------------------------------------------------------------------------------- /samples/sample_copy_path_flat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_copy_path_flat.png -------------------------------------------------------------------------------- /samples/sample_curve_rectangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_curve_rectangle.png -------------------------------------------------------------------------------- /samples/sample_fill_and_stroke2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_fill_and_stroke2.png -------------------------------------------------------------------------------- /samples/sample_multi_segment_caps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_multi_segment_caps.png -------------------------------------------------------------------------------- /samples/sample_rounded_rectangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_rounded_rectangle.png -------------------------------------------------------------------------------- /samples/sample_text_align_center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wikunia/Cairo.jl/master/samples/sample_text_align_center.png -------------------------------------------------------------------------------- /test/tex.jl: -------------------------------------------------------------------------------- 1 | using Cairo: tex2pango 2 | using Test 3 | 4 | fsize = 1.618034 5 | @test tex2pango("ƒ_{Nyquist} [\\mu K]",fsize) == "ƒNyquist [μK]" 6 | -------------------------------------------------------------------------------- /.github/workflows/TagBot.yml: -------------------------------------------------------------------------------- 1 | name: TagBot 2 | on: 3 | schedule: 4 | - cron: 43 22 * * * 5 | jobs: 6 | TagBot: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: JuliaRegistries/TagBot@v1 10 | with: 11 | token: ${{ secrets.GITHUB_TOKEN }} 12 | -------------------------------------------------------------------------------- /.github/workflows/CompatHelper.yml: -------------------------------------------------------------------------------- 1 | name: CompatHelper 2 | 3 | on: 4 | schedule: 5 | - cron: '00 00 * * *' 6 | 7 | jobs: 8 | CompatHelper: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Pkg.add("CompatHelper") 12 | run: julia -e 'using Pkg; Pkg.add("CompatHelper")' 13 | - name: CompatHelper.main() 14 | env: 15 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 16 | run: julia -e 'using CompatHelper; CompatHelper.main()' 17 | -------------------------------------------------------------------------------- /.drone.yml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: pipeline 3 | name: linux - arm - Julia 1.3 4 | 5 | platform: 6 | os: linux 7 | arch: arm 8 | 9 | steps: 10 | - name: build 11 | image: julia:1.3 12 | commands: 13 | - "julia --project=. --check-bounds=yes --color=yes -e 'using InteractiveUtils; versioninfo(verbose=true); using Pkg; Pkg.build(); Pkg.test(coverage=true)'" 14 | 15 | --- 16 | kind: pipeline 17 | name: linux - arm64 - Julia 1.3 18 | 19 | platform: 20 | os: linux 21 | arch: arm64 22 | 23 | steps: 24 | - name: build 25 | image: julia:1.3 26 | commands: 27 | - "julia --project=. --check-bounds=yes --color=yes -e 'using InteractiveUtils; versioninfo(verbose=true); using Pkg; Pkg.build(); Pkg.test(coverage=true)'" 28 | 29 | ... 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/JuliaGraphics/Cairo.jl.svg)](https://travis-ci.org/JuliaGraphics/Cairo.jl) 2 | [![Build status](https://ci.appveyor.com/api/projects/status/l3ega4q8o49edcn1?svg=true)](https://ci.appveyor.com/project/lobingera/cairo-jl-f7sfx) 3 | [![Coverage Status](https://coveralls.io/repos/JuliaGraphics/Cairo.jl/badge.svg?branch=master&service=github)](https://coveralls.io/github/JuliaGraphics/Cairo.jl?branch=master) 4 | 5 | ## Bindings to the Cairo graphics library ## 6 | 7 | Adaptation to [Cairo](https://www.cairographics.org/), a 2D graphics library with support for multiple output devices. 8 | 9 | Some of the functions implemented by this wrapper may be documented in [Graphics.jl](https://juliagraphics.github.io/Graphics.jl/stable/). 10 | 11 | There is an extensive set of [examples](samples/Samples.md). 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | ## Documentation: http://docs.travis-ci.com/user/languages/julia/ 2 | language: julia 3 | os: 4 | - linux 5 | - freebsd 6 | - osx 7 | julia: 8 | - 1.3 9 | - nightly 10 | notifications: 11 | email: false 12 | git: 13 | depth: 99999999 14 | 15 | ## uncomment the following lines to allow failures on nightly julia 16 | ## (tests will run but not make your overall status red) 17 | matrix: 18 | allow_failures: 19 | - julia: nightly 20 | 21 | branches: 22 | only: 23 | - master 24 | - gh-pages # For building documentation 25 | - /^testing-.*$/ # testing branches 26 | - /^v[0-9]+\.[0-9]+\.[0-9]+$/ # version tags 27 | 28 | cache: 29 | directories: 30 | - $HOME/.julia/artifacts 31 | 32 | after_success: 33 | - julia -e 'using Pkg; Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder()); Coveralls.submit(Coveralls.process_folder())' 34 | -------------------------------------------------------------------------------- /samples/sample_image.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | ## original example, following here 14 | 15 | image = read_from_png("data/mulberry.png"); 16 | w = image.width; 17 | h = image.height; 18 | 19 | translate(cr, 128.0, 128.0); 20 | rotate(cr, 45* pi/180); 21 | scale(cr, 256.0/w, 256.0/h); 22 | translate(cr, -0.5*w, -0.5*h); 23 | 24 | set_source_surface(cr, image, 0, 0); 25 | paint(cr); 26 | #surface_destroy (image); 27 | 28 | ## mark picture with current date 29 | restore(cr); 30 | move_to(cr,0.0,12.0); 31 | set_source_rgb(cr, 0,0,0); 32 | show_text(cr,Libc.strftime(time())); 33 | write_to_png(c,"sample_image.png"); 34 | -------------------------------------------------------------------------------- /samples/sample_multi_segment_caps.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | ## original example, following here 14 | 15 | move_to(cr, 50.0, 75.0); 16 | line_to(cr, 200.0, 75.0); 17 | 18 | move_to(cr, 50.0, 125.0); 19 | line_to(cr, 200.0, 125.0); 20 | 21 | move_to(cr, 50.0, 175.0); 22 | line_to(cr, 200.0, 175.0); 23 | 24 | set_line_width(cr, 30.0); 25 | set_line_cap(cr, Cairo.CAIRO_LINE_CAP_ROUND); 26 | stroke(cr); 27 | 28 | ## mark picture with current date 29 | restore(cr); 30 | move_to(cr,0.0,12.0); 31 | set_source_rgb(cr, 0,0,0); 32 | show_text(cr,Libc.strftime(time())); 33 | write_to_png(c,"sample_multi_segment_caps.png"); 34 | -------------------------------------------------------------------------------- /Project.toml: -------------------------------------------------------------------------------- 1 | name = "Cairo" 2 | uuid = "159f3aea-2a34-519c-b102-8c37f9878175" 3 | version = "1.0.4" 4 | 5 | [deps] 6 | Cairo_jll = "83423d85-b0ee-5818-9007-b63ccbeb887a" 7 | Colors = "5ae59095-9a9b-59fe-a467-6f913c188581" 8 | Glib_jll = "7746bdde-850d-59dc-9ae8-88ece973131d" 9 | Graphics = "a2bd30eb-e257-5431-a919-1863eab51364" 10 | Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" 11 | Pango_jll = "36c8627f-9965-5494-a995-c6b170f724f3" 12 | 13 | [compat] 14 | julia = "1.3" 15 | Cairo_jll = "1.16.0" 16 | Colors = "0.9, 0.10, 0.11, 0.12" 17 | Glib_jll = "2.59.0" 18 | Graphics = "0.4, 1" 19 | Pango_jll = "1.42.4" 20 | 21 | [extras] 22 | Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" 23 | Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" 24 | Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" 25 | Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" 26 | 27 | [targets] 28 | test = ["Base64", "Random", "Printf", "Test"] 29 | -------------------------------------------------------------------------------- /test/test_stream.jl: -------------------------------------------------------------------------------- 1 | # So that this test can be run independently 2 | using Cairo 3 | using Base64 4 | 5 | include("shape_functions.jl") 6 | 7 | @testset "Test that writing images to a Julia IO object works" begin 8 | c = CairoRGBSurface(256,256) 9 | cr = CairoContext(c) 10 | ddots4(cr,256,246,1.0,3000) 11 | buf = IOBuffer() 12 | pipe = Base64EncodePipe(buf) 13 | write_to_png(c,pipe) 14 | close(pipe) 15 | 16 | # Catch short writes 17 | 18 | str = String(take!(buf)) 19 | str_data = codeunits(str) 20 | 21 | @test length(str_data) > 200 22 | end 23 | 24 | @testset "Test that writing images to a temp file works" begin 25 | c = CairoRGBSurface(256,256) 26 | cr = CairoContext(c) 27 | ddots4(cr,256,246,1.0,3000) 28 | fn = tempname()*".png" 29 | @test write_to_png(c,fn) == Cairo.STATUS_SUCCESS 30 | @test isfile(fn) 31 | rm(fn) # clean up 32 | end 33 | -------------------------------------------------------------------------------- /samples/sample_clip.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | ## original example, following here 14 | 15 | arc(cr, 128.0, 128.0, 76.8, 0, 2 * pi); 16 | clip(cr); 17 | 18 | new_path(cr); # current path is not consumed by cairo_clip() 19 | rectangle(cr, 0, 0, 256, 256); 20 | fill(cr); 21 | set_source_rgb(cr, 0, 1, 0); 22 | move_to(cr, 0, 0); 23 | line_to(cr, 256, 256); 24 | move_to(cr, 256, 0); 25 | line_to(cr, 0, 256); 26 | set_line_width(cr, 10.0); 27 | stroke(cr); 28 | 29 | ## mark picture with current date 30 | restore(cr); 31 | move_to(cr,0.0,12.0); 32 | set_source_rgb(cr, 0,0,0); 33 | show_text(cr,Libc.strftime(time())); 34 | write_to_png(c,"sample_clip.png"); 35 | -------------------------------------------------------------------------------- /samples/sample_clip_image.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | 14 | ## original example, following here 15 | 16 | arc(cr, 128.0, 128.0, 76.8, 0, 2*pi); 17 | clip(cr); 18 | new_path(cr); # path not consumed by clip 19 | 20 | image = read_from_png("data/mulberry.png"); # should be create_from_png 21 | w = image.width; 22 | h = image.height; 23 | 24 | scale(cr, 256.0/w, 256.0/h); 25 | 26 | set_source_surface(cr, image, 0, 0); 27 | paint(cr); 28 | 29 | #cairo_surface_destroy not used here 30 | 31 | ## mark picture with current date 32 | restore(cr); 33 | move_to(cr,0.0,12.0); 34 | set_source_rgb(cr, 0,0,0); 35 | show_text(cr,Libc.strftime(time())); 36 | write_to_png(c,"sample_clip_image.png"); 37 | -------------------------------------------------------------------------------- /samples/sample_curve_to.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | 14 | ## original example, following here 15 | 16 | x=25.6; y=128.0; 17 | x1=102.4; y1=230.4; 18 | x2=153.6; y2=25.6; 19 | x3=230.4; y3=128.0; 20 | 21 | move_to(cr, x, y); 22 | curve_to(cr, x1, y1, x2, y2, x3, y3); 23 | 24 | set_line_width(cr, 10.0); 25 | stroke(cr); 26 | 27 | set_source_rgba(cr, 1, 0.2, 0.2, 0.6); 28 | set_line_width(cr, 6.0); 29 | move_to(cr,x,y); line_to(cr,x1,y1); 30 | move_to(cr,x2,y2); line_to(cr,x3,y3); 31 | stroke(cr); 32 | 33 | ## mark picture with current date 34 | restore(cr); 35 | move_to(cr,0.0,12.0); 36 | set_source_rgb(cr, 0,0,0); 37 | show_text(cr,Libc.strftime(time())); 38 | write_to_png(c,"sample_curve_to.png"); 39 | -------------------------------------------------------------------------------- /samples/sample_set_dash.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | 14 | ## api example, use set_line_type 15 | 16 | dashes_by_name = [ 17 | "solid", 18 | "dot", 19 | "dotdashed", 20 | "longdashed", 21 | "dash", 22 | "dotdotdashed", 23 | "dotdotdotdashed"] 24 | 25 | set_line_width(cr, 3.0); 26 | 27 | for k=1:7 28 | save(cr) 29 | set_line_type(cr, dashes_by_name[k]) 30 | move_to(cr,16.0,16.0+(k*32.0)) 31 | line_to(cr,240.0,16.0+(k*32.0)) 32 | stroke(cr) 33 | restore(cr) 34 | end 35 | 36 | ## mark picture with current date 37 | restore(cr); 38 | move_to(cr,0.0,12.0); 39 | set_source_rgb(cr, 0,0,0); 40 | show_text(cr,Libc.strftime(time())); 41 | write_to_png(c,"sample_set_dash.png"); 42 | -------------------------------------------------------------------------------- /samples/sample_pango_text1.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | using Printf 4 | 5 | c = CairoRGBSurface(256,256); 6 | cr = CairoContext(c); 7 | 8 | save(cr); 9 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 10 | rectangle(cr,0.0,0.0,256.0,256.0); # background 11 | fill(cr); 12 | restore(cr); 13 | 14 | save(cr); 15 | 16 | set_font_face(cr, "Sans 16") 17 | 18 | text(cr,40.0,40.0,"EF",markup=true) 19 | text(cr,40.0,60.0,"EGDC") 20 | 21 | text(cr,40.0,90.0,"EFGH",markup=true) 22 | text(cr,40.0,110.0,"EGDC",markup=true) 23 | 24 | text(cr,40.0,140.0,"GEFJ",markup=true) 25 | text(cr,40.0,160.0,"EGDC") 26 | 27 | 28 | ## mark picture with current date 29 | restore(cr); 30 | move_to(cr,0.0,12.0); 31 | set_source_rgb(cr, 0,0,0); 32 | show_text(cr,Libc.strftime(time())); 33 | write_to_png(c,"sample_pango_text1.png"); 34 | -------------------------------------------------------------------------------- /samples/sample_dash.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | ## original example, following here 14 | 15 | dashes = [50.0, # ink 16 | 10.0, # skip 17 | 10.0, # ink 18 | 10.0 # skip 19 | ]; 20 | #ndash = length(dashes); not implemented as ndash on set_dash 21 | offset = -50.0; 22 | 23 | set_dash(cr, dashes, offset); 24 | set_line_width(cr, 10.0); 25 | 26 | move_to(cr, 128.0, 25.6); 27 | line_to(cr, 230.4, 230.4); 28 | rel_line_to(cr, -102.4, 0.0); 29 | curve_to(cr, 51.2, 230.4, 51.2, 128.0, 128.0, 128.0); 30 | 31 | stroke(cr); 32 | 33 | 34 | ## mark picture with current date 35 | restore(cr); 36 | move_to(cr,0.0,12.0); 37 | set_source_rgb(cr, 0,0,0); 38 | show_text(cr,Libc.strftime(time())); 39 | write_to_png(c,"sample_dash.png"); 40 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - julia_version: 1.3 4 | - julia_version: nightly 5 | 6 | platform: 7 | - x86 # 32-bit 8 | - x64 # 64-bit 9 | 10 | ## uncomment the following lines to allow failures on nightly julia 11 | ## (tests will run but not make your overall status red) 12 | matrix: 13 | allow_failures: 14 | - platform: x86 15 | - julia_version: latest 16 | 17 | branches: 18 | only: 19 | - master 20 | - /release-.*/ 21 | 22 | cache: 23 | - '%USERPROFILE%\.julia\artifacts' 24 | 25 | notifications: 26 | - provider: Email 27 | on_build_success: false 28 | on_build_failure: false 29 | on_build_status_changed: false 30 | 31 | install: 32 | - ps: iex ((new-object net.webclient).DownloadString("https://raw.githubusercontent.com/JuliaCI/Appveyor.jl/version-1/bin/install.ps1")) 33 | 34 | build_script: 35 | - echo "%JL_BUILD_SCRIPT%" 36 | - C:\julia\bin\julia -e "%JL_BUILD_SCRIPT%" 37 | 38 | test_script: 39 | - echo "%JL_TEST_SCRIPT%" 40 | - C:\julia\bin\julia -e "%JL_TEST_SCRIPT%" 41 | -------------------------------------------------------------------------------- /samples/sample_fill_and_stroke2.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | ## original example, following here 14 | move_to(cr, 128.0, 25.6); 15 | line_to(cr, 230.4, 230.4); 16 | rel_line_to(cr, -102.4, 0.0); 17 | curve_to(cr, 51.2, 230.4, 51.2, 128.0, 128.0, 128.0); 18 | close_path(cr); 19 | 20 | move_to(cr, 64.0, 25.6); 21 | rel_line_to(cr, 51.2, 51.2); 22 | rel_line_to(cr, -51.2, 51.2); 23 | rel_line_to(cr, -51.2, -51.2); 24 | close_path(cr); 25 | 26 | set_line_width(cr, 10.0); 27 | set_source_rgb(cr, 0, 0, 1); 28 | fill_preserve(cr); 29 | set_source_rgb(cr, 0, 0, 0); 30 | stroke(cr); 31 | 32 | ## mark picture with current date 33 | restore(cr); 34 | move_to(cr,0.0,12.0); 35 | set_source_rgb(cr, 0,0,0); 36 | show_text(cr,Libc.strftime(time())); 37 | write_to_png(c,"sample_fill_and_stroke2.png"); 38 | -------------------------------------------------------------------------------- /samples/sample_arc.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | 4 | c = CairoRGBSurface(256,256); 5 | cr = CairoContext(c); 6 | 7 | save(cr); 8 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 9 | rectangle(cr,0.0,0.0,256.0,256.0); # background 10 | fill(cr); 11 | restore(cr); 12 | 13 | ## original example, following here 14 | xc = 128.0; 15 | yc = 128.0; 16 | radius = 100.0; 17 | angle1 = 45.0 * (pi/180.0); # angles are specified 18 | angle2 = 180.0 * (pi/180.0); # in radians 19 | 20 | set_line_width(cr, 10.0); 21 | arc(cr, xc, yc, radius, angle1, angle2); 22 | stroke(cr); 23 | 24 | # draw helping lines 25 | set_source_rgba(cr, 1, 0.2, 0.2, 0.6); 26 | set_line_width(cr, 6.0); 27 | 28 | arc(cr, xc, yc, 10.0, 0, 2*pi); 29 | fill(cr); 30 | 31 | arc(cr, xc, yc, radius, angle1, angle1); 32 | line_to(cr, xc, yc); 33 | arc(cr, xc, yc, radius, angle2, angle2); 34 | line_to(cr, xc, yc); 35 | stroke(cr); 36 | 37 | ## mark picture with current date 38 | move_to(cr,0.0,12.0); 39 | set_source_rgb(cr, 0,0,0); 40 | show_text(cr,Libc.strftime(time())); 41 | write_to_png(c,"sample_arc.png"); 42 | -------------------------------------------------------------------------------- /samples/sample_arc_negative.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | ## original example, following here 13 | xc = 128.0; 14 | yc = 128.0; 15 | radius = 100.0; 16 | angle1 = 45.0 * (pi/180.0); # angles are specified 17 | angle2 = 180.0 * (pi/180.0); # in radians 18 | 19 | set_line_width(cr, 10.0); 20 | arc_negative(cr, xc, yc, radius, angle1, angle2); 21 | stroke(cr); 22 | 23 | # draw helping lines 24 | set_source_rgba(cr, 1, 0.2, 0.2, 0.6); 25 | set_line_width(cr, 6.0); 26 | 27 | arc(cr, xc, yc, 10.0, 0, 2*pi); 28 | fill(cr); 29 | 30 | arc(cr, xc, yc, radius, angle1, angle1); 31 | line_to(cr, xc, yc); 32 | arc(cr, xc, yc, radius, angle2, angle2); 33 | line_to(cr, xc, yc); 34 | stroke(cr); 35 | 36 | ## mark picture with current date 37 | move_to(cr,0.0,12.0); 38 | set_source_rgb(cr, 0,0,0); 39 | show_text(cr,Libc.strftime(time())); 40 | write_to_png(c,"sample_arc_negative.png"); 41 | -------------------------------------------------------------------------------- /samples/sample_image_copy.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | using Graphics 4 | 5 | c = CairoRGBSurface(256,256); 6 | cr = CairoContext(c); 7 | 8 | save(cr); 9 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 10 | rectangle(cr,0.0,0.0,256.0,256.0); # background 11 | fill(cr); 12 | restore(cr); 13 | 14 | save(cr); 15 | 16 | # put image top left 17 | s = read_from_png("data/mulberry.png"); 18 | Cairo.image(cr,s,0,0,128,128) 19 | 20 | # copy inplace, so to apply copy as source, need coordinate translate 21 | c1 = copy(cr) 22 | 23 | save(cr) 24 | translate(cr,128,0) 25 | rectangle(cr,0,0,256,256) 26 | set_source_surface(cr,c1.surface) 27 | paint(cr) 28 | restore(cr) 29 | 30 | # copy centered part 31 | c2 = copy(cr,Graphics.BoundingBox(64,192,0,128)) 32 | 33 | save(cr) 34 | 35 | rectangle(cr,0,0,256,256) 36 | set_source_surface(cr,c2.surface,64,128) 37 | paint(cr) 38 | restore(cr) 39 | 40 | ## mark picture with current date 41 | restore(cr); 42 | move_to(cr,0.0,12.0); 43 | set_source_rgb(cr, 0,0,0); 44 | show_text(cr,Libc.strftime(time())); 45 | write_to_png(c,"sample_image_copy.png"); 46 | -------------------------------------------------------------------------------- /samples/sample_set_line_join.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | ## original example, following here 14 | set_line_width(cr, 40.96); 15 | move_to(cr, 76.8, 84.48); 16 | rel_line_to(cr, 51.2, -51.2); 17 | rel_line_to(cr, 51.2, 51.2); 18 | set_line_join(cr, Cairo.CAIRO_LINE_JOIN_MITER); # default 19 | stroke(cr); 20 | 21 | move_to(cr, 76.8, 161.28); 22 | rel_line_to(cr, 51.2, -51.2); 23 | rel_line_to(cr, 51.2, 51.2); 24 | set_line_join(cr, Cairo.CAIRO_LINE_JOIN_BEVEL); 25 | stroke(cr); 26 | 27 | move_to(cr, 76.8, 238.08); 28 | rel_line_to(cr, 51.2, -51.2); 29 | rel_line_to(cr, 51.2, 51.2); 30 | set_line_join(cr, Cairo.CAIRO_LINE_JOIN_ROUND); 31 | stroke(cr); 32 | 33 | ## mark picture with current date 34 | restore(cr); 35 | move_to(cr,0.0,12.0); 36 | set_source_rgb(cr, 0,0,0); 37 | show_text(cr,Libc.strftime(time())); 38 | write_to_png(c,"sample_set_line_join.png"); 39 | -------------------------------------------------------------------------------- /samples/sample_imagepattern.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | ## original example, following here 14 | image = read_from_png("data/mulberry.png"); 15 | w = image.width; 16 | h = image.height; 17 | 18 | pattern = CairoPattern(image); 19 | pattern_set_extend(pattern, Cairo.EXTEND_REPEAT); 20 | 21 | translate(cr, 128.0, 128.0); 22 | rotate(cr, pi / 4); 23 | scale(cr, 1 / sqrt(2), 1 / sqrt(2)); 24 | translate(cr, -128.0, -128.0); 25 | 26 | m = CairoMatrix(w/256.0 * 5.0,0,0,h/256.0 * 5.0,0,0); 27 | #matrix_init_scale (&matrix, w/256.0 * 5.0, h/256.0 * 5.0); 28 | 29 | set_matrix(pattern, m); 30 | set_source(cr, pattern); 31 | 32 | rectangle(cr, 0, 0, 256.0, 256.0); 33 | fill(cr); 34 | 35 | ## mark picture with current date 36 | restore(cr); 37 | move_to(cr,0.0,12.0); 38 | set_source_rgb(cr, 0,0,0); 39 | show_text(cr,Libc.strftime(time())); 40 | write_to_png(c,"sample_imagepattern.png"); 41 | -------------------------------------------------------------------------------- /samples/sample_pango_text.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | using Printf 4 | 5 | c = CairoRGBSurface(256,256); 6 | cr = CairoContext(c); 7 | 8 | save(cr); 9 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 10 | rectangle(cr,0.0,0.0,256.0,256.0); # background 11 | fill(cr); 12 | restore(cr); 13 | 14 | save(cr); 15 | 16 | set_font_face(cr, "Sans 16") 17 | 18 | text(cr,16.0,40.0,"Hamburgefons") 19 | text(cr,16.0,72.0,"sp⁰¹²³,min⁻²,αΑβΒφϕΦγΓ") 20 | text(cr,16.0,104.0,"TextBoldItalicsuper-2",markup=true) 21 | 22 | text(cr,40.0,224.0,"Es geht aufwärts !",markup=true,angle=30.0) 23 | 24 | #using textwidth and height 25 | 26 | set_font_face(cr, "Sans 12") 27 | 28 | a = "A" 29 | aheight = textheight(cr,a) 30 | awidth = textwidth(cr,a) 31 | atext = @sprintf("%s wd=%2.2f,ht=%2.2f",a,awidth,aheight) 32 | text(cr,16.0,240.0,atext,markup=true) 33 | 34 | 35 | ## mark picture with current date 36 | restore(cr); 37 | move_to(cr,0.0,12.0); 38 | set_source_rgb(cr, 0,0,0); 39 | show_text(cr,Libc.strftime(time())); 40 | write_to_png(c,"sample_pango_text.png"); 41 | -------------------------------------------------------------------------------- /samples/sample_text.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | ## original example, following here 14 | 15 | select_font_face(cr, "Sans", Cairo.FONT_SLANT_NORMAL, 16 | Cairo.FONT_WEIGHT_BOLD); 17 | set_font_size(cr, 90.0); 18 | 19 | move_to(cr, 10.0, 135.0); 20 | show_text(cr, "Hello"); 21 | 22 | move_to(cr, 70.0, 165.0); 23 | text_path(cr, "void"); 24 | set_source_rgb(cr, 0.5, 0.5, 1); 25 | fill_preserve(cr); 26 | set_source_rgb(cr, 0, 0, 0); 27 | set_line_width(cr, 2.56); 28 | stroke(cr); 29 | 30 | # draw helping lines 31 | set_source_rgba(cr, 1, 0.2, 0.2, 0.6); 32 | arc(cr, 10.0, 135.0, 5.12, 0, 2*pi); 33 | close_path(cr); 34 | arc(cr, 70.0, 165.0, 5.12, 0, 2*pi); 35 | fill(cr); 36 | 37 | 38 | ## mark picture with current date 39 | restore(cr); 40 | move_to(cr,0.0,12.0); 41 | set_source_rgb(cr, 0,0,0); 42 | show_text(cr,Libc.strftime(time())); 43 | write_to_png(c,"sample_text.png"); 44 | -------------------------------------------------------------------------------- /samples/sample_gradient.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | 14 | ## original example, following here 15 | 16 | pat = pattern_create_linear(0.0, 0.0, 0.0, 256.0); 17 | pattern_add_color_stop_rgb(pat, 1, 0, 0, 0); # alpha=1 18 | pattern_add_color_stop_rgb(pat, 0, 1, 1, 1); 19 | rectangle(cr, 0, 0, 256, 256); 20 | set_source(cr, pat); 21 | fill(cr); 22 | destroy(pat); 23 | 24 | pat = pattern_create_radial(115.2, 102.4, 25.6, 25 | 102.4, 102.4, 128.0); 26 | pattern_add_color_stop_rgba(pat, 0, 1, 1, 1, 1); # explicit alpha=1 27 | pattern_add_color_stop_rgba(pat, 1, 0, 0, 0, 1); 28 | set_source(cr, pat); 29 | arc(cr, 128.0, 128.0, 76.8, 0, 2 * pi); 30 | fill(cr); 31 | destroy(pat); 32 | 33 | ## mark picture with current date 34 | restore(cr); 35 | move_to(cr,0.0,12.0); 36 | set_source_rgb(cr, 0,0,0); 37 | show_text(cr,Libc.strftime(time())); 38 | write_to_png(c,"sample_gradient.png"); 39 | -------------------------------------------------------------------------------- /samples/sample_record0.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoARGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgba(cr,0.0,0.0,0.0,0.0); # transparent black 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | save(cr); 12 | 13 | s1 = CairoRecordingSurface() 14 | c1 = CairoContext(s1) 15 | 16 | ## original example, following here 17 | move_to(c1, 128.0, 25.6); 18 | line_to(c1, 230.4, 230.4); 19 | rel_line_to(c1, -102.4, 0.0); 20 | curve_to(c1, 51.2, 230.4, 51.2, 128.0, 128.0, 128.0); 21 | close_path(c1); 22 | 23 | move_to(c1, 64.0, 25.6); 24 | rel_line_to(c1, 51.2, 51.2); 25 | rel_line_to(c1, -51.2, 51.2); 26 | rel_line_to(c1, -51.2, -51.2); 27 | close_path(c1); 28 | 29 | set_line_width(c1, 10.0); 30 | set_source_rgb(c1, 0, 0, 1); 31 | fill_preserve(c1); 32 | set_source_rgb(c1, 0, 0, 0); 33 | stroke(c1); 34 | 35 | ## now using the recorded painting 36 | set_source(cr, s1, 0.0, 0.0) 37 | paint(cr) 38 | 39 | 40 | ## mark picture with current date 41 | restore(cr); 42 | move_to(cr,0.0,12.0); 43 | set_source_rgb(cr, 0,0,0); 44 | show_text(cr,Libc.strftime(time())); 45 | write_to_png(c,"sample_record0.png"); 46 | -------------------------------------------------------------------------------- /samples/sample_set_line_cap.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | ## original example, following here 14 | set_line_width(cr, 30.0); 15 | set_line_cap(cr, Cairo.CAIRO_LINE_CAP_BUTT); # default 16 | move_to(cr, 64.0, 50.0); line_to(cr, 64.0, 200.0); 17 | stroke(cr); 18 | set_line_cap(cr, Cairo.CAIRO_LINE_CAP_ROUND); 19 | move_to(cr, 128.0, 50.0); line_to(cr, 128.0, 200.0); 20 | stroke(cr); 21 | set_line_cap(cr, Cairo.CAIRO_LINE_CAP_SQUARE); 22 | move_to(cr, 192.0, 50.0); line_to(cr, 192.0, 200.0); 23 | stroke(cr); 24 | 25 | # draw helping lines 26 | set_source_rgb(cr, 1, 0.2, 0.2); 27 | set_line_width(cr, 2.56); 28 | move_to(cr, 64.0, 50.0); line_to(cr, 64.0, 200.0); 29 | move_to(cr, 128.0, 50.0); line_to(cr, 128.0, 200.0); 30 | move_to(cr, 192.0, 50.0); line_to(cr, 192.0, 200.0); 31 | stroke(cr); 32 | 33 | ## mark picture with current date 34 | restore(cr); 35 | move_to(cr,0.0,12.0); 36 | set_source_rgb(cr, 0,0,0); 37 | show_text(cr,Libc.strftime(time())); 38 | write_to_png(c,"sample_set_line_cap.png"); 39 | -------------------------------------------------------------------------------- /samples/sample_fill_style.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | ## original example, following here 14 | set_line_width(cr, 6); 15 | 16 | rectangle(cr, 12, 12, 232, 70); 17 | new_sub_path(cr); arc(cr, 64, 64, 40, 0, 2*pi); 18 | new_sub_path(cr); arc_negative(cr, 192, 64, 40, 0, -2*pi); 19 | 20 | set_fill_type(cr, Cairo.CAIRO_FILL_RULE_EVEN_ODD); # should be set_fill_rule 21 | set_source_rgb(cr, 0, 0.7, 0); fill_preserve(cr); 22 | set_source_rgb(cr, 0, 0, 0); stroke(cr); 23 | 24 | translate(cr, 0, 128); 25 | rectangle(cr, 12, 12, 232, 70); 26 | new_sub_path(cr); arc(cr, 64, 64, 40, 0, 2*pi); 27 | new_sub_path(cr); arc_negative(cr, 192, 64, 40, 0, -2*pi); 28 | 29 | set_fill_type(cr, Cairo.CAIRO_FILL_RULE_WINDING); 30 | set_source_rgb(cr, 0, 0, 0.9); fill_preserve(cr); 31 | set_source_rgb(cr, 0, 0, 0); stroke(cr); 32 | 33 | ## mark picture with current date 34 | restore(cr); 35 | move_to(cr,0.0,12.0); 36 | set_source_rgb(cr, 0,0,0); 37 | show_text(cr,Libc.strftime(time())); 38 | write_to_png(c,"sample_fill_style.png"); 39 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Cairo.jl is licensed under the MIT License: 2 | 3 | > Copyright (c) 2012-2013: Jeff Bezanson, Keno Fischer, Tim Holy, Mike 4 | > Nolta, Viral Shah, and other contributors.> 5 | 6 | > Permission is hereby granted, free of charge, to any person obtaining 7 | > a copy of this software and associated documentation files (the 8 | > "Software"), to deal in the Software without restriction, including 9 | > without limitation the rights to use, copy, modify, merge, publish, 10 | > distribute, sublicense, and/or sell copies of the Software, and to 11 | > permit persons to whom the Software is furnished to do so, subject to 12 | > the following conditions: 13 | > 14 | > The above copyright notice and this permission notice shall be 15 | > included in all copies or substantial portions of the Software. 16 | > 17 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | > EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | > MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | > NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 | > LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 | > OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | > WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /samples/sample_record1.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoARGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgba(cr,0.0,0.0,0.0,0.0); # transparent black 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | save(cr); 12 | 13 | ## paint the following to a Recording Surface 14 | s1 = CairoRecordingSurface() 15 | c1 = CairoContext(s1) 16 | 17 | move_to(c1, 128.0, 25.6); 18 | line_to(c1, 230.4, 230.4); 19 | rel_line_to(c1, -102.4, 0.0); 20 | curve_to(c1, 51.2, 230.4, 51.2, 128.0, 128.0, 128.0); 21 | close_path(c1); 22 | 23 | move_to(c1, 64.0, 25.6); 24 | rel_line_to(c1, 51.2, 51.2); 25 | rel_line_to(c1, -51.2, 51.2); 26 | rel_line_to(c1, -51.2, -51.2); 27 | close_path(c1); 28 | 29 | set_line_width(c1, 10.0); 30 | set_source_rgb(c1, 0, 0, 1); 31 | fill_preserve(c1); 32 | set_source_rgb(c1, 0, 0, 0); 33 | stroke(c1); 34 | 35 | ## play back on transform coord 36 | scale(cr,0.5,0.5) 37 | set_source(cr, s1, 128.0, 128.0) 38 | 39 | paint(cr) 40 | 41 | 42 | ## mark picture with current date 43 | restore(cr); 44 | move_to(cr,0.0,12.0); 45 | set_source_rgb(cr, 0,0,0); 46 | show_text(cr,Libc.strftime(time())); 47 | write_to_png(c,"sample_record1.png"); 48 | 49 | ## write to script 50 | #s2 = Cairo.CairoScript("cairo-record1.cs") 51 | #Cairo.script_from_recording_surface(s2,s1) 52 | -------------------------------------------------------------------------------- /samples/sample_text_extents.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | ## original example, following here 14 | select_font_face(cr, "Sans", Cairo.FONT_SLANT_NORMAL, 15 | Cairo.FONT_WEIGHT_NORMAL); 16 | set_font_size(cr, 100.0); 17 | extents = text_extents(cr, "cairo"); 18 | 19 | # 20 | # typedef struct { 21 | # double x_bearing; 22 | # double y_bearing; 23 | # double width; 24 | # double height; 25 | # double x_advance; 26 | # double y_advance; 27 | # } cairo_text_extents_t; 28 | 29 | x = 25.0; 30 | y = 150.0; 31 | 32 | move_to(cr, x, y); 33 | show_text(cr, "cairo"); 34 | 35 | # draw helping lines 36 | set_source_rgba(cr, 1, 0.2, 0.2, 0.6); 37 | set_line_width(cr, 6.0); 38 | arc(cr, x, y, 10.0, 0, 2*pi); 39 | fill(cr); 40 | move_to(cr, x,y); 41 | rel_line_to(cr, 0, -extents[4]); 42 | rel_line_to(cr, extents[3], 0); 43 | rel_line_to(cr, extents[1], -extents[2]); 44 | stroke(cr); 45 | ## mark picture with current date 46 | restore(cr); 47 | move_to(cr,0.0,12.0); 48 | set_source_rgb(cr, 0,0,0); 49 | show_text(cr,Libc.strftime(time())); 50 | write_to_png(c,"sample_text_extents.png"); 51 | -------------------------------------------------------------------------------- /samples/sample_text_align_center.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | ## original example, following here 14 | select_font_face(cr, "Sans", Cairo.FONT_SLANT_NORMAL, 15 | Cairo.FONT_WEIGHT_NORMAL); 16 | set_font_size(cr, 52.0); 17 | extents = text_extents(cr, "cairo"); 18 | 19 | # 20 | # typedef struct { 21 | # double x_bearing; 22 | # double y_bearing; 23 | # double width; 24 | # double height; 25 | # double x_advance; 26 | # double y_advance; 27 | # } cairo_text_extents_t; 28 | 29 | x = 128.0-(extents[3]/2 + extents[1]); 30 | y = 128.0-(extents[4]/2 + extents[2]); 31 | 32 | move_to(cr, x, y); 33 | show_text(cr, "cairo"); 34 | 35 | # draw helping lines 36 | set_source_rgba(cr, 1, 0.2, 0.2, 0.6); 37 | set_line_width(cr, 6.0); 38 | arc(cr, x, y, 10.0, 0, 2*pi); 39 | fill(cr); 40 | move_to(cr, 128.0, 0); 41 | rel_line_to(cr, 0, 256); 42 | move_to(cr, 0, 128.0); 43 | rel_line_to(cr, 256, 0); 44 | stroke(cr); 45 | 46 | ## mark picture with current date 47 | restore(cr); 48 | move_to(cr,0.0,12.0); 49 | set_source_rgb(cr, 0,0,0); 50 | show_text(cr,Libc.strftime(time())); 51 | write_to_png(c,"sample_text_align_center.png"); 52 | -------------------------------------------------------------------------------- /samples/sample_script0.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoARGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.5,0.5,0.5); 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | save(cr); 12 | 13 | ## paint the following to a Recording Surface 14 | s1 = CairoRecordingSurface() 15 | c1 = CairoContext(s1) 16 | 17 | move_to(c1, 128.0, 25.6); 18 | line_to(c1, 230.4, 230.4); 19 | rel_line_to(c1, -102.4, 0.0); 20 | curve_to(c1, 51.2, 230.4, 51.2, 128.0, 128.0, 128.0); 21 | close_path(c1); 22 | 23 | move_to(c1, 64.0, 25.6); 24 | rel_line_to(c1, 51.2, 51.2); 25 | rel_line_to(c1, -51.2, 51.2); 26 | rel_line_to(c1, -51.2, -51.2); 27 | close_path(c1); 28 | 29 | set_line_width(c1, 10.0); 30 | set_source_rgb(c1, 0, 0, 1); 31 | fill_preserve(c1); 32 | set_source_rgb(c1, 0, 0, 0); 33 | stroke(c1); 34 | 35 | ## write to script 36 | 37 | io = IOBuffer() 38 | s2 = Cairo.CairoScript(io) 39 | Cairo.script_from_recording_surface(s2,s1); 40 | destroy(s2) 41 | 42 | seek(io,0) 43 | r = String(read(io)) 44 | 45 | r1 = split(r,"\n") 46 | 47 | t1 = 24.0 48 | for x in r1 49 | move_to(cr,0.0,t1) 50 | show_text(cr,x) 51 | global t1 += 12.0 52 | end 53 | 54 | 55 | ## mark picture with current date 56 | restore(cr); 57 | move_to(cr,0.0,12.0); 58 | set_source_rgb(cr, 0,0,0); 59 | show_text(cr,Libc.strftime(time())); 60 | write_to_png(c,"sample_script0.png"); 61 | 62 | -------------------------------------------------------------------------------- /samples/sample_rounded_rectangle.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | ## original example, following here 14 | 15 | # a custom shape that could be wrapped in a function */ 16 | x = 25.6; # parameters like cairo_rectangle */ 17 | y = 25.6; 18 | xw = 204.8; 19 | yw = 204.8; 20 | aspect = 1.0; # aspect ratio */ 21 | corner_radius = yw / 10.0; #* and corner curvature radius */ 22 | 23 | radius = corner_radius / aspect; 24 | degrees = pi / 180.0; 25 | 26 | new_sub_path(cr); 27 | arc(cr, x + xw - radius, y + radius, radius, -90 * degrees, 0 * degrees); 28 | arc(cr, x + xw - radius, y + yw - radius, radius, 0 * degrees, 90 * degrees); 29 | arc(cr, x + radius, y + yw - radius, radius, 90 * degrees, 180 * degrees); 30 | arc(cr, x + radius, y + radius, radius, 180 * degrees, 270 * degrees); 31 | close_path(cr); 32 | 33 | set_source_rgb(cr, 0.5, 0.5, 1); 34 | fill_preserve(cr); 35 | set_source_rgba(cr, 0.5, 0, 0, 0.5); 36 | set_line_width(cr, 10.0); 37 | stroke(cr); 38 | 39 | ## mark picture with current date 40 | restore(cr); 41 | move_to(cr,0.0,12.0); 42 | set_source_rgb(cr, 0,0,0); 43 | show_text(cr,Libc.strftime(time())); 44 | write_to_png(c,"sample_rounded_rectangle.png"); 45 | -------------------------------------------------------------------------------- /samples/sample_current_point.jl: -------------------------------------------------------------------------------- 1 | using Cairo 2 | 3 | function common_header() 4 | ## header to provide surface and context 5 | c = CairoRGBSurface(256,256); 6 | cr = CairoContext(c); 7 | 8 | save(cr); 9 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 10 | rectangle(cr,0.0,0.0,256.0,256.0); # background 11 | fill(cr); 12 | restore(cr); 13 | 14 | return c,cr 15 | end 16 | 17 | function write_out_picture(filename::AbstractString,c::CairoSurface) 18 | ## mark picture with current date 19 | move_to(cr,0.0,12.0); 20 | set_source_rgb(cr, 0,0,0); 21 | show_text(cr,Libc.strftime(time())); 22 | ## 23 | write_to_png(c,filename); 24 | nothing 25 | end 26 | 27 | function example_current_point(cr) 28 | save(cr); 29 | 30 | x=25.6; y=128.0; 31 | x1=102.4; y1=30.4; 32 | x2=123.6; y2=45.6; 33 | x3=130.4; y3=128.0; 34 | 35 | move_to(cr, x, y); 36 | curve_to(cr, x1, y1, x2, y2, x3, y3); 37 | 38 | if has_current_point(cr) 39 | x,y = get_current_point(cr); 40 | save(cr) 41 | move_to(cr,x,y) 42 | set_source_rgb(cr, 0,0,1.0); 43 | show_text(cr,"current point") 44 | restore(cr) 45 | end 46 | 47 | set_line_width(cr, 10.0); 48 | stroke(cr); 49 | 50 | 51 | restore(cr); 52 | save(cr); 53 | 54 | nothing 55 | end 56 | 57 | 58 | c,cr = common_header(); 59 | save(cr); 60 | example_current_point(cr); 61 | restore(cr); 62 | write_out_picture("sample_current_point.png",c); 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /samples/sample_imagestream.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | # example, following here 14 | 15 | inline_png2 = b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00d\x00\x00\x00d\x08\x02\x00\x00\x00\xff\x80\x02\x03\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x01=IDATx\x9c\xed\xdc\xc1i\x85@\x14@\xd1IH!\x96bi\x96f)\x96\x92E@!\x01\x7f\xeeF\xfdp\xce\xca\x9d\xc3\xe5\xb9{\xce\xc7\xb2,\x83\xff\xf9\xbc\xfb\x00\xefD\xac@\xac@\xac@\xac@\xac@\xac@\xac@\xac\xe0\xeb\xee\x03\xfc\xb1\xaec]\xc7\x18c\x9e\xc7<\xdf{\x96_LV V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V V\xf0j[\xf9gq\xf8J\xdbv<\\\xff\xf6\xd3\xfd\xe8\xe7\xc5\xdam\xdb\x11\xee2\xa7\xb1|\x86\xc1\xab\xc9\xba~m\x7f\x1f\xa8i\x1a\xd3t\xf5\xdbO=/\xd6\xba\x1e\xb1\xfca\xf1\xbe\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\xc4\n\x9ew\x1f\xfc\xf3\xae\x81\xdf\x99\xac@\xac@\xac@\xac@\xac@\xac@\xac@\xac@\xac\xe0\x1b\xaf\xef\x1c\xd4\x17\xfe\xcaX\x00\x00\x00\x00IEND\xaeB`\x82" 16 | png_stream = IOBuffer(); 17 | write(png_stream,inline_png2); 18 | seekstart(png_stream); 19 | 20 | imagesurface = read_from_png(png_stream); 21 | set_source_surface(cr, imagesurface, 0, 0); 22 | paint(cr); 23 | 24 | ## mark picture with current date 25 | restore(cr); 26 | move_to(cr,0.0,12.0); 27 | set_source_rgb(cr, 0,0,0); 28 | show_text(cr,Libc.strftime(time())); 29 | write_to_png(c,"sample_imagestream.png"); 30 | -------------------------------------------------------------------------------- /samples/sample_alpha_paint.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | using Colors 4 | 5 | c = CairoRGBSurface(256,256) 6 | cr = CairoContext(c) 7 | 8 | save(cr) 9 | 10 | z = Array{RGB24}(undef, 2, 2) 11 | c1 = convert(RGB24,colorant"grey20") 12 | c2 = convert(RGB24,colorant"grey80") 13 | z[1,1] = c1 14 | z[1,2] = c2 15 | z[2,1] = c2 16 | z[2,2] = c1 17 | 18 | img = CairoImageSurface(z) 19 | pattern = CairoPattern(img) 20 | pattern_set_extend(pattern, Cairo.EXTEND_REPEAT) 21 | pattern_set_filter(pattern, Cairo.FILTER_BILINEAR) 22 | 23 | m = CairoMatrix(1/8.0,0,0,1/8.0,0,0) 24 | 25 | set_matrix(pattern, m) 26 | set_source(cr, pattern) 27 | paint(cr) 28 | restore(cr) 29 | 30 | save(cr) 31 | 32 | # 5 uses of set_source 33 | 34 | # color 35 | save(cr) 36 | rectangle(cr,16,32,224,32) 37 | set_source(cr, colorant"red4") 38 | fill(cr) 39 | restore(cr) 40 | 41 | # color with alpha 42 | save(cr) 43 | rectangle(cr,16,72,224,32) 44 | set_source(cr, alphacolor(colorant"blue",0.5)) 45 | fill(cr) 46 | restore(cr) 47 | 48 | # image from surface 49 | save(cr) 50 | rectangle(cr,16,112,224,32) 51 | clip(cr) 52 | new_path(cr) 53 | s = read_from_png("data/mulberry.png") 54 | set_source(cr,s) 55 | paint_with_alpha(cr,0.6) 56 | restore(cr) 57 | 58 | # image from context (from surface) 59 | save(cr) 60 | rectangle(cr,16,152,224,32) 61 | clip(cr) 62 | new_path(cr) 63 | set_source(cr,creategc(s)) 64 | paint(cr) 65 | restore(cr) 66 | 67 | # image for surface with offset 68 | save(cr) 69 | rectangle(cr,16,192,224,32) 70 | clip(cr) 71 | set_source(cr,s,0.0,40.0) 72 | paint(cr) 73 | restore(cr) 74 | 75 | 76 | 77 | ## mark picture with current date 78 | restore(cr) 79 | move_to(cr,0.0,12.0) 80 | set_source_rgb(cr, 0,0,0) 81 | show_text(cr,Libc.strftime(time())) 82 | write_to_png(c,"sample_alpha_paint.png") 83 | -------------------------------------------------------------------------------- /samples/sample_copy_path.jl: -------------------------------------------------------------------------------- 1 | using Cairo 2 | 3 | function common_header() 4 | ## header to provide surface and context 5 | c = CairoRGBSurface(256,256); 6 | cr = CairoContext(c); 7 | 8 | save(cr); 9 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 10 | rectangle(cr,0.0,0.0,256.0,256.0); # background 11 | fill(cr); 12 | restore(cr); 13 | 14 | return c,cr 15 | end 16 | 17 | function write_out_picture(filename::AbstractString,c::CairoSurface) 18 | ## mark picture with current date 19 | move_to(cr,0.0,12.0); 20 | set_source_rgb(cr, 0,0,0); 21 | show_text(cr,Libc.strftime(time())); 22 | ## 23 | write_to_png(c,filename); 24 | nothing 25 | end 26 | 27 | function example_copy_path(cr) 28 | 29 | save(cr); 30 | # single (large) character set with text_path+stroke 31 | select_font_face(cr, "Sans", Cairo.FONT_SLANT_NORMAL, 32 | Cairo.FONT_WEIGHT_BOLD); 33 | set_font_size(cr, 100.0); 34 | translate(cr, 10.0, 100.0); 35 | text_path(cr, "J"); 36 | stroke_preserve(cr); 37 | 38 | # copied and converted 39 | opath = Cairo.convert_cairo_path_data(Cairo.copy_path(cr)); 40 | 41 | restore(cr); 42 | 43 | l = 2 # something like a line counter 44 | 45 | # loop over all entries and just print out command and available points 46 | for x in opath 47 | if x.element_type == Cairo.CAIRO_PATH_MOVE_TO 48 | s0 = "moveto" 49 | elseif x.element_type == Cairo.CAIRO_PATH_LINE_TO 50 | s0 = "lineto" 51 | elseif x.element_type == Cairo.CAIRO_PATH_CURVE_TO 52 | s0 = "curveto" 53 | elseif x.element_type == Cairo.CAIRO_PATH_CLOSE_PATH 54 | s0 = "closepath" 55 | end 56 | s1 = repr(x.points) 57 | move_to(cr,100.0,14.0*l) 58 | l += 1 59 | show_text(cr,s0*s1) 60 | end 61 | nothing 62 | end 63 | 64 | 65 | c,cr = common_header(); 66 | save(cr); 67 | example_copy_path(cr); 68 | restore(cr); 69 | write_out_picture("sample_copy_path.png",c); 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /samples/sample_copy_path_flat.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | 4 | c = CairoRGBSurface(256,256) 5 | cr = CairoContext(c) 6 | 7 | save(cr) 8 | set_source_rgb(cr,0.8,0.8,0.8) # light gray 9 | rectangle(cr,0.0,0.0,256.0,256.0) # background 10 | fill(cr) 11 | restore(cr) 12 | 13 | save(cr) 14 | 15 | ## original example, following here 16 | move_to(cr, 16.0, 32.0) 17 | curve_to(cr, 16.0, 16.0, 16.0, 16.0, 32.0, 16.0) 18 | 19 | opath = Cairo.convert_cairo_path_data(Cairo.copy_path(cr)) 20 | dx,dy,ex,ey = path_extents(cr) 21 | 22 | fpath = Cairo.convert_cairo_path_data(Cairo.copy_path_flat(cr)) 23 | 24 | stroke(cr) 25 | 26 | restore(cr) 27 | 28 | l = 2 # something like a line counter 29 | 30 | # loop over all entries and just print out command and available points 31 | for x in opath 32 | if x.element_type == Cairo.CAIRO_PATH_MOVE_TO 33 | s0 = "moveto" 34 | elseif x.element_type == Cairo.CAIRO_PATH_LINE_TO 35 | s0 = "lineto" 36 | elseif x.element_type == Cairo.CAIRO_PATH_CURVE_TO 37 | s0 = "curveto" 38 | elseif x.element_type == Cairo.CAIRO_PATH_CLOSE_PATH 39 | s0 = "closepath" 40 | end 41 | s1 = repr(x.points) 42 | move_to(cr,10.0,16.0+(14.0*l)) 43 | global l += 1 44 | show_text(cr,s0*s1) 45 | end 46 | 47 | l = 2 # something like a line counter 48 | 49 | # loop over all entries and just print out command and available points 50 | for x in fpath 51 | if x.element_type == Cairo.CAIRO_PATH_MOVE_TO 52 | s0 = "moveto" 53 | elseif x.element_type == Cairo.CAIRO_PATH_LINE_TO 54 | s0 = "lineto" 55 | elseif x.element_type == Cairo.CAIRO_PATH_CURVE_TO 56 | s0 = "curveto" 57 | elseif x.element_type == Cairo.CAIRO_PATH_CLOSE_PATH 58 | s0 = "closepath" 59 | end 60 | s1 = repr(x.points) 61 | move_to(cr,10.0,50.0+(14.0*l)) 62 | global l += 1 63 | show_text(cr,s0*s1) 64 | end 65 | 66 | 67 | ## mark picture with current date 68 | restore(cr) 69 | 70 | move_to(cr,0.0,12.0) 71 | set_source_rgb(cr, 0,0,0) 72 | show_text(cr,Libc.strftime(time())) 73 | 74 | write_to_png(c,"sample_copy_path_flat.png") 75 | -------------------------------------------------------------------------------- /test/test_speed.jl: -------------------------------------------------------------------------------- 1 | using Cairo 2 | include("shape_functions.jl") 3 | 4 | function test_all(;tmax = 2.0, save_flag = false) 5 | print("cairo version: ",Cairo.libcairo_version,"\n"); 6 | size_surface = [512];#,512,1024]; #three sizes of a surface 7 | paint_width = [0.5,1.0,3.0,5.0]; 8 | shapes = [ddots1, ddots2, ddots3, ddots4, ddots5, 9 | rdots1, rdots2, rdots3, rdots4, rdots5, rdots6, 10 | lines0, lines1, lines2, lines3, lines4]; 11 | n_elements = [100,300,1000,3000,10000,30000,100000]; 12 | 13 | n_tests = length(size_surface) * length(paint_width) * length(shapes); 14 | test_data = zeros(n_tests+1,3 + length(n_elements)); 15 | test_data[1,3+(1:length(n_elements))] = n_elements; 16 | i = 1; 17 | 18 | if save_flag && !isdir("test_results") 19 | mkdir("test_results") 20 | end 21 | 22 | for s_size in size_surface 23 | s = Cairo.CairoARGBSurface(s_size,s_size); 24 | c = Cairo.CairoContext(s); 25 | print("Surface Size: ",s_size,"\n") 26 | for w in paint_width 27 | print("Paint Width: ",w,"\n") 28 | for m_index in 1:length(shapes) 29 | test_data[i,1] = s_size; 30 | test_data[i,2] = w; 31 | test_data[i,3] = m_index; 32 | m = shapes[m_index]; 33 | for n_index in 1:length(n_elements) 34 | n = n_elements[n_index]; 35 | t = @elapsed(m(c,s_size,s_size,w,n)); 36 | print(m," ",@sprintf("%6d",n)," elapsed time: ",@sprintf("%f seconds",t),"\n"); 37 | test_data[i+1,3+n_index] = t; 38 | if save_flag 39 | write_to_png(s,@sprintf("test_results/test_speed_%2.1f_%02d_%02d.png",w,m_index,n_index)); 40 | end 41 | if t > tmax && n_index < length(n_elements) 42 | println("Remaining tests in this sequence skipped") 43 | break 44 | end 45 | end 46 | print("\n") 47 | i += 1; 48 | end 49 | end 50 | end 51 | end 52 | 53 | test_all() 54 | -------------------------------------------------------------------------------- /samples/sample_meshpattern.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | ## original example, taken from cairo/test/pattern-mesh.c 14 | function draw(cr, width::Int, height::Int) 15 | 16 | PAT_WIDTH = 170 17 | PAT_HEIGHT = 170 18 | SIZE = PAT_WIDTH 19 | PAD = 2 20 | WIDTH = (PAD + SIZE + PAD) 21 | HEIGHT = WIDTH 22 | 23 | pattern = CairoPatternMesh(); 24 | 25 | #cairo_test_paint_checkered (cr); ? 26 | 27 | translate(cr, PAD, PAD); 28 | translate(cr, 10, 10); 29 | 30 | mesh_pattern_begin_patch(pattern); 31 | 32 | mesh_pattern_move_to(pattern, 0, 0); 33 | mesh_pattern_curve_to(pattern, 30, -30, 60, 30, 100, 0); 34 | mesh_pattern_curve_to(pattern, 60, 30, 130, 60, 100, 100); 35 | mesh_pattern_curve_to(pattern, 60, 70, 30, 130, 0, 100); 36 | mesh_pattern_curve_to(pattern, 30, 70, -30, 30, 0, 0); 37 | 38 | mesh_pattern_set_corner_color_rgb(pattern, 0, 1, 0, 0); 39 | mesh_pattern_set_corner_color_rgb(pattern, 1, 0, 1, 0); 40 | mesh_pattern_set_corner_color_rgb(pattern, 2, 0, 0, 1); 41 | mesh_pattern_set_corner_color_rgb(pattern, 3, 1, 1, 0); 42 | 43 | mesh_pattern_end_patch(pattern); 44 | 45 | mesh_pattern_begin_patch(pattern); 46 | 47 | mesh_pattern_move_to(pattern, 50, 50); 48 | mesh_pattern_curve_to(pattern, 80, 20, 110, 80, 150, 50); 49 | mesh_pattern_curve_to(pattern, 110, 80, 180, 110, 150, 150); 50 | mesh_pattern_curve_to(pattern, 110, 120, 80, 180, 50, 150); 51 | mesh_pattern_curve_to(pattern, 80, 120, 20, 80, 50, 50); 52 | 53 | mesh_pattern_set_corner_color_rgba(pattern, 0, 1, 0, 0, 0.3); 54 | mesh_pattern_set_corner_color_rgb(pattern, 1, 0, 1, 0); 55 | mesh_pattern_set_corner_color_rgba(pattern, 2, 0, 0, 1, 0.3); 56 | mesh_pattern_set_corner_color_rgb(pattern, 3, 1, 1, 0); 57 | 58 | mesh_pattern_end_patch(pattern); 59 | 60 | set_source(cr, pattern); 61 | paint(cr); 62 | #pattern_destroy (pattern); 63 | 64 | end 65 | 66 | draw(cr,170,170); 67 | 68 | ## mark picture with current date 69 | restore(cr); 70 | move_to(cr,0.0,12.0); 71 | set_source_rgb(cr, 0,0,0); 72 | show_text(cr,Libc.strftime(time())); 73 | write_to_png(c,"sample_meshpattern.png"); 74 | -------------------------------------------------------------------------------- /samples/sample_operators.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoARGBSurface(512,512); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,512.0,512.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | 14 | function operator_demo(operator_index) 15 | c = CairoARGBSurface(126,98); 16 | cr = CairoContext(c); 17 | operators = [ 18 | (Cairo.OPERATOR_CLEAR,"OPERATOR_CLEAR"), 19 | (Cairo.OPERATOR_SOURCE,"OPERATOR_SOURCE"), 20 | (Cairo.OPERATOR_OVER,"OPERATOR_OVER"), 21 | (Cairo.OPERATOR_IN,"OPERATOR_IN"), 22 | (Cairo.OPERATOR_OUT,"OPERATOR_OUT"), 23 | (Cairo.OPERATOR_ATOP,"OPERATOR_ATOP"), 24 | (Cairo.OPERATOR_DEST,"OPERATOR_DEST"), 25 | (Cairo.OPERATOR_DEST_OVER,"OPERATOR_DEST_OVER"), 26 | (Cairo.OPERATOR_DEST_IN,"OPERATOR_DEST_IN"), 27 | (Cairo.OPERATOR_DEST_OUT,"OPERATOR_DEST_OUT"), 28 | (Cairo.OPERATOR_DEST_ATOP,"OPERATOR_DEST_ATOP"), 29 | (Cairo.OPERATOR_XOR,"OPERATOR_XOR"), 30 | (Cairo.OPERATOR_ADD,"OPERATOR_ADD"), 31 | (Cairo.OPERATOR_SATURATE,"OPERATOR_SATURATE"), 32 | (Cairo.OPERATOR_MULTIPLY,"OPERATOR_MULTIPLY"), 33 | (Cairo.OPERATOR_SCREEN,"OPERATOR_SCREEN"), 34 | (Cairo.OPERATOR_OVERLAY,"OPERATOR_OVERLAY"), 35 | (Cairo.OPERATOR_DARKEN,"OPERATOR_DARKEN"), 36 | (Cairo.OPERATOR_LIGHTEN,"OPERATOR_LIGHTEN")] 37 | 38 | save(cr) 39 | set_source_rgb(cr, 0.9, 0.9, 0.9) 40 | paint(cr); 41 | 42 | save(cr) 43 | scale(cr,6,6) 44 | rectangle(cr, 0, 5, 12, 9) 45 | set_source_rgba(cr, 0.7, 0, 0, 0.8) 46 | fill(cr) 47 | 48 | set_operator(cr, operators[operator_index][1]) 49 | 50 | rectangle(cr, 4, 2, 12, 9) 51 | set_source_rgba(cr, 0, 0, 0.9, 0.4) 52 | fill(cr) 53 | 54 | local_operator = get_operator(cr) 55 | restore(cr) 56 | 57 | move_to(cr,0,10) 58 | set_source_rgb(cr, 0,0,0) 59 | show_text(cr,operators[local_operator+1][2]) 60 | 61 | restore(cr) 62 | c 63 | end 64 | 65 | for k=1:19 66 | save(cr) 67 | translate(cr,6+(128*mod(k-1,4)),24+(100*div(k-1,4))) 68 | set_source(cr,operator_demo(k)) 69 | paint(cr) 70 | restore(cr) 71 | end 72 | 73 | ## mark picture with current date 74 | restore(cr); 75 | move_to(cr,0.0,12.0); 76 | set_source_rgb(cr, 0,0,0); 77 | show_text(cr,Libc.strftime(time())); 78 | write_to_png(c,"sample_operators.png"); 79 | -------------------------------------------------------------------------------- /samples/sample_curve_rectangle.jl: -------------------------------------------------------------------------------- 1 | ## header to provide surface and context 2 | using Cairo 3 | c = CairoRGBSurface(256,256); 4 | cr = CairoContext(c); 5 | 6 | save(cr); 7 | set_source_rgb(cr,0.8,0.8,0.8); # light gray 8 | rectangle(cr,0.0,0.0,256.0,256.0); # background 9 | fill(cr); 10 | restore(cr); 11 | 12 | save(cr); 13 | 14 | ## original example, following here 15 | 16 | # custom shape wrapped in a function 17 | function shape_curve_rectangle(cr::CairoContext,x0::Real,y0::Real, 18 | rect_width::Real, rect_height::Real, radius::Real) 19 | 20 | save(cr); 21 | 22 | x1=x0+rect_width; 23 | y1=y0+rect_height; 24 | 25 | if (rect_width == 0 || rect_height == 0) 26 | return; 27 | end 28 | if (rect_width/2 < radius) 29 | if (rect_height/2 < radius) 30 | move_to(cr, x0, (y0 + y1)/2); 31 | curve_to(cr, x0 ,y0, x0, y0, (x0 + x1)/2, y0); 32 | curve_to(cr, x1, y0, x1, y0, x1, (y0 + y1)/2); 33 | curve_to(cr, x1, y1, x1, y1, (x1 + x0)/2, y1); 34 | curve_to(cr, x0, y1, x0, y1, x0, (y0 + y1)/2); 35 | else 36 | move_to(cr, x0, y0 + radius); 37 | curve_to(cr, x0 ,y0, x0, y0, (x0 + x1)/2, y0); 38 | curve_to(cr, x1, y0, x1, y0, x1, y0 + radius); 39 | line_to(cr, x1 , y1 - radius); 40 | curve_to(cr, x1, y1, x1, y1, (x1 + x0)/2, y1); 41 | curve_to(cr, x0, y1, x0, y1, x0, y1- radius); 42 | end 43 | 44 | else 45 | if (rect_height/2 < radius) 46 | move_to(cr, x0, (y0 + y1)/2); 47 | curve_to(cr, x0 , y0, x0 , y0, x0 + radius, y0); 48 | line_to(cr, x1 - radius, y0); 49 | curve_to(cr, x1, y0, x1, y0, x1, (y0 + y1)/2); 50 | curve_to(cr, x1, y1, x1, y1, x1 - radius, y1); 51 | line_to(cr, x0 + radius, y1); 52 | curve_to(cr, x0, y1, x0, y1, x0, (y0 + y1)/2); 53 | else 54 | move_to(cr, x0, y0 + radius); 55 | curve_to(cr, x0 , y0, x0 , y0, x0 + radius, y0); 56 | line_to(cr, x1 - radius, y0); 57 | curve_to(cr, x1, y0, x1, y0, x1, y0 + radius); 58 | line_to(cr, x1 , y1 - radius); 59 | curve_to(cr, x1, y1, x1, y1, x1 - radius, y1); 60 | line_to(cr, x0 + radius, y1); 61 | curve_to(cr, x0, y1, x0, y1, x0, y1- radius); 62 | end 63 | end 64 | close_path(cr); 65 | 66 | set_source_rgb(cr, 0.5, 0.5, 1); 67 | fill_preserve(cr); 68 | set_source_rgba(cr, 0.5, 0, 0, 0.5); 69 | set_line_width(cr, 10.0); 70 | stroke(cr); 71 | restore(cr); 72 | return; 73 | end 74 | 75 | shape_curve_rectangle(cr,25.6,25.6,204.8,204.8,102.4); 76 | 77 | ## mark picture with current date 78 | restore(cr); 79 | move_to(cr,0.0,12.0); 80 | set_source_rgb(cr, 0,0,0); 81 | show_text(cr,Libc.strftime(time())); 82 | write_to_png(c,"sample_curve_rectangle.png"); 83 | -------------------------------------------------------------------------------- /test/test_painting.jl: -------------------------------------------------------------------------------- 1 | # some collection of some painting plus support functions 2 | 3 | """ 4 | function ngray(base::Int,digits::Int,value::Int) 5 | Convert a value to a graycode with the given base and digits 6 | """ 7 | function ngray(base::Int,digits::Int,value::Int) 8 | baseN = zeros(Int,digits) 9 | gray = zeros(Int,1,digits) 10 | 11 | for i=1:digits 12 | baseN[i] = value % base 13 | value = div(value,base) 14 | end 15 | 16 | shift = 0 17 | for i=digits:-1:1 18 | gray[i] = (baseN[i] + shift) % base 19 | shift = shift + base - gray[i] 20 | end 21 | gray 22 | end 23 | 24 | """ 25 | function hilbert_curve(c,x,y,lg,i1,i2) 26 | recursive hilbert curve (2D), appends pairs of x,y to c, lg = dimension/length 27 | """ 28 | function hilbert_curve(c,x,y,lg,i1,i2) 29 | if lg == 1 30 | append!(c,[x,y]) 31 | else 32 | lg = lg / 2; 33 | hilbert_curve(c,x+i1*lg,y+i1*lg,lg,i1,1-i2); 34 | hilbert_curve(c,x+i2*lg,y+(1-i2)*lg,lg,i1,i2); 35 | hilbert_curve(c,x+(1-i1)*lg,y+(1-i1)*lg,lg,i1,i2); 36 | hilbert_curve(c,x+(1-i2)*lg,y+i2*lg,lg,1-i1,i2); 37 | end 38 | end 39 | 40 | 41 | function hilbert_colored(surf) 42 | 43 | zscale = 8; 44 | n1 = 8; 45 | cr = CairoContext(surf) 46 | 47 | c = Float64[] 48 | hilbert_curve(c,0,0,64,0,0) 49 | 50 | move_to(cr,0,0) 51 | 52 | translate(cr,zscale/2,zscale/2) 53 | scale(cr,zscale,zscale) 54 | set_line_width(cr,zscale/2) 55 | set_line_cap(cr,Cairo.CAIRO_LINE_CAP_SQUARE) 56 | 57 | for k in zip(collect(1:2:(length(c)-2)),1:(length(1:2:(length(c)-2)))) 58 | move_to(cr,c[k[1]],c[k[1]+1]) 59 | line_to(cr,c[k[1]+2],c[k[1]+3]) 60 | 61 | c1 = ngray(n1,3,k[2]) 62 | set_source_rgb(cr,c1[1]/float(n1-1),c1[2]/float(n1-1),c1[3]/float(n1-1)) 63 | stroke(cr) 64 | 65 | end 66 | end 67 | 68 | 69 | """ function hdraw(s,dim,zscale,linewidth) 70 | draws a hilbert curve with dimension dim (power of 2) and scales the drawing with 71 | zscale. 72 | """ 73 | function hdraw(s,dim,zscale,linewidth) 74 | 75 | cr = CairoContext(s) 76 | 77 | set_source_rgba(cr,0.0,0.0,1.0,0.5) 78 | 79 | set_line_width(cr,linewidth) 80 | set_line_cap(cr,Cairo.CAIRO_LINE_CAP_SQUARE) 81 | translate(cr,zscale/2,zscale/2) 82 | 83 | save(cr) 84 | c = Float64[] 85 | 86 | hilbert_curve(c,0,0,dim,0,0) 87 | 88 | scale(cr,zscale,zscale) 89 | 90 | move_to(cr,0,0) 91 | for k=1:div(length(c),2) 92 | line_to(cr,c[(k*2)-1],c[(k*2)]) 93 | end 94 | 95 | stroke(cr) 96 | restore(cr) 97 | end 98 | 99 | """ 100 | function simple_hist(data) 101 | simple histogram by population count in a Dict 102 | """ 103 | function simple_hist(data) 104 | # poor man's hist -> pop count in Dict 105 | 106 | pc = Dict() 107 | 108 | for d in data 109 | if d in keys(pc) 110 | pc[d] += 1 111 | else 112 | pc[d] = 1 113 | end 114 | end 115 | pc 116 | end 117 | 118 | """ 119 | function matrix_read(surface) 120 | paint the input surface into a matrix image of the same size to access 121 | the pixels. 122 | """ 123 | function matrix_read(surface) 124 | w = Int(surface.width) 125 | h = Int(surface.height) 126 | z = zeros(UInt32,w,h) 127 | surf = CairoImageSurface(z, Cairo.FORMAT_ARGB32) 128 | 129 | cr = CairoContext(surf) 130 | set_source_surface(cr,surface,0,0) 131 | paint(cr) 132 | 133 | surf.data 134 | end 135 | -------------------------------------------------------------------------------- /samples/Samples.md: -------------------------------------------------------------------------------- 1 | ## Sample programs # 2 | 3 | This is roughly a copy of the sample code listed at [cairographics.org/samples](http://www.cairographics.org/samples/). 4 | These examples are C code and assume that you've already set up a Cairo surface and Cairo Context. 5 | 6 | This (samples) directory contains ports of these examples to julia, additionally creating the Surface and Context, adding a time-stamp to the image, and saving the result to a .png file. 7 | 8 | ### arc # 9 | 10 | Example of using the arc path operator [sample_arc.jl](sample_arc.jl). 11 | Note: The path creation starts without current point, otherwise there would be a linesegment first, before starting of the arc. 12 | 13 | ![arc .png](sample_arc.png "arc example") 14 | 15 | ### arc_negative # 16 | 17 | Example of using the arc_negative path operator [sample_arc_negative.jl](sample_arc_negative.jl). 18 | 19 | ![arc_negative .png](sample_arc_negative.png "arc negative example") 20 | 21 | ### clip # 22 | 23 | A clip path, a circle is defined, then the drawing is done [sample_clip.jl](sample_clip.jl). 24 | 25 | ![clip .png](sample_clip.png "clip example") 26 | 27 | ### clip image # 28 | 29 | Like the previous, but now inserting a picture by reading a .png to an Image Surface. Note: the function is called read_from_png and creates an Image Surface; while in pure C cairo this would be a call of cairo_image_surface_create_from_png [sample_clip_image.jl](sample_clip_image.jl). 30 | 31 | ![clip image.png](sample_clip_image.png "clip image example") 32 | 33 | ### curve rectangle # 34 | 35 | Example of more complex path construction, here a rectangle constructed be four bezier segments. Note: Different as in the original example, this here now puts the path construction and stroke and fill operations into a function with coordinates and corner radius as arguments [sample_curve_rectangle.jl](sample_curve_rectangle.jl). 36 | 37 | ![curve rectangle .png](sample_curve_rectangle.png "curve rectangle example") 38 | 39 | ### curve to # 40 | 41 | Example of using the curve to path operator, which adds a cubic Bézier spline to the current path [sample_curve_to.jl](sample_curve_to.jl). 42 | 43 | ![curve to .png](sample_curve_to.png "curve to example") 44 | 45 | ### dash # 46 | 47 | Example of using a dash line pattern for stroking a path. Note: the julia set_dash uses the length of the dash array to set the ndash internally [sample_dash.jl](sample_dash.jl). 48 | 49 | ![dash .png](sample_dash.png "dash example") 50 | 51 | ### fill and stroke 2 # 52 | 53 | Example of creating a path of non connected areas and fill - while preserving the path - and stroke [sample_fill_and_stroke2.jl](sample_fill_and_stroke2.jl). 54 | 55 | ![fill and stroke2 .png](sample_fill_and_stroke2.png "fill and stroke2 example") 56 | 57 | ### fill style # 58 | 59 | Exmaple of using the different fill rules. The same path is filled and stroked [sample_fill_style.jl](sample_fill_style.jl). Note: the julia function is called set_fill_type while the pure C cairo is called with set_fill_rule. 60 | 61 | ![fill style .png](sample_fill_style.png "fill style example") 62 | 63 | ### gradient # 64 | 65 | Example of gradients - both linear and radiant - as definition and used for filling [sample_gradient.jl](sample_gradient.jl). 66 | 67 | ![gradient .png](sample_gradient.png "gradient example") 68 | 69 | ### image # 70 | 71 | Example of painting with a Image Surface as source [sample_image.jl](sample_image.jl). 72 | 73 | ![image .png](sample_image.png "image example") 74 | 75 | ### image pattern # 76 | 77 | Example of painting with a Image Surface as pattern [sample_imagepattern.jl] (sample_imagepattern.jl). 78 | 79 | ![imagepattern .png](sample_imagepattern.png "imagepattern example") 80 | 81 | ### multi segment caps # 82 | 83 | Example of stroking a path with non connected segments [sample_multi_segment_caps.jl](sample_multi_segment_caps.jl). 84 | 85 | ![multi segment caps .png](sample_multi_segment_caps.png "multi segment caps example") 86 | 87 | ### rounded rectangle # 88 | 89 | Example of more path operators, custom shape could be wrapped in a function [sample_rounded_rectangle.jl](sample_rounded_rectangle.jl). 90 | 91 | ![rounded rectangle .png](sample_rounded_rectangle.png "rounded rectangle example") 92 | 93 | ### set line caps 94 | 95 | Examples of the line cap settings [sample_set_line_cap.jl](sample_set_line_cap.jl). 96 | 97 | ![set line cap .png](sample_set_line_cap.png "line caps example") 98 | 99 | ### set line join 100 | 101 | Examples of the line join settings [sample_set_line_join.jl](sample_set_line_join.jl). 102 | 103 | ![set line join .png](sample_set_line_join.png "line join example") 104 | 105 | ### text 106 | 107 | Example of setting text, one with text_show, second with text_path extending the current path and fill and stroke the outline [sample_text.jl](sample_text.jl). 108 | 109 | ![text .png](sample_text.png "text example") 110 | 111 | ### text align center 112 | 113 | Example of getting the text extents, then centering the text around 128.0,128.0 [sample_text_align_center.jl](sample_text_align_center.jl). 114 | 115 | ![text align center.png](sample_text_align_center.png "text align example") 116 | 117 | ### text extents 118 | 119 | Example of getting the text extents, plotting the dimension [sample_text_extents.jl](sample_text_extents.jl). 120 | 121 | ![text extents .png](sample_text_extents.png "text extents example") 122 | 123 | ### copy path 124 | 125 | Example of getting the path to a single character via text_path, copy_path and convert to an Array of CairoPathEntry [sample_copy_path.jl](sample_copy_path.jl). 126 | 127 | ![copy path .png](sample_copy_path.png "copy path example") 128 | 129 | ### image (from stream) 130 | 131 | Example of painting with a Image Surface as source that was created by reading from a stream. The example reads the png data from an inline string [sample_imagestream.jl](sample_imagestream.jl). 132 | 133 | ![image .png](sample_imagestream.png "imagestream example") 134 | 135 | 136 | ## More Samples for Testing 137 | 138 | The following examples have been created to have more coverage in testing (all samples_X are executed). 139 | 140 | ### alpha paint 141 | 142 | Example to use set_source with different input (for multiple dispatch). For better viewing the background is not plain gray anymore, but has structure 143 | [sample_alpha_paint.jl](sample_alpha_paint.jl). 144 | 145 | ![alpha paint .png](sample_alpha_paint.png "set source example") 146 | 147 | ### image copy 148 | 149 | Example to use copy(Image). You need to take care about coordinate transformation, as the copy is inplace [sample_image_copy.jl](sample_image_copy.jl). 150 | 151 | ![image copy .png](sample_image_copy.png "image copy example") 152 | 153 | ### operators 154 | 155 | Example to use the defined operators for set_operator with two filled rectangles [sample_operators.jl](sample_operators.jl). 156 | 157 | ![operators .png](sample_operators.png "operators example") 158 | 159 | ### set dash 160 | 161 | Example to use the set line type function (input to set_dash) [sample_set_dash.jl](sample_set_dash.jl). 162 | 163 | ![set dash .png](sample_set_dash.png "line type example") 164 | 165 | ### copy path flat 166 | 167 | [sample_copy_path_flat.jl](sample_copy_path_flat.jl). 168 | 169 | ![copy path flat.png](sample_copy_path_flat.png "copy path flat example") 170 | 171 | ### pango text 172 | 173 | Example of a few (but not all) pango text formating options [sample_pango_text.jl](sample_pango_text.jl). 174 | 175 | ![pango text.png](sample_pango_text.png "pango text example") 176 | 177 | ### mesh pattern 178 | 179 | Example of creating and using a mesh pattern [sample_meshpattern.jl](sample_meshpattern.jl). 180 | Mesh patterns are tensor-product patch meshes (type 7 shadings in PDF), read more in [http://www.cairographics.org/manual/cairo-cairo-pattern-t.html#cairo-pattern-create-mesh] or [http://www.w3.org/TR/SVG2/pservers.html#MeshGradients]. 181 | 182 | ![mesh pattern .png](sample_meshpattern.png "mesh pattern example") 183 | 184 | ### Recording and Scripting Surfaces 185 | 186 | Example of using Recording surface, simple copy, then scaled and offset. 187 | 188 | ![sample record0.png](sample_record0.png "record0 example") 189 | ![sample record1.png](sample_record1.png "record1 example") 190 | 191 | Example of writing to script, put script text into frame. 192 | 193 | ![sample script0.png](sample_script0.png "scrip0 example") 194 | 195 | ### current point 196 | 197 | Example of using current point 198 | 199 | ![sample current point.png](sample_current_point.png "current point example") -------------------------------------------------------------------------------- /test/runtests.jl: -------------------------------------------------------------------------------- 1 | using Cairo 2 | using Colors 3 | import Base.Sys 4 | 5 | import Base.show 6 | 7 | using Test 8 | 9 | # Test that an the CairoSurface holds a reference to the passed IOBuffer 10 | @testset "IOBuffer Rooting " begin 11 | CairoSVGSurface(IOBuffer(), 200, 110) 12 | GC.gc() 13 | GC.gc() 14 | end 15 | 16 | # Image Surface 17 | @testset "Image Surface " begin 18 | 19 | surf = CairoImageSurface(100, 200, Cairo.FORMAT_ARGB32) 20 | @test width(surf) == 100 21 | @test height(surf) == 200 22 | ctx = CairoContext(surf) 23 | @test width(ctx) == 100 24 | @test height(ctx) == 200 25 | 26 | surf = CairoImageSurface(fill(RGB24(0), 10, 10)) 27 | @test Cairo.format(surf) == RGB24 28 | io = IOBuffer() 29 | show(io, MIME("image/png"), surf) 30 | 31 | seek(io,0) 32 | str_data = Vector{UInt8}(read(io)) 33 | 34 | @test length(str_data) > 8 && str_data[1:8] == [0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a] 35 | surf = CairoImageSurface(fill(ARGB32(0), 10, 10)) 36 | @test Cairo.format(surf) == ARGB32 37 | 38 | end 39 | 40 | @testset "Conversions " begin 41 | 42 | include("shape_functions.jl") 43 | include("test_stream.jl") 44 | 45 | function test_pattern_get_surface() 46 | # test getting a surface from a surface pattern 47 | surf = CairoImageSurface(100, 200, Cairo.FORMAT_ARGB32) 48 | ctx = CairoContext(surf) 49 | Cairo.push_group(ctx) 50 | pattern = Cairo.pop_group(ctx) 51 | group_surf = Cairo.pattern_get_surface(pattern) 52 | @test group_surf.width == 100 53 | @test group_surf.height == 200 54 | 55 | # test that surfaces can't be gotten from non-surface patterns 56 | pattern = Cairo.pattern_create_linear(0, 0, 100, 200) 57 | @test_throws ErrorException Cairo.pattern_get_surface(pattern) 58 | end 59 | 60 | test_pattern_get_surface() 61 | 62 | # Test creating a CairoContext from a cairo_t pointer 63 | surf = CairoImageSurface(fill(ARGB32(0), 10, 10)) 64 | ctx_ptr = ccall((:cairo_create, Cairo.libcairo),Ptr{Nothing}, (Ptr{Nothing}, ), surf.ptr) 65 | ctx = CairoContext(ctx_ptr) 66 | ccall((:cairo_destroy,Cairo.libcairo),Nothing, (Ptr{Nothing}, ), ctx_ptr) 67 | 68 | @test isa(ctx, CairoContext) 69 | end 70 | 71 | @testset "TexLexer " begin 72 | include("tex.jl") 73 | end 74 | 75 | # Run all the samples -> success, if output file exits 76 | @testset "Samples " begin 77 | 78 | samples_dir_path = joinpath(dirname(dirname(@__FILE__)), "samples") 79 | samples_files = filter(str->endswith(str,".jl"), readdir(samples_dir_path)) 80 | # filter known >= 1.12 -> sample_meshpattern.jl 81 | if Cairo.libcairo_version < v"1.12.0" 82 | files_to_exclude = ["sample_meshpattern.jl","sample_record0.jl","sample_record1.jl","sample_script0.jl"] 83 | samples_files = setdiff(samples_files, files_to_exclude) 84 | end 85 | 86 | @testset "sample: $test_file_name" for test_file_name in samples_files 87 | # Run each sample script in a separate module to avoid pollution 88 | s = Symbol(test_file_name) 89 | mod = @eval(Main, module $s end) 90 | @eval mod include($(joinpath(samples_dir_path, test_file_name))) 91 | 92 | output_png_name = replace(test_file_name,".jl" => ".png") 93 | @test isfile(output_png_name) 94 | rm(output_png_name) 95 | end 96 | end 97 | 98 | # Run some painting, check the colored pixels by counting them 99 | @testset "Bitmap Painting" begin 100 | 101 | include("test_painting.jl") 102 | 103 | # fill all 104 | z = zeros(UInt32,512,512); 105 | surf = CairoImageSurface(z, Cairo.FORMAT_ARGB32) 106 | # fills a 512x512 pixel area with blue,0.5 by using a hilbert curve of 107 | # dimension 64 (scaled by 8 -> 512) and a linewidth of 8 108 | hdraw(surf,64,8,8) 109 | 110 | d = simple_hist(surf.data) 111 | 112 | @test length(d) == 1 113 | @test collect(keys(d))[1] == 0x80000080 114 | 115 | # fill 1/4 (upper quarter) 116 | z = zeros(UInt32,512,512); 117 | surf = CairoImageSurface(z, Cairo.FORMAT_ARGB32) 118 | # fills a 256x256 pixel area with blue,0.5 by using a hilbert curve of 119 | # dimension 32 (scaled by 8 -> 256) and a linewidth of 8 120 | hdraw(surf,32,8,8) 121 | 122 | d = simple_hist(surf.data) 123 | 124 | @test length(d) == 2 125 | @test d[0x80000080] == 256*256 126 | 127 | # fill ~1/2 full, 128 | z = zeros(UInt32,512,512); 129 | surf = CairoImageSurface(z, Cairo.FORMAT_ARGB32) 130 | # fills a 512x512 pixel area with blue,0.5 by using a hilbert curve of 131 | # dimension 64 (scaled by 8 -> 512) and a linewidth of 4 -> 1/4 of pixels -16 132 | hdraw(surf,64,8,4) 133 | 134 | d = simple_hist(surf.data) 135 | 136 | @test length(d) == 2 137 | @test d[0x80000080] == ((512*256)-16) 138 | end 139 | 140 | # vector surfaces 141 | @testset "Vector Surfaces" begin 142 | 143 | output_file_name = "a.svg" 144 | surf = CairoSVGSurface(output_file_name,512,512) 145 | hdraw(surf,64,8,4) 146 | finish(surf) 147 | 148 | @test isfile(output_file_name) 149 | rm(output_file_name) 150 | 151 | io = IOBuffer() 152 | surf = CairoSVGSurface(io,512,512) 153 | hdraw(surf,64,8,4) 154 | finish(surf) 155 | 156 | seek(io,0) 157 | str_data = Vector{UInt8}(read(io)) 158 | 159 | @test length(str_data) > 31000 && str_data[1:13] == [0x3c,0x3f,0x78,0x6d,0x6c,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e] 160 | 161 | output_file_name = "a.pdf" 162 | surf = CairoPDFSurface(output_file_name,512,512) 163 | hdraw(surf,64,8,4) 164 | finish(surf) 165 | 166 | @test isfile(output_file_name) 167 | rm(output_file_name) 168 | 169 | io = IOBuffer() 170 | surf = CairoPDFSurface(io,512,512) 171 | hdraw(surf,64,8,4) 172 | finish(surf) 173 | 174 | seek(io,0) 175 | str_data = Vector{UInt8}(read(io)) 176 | 177 | @test length(str_data) > 3000 && str_data[1:7] == [0x25,0x50,0x44,0x46,0x2d,0x31,0x2e] 178 | 179 | output_file_name = "a.eps" 180 | surf = CairoEPSSurface(output_file_name,512,512) 181 | hdraw(surf,64,8,4) 182 | finish(surf) 183 | 184 | @test isfile(output_file_name) 185 | rm(output_file_name) 186 | 187 | io = IOBuffer() 188 | surf = CairoEPSSurface(io,512,512) 189 | hdraw(surf,64,8,4) 190 | finish(surf) 191 | 192 | seek(io,0) 193 | str_data = Vector{UInt8}(read(io)) 194 | 195 | @test length(str_data) > 3000 && str_data[1:10] == [0x25,0x21,0x50,0x53,0x2d,0x41,0x64,0x6f,0x62,0x65] 196 | 197 | output_file_name = "a.ps" 198 | surf = CairoPSSurface(output_file_name,512,512) 199 | hdraw(surf,64,8,4) 200 | finish(surf) 201 | 202 | @test isfile(output_file_name) 203 | rm(output_file_name) 204 | 205 | io = IOBuffer() 206 | surf = CairoPSSurface(io,512,512) 207 | hdraw(surf,64,8,4) 208 | finish(surf) 209 | 210 | seek(io,0) 211 | str_data = Vector{UInt8}(read(io)) 212 | 213 | @test length(str_data) > 3000 && str_data[1:10] == [0x25,0x21,0x50,0x53,0x2d,0x41,0x64,0x6f,0x62,0x65] 214 | 215 | if Cairo.libcairo_version >= v"1.12.0" 216 | 217 | # just write to surface and test for content 218 | io = IOBuffer() 219 | surf = CairoScriptSurface(io,512,512) 220 | hdraw(surf,64,8,4) 221 | finish(surf) 222 | 223 | seek(io,0) 224 | str_data = Vector{UInt8}(read(io)) 225 | 226 | @test length(str_data) > 3000 && str_data[1:10] == [0x25,0x21,0x43,0x61,0x69,0x72,0x6f,0x53,0x63,0x72] 227 | 228 | # create_for_target 229 | z = zeros(UInt32,512,512); 230 | surf = CairoImageSurface(z, Cairo.FORMAT_ARGB32) 231 | 232 | io = IOBuffer() 233 | scsurf = CairoScriptSurface(io,surf) 234 | hdraw(scsurf,64,8,8) 235 | finish(surf) 236 | destroy(scsurf) 237 | 238 | seek(io,0) 239 | str_data = Vector{UInt8}(read(io)) 240 | 241 | @test length(str_data) > 3000 && str_data[1:10] == [0x25,0x21,0x43,0x61,0x69,0x72,0x6f,0x53,0x63,0x72] 242 | 243 | d = simple_hist(surf.data) 244 | 245 | @test length(d) == 1 246 | @test collect(keys(d))[1] == 0x80000080 247 | 248 | 249 | end 250 | end 251 | 252 | # pixel/bitmap surfaces 253 | @testset "Bitmap Surfaces" begin 254 | 255 | z = zeros(UInt32,512,512) 256 | surf = CairoImageSurface(z, Cairo.FORMAT_ARGB32) 257 | 258 | hilbert_colored(surf) 259 | d1 = matrix_read(surf) 260 | d = simple_hist(d1) 261 | 262 | @test length(d) == 513 # 512 colors and empty background 263 | 264 | surf = CairoARGBSurface(z) 265 | 266 | hilbert_colored(surf) 267 | d1 = matrix_read(surf) 268 | d = simple_hist(d1) 269 | 270 | @test length(d) == 513 271 | 272 | surf = CairoRGBSurface(z) 273 | 274 | hilbert_colored(surf) 275 | d1 = matrix_read(surf) 276 | d = simple_hist(d1) 277 | 278 | @test length(d) == 512 # black is included 279 | end 280 | 281 | @testset "Assert/Status " begin 282 | 283 | z = zeros(UInt32,512,512); 284 | surf = CairoImageSurface(z, Cairo.FORMAT_ARGB32) 285 | 286 | @test Cairo.status(surf) == 0 287 | 288 | pa = surf.ptr 289 | surf.ptr = C_NULL 290 | 291 | @test destroy(surf) == nothing 292 | 293 | surf.ptr = pa 294 | cr = Cairo.CairoContext(surf) 295 | 296 | pa = cr.ptr 297 | cr.ptr = C_NULL 298 | 299 | @test destroy(cr) == nothing 300 | 301 | @test push_group(cr) == nothing 302 | @test pop_group(cr) == nothing 303 | 304 | @test_throws AssertionError Cairo.align2offset("to") 305 | 306 | @test_throws ErrorException Cairo.set_line_type(cr,"nondef") 307 | end 308 | 309 | @testset "reset_transform" begin 310 | using Graphics 311 | 312 | z = zeros(UInt32,512,512); 313 | surf = CairoImageSurface(z, Cairo.FORMAT_ARGB32) 314 | 315 | @test Cairo.status(surf) == 0 316 | 317 | pa = surf.ptr 318 | surf.ptr = C_NULL 319 | 320 | @test destroy(surf) == nothing 321 | 322 | surf.ptr = pa 323 | cr = Cairo.CairoContext(surf) 324 | 325 | m1 = CairoMatrix(1, 0, 0, 1, 0, 0) 326 | m2 = CairoMatrix(1.0,2.0,2.0,1.0,0.,0.) 327 | m = get_matrix(cr) 328 | @test m == m1 329 | set_matrix(cr, m2) 330 | @test get_matrix(cr) == m2 331 | Graphics.reset_transform(cr) 332 | @test get_matrix(cr) == m1 333 | @test destroy(cr) == nothing 334 | end 335 | 336 | nothing 337 | -------------------------------------------------------------------------------- /test/shape_functions.jl: -------------------------------------------------------------------------------- 1 | using Cairo 2 | using Random 3 | 4 | # shape functions, 5 | 6 | 7 | function randpos(n,w::Real,h::Real) 8 | @static if VERSION >= v"0.7" 9 | Random.seed!(141413) 10 | else 11 | srand(141413) 12 | end 13 | px = rand(n)*w 14 | py = rand(n)*h 15 | return (px,py) 16 | end 17 | 18 | function clear_bg(c::CairoContext,w::Real,h::Real) 19 | save(c) 20 | set_source_rgb(c,1.0,1.0,1.0) 21 | rectangle(c, 0,0,w,h) 22 | paint(c) 23 | restore(c) 24 | end 25 | 26 | # ddotsx: fill random dots with different methods, disc only (no ring) 27 | function ddots1(cr::CairoContext, rect_width::Real, rect_height::Real, radius::Real, n::Int) 28 | 29 | clear_bg(cr,rect_width,rect_height) 30 | px,py = randpos(n,rect_width,rect_height) 31 | 32 | new_path(cr) 33 | for i=1:n 34 | move_to(cr,px[i],py[i]) 35 | rel_move_to(cr,radius,0) 36 | arc(cr, px[i], py[i], radius, 0, 2*pi) 37 | end 38 | close_path(cr) 39 | 40 | set_source_rgb(cr, 0, 0, 1.0) 41 | fill(cr) 42 | end 43 | 44 | function ddots2(cr::CairoContext, rect_width::Real, rect_height::Real, radius::Real, n::Int) 45 | 46 | clear_bg(cr,rect_width,rect_height) 47 | px,py = randpos(n,rect_width,rect_height) 48 | 49 | for i=1:n 50 | new_path(cr) 51 | move_to(cr,px[i],py[i]) 52 | rel_move_to(cr,radius,0) 53 | arc(cr, px[i], py[i], radius, 0, 2*pi) 54 | close_path(cr) 55 | set_source_rgb(cr, 0, 0, 1.0) 56 | fill(cr) 57 | end 58 | end 59 | 60 | 61 | function ddots3(cr::CairoContext, rect_width::Real, rect_height::Real, radius::Real, n::Int) 62 | 63 | clear_bg(cr,rect_width,rect_height) 64 | px,py = randpos(n,rect_width,rect_height) 65 | 66 | new_path(cr) 67 | 68 | set_source_rgb(cr, 0, 0, 1.0) 69 | set_line_cap(cr,Cairo.CAIRO_LINE_CAP_ROUND) 70 | set_line_width(cr,radius*2.0) 71 | 72 | for i=1:n 73 | move_to(cr,px[i],py[i]) 74 | rel_line_to(cr,0,0) 75 | stroke(cr) 76 | end 77 | 78 | close_path(cr) 79 | 80 | end 81 | 82 | function ddots4(cr::CairoContext, 83 | rect_width::Real, rect_height::Real, radius::Real, n::Int) 84 | 85 | clear_bg(cr,rect_width,rect_height) 86 | px,py = randpos(n,rect_width,rect_height) 87 | 88 | cc = radius + 1 89 | 90 | rectangle(cr,0,0,2*cc,2*cc) 91 | clip(cr) 92 | push_group(cr) 93 | arc(cr,radius,radius,radius,0,2*pi) 94 | set_source_rgb(cr,0,0,1.0) 95 | fill(cr) 96 | p = pop_group(cr) 97 | reset_clip(cr) 98 | 99 | for i=1:n 100 | save(cr) 101 | translate(cr,px[i]-cc,py[i]-cc) 102 | set_source(cr,p) 103 | paint(cr) 104 | restore(cr) 105 | end 106 | end 107 | 108 | function ddots5(cr::CairoContext, 109 | rect_width::Real, rect_height::Real, radius::Real, n::Int) 110 | 111 | clear_bg(cr,rect_width,rect_height) 112 | px,py = randpos(n,rect_width,rect_height) 113 | 114 | cc = radius + 1 115 | 116 | s1 = Cairo.CairoARGBSurface(cc*2,cc*2) 117 | c1 = Cairo.CairoContext(s1) 118 | rectangle(c1,0,0,2*cc,2*cc) 119 | set_source_rgba(c1,0,0,0,0) 120 | paint(c1) 121 | new_path(c1) 122 | arc(c1,radius,radius,radius,0,2*pi) 123 | set_source_rgb(c1,0,0,1.0) 124 | fill(c1) 125 | 126 | p = Cairo.CairoPattern(s1) 127 | 128 | for i=1:n 129 | save(cr) 130 | translate(cr,px[i]-cc,py[i]-cc) 131 | set_source(cr,p) 132 | paint(cr) 133 | restore(cr) 134 | end 135 | end 136 | 137 | # rdotsx: fill random dots with different methods 138 | function rdots1(cr::CairoContext, rect_width::Real, rect_height::Real, radius::Real, n::Int) 139 | 140 | clear_bg(cr,rect_width,rect_height) 141 | px,py = randpos(n,rect_width,rect_height) 142 | 143 | new_path(cr) 144 | for i=1:n 145 | move_to(cr,px[i],py[i]) 146 | rel_move_to(cr,radius,0) 147 | arc(cr, px[i], py[i], radius, 0, 2*pi) 148 | end 149 | close_path(cr) 150 | 151 | set_source_rgb(cr, 0, 0, 1.0) 152 | fill_preserve(cr) 153 | set_line_width(cr,1.0) 154 | set_source_rgb(cr, 0, 0, 0) 155 | stroke(cr) 156 | end 157 | 158 | function rdots2(cr::CairoContext, rect_width::Real, rect_height::Real, radius::Real, n::Int) 159 | 160 | clear_bg(cr,rect_width,rect_height) 161 | px,py = randpos(n,rect_width,rect_height) 162 | 163 | for i=1:n 164 | new_path(cr) 165 | move_to(cr,px[i],py[i]) 166 | rel_move_to(cr,radius,0) 167 | arc(cr, px[i], py[i], radius, 0, 2*pi) 168 | close_path(cr) 169 | set_source_rgb(cr, 0, 0, 1.0) 170 | fill_preserve(cr) 171 | set_line_width(cr,1.0) 172 | set_source_rgb(cr, 0, 0, 0) 173 | stroke(cr) 174 | end 175 | end 176 | 177 | 178 | function rdots3(cr::CairoContext, rect_width::Real, rect_height::Real, radius::Real, n::Int) 179 | 180 | clear_bg(cr,rect_width,rect_height) 181 | px,py = randpos(n,rect_width,rect_height) 182 | 183 | new_path(cr) 184 | 185 | set_line_cap(cr,Cairo.CAIRO_LINE_CAP_ROUND) 186 | 187 | set_source_rgb(cr, 0, 0, 0) 188 | set_line_width(cr,radius*2 + 2.0) 189 | for i=1:n 190 | move_to(cr,px[i],py[i]) 191 | rel_line_to(cr,0,0) 192 | stroke(cr) 193 | end 194 | 195 | set_source_rgb(cr, 0, 0, 1.0) 196 | set_line_width(cr,radius*2) 197 | for i=1:n 198 | move_to(cr,px[i],py[i]) 199 | rel_line_to(cr,0,0) 200 | stroke(cr) 201 | end 202 | 203 | 204 | end 205 | 206 | function rdots4(cr::CairoContext, 207 | rect_width::Real, rect_height::Real, radius::Real, n::Int) 208 | 209 | clear_bg(cr,rect_width,rect_height) 210 | px,py = randpos(n,rect_width,rect_height) 211 | 212 | cc = radius + 3.0 213 | 214 | rectangle(cr,0,0,2*cc,2*cc) 215 | clip(cr) 216 | push_group(cr) 217 | arc(cr,radius,radius,radius,0,2*pi) 218 | set_source_rgb(cr,0,0,1.0) 219 | fill_preserve(cr) 220 | set_source_rgb(cr,0,0,0) 221 | set_line_width(cr,1.0) 222 | stroke(cr) 223 | p = pop_group(cr) 224 | reset_clip(cr) 225 | 226 | for i=1:n 227 | save(cr) 228 | translate(cr,px[i]-cc,py[i]-cc) 229 | set_source(cr,p) 230 | paint(cr) 231 | restore(cr) 232 | end 233 | end 234 | 235 | function rdots5(cr::CairoContext, 236 | rect_width::Real, rect_height::Real, radius::Real, n::Int) 237 | 238 | clear_bg(cr,rect_width,rect_height) 239 | px,py = randpos(n,rect_width,rect_height) 240 | 241 | cc = radius + 3.0 242 | 243 | s1 = Cairo.CairoARGBSurface(cc*2,cc*2) 244 | c1 = Cairo.CairoContext(s1) 245 | rectangle(c1,0,0,2*cc,2*cc) 246 | set_source_rgba(c1,0,0,0,0) 247 | paint(c1) 248 | new_path(c1) 249 | arc(c1,radius+1,radius+1,radius,0,2*pi) 250 | set_source_rgb(c1,0,0,1.0) 251 | fill_preserve(c1) 252 | set_source_rgb(c1,0,0,0) 253 | set_line_width(c1,1.0) 254 | stroke(c1) 255 | 256 | p = Cairo.CairoPattern(s1) 257 | 258 | for i=1:n 259 | save(cr) 260 | translate(cr,px[i]-cc,py[i]-cc) 261 | set_source(cr,p) 262 | paint(cr) 263 | restore(cr) 264 | end 265 | end 266 | 267 | # alpha transparency using paint_with_alpha 268 | function rdots6(cr::CairoContext, 269 | rect_width::Real, rect_height::Real, radius::Real, n::Int) 270 | 271 | clear_bg(cr,rect_width,rect_height) 272 | px,py = randpos(n,rect_width,rect_height) 273 | 274 | cc = radius + 3.0 275 | 276 | s1 = Cairo.CairoARGBSurface(cc*2,cc*2) 277 | c1 = Cairo.CairoContext(s1) 278 | rectangle(c1,0,0,2*cc,2*cc) 279 | set_source_rgba(c1,0,0,0,0) 280 | paint_with_alpha(c1, 0.5) 281 | new_path(c1) 282 | arc(c1,radius+1,radius+1,radius,0,2*pi) 283 | set_source_rgb(c1,0,0,1.0) 284 | fill_preserve(c1) 285 | set_source_rgb(c1,0,0,0) 286 | set_line_width(c1,1.0) 287 | stroke(c1) 288 | 289 | p = Cairo.CairoPattern(s1) 290 | 291 | for i=1:n 292 | save(cr) 293 | translate(cr,px[i]-cc,py[i]-cc) 294 | set_source(cr,p) 295 | paint_with_alpha(cr, 1 - i/n) 296 | restore(cr) 297 | end 298 | end 299 | 300 | # lines0, random x,y lines 301 | function lines0(cr::CairoContext, rect_width::Real, rect_height::Real, width::Real, n::Int) 302 | 303 | clear_bg(cr,rect_width,rect_height) 304 | px,py = randpos(n,rect_width,rect_height) 305 | 306 | new_path(cr) 307 | 308 | set_source_rgb(cr, 0, 0, 1.0) 309 | set_line_width(cr,width) 310 | 311 | new_path(cr) 312 | move_to(cr,px[1],py[1]) 313 | for i=2:n 314 | line_to(cr,px[i],py[i]) 315 | end 316 | stroke(cr) 317 | end 318 | 319 | # lines1, x sorted, line a plot 320 | function lines1(cr::CairoContext, rect_width::Real, rect_height::Real, width::Real, n::Int) 321 | 322 | clear_bg(cr,rect_width,rect_height) 323 | px,py = randpos(n,rect_width,rect_height) 324 | 325 | px = sort(px) 326 | 327 | set_source_rgb(cr, 0, 0, 1.0) 328 | set_line_width(cr,width) 329 | 330 | new_path(cr) 331 | move_to(cr,px[1],py[1]) 332 | for i=2:n 333 | line_to(cr,px[i],py[i]) 334 | end 335 | stroke(cr) 336 | end 337 | 338 | # lines2, x sorted, independent lines per coord 339 | function lines2(cr::CairoContext, rect_width::Real, rect_height::Real, width::Real, n::Int) 340 | 341 | clear_bg(cr,rect_width,rect_height) 342 | px,py = randpos(n,rect_width,rect_height) 343 | 344 | px = sort(px) 345 | 346 | set_source_rgb(cr, 0, 0, 1.0) 347 | set_line_width(cr,width) 348 | 349 | new_path(cr) 350 | for i=1:n-1 351 | move_to(cr,px[i],py[i]) 352 | line_to(cr,px[i+1],py[i+1]) 353 | stroke(cr) 354 | end 355 | end 356 | 357 | # lines3, x sorted, in clusters of 100 358 | function lines3(cr::CairoContext, rect_width::Real, rect_height::Real, width::Real, n::Int) 359 | 360 | clear_bg(cr,rect_width,rect_height) 361 | px,py = randpos(n,rect_width,rect_height) 362 | 363 | px = sort(px) 364 | 365 | set_source_rgb(cr, 0, 0, 1.0) 366 | set_line_width(cr,width) 367 | new_path(cr) 368 | for c = 1:100:n 369 | move_to(cr,px[c],py[c]) 370 | for i=c:min(c+100,n) 371 | line_to(cr,px[i],py[i]) 372 | end 373 | stroke(cr) 374 | end 375 | end 376 | 377 | # lines4, x sorted, in clusters of 1000 378 | function lines4(cr::CairoContext, rect_width::Real, rect_height::Real, width::Real, n::Int) 379 | 380 | clear_bg(cr,rect_width,rect_height) 381 | px,py = randpos(n,rect_width,rect_height) 382 | 383 | px = sort(px) 384 | 385 | set_source_rgb(cr, 0, 0, 1.0) 386 | set_line_width(cr,width) 387 | new_path(cr) 388 | for c = 1:1000:n 389 | move_to(cr,px[c],py[c]) 390 | for i=c:min(c+1000,n) 391 | line_to(cr,px[i],py[i]) 392 | end 393 | stroke(cr) 394 | end 395 | end 396 | -------------------------------------------------------------------------------- /src/constants.jl: -------------------------------------------------------------------------------- 1 | ## Cairo Constants ## 2 | 3 | # deprecated exports---do not add more! 4 | export CAIRO_FORMAT_ARGB32, 5 | CAIRO_FORMAT_RGB24, 6 | CAIRO_FORMAT_A8, 7 | CAIRO_FORMAT_A1, 8 | CAIRO_FORMAT_RGB16_565, 9 | CAIRO_CONTENT_COLOR, 10 | CAIRO_CONTENT_ALPHA, 11 | CAIRO_CONTENT_COLOR_ALPHA, 12 | CAIRO_FILTER_FAST, 13 | CAIRO_FILTER_GOOD, 14 | CAIRO_FILTER_BEST, 15 | CAIRO_FILTER_NEAREST, 16 | CAIRO_FILTER_BILINEAR, 17 | CAIRO_FILTER_GAUSSIAN 18 | 19 | const format_t = Int32 20 | const FORMAT_INVALID = Int32(-1) 21 | const FORMAT_ARGB32 = Int32(0) 22 | const FORMAT_RGB24 = Int32(1) 23 | const FORMAT_A8 = Int32(2) 24 | const FORMAT_A1 = Int32(3) 25 | const FORMAT_RGB16_565 = Int32(4) 26 | const FORMAT_RGB30 = Int32(5) 27 | 28 | const status_t = Int32 29 | const STATUS_SUCCESS = Int32(0) 30 | const STATUS_NO_MEMORY = Int32(1) 31 | const STATUS_INVALID_RESTORE = Int32(2) 32 | const STATUS_INVALID_POP_GROUP = Int32(3) 33 | const STATUS_NO_CURRENT_POINT = Int32(4) 34 | const STATUS_INVALID_MATRIX = Int32(5) 35 | const STATUS_INVALID_STATUS = Int32(6) 36 | const STATUS_NULL_POINTER = Int32(7) 37 | const STATUS_INVALID_STRING = Int32(8) 38 | const STATUS_INVALID_PATH_DATA = Int32(9) 39 | const STATUS_READ_ERROR = Int32(10) 40 | const STATUS_WRITE_ERROR = Int32(11) 41 | const STATUS_SURFACE_FINISHED = Int32(12) 42 | const STATUS_SURFACE_TYPE_MISMATCH = Int32(13) 43 | const STATUS_PATTERN_TYPE_MISMATCH = Int32(14) 44 | const STATUS_INVALID_CONTENT = Int32(15) 45 | const STATUS_INVALID_FORMAT = Int32(16) 46 | const STATUS_INVALID_VISUAL = Int32(17) 47 | const STATUS_FILE_NOT_FOUND = Int32(17) 48 | const STATUS_INVALID_DASH = Int32(18) 49 | const STATUS_INVALID_DSC_COMMENT = Int32(19) 50 | const STATUS_INVALID_INDEX = Int32(20) 51 | const STATUS_CLIP_NOT_REPRESENTABLE = Int32(21) 52 | const STATUS_TEMP_FILE_ERROR = Int32(22) 53 | const STATUS_INVALID_STRIDE = Int32(23) 54 | const STATUS_FONT_TYPE_MISMATCH = Int32(24) 55 | const STATUS_USER_FONT_IMMUTABLE = Int32(25) 56 | const STATUS_USER_FONT_ERROR = Int32(26) 57 | const STATUS_NEGATIVE_COUNT = Int32(27) 58 | const STATUS_INVALID_CLUSTERS = Int32(28) 59 | const STATUS_INVALID_SLANT = Int32(29) 60 | const STATUS_INVALID_WEIGHT = Int32(30) 61 | const STATUS_INVALID_SIZE = Int32(31) 62 | const STATUS_USER_FONT_NOT_IMPLEMENTED = Int32(32) 63 | const STATUS_DEVICE_TYPE_MISMATCH = Int32(33) 64 | const STATUS_DEVICE_ERROR = Int32(34) 65 | const STATUS_INVALID_MESH_CONSTRUCTION = Int32(35) 66 | const STATUS_DEVICE_FINISHED = Int32(36) 67 | const STATUS_LAST_STATUS = Int32(37) 68 | 69 | const surface_t = Int32 70 | const CAIRO_SURFACE_TYPE_IMAGE = Int32(0) 71 | const CAIRO_SURFACE_TYPE_PDF, = Int32(1) 72 | const CAIRO_SURFACE_TYPE_PS, = Int32(2) 73 | const CAIRO_SURFACE_TYPE_XLIB, = Int32(3) 74 | const CAIRO_SURFACE_TYPE_XCB, = Int32(4) 75 | const CAIRO_SURFACE_TYPE_GLITZ, = Int32(5) 76 | const CAIRO_SURFACE_TYPE_QUARTZ, = Int32(6) 77 | const CAIRO_SURFACE_TYPE_WIN32, = Int32(7) 78 | const CAIRO_SURFACE_TYPE_BEOS, = Int32(8) 79 | const CAIRO_SURFACE_TYPE_DIRECTFB, = Int32(9) 80 | const CAIRO_SURFACE_TYPE_SVG, = Int32(10) 81 | const CAIRO_SURFACE_TYPE_OS2, = Int32(11) 82 | const CAIRO_SURFACE_TYPE_WIN32_PRINTING, = Int32(12) 83 | const CAIRO_SURFACE_TYPE_QUARTZ_IMAGE, = Int32(13) 84 | const CAIRO_SURFACE_TYPE_SCRIPT, = Int32(14) 85 | const CAIRO_SURFACE_TYPE_QT, = Int32(15) 86 | const CAIRO_SURFACE_TYPE_RECORDING, = Int32(16) 87 | const CAIRO_SURFACE_TYPE_VG, = Int32(17) 88 | const CAIRO_SURFACE_TYPE_GL, = Int32(18) 89 | const CAIRO_SURFACE_TYPE_DRM, = Int32(19) 90 | const CAIRO_SURFACE_TYPE_TEE, = Int32(20) 91 | const CAIRO_SURFACE_TYPE_XML, = Int32(21) 92 | const CAIRO_SURFACE_TYPE_SKIA, = Int32(22) 93 | const CAIRO_SURFACE_TYPE_SUBSURFACE, = Int32(23) 94 | const CAIRO_SURFACE_TYPE_COGL = Int32(24) 95 | 96 | 97 | const font_slant_t = Int32 98 | const FONT_SLANT_NORMAL = Int32(0) 99 | const FONT_SLANT_ITALIC = Int32(1) 100 | const FONT_SLANT_OBLIQUE = Int32(2) 101 | 102 | const font_weight_t = Int32 103 | const FONT_WEIGHT_NORMAL = Int32(0) 104 | const FONT_WEIGHT_BOLD = Int32(1) 105 | 106 | const CONTENT_COLOR = Int32(0x1000) 107 | const CONTENT_ALPHA = Int32(0x2000) 108 | const CONTENT_COLOR_ALPHA = Int32(0x3000) 109 | 110 | const FILTER_FAST = 0 111 | const FILTER_GOOD = 1 112 | const FILTER_BEST = 2 113 | const FILTER_NEAREST = 3 114 | const FILTER_BILINEAR = 4 115 | const FILTER_GAUSSIAN = 5 116 | 117 | const EXTEND_NONE = 0 118 | const EXTEND_REPEAT = 1 119 | const EXTEND_REFLECT = 2 120 | const EXTEND_PAD = 3 121 | 122 | const ANTIALIAS_DEFAULT = 0 123 | const ANTIALIAS_NONE = 1 124 | const ANTIALIAS_GRAY = 2 125 | const ANTIALIAS_SUBPIXEL = 3 126 | # next 3 are not available on all Cairo installations (only since 1.12) 127 | const ANTIALIAS_FAST = 4 128 | const ANTIALIAS_GOOD = 5 129 | const ANTIALIAS_BEST = 6 130 | 131 | const OPERATOR_CLEAR = 0 132 | const OPERATOR_SOURCE = 1 133 | const OPERATOR_OVER = 2 134 | const OPERATOR_IN = 3 135 | const OPERATOR_OUT = 4 136 | const OPERATOR_ATOP = 5 137 | const OPERATOR_DEST = 6 138 | const OPERATOR_DEST_OVER = 7 139 | const OPERATOR_DEST_IN = 8 140 | const OPERATOR_DEST_OUT = 9 141 | const OPERATOR_DEST_ATOP = 10 142 | const OPERATOR_XOR = 11 143 | const OPERATOR_ADD = 12 144 | const OPERATOR_SATURATE = 13 145 | const OPERATOR_MULTIPLY = 14 146 | const OPERATOR_SCREEN = 15 147 | const OPERATOR_OVERLAY = 16 148 | const OPERATOR_DARKEN = 17 149 | const OPERATOR_LIGHTEN = 18 150 | 151 | 152 | ## LaTex Token Dicts ## 153 | const _common_token_dict = Dict( 154 | "\\{" => "{", 155 | "\\}" => "}", 156 | "\\_" => "_", 157 | "\\^" => "^", 158 | "\\-" => "-", 159 | 160 | ## ignore stray brackets 161 | "{" => "", 162 | "}" => "" 163 | ) 164 | 165 | const _text_token_dict = Dict( 166 | ## non-math symbols (p438) 167 | "\\S" => "\ua7", 168 | "\\P" => "\ub6", 169 | "\\dag" => "\u2020", 170 | "\\ddag" => "\u2021" 171 | ) 172 | 173 | const _math_token_dict = Dict( 174 | 175 | "-" => "\u2212", # minus sign 176 | 177 | ## spacing 178 | "\\quad" => "\u2003", # 1 em 179 | "\\qquad" => "\u2003\u2003", # 2 em 180 | "\\," => "\u2006", # 3/18 em 181 | "\\>" => "\u2005", # 4/18 em 182 | "\\;" => "\u2004", # 5/18 em 183 | 184 | ## lowercase greek 185 | "\\alpha" => "\u03b1", 186 | "\\beta" => "\u03b2", 187 | "\\gamma" => "\u03b3", 188 | "\\delta" => "\u03b4", 189 | "\\epsilon" => "\u03b5", 190 | "\\varepsilon" => "\u03f5", 191 | "\\zeta" => "\u03b6", 192 | "\\eta" => "\u03b7", 193 | "\\theta" => "\u03b8", 194 | "\\vartheta" => "\u03d1", 195 | "\\iota" => "\u03b9", 196 | "\\kappa" => "\u03ba", 197 | "\\lambda" => "\u03bb", 198 | "\\mu" => "\u03bc", 199 | "\\nu" => "\u03bd", 200 | "\\xi" => "\u03be", 201 | "\\omicron" => "\u03bf", 202 | "\\pi" => "\u03c0", 203 | "\\varpi" => "\u03d6", 204 | "\\rho" => "\u03c1", 205 | "\\varrho" => "\u03f1", 206 | "\\sigma" => "\u03c3", 207 | "\\varsigma" => "\u03c2", 208 | "\\tau" => "\u03c4", 209 | "\\upsilon" => "\u03c5", 210 | "\\phi" => "\u03d5", 211 | "\\varphi" => "\u03c6", 212 | "\\chi" => "\u03c7", 213 | "\\psi" => "\u03c8", 214 | "\\omega" => "\u03c9", 215 | 216 | ## uppercase greek 217 | "\\Alpha" => "\u0391", 218 | "\\Beta" => "\u0392", 219 | "\\Gamma" => "\u0393", 220 | "\\Delta" => "\u0394", 221 | "\\Epsilon" => "\u0395", 222 | "\\Zeta" => "\u0396", 223 | "\\Eta" => "\u0397", 224 | "\\Theta" => "\u0398", 225 | "\\Iota" => "\u0399", 226 | "\\Kappa" => "\u039a", 227 | "\\Lambda" => "\u039b", 228 | "\\Mu" => "\u039c", 229 | "\\Nu" => "\u039d", 230 | "\\Xi" => "\u039e", 231 | "\\Pi" => "\u03a0", 232 | "\\Rho" => "\u03a1", 233 | "\\Sigma" => "\u03a3", 234 | "\\Tau" => "\u03a4", 235 | "\\Upsilon" => "\u03a5", 236 | "\\Phi" => "\u03a6", 237 | "\\Chi" => "\u03a7", 238 | "\\Psi" => "\u03a8", 239 | "\\Omega" => "\u03a9", 240 | 241 | ## miscellaneous 242 | "\\aleph" => "\u2135", 243 | "\\hbar" => "\u210f", 244 | "\\ell" => "\u2113", 245 | "\\wp" => "\u2118", 246 | "\\Re" => "\u211c", 247 | "\\Im" => "\u2111", 248 | "\\partial" => "\u2202", 249 | "\\infty" => "\u221e", 250 | "\\prime" => "\u2032", 251 | "\\emptyset" => "\u2205", 252 | "\\nabla" => "\u2206", 253 | "\\surd" => "\u221a", 254 | "\\top" => "\u22a4", 255 | "\\bot" => "\u22a5", 256 | "\\|" => "\u2225", 257 | "\\angle" => "\u2220", 258 | "\\triangle" => "\u25b3", # == \bigtriangleup 259 | "\\backslash" => "\u2216", 260 | "\\forall" => "\u2200", 261 | "\\exists" => "\u2203", 262 | "\\neg" => "\uac", 263 | "\\flat" => "\u266d", 264 | "\\natural" => "\u266e", 265 | "\\sharp" => "\u266f", 266 | "\\clubsuit" => "\u2663", 267 | "\\diamondsuit" => "\u2662", 268 | "\\heartsuit" => "\u2661", 269 | "\\spadesuit" => "\u2660", 270 | 271 | ## large operators 272 | "\\sum" => "\u2211", 273 | "\\prod" => "\u220f", 274 | "\\coprod" => "\u2210", 275 | "\\int" => "\u222b", 276 | "\\oint" => "\u222e", 277 | "\\bigcap" => "\u22c2", 278 | "\\bigcup" => "\u22c3", 279 | "\\bigscup" => "\u2a06", 280 | "\\bigvee" => "\u22c1", 281 | "\\bigwedge" => "\u22c0", 282 | "\\bigodot" => "\u2a00", 283 | "\\bigotimes" => "\u2a02", 284 | "\\bigoplus" => "\u2a01", 285 | "\\biguplus" => "\u2a04", 286 | 287 | ## binary operations 288 | "\\pm" => "\ub1", 289 | "\\mp" => "\u2213", 290 | "\\setminus" => "\u2216", 291 | "\\cdot" => "\u22c5", 292 | "\\times" => "\ud7", 293 | "\\ast" => "\u2217", 294 | "\\star" => "\u22c6", 295 | "\\diamond" => "\u22c4", 296 | "\\circ" => "\u2218", 297 | "\\bullet" => "\u2219", 298 | "\\div" => "\uf7", 299 | "\\cap" => "\u2229", 300 | "\\cup" => "\u222a", 301 | "\\uplus" => "\u228c", # 228e? 302 | "\\sqcap" => "\u2293", 303 | "\\sqcup" => "\u2294", 304 | "\\triangleleft" => "\u22b2", 305 | "\\triangleright" => "\u22b3", 306 | "\\wr" => "\u2240", 307 | "\\bigcirc" => "\u25cb", 308 | "\\bigtriangleup" => "\u25b3", # == \triangle 309 | "\\bigtriangledown" => "\u25bd", 310 | "\\vee" => "\u2228", 311 | "\\wedge" => "\u2227", 312 | "\\oplus" => "\u2295", 313 | "\\ominus" => "\u2296", 314 | "\\otimes" => "\u2297", 315 | "\\oslash" => "\u2298", 316 | "\\odot" => "\u2299", 317 | "\\dagger" => "\u2020", 318 | "\\ddagger" => "\u2021", 319 | "\\amalg" => "\u2210", 320 | 321 | ## relations 322 | "\\leq" => "\u2264", 323 | "\\prec" => "\u227a", 324 | "\\preceq" => "\u227c", 325 | "\\ll" => "\u226a", 326 | "\\subset" => "\u2282", 327 | "\\subseteq" => "\u2286", 328 | "\\sqsubseteq" => "\u2291", 329 | "\\in" => "\u2208", 330 | "\\vdash" => "\u22a2", 331 | "\\smile" => "\u2323", 332 | "\\frown" => "\u2322", 333 | "\\geq" => "\u2265", 334 | "\\succ" => "\u227b", 335 | "\\succeq" => "\u227d", 336 | "\\gg" => "\u226b", 337 | "\\supset" => "\u2283", 338 | "\\supseteq" => "\u2287", 339 | "\\sqsupseteq" => "\u2292", 340 | "\\ni" => "\u220b", 341 | "\\dashv" => "\u22a3", 342 | "\\mid" => "\u2223", 343 | "\\parallel" => "\u2225", 344 | "\\equiv" => "\u2261", 345 | "\\sim" => "\u223c", 346 | "\\simeq" => "\u2243", 347 | "\\asymp" => "\u224d", 348 | "\\approx" => "\u2248", 349 | "\\cong" => "\u2245", 350 | "\\bowtie" => "\u22c8", 351 | "\\propto" => "\u221d", 352 | "\\models" => "\u22a7", # 22a8? 353 | "\\doteq" => "\u2250", 354 | "\\perp" => "\u27c2", 355 | 356 | ## arrows 357 | "\\leftarrow" => "\u2190", 358 | "\\Leftarrow" => "\u21d0", 359 | "\\rightarrow" => "\u2192", 360 | "\\Rightarrow" => "\u21d2", 361 | "\\leftrightarrow" => "\u2194", 362 | "\\Leftrightarrow" => "\u21d4", 363 | "\\mapsto" => "\u21a6", 364 | "\\hookleftarrow" => "\u21a9", 365 | "\\leftharpoonup" => "\u21bc", 366 | "\\leftharpoondown" => "\u21bd", 367 | "\\rightleftharpoons" => "\u21cc", 368 | "\\longleftarrow" => "\u27f5", 369 | "\\Longleftarrow" => "\u27f8", 370 | "\\longrightarrow" => "\u27f6", 371 | "\\Longrightarrow" => "\u27f9", 372 | "\\longleftrightarrow" => "\u27f7", 373 | "\\Longleftrightarrow" => "\u27fa", 374 | "\\hookrightarrow" => "\u21aa", 375 | "\\rightharpoonup" => "\u21c0", 376 | "\\rightharpoondown" => "\u21c1", 377 | "\\uparrow" => "\u2191", 378 | "\\Uparrow" => "\u21d1", 379 | "\\downarrow" => "\u2193", 380 | "\\Downarrow" => "\u21d3", 381 | "\\updownarrow" => "\u2195", 382 | "\\Updownarrow" => "\u21d5", 383 | "\\nearrow" => "\u2197", 384 | "\\searrow" => "\u2198", 385 | "\\swarrow" => "\u2199", 386 | "\\nwarrow" => "\u2196", 387 | 388 | ## openings 389 | # "\\lbrack" => "[", 390 | # "\\lbrace" => "{", 391 | "\\langle" => "\u27e8", 392 | "\\lfloor" => "\u230a", 393 | "\\lceil" => "\u2308", 394 | 395 | ## closings 396 | # "\\rbrack" => "]", 397 | # "\\rbrace" => "}", 398 | "\\rangle" => "\u27e9", 399 | "\\rfloor" => "\u230b", 400 | "\\rceil" => "\u2309", 401 | 402 | ## alternate names 403 | "\\ne" => "\u2260", 404 | "\\neq" => "\u2260", 405 | "\\le" => "\u2264", 406 | "\\ge" => "\u2265", 407 | "\\to" => "\u2192", 408 | "\\gets" => "\u2192", 409 | "\\owns" => "\u220b", 410 | "\\land" => "\u2227", 411 | "\\lor" => "\u2228", 412 | "\\lnot" => "\uac", 413 | "\\vert" => "\u2223", 414 | "\\Vert" => "\u2225", 415 | 416 | ## extensions 417 | "\\deg" => "\ub0", 418 | "\\degr" => "\ub0", 419 | "\\degree" => "\ub0", 420 | "\\degrees" => "\ub0", 421 | "\\arcdeg" => "\ub0", 422 | "\\arcmin" => "\u2032", 423 | "\\arcsec" => "\u2033" 424 | ) 425 | 426 | const CAIRO_FILL_RULE_WINDING = Int32(0); 427 | const CAIRO_FILL_RULE_EVEN_ODD = Int32(1); 428 | 429 | const CAIRO_LINE_CAP_BUTT = Int32(0); 430 | const CAIRO_LINE_CAP_ROUND = Int32(1); 431 | const CAIRO_LINE_CAP_SQUARE = Int32(2); 432 | 433 | const CAIRO_LINE_JOIN_MITER = Int32(0); 434 | const CAIRO_LINE_JOIN_ROUND = Int32(1); 435 | const CAIRO_LINE_JOIN_BEVEL = Int32(2); 436 | 437 | #typedef enum _cairo_path_data_type { 438 | # CAIRO_PATH_MOVE_TO, 439 | # CAIRO_PATH_LINE_TO, 440 | # CAIRO_PATH_CURVE_TO, 441 | # CAIRO_PATH_CLOSE_PATH 442 | #} cairo_path_data_type_t; 443 | 444 | const CAIRO_PATH_MOVE_TO = Int32(0); 445 | const CAIRO_PATH_LINE_TO = Int32(1); 446 | const CAIRO_PATH_CURVE_TO = Int32(2); 447 | const CAIRO_PATH_CLOSE_PATH = Int32(3); 448 | 449 | 450 | -------------------------------------------------------------------------------- /src/Cairo.jl: -------------------------------------------------------------------------------- 1 | module Cairo 2 | 3 | import Base.Sys 4 | 5 | # For libcairo 6 | using Cairo_jll 7 | # For libpangocairo 8 | using Pango_jll 9 | # For libgobject 10 | using Glib_jll 11 | 12 | # Deprecate old library variables 13 | Base.@deprecate_binding _jl_libcairo Cairo.libcairo false 14 | Base.@deprecate_binding _jl_libgobject Cairo.libgobject false 15 | Base.@deprecate_binding _jl_libpango Cairo.libpango false 16 | Base.@deprecate_binding _jl_libpangocairo Cairo.libpango false 17 | 18 | using Colors 19 | 20 | import Graphics 21 | using Graphics: BoundingBox, GraphicsContext, GraphicsDevice 22 | import Graphics: arc, clip, clip_preserve, close_path, creategc, device_to_user!, device_to_user_distance!, fill_preserve, height, line_to, move_to, new_path, new_sub_path, paint, rectangle, rel_line_to, rel_move_to, reset_clip, restore, rotate, save, scale, set_dash, set_line_width, set_source, set_source_rgb, set_source_rgba, stroke, stroke_preserve, stroke_transformed, stroke_transformed_preserve, textwidth, translate, user_to_device!, user_to_device_distance!, width, circle, reset_transform 23 | import Base: copy, fill 24 | 25 | libcairo_version = VersionNumber(unsafe_string( 26 | ccall((:cairo_version_string,Cairo.libcairo),Cstring,()) )) 27 | libpango_version = VersionNumber(unsafe_string( 28 | ccall((:pango_version_string,Cairo.libpango),Cstring,()) )) 29 | if !Sys.iswindows() 30 | libpangocairo_version = VersionNumber(unsafe_string( 31 | ccall((:pango_version_string,Cairo.libpangocairo),Cstring,()) )) 32 | libgobject_version = VersionNumber( 33 | unsafe_load(cglobal((:glib_major_version, Cairo.libgobject), Cuint)), 34 | unsafe_load(cglobal((:glib_minor_version, Cairo.libgobject), Cuint)), 35 | unsafe_load(cglobal((:glib_micro_version, Cairo.libgobject), Cuint))) 36 | end 37 | 38 | import Base.show 39 | 40 | include("constants.jl") 41 | 42 | export 43 | # drawing surface and context types 44 | CairoSurface, CairoContext, CairoPattern, 45 | 46 | # surface constructors 47 | CairoRGBSurface, CairoPDFSurface, CairoEPSSurface, CairoXlibSurface, 48 | CairoARGBSurface, CairoSVGSurface, CairoImageSurface, CairoQuartzSurface, 49 | CairoWin32Surface, CairoScriptSurface, CairoRecordingSurface, 50 | CairoPSSurface, surface_create_similar, 51 | 52 | # surface and context management 53 | finish, destroy, status, get_source, 54 | creategc, save, restore, show_page, width, height, 55 | 56 | # pattern 57 | pattern_create_radial, pattern_create_linear, 58 | pattern_add_color_stop_rgb, pattern_add_color_stop_rgba, 59 | pattern_set_filter, pattern_set_extend, pattern_get_surface, 60 | 61 | # mesh patterns (version > 1.12) 62 | CairoPatternMesh, 63 | mesh_pattern_begin_patch, mesh_pattern_end_patch, 64 | mesh_pattern_move_to, mesh_pattern_line_to, 65 | mesh_pattern_curve_to, 66 | mesh_pattern_set_corner_color_rgb, 67 | mesh_pattern_set_corner_color_rgba, 68 | 69 | # drawing attribute manipulation 70 | set_antialias, get_antialias, 71 | set_fill_type, set_line_width, set_dash, 72 | set_source_rgb, set_source_rgba, set_source_surface, set_line_type, 73 | set_line_cap, set_line_join, 74 | set_operator, get_operator, set_source, 75 | CairoMatrix, 76 | 77 | # coordinate systems 78 | reset_transform, rotate, scale, translate, user_to_device!, 79 | device_to_user!, user_to_device_distance!, device_to_user_distance!, 80 | get_matrix, set_matrix, 81 | 82 | # clipping 83 | clip, clip_preserve, reset_clip, 84 | 85 | # fill, stroke, path, and shape commands 86 | fill, fill_preserve, new_path, new_sub_path, close_path, paint, paint_with_alpha, stroke, 87 | stroke_preserve, stroke_transformed, stroke_transformed_preserve, 88 | move_to, line_to, rel_line_to, rel_move_to, 89 | rectangle, circle, arc, arc_negative, 90 | curve_to, rel_curve_to, 91 | path_extents, 92 | 93 | # path copy 94 | copy_path, copy_path_flat, convert_cairo_path_data, 95 | 96 | # other path operations 97 | get_current_point, has_current_point, 98 | 99 | # text 100 | text, 101 | update_layout, show_layout, get_layout_size, layout_text, 102 | set_text, set_latex, 103 | set_font_face, set_font_size, select_font_face, 104 | textwidth, textheight, text_extents, 105 | TeXLexer, tex2pango, show_text, text_path, 106 | 107 | # images 108 | write_to_png, image, read_from_png, 109 | 110 | # push+pop group 111 | push_group, pop_group 112 | 113 | ## head docstring following 114 | 115 | " 116 | Surfaces, the canvas you are painting on 117 | 118 | CairoSurface, CairoRGBSurface, CairoPDFSurface, CairoEPSSurface, 119 | CairoXlibSurface, CairoARGBSurface, CairoSVGSurface, 120 | CairoImageSurface, CairoQuartzSurface, 121 | CairoWin32Surface, CairoScriptSurface, CairoRecordingSurface, 122 | CairoPSSurface, 123 | 124 | Context, the handle to coordinate transformation, paint+Color 125 | 126 | CairoContext, finish, destroy, status, get_source, 127 | creategc, save, restore, show_page, width, height 128 | 129 | Path creation API 130 | 131 | new_path, new_sub_path, close_path, 132 | move_to, line_to, rel_line_to, rel_move_to, 133 | rectangle, circle, arc, arc_negative, 134 | curve_to, rel_curve_to, 135 | path_extents, 136 | 137 | 138 | Stroking and painting API 139 | 140 | fill, fill_preserve, paint, paint_with_alpha, stroke, 141 | stroke_preserve, stroke_transformed, stroke_transformed_preserve 142 | 143 | CairoContext, finish, destroy, status, get_source, 144 | creategc, save, restore, show_page, width, height 145 | 146 | " 147 | Cairo 148 | 149 | function write_to_stream_callback(s::IO, buf::Ptr{UInt8}, len::UInt32) 150 | n = unsafe_write(s,buf,len) 151 | Int32((n == len) ? 0 : 11) 152 | end 153 | 154 | get_stream_callback(::Type{T}) where T = @cfunction write_to_stream_callback Int32 (Ref{T}, Ptr{UInt8}, UInt32) 155 | 156 | function read_from_stream_callback(s::IO, buf::Ptr{UInt8}, len::UInt32) 157 | # wrap the provided buf into a julia Array 158 | b1 = unsafe_wrap(Array,buf,len) 159 | 160 | # read from stream 161 | nb = readbytes!(s,b1,len) 162 | 163 | # provide a return status 164 | (nb == len) ? STATUS_SUCCESS : STATUS_READ_ERROR 165 | end 166 | 167 | get_readstream_callback(::Type{T}) where T = @cfunction read_from_stream_callback Int32 (Ref{T}, Ptr{UInt8}, UInt32) 168 | 169 | abstract type CairoSurface{T<:Union{UInt32,RGB24,ARGB32}} <: GraphicsDevice end 170 | 171 | mutable struct CairoSurfaceBase{T<:Union{UInt32,RGB24,ARGB32}} <: CairoSurface{T} 172 | ptr::Ptr{Nothing} 173 | width::Float64 174 | height::Float64 175 | 176 | function CairoSurface{T}(ptr::Ptr{Nothing}, w, h) where {T} 177 | self = new{T}(ptr, w, h) 178 | finalizer(destroy, self) 179 | self 180 | end 181 | function CairoSurface{T}(ptr::Ptr{Nothing}) where {T} 182 | ccall( 183 | (:cairo_surface_reference,libcairo), 184 | Ptr{Nothing}, (Ptr{Nothing}, ), ptr) 185 | self = new{T}(ptr) 186 | finalizer(destroy, self) 187 | self 188 | end 189 | end 190 | 191 | 192 | mutable struct CairoSurfaceImage{T<:Union{UInt32,RGB24,ARGB32}} <: CairoSurface{T} 193 | ptr::Ptr{Nothing} 194 | width::Float64 195 | height::Float64 196 | data::Matrix{T} 197 | 198 | function CairoSurface{T}(ptr::Ptr{Nothing}, w, h, data::Matrix{T}) where {T} 199 | self = new{T}(ptr, w, h, data) 200 | finalizer(destroy, self) 201 | self 202 | end 203 | end 204 | 205 | mutable struct CairoSurfaceIOStream{T<:Union{UInt32,RGB24,ARGB32}} <: CairoSurface{T} 206 | ptr::Ptr{Nothing} 207 | width::Float64 208 | height::Float64 209 | stream::IO 210 | 211 | function CairoSurface{T}(ptr::Ptr{Nothing}, w, h, stream::IO) where {T} 212 | self = new{T}(ptr, w, h, stream) 213 | finalizer(destroy, self) 214 | self 215 | end 216 | end 217 | function get_stream_ptr(surf::T) where {T<:CairoSurfaceIOStream} 218 | GC.@preserve surf begin 219 | return unsafe_load(Ptr{Ptr{Nothing}}(pointer_from_objref(surf) + fieldoffset(T, 4))) 220 | end 221 | end 222 | 223 | 224 | CairoSurface(ptr, w, h) = CairoSurface{UInt32}(ptr, w, h) 225 | CairoSurface(ptr, w, h, data) = CairoSurface{eltype(data)}(ptr, w, h, data) 226 | CairoSurface(ptr, w, h, stream::IO) = CairoSurface{UInt32}(ptr, w, h, stream) 227 | CairoSurface(ptr) = CairoSurface{UInt32}(ptr) 228 | 229 | width(surface::CairoSurface) = surface.width 230 | height(surface::CairoSurface) = surface.height 231 | 232 | function destroy(surface::CairoSurface) 233 | if surface.ptr == C_NULL 234 | return 235 | end 236 | ccall((:cairo_surface_destroy,libcairo), Nothing, (Ptr{Nothing},), surface.ptr) 237 | surface.ptr = C_NULL 238 | nothing 239 | end 240 | 241 | # function resize(surface::CairoSurface, w, h) 242 | # if OS_NAME == :Linux 243 | # CairoXlibSurfaceSetSize(surface.ptr, w, h) 244 | # elseif OS_NAME == :Darwin 245 | # elseif OS_NAME == :Windows 246 | # else 247 | # error("Unsupported operating system") 248 | # end 249 | # surface.width = w 250 | # surface.height = h 251 | # end 252 | 253 | for name in (:finish,:flush,:mark_dirty) 254 | @eval begin 255 | $name(surface::CairoSurface) = 256 | ccall(($(string("cairo_surface_",name)),libcairo), 257 | Nothing, (Ptr{Nothing},), surface.ptr) 258 | end 259 | end 260 | 261 | function status(surface::CairoSurface) 262 | ccall((:cairo_surface_status,libcairo), 263 | Int32, (Ptr{Nothing},), surface.ptr) 264 | end 265 | 266 | function CairoImageSurface(w::Real, h::Real, format::Integer) 267 | ptr = ccall((:cairo_image_surface_create,libcairo), 268 | Ptr{Nothing}, (Int32,Int32,Int32), format, w, h) 269 | CairoSurface(ptr, w, h) 270 | end 271 | 272 | CairoRGBSurface(w::Real, h::Real) = CairoImageSurface(w, h, FORMAT_RGB24) 273 | CairoARGBSurface(w::Real, h::Real) = CairoImageSurface(w, h, FORMAT_ARGB32) 274 | CairoARGBSurface(img) = CairoImageSurface(img, FORMAT_ARGB32) 275 | CairoRGBSurface(img) = CairoImageSurface(img, FORMAT_RGB24) 276 | 277 | function CairoImageSurface(img::Array{UInt32,2}, format::Integer; flipxy::Bool = true) 278 | if flipxy 279 | img = permutedims(img, (2,1)) 280 | end 281 | w,h = size(img) 282 | stride = format_stride_for_width(format, w) 283 | @assert stride == 4w 284 | ptr = ccall((:cairo_image_surface_create_for_data,libcairo), 285 | Ptr{Nothing}, (Ptr{Nothing},Int32,Int32,Int32,Int32), 286 | img, format, w, h, stride) 287 | CairoSurface(ptr, w, h, img) 288 | end 289 | 290 | function CairoImageSurface(img::Matrix{T}) where {T<:Union{RGB24,ARGB32}} 291 | w,h = size(img) 292 | stride = format_stride_for_width(format(T), w) 293 | @assert stride == 4w 294 | ptr = ccall((:cairo_image_surface_create_for_data,libcairo), 295 | Ptr{Nothing}, (Ptr{Nothing},Int32,Int32,Int32,Int32), 296 | img, format(T), w, h, stride) 297 | CairoSurface(ptr, w, h, img) 298 | end 299 | 300 | format(::Type{RGB24}) = FORMAT_RGB24 301 | format(::Type{ARGB32}) = FORMAT_ARGB32 302 | format(surf::CairoSurface{T}) where {T<:Union{RGB24,ARGB32}} = T 303 | 304 | ## PDF ## 305 | 306 | function CairoPDFSurface(stream::T, w::Real, h::Real) where {T<:IO} 307 | callback = get_stream_callback(T) 308 | surf = CairoSurface(C_NULL, w, h, stream) 309 | GC.@preserve surf begin 310 | surf.ptr = ccall((:cairo_pdf_surface_create_for_stream,libcairo), Ptr{Nothing}, 311 | (Ptr{Nothing}, Ptr{Nothing}, Float64, Float64), callback, 312 | get_stream_ptr(surf), w, h) 313 | end 314 | return surf 315 | end 316 | 317 | function CairoPDFSurface(filename::AbstractString, w_pts::Real, h_pts::Real) 318 | ptr = ccall((:cairo_pdf_surface_create,libcairo), Ptr{Nothing}, 319 | (Ptr{UInt8},Float64,Float64), String(filename), w_pts, h_pts) 320 | CairoSurface(ptr, w_pts, h_pts) 321 | end 322 | 323 | ## EPS ## 324 | 325 | function CairoEPSSurface(stream::T, w::Real, h::Real) where {T<:IO} 326 | callback = get_stream_callback(T) 327 | surf = CairoSurface(C_NULL, w, h, stream) 328 | GC.@preserve surf begin 329 | surf.ptr = ccall((:cairo_ps_surface_create_for_stream,libcairo), Ptr{Nothing}, 330 | (Ptr{Nothing}, Ptr{Nothing}, Float64, Float64), 331 | callback, get_stream_ptr(surf), w, h) 332 | ccall((:cairo_ps_surface_set_eps,libcairo), Nothing, 333 | (Ptr{Nothing},Int32), surf.ptr, 1) 334 | end 335 | return surf 336 | end 337 | 338 | function CairoEPSSurface(filename::AbstractString, w_pts::Real, h_pts::Real) 339 | ptr = ccall((:cairo_ps_surface_create,libcairo), Ptr{Nothing}, 340 | (Ptr{UInt8},Float64,Float64), String(filename), w_pts, h_pts) 341 | ccall((:cairo_ps_surface_set_eps,libcairo), Nothing, 342 | (Ptr{Nothing},Int32), ptr, 1) 343 | CairoSurface(ptr, w_pts, h_pts) 344 | end 345 | 346 | ## PS ## 347 | 348 | function CairoPSSurface(stream::T, w::Real, h::Real) where {T<:IO} 349 | callback = get_stream_callback(T) 350 | surf = CairoSurface(C_NULL, w, h, stream) 351 | GC.@preserve surf begin 352 | surf.ptr = ccall((:cairo_ps_surface_create_for_stream,libcairo), Ptr{Nothing}, 353 | (Ptr{Nothing}, Ptr{Nothing}, Float64, Float64), 354 | callback, get_stream_ptr(surf), w, h) 355 | ccall((:cairo_ps_surface_set_eps,libcairo), Nothing, 356 | (Ptr{Nothing},Int32), surf.ptr, 0) 357 | end 358 | return surf 359 | end 360 | 361 | function CairoPSSurface(filename::AbstractString, w_pts::Real, h_pts::Real) 362 | ptr = ccall((:cairo_ps_surface_create,libcairo), Ptr{Nothing}, 363 | (Ptr{UInt8},Float64,Float64), String(filename), w_pts, h_pts) 364 | ccall((:cairo_ps_surface_set_eps,libcairo), Nothing, 365 | (Ptr{Nothing},Int32), ptr, 0) 366 | CairoSurface(ptr, w_pts, h_pts) 367 | end 368 | 369 | ## Xlib ## 370 | 371 | function CairoXlibSurface(display, drawable, visual, w, h) 372 | ptr = ccall((:cairo_xlib_surface_create,libcairo), Ptr{Nothing}, 373 | (Ptr{Nothing}, Int, Ptr{Nothing}, Int32, Int32), 374 | display, drawable, visual, w, h) 375 | CairoSurface(ptr, w, h) 376 | end 377 | 378 | CairoXlibSurfaceSetSize(surface, w, h) = 379 | ccall((:cairo_xlib_surface_set_size,libcairo), Nothing, 380 | (Ptr{Nothing}, Int32, Int32), 381 | surface, w, h) 382 | 383 | ## Quartz ## 384 | function CairoQuartzSurface(context, w, h) 385 | ptr = ccall((:cairo_quartz_surface_create_for_cg_context,libcairo), 386 | Ptr{Nothing}, (Ptr{Nothing}, UInt32, UInt32), context, w, h) 387 | CairoSurface(ptr, w, h) 388 | end 389 | 390 | ## Win32 ## 391 | 392 | function CairoWin32Surface(hdc,w,h) 393 | ptr = ccall((:cairo_win32_surface_create, libcairo), 394 | Ptr{Nothing}, (Ptr{Nothing},), hdc) 395 | CairoSurface(ptr,w,h) 396 | end 397 | 398 | ## SVG ## 399 | 400 | function CairoSVGSurface(stream::T, w::Real, h::Real) where {T<:IO} 401 | callback = get_stream_callback(T) 402 | surf = CairoSurface(C_NULL, w, h, stream) 403 | GC.@preserve surf begin 404 | surf.ptr = ccall((:cairo_svg_surface_create_for_stream,libcairo), Ptr{Nothing}, 405 | (Ptr{Nothing}, Ptr{Nothing}, Float64, Float64), callback, 406 | get_stream_ptr(surf), w, h) 407 | end 408 | return surf 409 | end 410 | 411 | function CairoSVGSurface(filename::AbstractString, w::Real, h::Real) 412 | ptr = ccall((:cairo_svg_surface_create,libcairo), Ptr{Nothing}, 413 | (Ptr{UInt8},Float64,Float64), String(filename), w, h) 414 | CairoSurface(ptr, w, h) 415 | end 416 | 417 | ## PNG ## 418 | 419 | function read_from_png(filename::AbstractString) 420 | ptr = ccall((:cairo_image_surface_create_from_png,libcairo), 421 | Ptr{Nothing}, (Ptr{UInt8},), String(filename)) 422 | w = ccall((:cairo_image_surface_get_width,libcairo), 423 | Int32, (Ptr{Nothing},), ptr) 424 | h = ccall((:cairo_image_surface_get_height,libcairo), 425 | Int32, (Ptr{Nothing},), ptr) 426 | CairoSurface(ptr, w, h) 427 | end 428 | 429 | function write_to_png(surface::CairoSurface, stream::T) where {T<:IO} 430 | callback = get_stream_callback(T) 431 | ccall((:cairo_surface_write_to_png_stream,libcairo), status_t, 432 | (Ptr{UInt8},Ptr{Nothing},Any), surface.ptr, callback, stream) 433 | end 434 | 435 | function write_to_png(surface::CairoSurface, filename::AbstractString) 436 | ccall((:cairo_surface_write_to_png,libcairo), status_t, 437 | (Ptr{UInt8},Ptr{UInt8}), surface.ptr, String(filename)) 438 | end 439 | 440 | show(io::IO, ::MIME"image/png", surface::CairoSurface) = 441 | write_to_png(surface, io) 442 | 443 | function read_from_png(stream::T) where {T<:IO} 444 | callback = get_readstream_callback(T) 445 | ptr = ccall((:cairo_image_surface_create_from_png_stream, Cairo.libcairo), 446 | Ptr{Nothing}, (Ptr{Nothing},Ref{IO}), callback, stream) 447 | w = ccall((:cairo_image_surface_get_width,Cairo.libcairo), 448 | Int32, (Ptr{Nothing},), ptr) 449 | h = ccall((:cairo_image_surface_get_height,Cairo.libcairo), 450 | Int32, (Ptr{Nothing},), ptr) 451 | Cairo.CairoSurface(ptr, w, h) 452 | end 453 | 454 | 455 | ## Generic ## 456 | 457 | function surface_create_similar(s::CairoSurface, w = width(s), h = height(s)) 458 | ptr = ccall((:cairo_surface_create_similar,libcairo), Ptr{Nothing}, 459 | (Ptr{Nothing}, Int32, Int32, Int32), 460 | s.ptr, CONTENT_COLOR_ALPHA, w, h) 461 | CairoSurface(ptr, w, h) 462 | end 463 | 464 | # Utilities 465 | 466 | function format_stride_for_width(format::Integer, width::Integer) 467 | ccall((:cairo_format_stride_for_width,libcairo), Int32, 468 | (Int32,Int32), format, width) 469 | end 470 | 471 | 472 | ## Scripting (only target IO stream) 473 | 474 | mutable struct CairoScript <: GraphicsDevice 475 | ptr::Ptr{Nothing} 476 | stream::IO 477 | 478 | function CairoScript(stream::T) where {T<:IO} 479 | callback = get_stream_callback(T) 480 | self = new(C_NULL, stream) 481 | GC.@preserve self begin 482 | self.ptr = ccall((:cairo_script_create_for_stream,libcairo), Ptr{Nothing}, 483 | (Ptr{Nothing}, Ptr{Nothing}), callback, get_stream_ptr(self)) 484 | end 485 | finalizer(destroy, self) 486 | self 487 | end 488 | end 489 | function get_stream_ptr(s::T) where {T<:CairoScript} 490 | GC.@preserve s begin 491 | return unsafe_load(Ptr{Ptr{Nothing}}(pointer_from_objref(s) + fieldoffset(T, 2))) 492 | end 493 | end 494 | 495 | function destroy(s::CairoScript) 496 | if s.ptr == C_NULL 497 | return 498 | end 499 | ccall((:cairo_device_destroy,libcairo), Nothing, (Ptr{Nothing},), s.ptr) 500 | s.ptr = C_NULL 501 | nothing 502 | end 503 | 504 | function CairoScriptSurface(stream::IO, w::Real, h::Real) 505 | s = CairoScript(stream) 506 | ptr = ccall((:cairo_script_surface_create,libcairo), Ptr{Nothing}, 507 | (Ptr{Nothing},Int32,Float64,Float64),s.ptr ,CONTENT_COLOR_ALPHA, w, h) 508 | CairoSurface(ptr, w, h, stream) 509 | end 510 | 511 | function CairoScriptSurface(stream::IO, sc::CairoSurface) 512 | s = CairoScript(stream) 513 | ptr = ccall((:cairo_script_surface_create_for_target,libcairo), Ptr{Nothing}, 514 | (Ptr{Nothing},Ptr{Nothing}),s.ptr, sc.ptr) 515 | CairoSurface(ptr, sc.width, sc.height) 516 | end 517 | 518 | 519 | 520 | mutable struct CairoRectangle 521 | x0::Float64 522 | y0::Float64 523 | x1::Float64 524 | y1::Float64 525 | end 526 | 527 | CairoRectangle() = CairoRectangle(0.0, 0.0, 0.0, 0.0) 528 | 529 | function CairoRecordingSurface(content::Int32,extents::CairoRectangle) 530 | ptr = ccall((:cairo_recording_surface_create,libcairo), Ptr{Nothing}, 531 | (Int32,Ptr{Nothing}),content, Ref(extents)) 532 | CairoSurface(ptr) 533 | end 534 | function CairoRecordingSurface(content::Int32) 535 | ptr = ccall((:cairo_recording_surface_create,libcairo), Ptr{Nothing}, 536 | (Int32,Ptr{Nothing}),content, C_NULL) 537 | CairoSurface(ptr) 538 | end 539 | 540 | CairoRecordingSurface() = CairoRecordingSurface(CONTENT_COLOR_ALPHA) 541 | 542 | 543 | function script_from_recording_surface(s::CairoScript,r::CairoSurface) 544 | ccall((:cairo_script_from_recording_surface,libcairo), Int32, 545 | (Ptr{Nothing},Ptr{Nothing}),s.ptr, r.ptr) 546 | end 547 | # ----------------------------------------------------------------------------- 548 | 549 | mutable struct CairoContext <: GraphicsContext 550 | ptr::Ptr{Nothing} 551 | surface::CairoSurface 552 | layout::Ptr{Nothing} # cache PangoLayout 553 | 554 | function CairoContext(surface::CairoSurface) 555 | ptr = ccall((:cairo_create,libcairo), 556 | Ptr{Nothing}, (Ptr{Nothing},), surface.ptr) 557 | layout = ccall((:pango_cairo_create_layout,libpangocairo), 558 | Ptr{Nothing}, (Ptr{Nothing},), ptr) 559 | self = new(ptr, surface, layout) 560 | finalizer(destroy, self) 561 | self 562 | end 563 | function CairoContext(ptr::Ptr{Nothing}) 564 | ccall((:cairo_reference,libcairo), 565 | Ptr{Nothing}, (Ptr{Nothing},), ptr) 566 | surface_p = ccall((:cairo_get_target,libcairo), 567 | Ptr{Nothing}, (Ptr{Nothing},), ptr) 568 | surface = CairoSurface(surface_p) 569 | layout = ccall((:pango_cairo_create_layout,libpangocairo), 570 | Ptr{Nothing}, (Ptr{Nothing},), ptr) 571 | self = new(ptr,surface,layout) 572 | finalizer(destroy, self) 573 | self 574 | end 575 | 576 | 577 | end 578 | 579 | creategc(s::CairoSurface) = CairoContext(s) 580 | 581 | function destroy(ctx::CairoContext) 582 | if ctx.ptr == C_NULL 583 | return 584 | end 585 | ccall((:g_object_unref,libgobject), Nothing, (Ptr{Nothing},), ctx.layout) 586 | _destroy(ctx) 587 | ctx.ptr = C_NULL 588 | nothing 589 | end 590 | 591 | width(ctx::CairoContext) = width(ctx.surface) 592 | height(ctx::CairoContext) = height(ctx.surface) 593 | 594 | function copy(ctx::CairoContext) 595 | surf = surface_create_similar(ctx.surface) 596 | c = creategc(surf) 597 | set_source_surface(c, ctx.surface) 598 | paint(c) 599 | set_matrix(c, get_matrix(ctx)) 600 | c 601 | end 602 | 603 | # Copy a rectangular region 604 | function copy(ctx::CairoContext, bb::BoundingBox) 605 | w = width(bb) 606 | h = height(bb) 607 | surf = surface_create_similar(ctx.surface, ceil(Int,w), ceil(Int,h)) 608 | c = creategc(surf) 609 | set_source_surface(c, ctx.surface, -bb.xmin, -bb.ymin) 610 | rectangle(c, 0, 0, w, h) 611 | fill(c) 612 | set_matrix(c, get_matrix(ctx)) 613 | c 614 | end 615 | 616 | for (NAME, FUNCTION) in Any[(:_destroy, :cairo_destroy), 617 | (:save, :cairo_save), 618 | (:restore, :cairo_restore), 619 | (:show_page, :cairo_show_page), 620 | (:clip, :cairo_clip), 621 | (:clip_preserve, :cairo_clip_preserve), 622 | (:reset_clip, :cairo_reset_clip), 623 | (:reset_transform, :cairo_identity_matrix), 624 | (:fill, :cairo_fill), 625 | (:fill_preserve, :cairo_fill_preserve), 626 | (:new_path, :cairo_new_path), 627 | (:new_sub_path, :cairo_new_sub_path), 628 | (:close_path, :cairo_close_path), 629 | (:paint, :cairo_paint), 630 | (:stroke_transformed, :cairo_stroke), 631 | (:stroke_transformed_preserve, :cairo_stroke_preserve)] 632 | @eval begin 633 | $NAME(ctx::CairoContext) = 634 | ccall(($(Expr(:quote,FUNCTION)),libcairo), 635 | Nothing, (Ptr{Nothing},), ctx.ptr) 636 | end 637 | end 638 | 639 | function stroke(ctx::CairoContext) 640 | save(ctx) 641 | # use uniform scale for stroking 642 | reset_transform(ctx) 643 | ccall((:cairo_stroke, libcairo), Nothing, (Ptr{Nothing},), ctx.ptr) 644 | restore(ctx) 645 | end 646 | 647 | function stroke_preserve(ctx::CairoContext) 648 | save(ctx) 649 | reset_transform(ctx) 650 | ccall((:cairo_stroke_preserve, libcairo), Nothing, (Ptr{Nothing},), ctx.ptr) 651 | restore(ctx) 652 | end 653 | 654 | function paint_with_alpha(ctx::CairoContext, a) 655 | ccall((:cairo_paint_with_alpha, libcairo), 656 | Nothing, (Ptr{Nothing}, Float64), ctx.ptr, a) 657 | end 658 | 659 | function get_operator(ctx::CairoContext) 660 | Int(ccall((:cairo_get_operator,libcairo), Int32, (Ptr{Nothing},), ctx.ptr)) 661 | end 662 | 663 | 664 | for (NAME, FUNCTION) in Any[(:set_fill_type, :cairo_set_fill_rule), 665 | (:set_operator, :cairo_set_operator), 666 | (:set_line_cap, :cairo_set_line_cap), 667 | (:set_line_join, :cairo_set_line_join)] 668 | @eval begin 669 | $NAME(ctx::CairoContext, i0::Integer) = 670 | ccall(($(Expr(:quote,FUNCTION)),libcairo), 671 | Nothing, (Ptr{Nothing},Int32), ctx.ptr, i0) 672 | end 673 | end 674 | 675 | for (NAME, FUNCTION) in Any[(:set_line_width, :cairo_set_line_width), 676 | (:rotate, :cairo_rotate), 677 | (:set_font_size, :cairo_set_font_size)] 678 | @eval begin 679 | $NAME(ctx::CairoContext, d0::Real) = 680 | ccall(($(Expr(:quote,FUNCTION)),libcairo), 681 | Nothing, (Ptr{Nothing},Float64), ctx.ptr, d0) 682 | end 683 | end 684 | 685 | for (NAME, FUNCTION) in Any[(:line_to, :cairo_line_to), 686 | (:move_to, :cairo_move_to), 687 | (:rel_line_to, :cairo_rel_line_to), 688 | (:rel_move_to, :cairo_rel_move_to), 689 | (:scale, :cairo_scale), 690 | (:translate, :cairo_translate)] 691 | @eval begin 692 | $NAME(ctx::CairoContext, d0::Real, d1::Real) = 693 | ccall(($(Expr(:quote,FUNCTION)),libcairo), 694 | Nothing, (Ptr{Nothing},Float64,Float64), ctx.ptr, d0, d1) 695 | end 696 | end 697 | 698 | for (NAME, FUNCTION) in Any[(:curve_to, :cairo_curve_to), 699 | (:rel_curve_to, :cairo_rel_curve_to)] 700 | @eval begin 701 | $NAME(ctx::CairoContext, d0::Real, d1::Real, d2::Real, d3::Real, d4::Real, d5::Real) = 702 | ccall(($(Expr(:quote,FUNCTION)),libcairo), 703 | Nothing, (Ptr{Nothing},Float64,Float64,Float64,Float64,Float64,Float64), ctx.ptr, d0, d1, d2, d3, d4, d5) 704 | end 705 | end 706 | 707 | for (NAME, FUNCTION) in Any[(:arc, :cairo_arc), 708 | (:arc_negative, :cairo_arc_negative)] 709 | @eval begin 710 | $NAME(ctx::CairoContext, xc::Real, yc::Real, radius::Real, angle1::Real, angle2::Real) = 711 | ccall(($(Expr(:quote,FUNCTION)),libcairo), 712 | Nothing, (Ptr{Nothing},Float64,Float64,Float64,Float64,Float64), 713 | ctx.ptr, xc, yc, radius, angle1, angle2) 714 | end 715 | end 716 | 717 | 718 | set_source_rgb(ctx::CairoContext, r::Real, g::Real, b::Real) = 719 | ccall((:cairo_set_source_rgb,libcairo), 720 | Nothing, (Ptr{Nothing},Float64,Float64,Float64), ctx.ptr, r, g, b) 721 | 722 | set_source_rgba(ctx::CairoContext, r::Real, g::Real, b::Real, a::Real) = 723 | ccall((:cairo_set_source_rgba,libcairo), Nothing, 724 | (Ptr{Nothing},Float64,Float64,Float64,Float64), 725 | ctx.ptr, r, g, b, a) 726 | 727 | function set_source(ctx::CairoContext, c::Color) 728 | rgb = convert(RGB, c) 729 | set_source_rgb(ctx, rgb.r, rgb.g, rgb.b) 730 | end 731 | 732 | function set_source(ctx::CairoContext, ac::TransparentColor) 733 | rgba = convert(RGBA, ac) 734 | set_source_rgba(ctx, rgba.r, rgba.g, rgba.b, rgba.alpha) 735 | end 736 | 737 | set_source(dest::CairoContext, src::CairoContext) = set_source_surface(dest, src.surface) 738 | 739 | set_source(dest::CairoContext, src::CairoSurface) = set_source_surface(dest, src) 740 | 741 | rectangle(ctx::CairoContext, x::Real, y::Real, w::Real, h::Real) = 742 | ccall((:cairo_rectangle,libcairo), Nothing, 743 | (Ptr{Nothing},Float64,Float64,Float64,Float64), 744 | ctx.ptr, x, y, w, h) 745 | 746 | function set_dash(ctx::CairoContext, dashes::Vector{Float64}, offset::Real = 0.0) 747 | ccall((:cairo_set_dash,libcairo), Nothing, 748 | (Ptr{Nothing},Ptr{Float64},Int32,Float64), ctx.ptr, dashes, length(dashes), offset) 749 | end 750 | 751 | function set_source_surface(ctx::CairoContext, s::CairoSurface, x::Real = 0.0, y::Real = 0.0) 752 | ccall((:cairo_set_source_surface,libcairo), Nothing, 753 | (Ptr{Nothing},Ptr{Nothing},Float64,Float64), ctx.ptr, s.ptr, x, y) 754 | end 755 | 756 | function set_source(ctx::CairoContext, s::CairoSurface, x::Real, y::Real) 757 | set_source_surface(ctx, s, x, y) 758 | end 759 | 760 | 761 | # cairo_path data and functions 762 | 763 | mutable struct CairoPath_t 764 | status::Cairo.status_t 765 | data::Ptr{Float64} 766 | num_data::UInt32 767 | end 768 | 769 | mutable struct CairoPath <: GraphicsDevice 770 | ptr::Ptr{CairoPath_t} 771 | 772 | function CairoPath(ptr::Ptr{Nothing}) 773 | self = new(ptr) 774 | finalizer(destroy, self) 775 | self 776 | end 777 | end 778 | 779 | # Abstract, contains type (moveto,lineto,curveto,closepath) and points 780 | mutable struct CairoPathEntry 781 | element_type::UInt32 782 | points::Array{Float64,1} 783 | end 784 | 785 | 786 | function destroy(path::CairoPath) 787 | if path.ptr == C_NULL 788 | return 789 | end 790 | ccall((:cairo_path_destroy,libcairo), Nothing, (Ptr{Nothing},), path.ptr) 791 | path.ptr = C_NULL 792 | nothing 793 | end 794 | 795 | function copy_path(ctx::CairoContext) 796 | ptr = ccall((:cairo_copy_path, libcairo), 797 | Ptr{Nothing}, (Ptr{Nothing},),ctx.ptr) 798 | path = CairoPath(ptr) 799 | finalizer(destroy, path) 800 | path 801 | end 802 | 803 | function copy_path_flat(ctx::CairoContext) 804 | ptr = ccall((:cairo_copy_path_flat, libcairo), 805 | Ptr{Nothing}, (Ptr{Nothing},),ctx.ptr) 806 | path = CairoPath(ptr) 807 | finalizer(destroy, path) 808 | path 809 | end 810 | 811 | function convert_cairo_path_data(p::CairoPath) 812 | c = unsafe_load(p.ptr) 813 | 814 | # The original data (pointed by c.data) is an array of Unions. We 815 | # define here by Float64 (most data is) and reinterpret in the header. 816 | 817 | path_data = CairoPathEntry[] 818 | @static if VERSION >= v"0.7" 819 | c_data = unsafe_wrap(Array, c.data, (Int(c.num_data*2), 1), own=false) 820 | else 821 | c_data = unsafe_wrap(Array, c.data, (Int(c.num_data*2), 1), false) 822 | end 823 | 824 | data_index = 1 825 | while data_index <= ((c.num_data)*2) 826 | 827 | # read header (reinterpret a Float64 to UInt64 and split to UInt32 x 2) 828 | element_length = reinterpret(UInt64,c_data[data_index]) >> 32 829 | element_type = reinterpret(UInt64,c_data[data_index]) & 0xffffffff 830 | 831 | # copy points x,y 832 | points = Vector{Float64}(undef, (element_length - 1) * 2) 833 | for i=1:(element_length-1)*2 834 | points[i] = c_data[data_index+i+1] 835 | end 836 | 837 | g = CairoPathEntry(element_type,points) 838 | push!(path_data,g) 839 | 840 | # goto next element 841 | data_index += (element_length*2) 842 | 843 | end 844 | path_data 845 | end 846 | 847 | # other path operations 848 | 849 | function get_current_point(ctx::CairoContext) 850 | 851 | x = Ref{Cdouble}(0) 852 | y = Ref{Cdouble}(0) 853 | ccall((:cairo_get_current_point, libcairo), 854 | Nothing, (Ptr{Nothing},Ref{Cdouble},Ref{Cdouble}),ctx.ptr,x,y) 855 | 856 | x[],y[] 857 | end 858 | 859 | function has_current_point(ctx::CairoContext) 860 | Bool(ccall((:cairo_has_current_point, libcairo), 861 | Cint, (Ptr{Nothing},),ctx.ptr)) 862 | end 863 | 864 | # user<->device coordinate translation 865 | 866 | for (fname,cname) in ((:user_to_device!,:cairo_user_to_device), 867 | (:device_to_user!,:cairo_device_to_user), 868 | (:user_to_device_distance!,:cairo_user_to_device_distance), 869 | (:device_to_user_distance!,:cairo_device_to_user_distance)) 870 | @eval begin 871 | function ($fname)(ctx::CairoContext, p::Vector{Float64}) 872 | ccall(($(Expr(:quote,cname)),libcairo), 873 | Nothing, (Ptr{Nothing}, Ptr{Float64}, Ptr{Float64}), 874 | ctx.ptr, pointer(p,1), pointer(p,2)) 875 | p 876 | end 877 | end 878 | end 879 | 880 | function image(ctx::CairoContext, s::CairoSurface, x, y, w, h) 881 | rectangle(ctx, x, y, w, h) 882 | save(ctx) 883 | translate(ctx, x, y) 884 | scale(ctx, w/s.width, h/s.height) 885 | set_source_surface(ctx, s, 0, 0) 886 | if abs(w) > s.width && abs(h) > s.height 887 | # use NEAREST filter when stretching an image 888 | # it's usually better to see pixels than a blurry mess when viewing 889 | # a small image 890 | p = get_source(ctx) 891 | pattern_set_filter(p, FILTER_NEAREST) 892 | end 893 | fill(ctx) 894 | restore(ctx) 895 | end 896 | 897 | image(ctx::CairoContext, img::Array{UInt32,2}, x, y, w, h) = 898 | image(ctx, CairoRGBSurface(img), x, y, w, h) 899 | 900 | function push_group(ctx::CairoContext) 901 | if ctx.ptr == C_NULL 902 | return 903 | end 904 | ccall((:cairo_push_group, libcairo), Nothing, (Ptr{Nothing},),ctx.ptr) 905 | nothing 906 | end 907 | 908 | function pop_group(ctx::CairoContext) 909 | if ctx.ptr == C_NULL 910 | return 911 | end 912 | ptr = ccall((:cairo_pop_group, libcairo), Ptr{Nothing}, (Ptr{Nothing},),ctx.ptr) 913 | pattern = CairoPattern(ptr) 914 | finalizer(destroy, pattern) 915 | pattern 916 | end 917 | 918 | # ----------------------------------------------------------------------------- 919 | 920 | mutable struct CairoPattern 921 | ptr::Ptr{Nothing} 922 | end 923 | 924 | function CairoPattern(s::CairoSurface) 925 | ptr = ccall((:cairo_pattern_create_for_surface, libcairo), 926 | Ptr{Nothing}, (Ptr{Nothing},), s.ptr) 927 | # Ideally we'd check the status, but at least for certain releases of the library 928 | # the return value seems not to be set properly (random values are returned) 929 | # status = ccall((:cairo_pattern_status, libcairo), 930 | # Cint, (Ptr{Nothing},), s.ptr) 931 | # if status != 0 932 | # error("Error creating Cairo pattern: ", bytestring( 933 | # ccall((:cairo_status_to_string, libcairo), 934 | # Ptr{UInt8}, (Cint,), status))) 935 | # end 936 | pattern = CairoPattern(ptr) 937 | finalizer(destroy, pattern) 938 | pattern 939 | end 940 | 941 | set_source(dest::CairoContext, src::CairoPattern) = 942 | ccall((:cairo_set_source, libcairo), 943 | Nothing, (Ptr{Nothing}, Ptr{Nothing}), dest.ptr, src.ptr) 944 | 945 | function get_source(ctx::CairoContext) 946 | CairoPattern(ccall((:cairo_get_source,libcairo), 947 | Ptr{Nothing}, (Ptr{Nothing},), ctx.ptr)) 948 | end 949 | 950 | function pattern_set_filter(p::CairoPattern, f) 951 | ccall((:cairo_pattern_set_filter,libcairo), Nothing, 952 | (Ptr{Nothing},Int32), p.ptr, f) 953 | end 954 | 955 | function pattern_set_extend(p::CairoPattern, val) 956 | ccall((:cairo_pattern_set_extend,libcairo), Nothing, 957 | (Ptr{Nothing},Int32), p.ptr, val) 958 | end 959 | 960 | function pattern_create_radial(cx0::Real, cy0::Real, radius0::Real, cx1::Real, cy1::Real, radius1::Real) 961 | ptr = ccall((:cairo_pattern_create_radial, libcairo), 962 | Ptr{Nothing}, (Float64,Float64,Float64,Float64,Float64,Float64),cx0,cy0,radius0,cx1,cy1,radius1) 963 | pattern = CairoPattern(ptr) 964 | finalizer(destroy, pattern) 965 | pattern 966 | end 967 | 968 | function pattern_create_linear(x0::Real, y0::Real, x1::Real, y1::Real) 969 | ptr = ccall((:cairo_pattern_create_linear, libcairo), 970 | Ptr{Nothing}, (Float64,Float64,Float64,Float64),x0,y0,x1,y1) 971 | pattern = CairoPattern(ptr) 972 | finalizer(destroy, pattern) 973 | pattern 974 | end 975 | 976 | function pattern_add_color_stop_rgb(pat::CairoPattern, offset::Real, red::Real, green::Real, blue::Real) 977 | ccall((:cairo_pattern_add_color_stop_rgb, libcairo), 978 | Nothing, (Ptr{Nothing},Float64,Float64,Float64,Float64),pat.ptr,offset,red,green,blue) 979 | end 980 | 981 | function pattern_add_color_stop_rgba(pat::CairoPattern, offset::Real, red::Real, green::Real, blue::Real, alpha::Real) 982 | ccall((:cairo_pattern_add_color_stop_rgba, libcairo), 983 | Nothing, (Ptr{Nothing},Float64,Float64,Float64,Float64,Float64),pat.ptr,offset,red,green,blue,alpha) 984 | end 985 | 986 | function pattern_get_surface(pat::CairoPattern) 987 | ptrref = Ref{Ptr{Nothing}}() 988 | status = ccall((:cairo_pattern_get_surface, libcairo), Cint, 989 | (Ptr{Nothing}, Ref{Ptr{Nothing}}), pat.ptr, ptrref) 990 | if status == STATUS_PATTERN_TYPE_MISMATCH 991 | error("Cannot get surface from a non-surface pattern.") 992 | end 993 | ptr = ptrref.x 994 | 995 | ccall((:cairo_surface_reference, libcairo), Ptr{Nothing}, (Ptr{Nothing},), ptr) 996 | typ = ccall((:cairo_surface_get_type, libcairo), Cint, (Ptr{Nothing},), ptr) 997 | 998 | w = 0.0 999 | h = 0.0 1000 | if typ == CAIRO_SURFACE_TYPE_IMAGE 1001 | w = ccall((:cairo_image_surface_get_width, libcairo), 1002 | Int32, (Ptr{Nothing},), ptr) 1003 | h = ccall((:cairo_image_surface_get_height, libcairo), 1004 | Int32, (Ptr{Nothing},), ptr) 1005 | end 1006 | return CairoSurface(ptr, w, h) 1007 | end 1008 | 1009 | function destroy(pat::CairoPattern) 1010 | if pat.ptr == C_NULL 1011 | return 1012 | end 1013 | ccall((:cairo_pattern_destroy,libcairo), Nothing, (Ptr{Nothing},), pat.ptr) 1014 | pat.ptr = C_NULL 1015 | nothing 1016 | end 1017 | 1018 | # mesh pattern 1019 | 1020 | # create mesh pattern 1021 | function CairoPatternMesh() 1022 | ptr = ccall((:cairo_pattern_create_mesh, libcairo), 1023 | Ptr{Nothing}, ()) 1024 | pattern = CairoPattern(ptr) 1025 | #status = ccall((:cairo_pattern_status, libcairo), 1026 | # Cint, (Ptr{Nothing},), pattern.ptr) 1027 | #if status != 0 1028 | # error("Error creating Cairo pattern: ", bytestring( 1029 | # ccall((:cairo_status_to_string, libcairo), 1030 | # Ptr{Uint8}, (Cint,), status))) 1031 | #end 1032 | finalizer(destroy, pattern) 1033 | pattern 1034 | end 1035 | 1036 | #for (NAME, FUNCTION) in Any[(:set_line_width, :cairo_set_line_width), 1037 | # (:rotate, :cairo_rotate), 1038 | # (:set_font_size, :cairo_set_font_size)] 1039 | # @eval begin 1040 | # $NAME(ctx::CairoContext, d0::Real) = 1041 | # ccall(($(Expr(:quote,FUNCTION)),libcairo), 1042 | # Nothing, (Ptr{Nothing},Float64), ctx.ptr, d0) 1043 | # end 1044 | #end 1045 | 1046 | for (NAME, FUNCTION) in Any[(:mesh_pattern_begin_patch, :cairo_mesh_pattern_begin_patch), 1047 | (:mesh_pattern_end_patch, :cairo_mesh_pattern_end_patch)] 1048 | @eval begin 1049 | $NAME(pattern::CairoPattern) = 1050 | ccall(($(Expr(:quote,FUNCTION)),libcairo), 1051 | Nothing, (Ptr{Nothing},), pattern.ptr) 1052 | end 1053 | end 1054 | 1055 | for (NAME, FUNCTION) in Any[(:mesh_pattern_line_to, :cairo_mesh_pattern_line_to), 1056 | (:mesh_pattern_move_to, :cairo_mesh_pattern_move_to)] 1057 | @eval begin 1058 | $NAME(pattern::CairoPattern, d0::Real, d1::Real) = 1059 | ccall(($(Expr(:quote,FUNCTION)),libcairo), 1060 | Nothing, (Ptr{Nothing},Float64,Float64), pattern.ptr, d0, d1) 1061 | end 1062 | end 1063 | 1064 | for (NAME, FUNCTION) in Any[(:mesh_pattern_curve_to, :cairo_mesh_pattern_curve_to)] 1065 | 1066 | @eval begin 1067 | $NAME(pattern::CairoPattern, d0::Real, d1::Real, d2::Real, d3::Real, d4::Real, d5::Real) = 1068 | ccall(($(Expr(:quote,FUNCTION)),libcairo), 1069 | Nothing, (Ptr{Nothing},Float64,Float64,Float64,Float64,Float64,Float64), pattern.ptr, d0, d1, d2, d3, d4, d5) 1070 | end 1071 | end 1072 | 1073 | 1074 | function mesh_pattern_set_corner_color_rgb(pat::CairoPattern, corner_num::Real, red::Real, green::Real, blue::Real) 1075 | ccall((:cairo_mesh_pattern_set_corner_color_rgb, libcairo), 1076 | Nothing, (Ptr{Nothing},Int32,Float64,Float64,Float64),pat.ptr,corner_num,red,green,blue) 1077 | end 1078 | 1079 | function mesh_pattern_set_corner_color_rgba(pat::CairoPattern, corner_num::Real, red::Real, green::Real, blue::Real, alpha::Real) 1080 | ccall((:cairo_mesh_pattern_set_corner_color_rgba, libcairo), 1081 | Nothing, (Ptr{Nothing},Int32,Float64,Float64,Float64,Float64),pat.ptr,corner_num,red,green,blue,alpha) 1082 | end 1083 | 1084 | # ---- 1085 | 1086 | set_antialias(ctx::CairoContext, a) = 1087 | ccall((:cairo_set_antialias,libcairo), Nothing, 1088 | (Ptr{Nothing},Cint), ctx.ptr, a) 1089 | 1090 | get_antialias(ctx::CairoContext) = 1091 | ccall((:cairo_get_antialias,libcairo), Cint, 1092 | (Ptr{Nothing},), ctx.ptr) 1093 | 1094 | # ----------------------------------------------------------------------------- 1095 | 1096 | struct CairoMatrix 1097 | xx::Float64 1098 | yx::Float64 1099 | xy::Float64 1100 | yy::Float64 1101 | x0::Float64 1102 | y0::Float64 1103 | end 1104 | 1105 | CairoMatrix() = CairoMatrix(0.0, 0.0, 0.0, 0.0, 0.0, 0.0) 1106 | 1107 | function get_matrix(ctx::CairoContext) 1108 | m = [CairoMatrix()] 1109 | ccall((:cairo_get_matrix, libcairo), Nothing, (Ptr{Nothing}, Ptr{Nothing}), ctx.ptr, m) 1110 | m[1] 1111 | end 1112 | 1113 | function set_matrix(ctx::CairoContext, m::CairoMatrix) 1114 | ccall((:cairo_set_matrix, libcairo), Nothing, (Ptr{Nothing}, Ptr{Nothing}), ctx.ptr, [m]) 1115 | end 1116 | 1117 | function set_matrix(p::CairoPattern, m::CairoMatrix) 1118 | ccall((:cairo_pattern_set_matrix, libcairo), Nothing, (Ptr{Nothing}, Ptr{Nothing}), p.ptr, [m]) 1119 | end 1120 | 1121 | 1122 | # ----------------------------------------------------------------------------- 1123 | function set_line_type(ctx::CairoContext, nick::AbstractString) 1124 | if nick == "solid" 1125 | dash = Float64[] 1126 | elseif nick == "dotted" || nick == "dot" 1127 | dash = [1.,3.] 1128 | elseif nick == "dotdashed" 1129 | dash = [1.,3.,4.,4.] 1130 | elseif nick == "longdashed" 1131 | dash = [6.,6.] 1132 | elseif nick == "shortdashed" || nick == "dash" || nick == "dashed" 1133 | dash = [4.,4.] 1134 | elseif nick == "dotdotdashed" 1135 | dash = [1.,3.,1.,3.,4.,4.] 1136 | elseif nick == "dotdotdotdashed" 1137 | dash = [1.,3.,1.,3.,1.,3.,4.,4.] 1138 | else 1139 | error("unknown line type ", nick) 1140 | end 1141 | set_dash(ctx, dash) 1142 | end 1143 | 1144 | # ----------------------------------------------------------------------------- 1145 | # text commands 1146 | 1147 | function set_font_face(ctx::CairoContext, str::AbstractString) 1148 | fontdesc = ccall((:pango_font_description_from_string,libpango), 1149 | Ptr{Nothing}, (Ptr{UInt8},), String(str)) 1150 | ccall((:pango_layout_set_font_description,libpango), Nothing, 1151 | (Ptr{Nothing},Ptr{Nothing}), ctx.layout, fontdesc) 1152 | ccall((:pango_font_description_free,libpango), Nothing, 1153 | (Ptr{Nothing},), fontdesc) 1154 | end 1155 | 1156 | function set_text(ctx::CairoContext, text::AbstractString, markup::Bool = false) 1157 | if markup 1158 | ccall((:pango_layout_set_markup,libpango), Nothing, 1159 | (Ptr{Nothing},Ptr{UInt8},Int32), ctx.layout, String(text), -1) 1160 | else 1161 | # clear attributes (from previous set markups) 1162 | ccall((:pango_layout_set_attributes,libpango), Nothing, 1163 | (Ptr{Nothing},Ptr{Nothing}), ctx.layout, C_NULL) 1164 | 1165 | ccall((:pango_layout_set_text,libpango), Nothing, 1166 | (Ptr{Nothing},Ptr{UInt8},Int32), ctx.layout, String(text), -1) 1167 | end 1168 | text 1169 | end 1170 | 1171 | function get_layout_size(ctx::CairoContext) 1172 | w = Vector{Int32}(undef, 2) 1173 | ccall((:pango_layout_get_pixel_size,libpango), Nothing, 1174 | (Ptr{Nothing},Ptr{Int32},Ptr{Int32}), ctx.layout, pointer(w,1), pointer(w,2)) 1175 | w 1176 | end 1177 | 1178 | function update_layout(ctx::CairoContext) 1179 | ccall((:pango_cairo_update_layout,libpangocairo), Nothing, 1180 | (Ptr{Nothing},Ptr{Nothing}), ctx.ptr, ctx.layout) 1181 | end 1182 | 1183 | function show_layout(ctx::CairoContext) 1184 | ccall((:pango_cairo_show_layout,libpangocairo), Nothing, 1185 | (Ptr{Nothing},Ptr{Nothing}), ctx.ptr, ctx.layout) 1186 | end 1187 | 1188 | text_extents(ctx::CairoContext,value::AbstractString) = 1189 | text_extents!(ctx,value, Matrix{Float64}(undef, 6, 1)) 1190 | 1191 | function text_extents!(ctx::CairoContext,value::AbstractString,extents) 1192 | ccall((:cairo_text_extents, libcairo), 1193 | Nothing, (Ptr{Nothing}, Ptr{UInt8}, Ptr{Float64}), 1194 | ctx.ptr, String(value), extents) 1195 | extents 1196 | end 1197 | 1198 | function path_extents(ctx::CairoContext) 1199 | dx1 = Cdouble[0] 1200 | dx2 = Cdouble[0] 1201 | dy1 = Cdouble[0] 1202 | dy2 = Cdouble[0] 1203 | 1204 | ccall((:cairo_path_extents, libcairo), 1205 | Nothing, (Ptr{Nothing}, Ptr{Cdouble}, Ptr{Cdouble}, 1206 | Ptr{Cdouble}, Ptr{Cdouble}), 1207 | ctx.ptr, dx1, dy1, dx2, dy2) 1208 | 1209 | return(dx1[1],dy1[1],dx2[1],dy2[1]) 1210 | end 1211 | 1212 | 1213 | function show_text(ctx::CairoContext,value::AbstractString) 1214 | ccall((:cairo_show_text, libcairo), 1215 | Nothing, (Ptr{Nothing}, Ptr{UInt8}), 1216 | ctx.ptr, String(value)) 1217 | end 1218 | 1219 | function text_path(ctx::CairoContext,value::AbstractString) 1220 | ccall((:cairo_text_path, libcairo), 1221 | Nothing, (Ptr{Nothing}, Ptr{UInt8}), 1222 | ctx.ptr, String(value)) 1223 | end 1224 | 1225 | 1226 | function select_font_face(ctx::CairoContext,family::AbstractString,slant,weight) 1227 | ccall((:cairo_select_font_face, libcairo), 1228 | Nothing, (Ptr{Nothing}, Ptr{UInt8}, 1229 | font_slant_t, font_weight_t), 1230 | ctx.ptr, String(family), 1231 | slant, weight) 1232 | end 1233 | 1234 | function align2offset(a::AbstractString) 1235 | if a == "center" return 0.5 1236 | elseif a == "left" return 0.0 1237 | elseif a == "right" return 1.0 1238 | elseif a == "top" return 0.0 1239 | elseif a == "bottom" return 1.0 1240 | end 1241 | @assert false 1242 | end 1243 | 1244 | function text(ctx::CairoContext, x::Real, y::Real, str::AbstractString; 1245 | halign::AbstractString = "left", valign::AbstractString = "bottom", angle::Real = 0, markup::Bool=false) 1246 | move_to(ctx, x, y) 1247 | save(ctx) 1248 | reset_transform(ctx) 1249 | rotate(ctx, -angle*pi/180.) 1250 | 1251 | set_text(ctx, str, markup) 1252 | update_layout(ctx) 1253 | 1254 | extents = get_layout_size(ctx) 1255 | dxrel = -align2offset(halign) 1256 | dyrel = align2offset(valign) 1257 | rel_move_to(ctx, dxrel*extents[1], -dyrel*extents[2]) 1258 | 1259 | show_layout(ctx) 1260 | restore(ctx) 1261 | w, h = Graphics.device_to_user(ctx, extents[1], extents[2]) 1262 | BoundingBox(x+dxrel*w, x+(dxrel+1)*w, y-dyrel*h, y+(1-dyrel)*h) 1263 | end 1264 | 1265 | function textwidth(ctx::CairoContext, str::AbstractString, markup::Bool = false) 1266 | set_text(ctx, str, markup) 1267 | extents = get_layout_size(ctx) 1268 | extents[1] 1269 | end 1270 | 1271 | function textheight(ctx::CairoContext, str::AbstractString, markup::Bool = false) 1272 | set_text(ctx, str, markup) 1273 | extents = get_layout_size(ctx) 1274 | extents[2] 1275 | end 1276 | 1277 | set_latex(ctx::CairoContext, str::AbstractString, fontsize::Real) = set_text(ctx, tex2pango(str, fontsize), true) 1278 | 1279 | mutable struct TeXLexer 1280 | str::String 1281 | len::Int 1282 | pos::Int 1283 | token_stack::Array{String,1} 1284 | 1285 | function TeXLexer(str::AbstractString) 1286 | s = String(str) 1287 | new(s, lastindex(s), 1, String[]) 1288 | end 1289 | end 1290 | 1291 | function get_token(self::TeXLexer) 1292 | if self.pos > self.len 1293 | return nothing 1294 | end 1295 | 1296 | if length(self.token_stack) > 0 1297 | return pop!(self.token_stack) 1298 | end 1299 | 1300 | str = self.str[self.pos:end] 1301 | re_control_sequence = r"^\\[a-zA-Z]+[ ]?|^\\[^a-zA-Z][ ]?" 1302 | m = match(re_control_sequence, str) 1303 | if m !== nothing 1304 | token = m.match 1305 | self.pos = self.pos + sizeof(token) 1306 | # consume trailing space 1307 | if length(token) > 2 && token[end] == ' ' 1308 | token = token[1:end-1] 1309 | end 1310 | else 1311 | @static if VERSION >= v"0.7" 1312 | token, self.pos = iterate(self.str, self.pos) 1313 | else 1314 | token, self.pos = next(self.str, self.pos) 1315 | end 1316 | token = string(token) 1317 | end 1318 | 1319 | return token 1320 | end 1321 | 1322 | function put_token(self::TeXLexer, token) 1323 | push!(self.token_stack, token) 1324 | end 1325 | 1326 | function peek(self::TeXLexer) 1327 | token = get_token(self) 1328 | put_token(self, token) 1329 | return token 1330 | end 1331 | 1332 | function map_text_token(token::AbstractString) 1333 | if haskey(_text_token_dict, token) 1334 | return _text_token_dict[token] 1335 | else 1336 | return get(_common_token_dict, token, token) 1337 | end 1338 | end 1339 | 1340 | function map_math_token(token::AbstractString) 1341 | if haskey(_math_token_dict, token) 1342 | return _math_token_dict[token] 1343 | else 1344 | return get(_common_token_dict, token, token) 1345 | end 1346 | end 1347 | 1348 | function math_group(lexer::TeXLexer) 1349 | output = "" 1350 | bracketmode = false 1351 | while true 1352 | token = get_token(lexer) 1353 | if token == nothing 1354 | break 1355 | end 1356 | 1357 | if token == "{" 1358 | bracketmode = true 1359 | elseif token == "}" 1360 | break 1361 | else 1362 | output = string(output, map_math_token(token)) 1363 | if !bracketmode 1364 | break 1365 | end 1366 | end 1367 | end 1368 | return output 1369 | end 1370 | 1371 | #font_code = [ "\\f0", "\\f1", "\\f2", "\\f3" ] 1372 | 1373 | function tex2pango(str::AbstractString, fontsize::Real) 1374 | output = "" 1375 | mathmode = true 1376 | font_stack = Any[] 1377 | font = 1 1378 | script_size = fontsize/1.618034 1379 | 1380 | lexer = TeXLexer(str) 1381 | while true 1382 | token = get_token(lexer) 1383 | if token == nothing 1384 | break 1385 | end 1386 | 1387 | more_output = "" 1388 | 1389 | if token == "\$" 1390 | # mathmode = !mathmode 1391 | more_output = "\$" 1392 | elseif token == "{" 1393 | push!(font_stack, font) 1394 | elseif token == "}" 1395 | old_font = pop!(font_stack) 1396 | if old_font != font 1397 | font = old_font 1398 | # more_output = font_code[font] 1399 | end 1400 | elseif token == "\\rm" 1401 | font = 1 1402 | # more_output = font_code[font] 1403 | elseif token == "\\it" 1404 | font = 2 1405 | # more_output = font_code[font] 1406 | elseif token == "\\bf" 1407 | font = 3 1408 | # more_output = font_code[font] 1409 | elseif !mathmode 1410 | more_output = map_text_token(token) 1411 | elseif token == "_" 1412 | more_output = string("", math_group(lexer), "") 1413 | #if peek(lexer) == "^" 1414 | # more_output = string("\\mk", more_output, "\\rt") 1415 | #end 1416 | elseif token == "^" 1417 | more_output = string("", math_group(lexer), "") 1418 | #if peek(lexer) == "_" 1419 | # more_output = string("\\mk", more_output, "\\rt") 1420 | #end 1421 | else 1422 | more_output = map_math_token(token) 1423 | end 1424 | 1425 | output = string(output, more_output) 1426 | end 1427 | return output 1428 | end 1429 | 1430 | 1431 | @deprecate text(ctx::CairoContext,x::Real,y::Real,str::AbstractString,fontsize::Real,halign::AbstractString,valign,angle) text(ctx,x,y,set_latex(ctx,str,fontsize),halign=halign,valign=valign,angle=angle,markup=true) 1432 | @deprecate layout_text(ctx::CairoContext, str::AbstractString, fontsize::Real) set_latex(ctx, str, fontsize) 1433 | @deprecate textwidth(ctx::CairoContext, str::AbstractString, fontsize::Real) textwidth(ctx, tex2pango(str, fontsize), true) 1434 | @deprecate textheight(ctx::CairoContext, str::AbstractString, fontsize::Real) textheight(ctx, tex2pango(str, fontsize), true) 1435 | @deprecate cairo_write_to_ios_callback(s::Ptr{Nothing}, buf::Ptr{UInt8}, len::UInt32) write_to_ios_callback(s, buf, len) 1436 | @deprecate cairo_write_to_stream_callback(s::IO, buf::Ptr{UInt8}, len::UInt32) write_to_stream_callback(s, buf, len) 1437 | @deprecate text_extents(ctx::CairoContext,value::AbstractString,extents) text_extents!(ctx,value,extents) 1438 | 1439 | end # module 1440 | --------------------------------------------------------------------------------