├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── settings.gradle
├── src
├── test
│ └── java
│ │ └── org
│ │ └── freedesktop
│ │ └── cairo
│ │ └── test
│ │ ├── CairoTest.java
│ │ ├── FontFaceTest.java
│ │ ├── LinearGradientTest.java
│ │ ├── SolidPatternTest.java
│ │ ├── RadialGradientTest.java
│ │ ├── ToyFontFaceTest.java
│ │ ├── GradientTest.java
│ │ ├── PathTest.java
│ │ ├── UserScaledFontTest.java
│ │ ├── SVGSurfaceTest.java
│ │ ├── RecordingSurfaceTest.java
│ │ ├── DeviceTest.java
│ │ ├── PatternTest.java
│ │ ├── FTFontFaceTest.java
│ │ ├── RasterSourceTest.java
│ │ ├── FontOptionsTest.java
│ │ ├── ScriptTest.java
│ │ ├── PSSurfaceTest.java
│ │ ├── TeeSurfaceTest.java
│ │ ├── FTScaledFontTest.java
│ │ ├── PDFSurfaceTest.java
│ │ ├── MeshTest.java
│ │ ├── MatrixTest.java
│ │ └── UserFontFaceTest.java
└── main
│ └── java
│ ├── io
│ └── github
│ │ └── jwharm
│ │ └── cairobindings
│ │ ├── package-info.java
│ │ ├── Flag.java
│ │ ├── ArenaCloseAction.java
│ │ ├── Platform.java
│ │ ├── Proxy.java
│ │ ├── LibLoad.java
│ │ └── Interop.java
│ ├── org
│ └── freedesktop
│ │ ├── cairo
│ │ ├── Point.java
│ │ ├── Circle.java
│ │ ├── RGBA.java
│ │ ├── Rect.java
│ │ ├── ScriptMode.java
│ │ ├── SurfaceObserverMode.java
│ │ ├── ScriptSurface.java
│ │ ├── UserDataKey.java
│ │ ├── PDFOutlineFlags.java
│ │ ├── ColorMode.java
│ │ ├── PDFMetadata.java
│ │ ├── FTSynthesize.java
│ │ ├── Dither.java
│ │ ├── DestroyFunc.java
│ │ ├── FontWeight.java
│ │ ├── SurfaceObserverCallback.java
│ │ ├── FontSlant.java
│ │ ├── RasterSourceFinishFunc.java
│ │ ├── TextClusterFlags.java
│ │ ├── RegionOverlap.java
│ │ ├── LineCap.java
│ │ ├── PathDataType.java
│ │ ├── LineJoin.java
│ │ ├── PathElement.java
│ │ ├── HintMetrics.java
│ │ ├── RasterSourceReleaseFunc.java
│ │ ├── TextCluster.java
│ │ ├── SubpixelOrder.java
│ │ ├── SVGUnit.java
│ │ ├── Content.java
│ │ ├── Extend.java
│ │ ├── Filter.java
│ │ ├── RasterSourceCopyFunc.java
│ │ ├── HintStyle.java
│ │ ├── SurfacePattern.java
│ │ ├── RasterSourceSnapshotFunc.java
│ │ ├── FillRule.java
│ │ ├── WriteFunc.java
│ │ ├── FontType.java
│ │ ├── PatternType.java
│ │ ├── ReadFunc.java
│ │ ├── Glyph.java
│ │ ├── MimeType.java
│ │ └── PSLevel.java
│ │ └── freetype
│ │ ├── FreeType2.java
│ │ ├── package-info.java
│ │ └── Face.java
│ └── module-info.java
├── .github
└── workflows
│ └── publish-pages.yml
├── .gitignore
└── gradlew.bat
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jwharm/cairo-java-bindings/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0'
3 | }
4 |
5 | rootProject.name = 'cairo'
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/CairoTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import static org.junit.jupiter.api.Assertions.*;
4 |
5 | import org.freedesktop.cairo.Cairo;
6 | import org.junit.jupiter.api.Test;
7 |
8 | class CairoTest {
9 |
10 | @Test
11 | void testVersionEncode() {
12 | assertEquals(10203, Cairo.versionEncode(1, 2, 3));
13 | }
14 |
15 | @Test
16 | void testVersionStringize() {
17 | assertEquals("1.2.3", Cairo.versionStringize(1, 2, 3));
18 | }
19 |
20 | @Test
21 | void testVersion() {
22 | assertTrue(Cairo.version() > 10000);
23 | }
24 |
25 | @Test
26 | void testVersionString() {
27 | assertNotNull(Cairo.versionString());
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/FontFaceTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 |
5 | import org.freedesktop.cairo.FontSlant;
6 | import org.freedesktop.cairo.FontType;
7 | import org.freedesktop.cairo.FontWeight;
8 | import org.freedesktop.cairo.Status;
9 | import org.freedesktop.cairo.ToyFontFace;
10 | import org.junit.jupiter.api.Test;
11 |
12 | class FontFaceTest {
13 |
14 | @Test
15 | void testStatus() {
16 | assertEquals(Status.SUCCESS, ToyFontFace.create("Arial", FontSlant.NORMAL, FontWeight.NORMAL).status());
17 | }
18 |
19 | @Test
20 | void testGetFontType() {
21 | assertEquals(FontType.TOY, ToyFontFace.create("Arial", FontSlant.NORMAL, FontWeight.NORMAL).getFontType());
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/LinearGradientTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 |
5 | import org.freedesktop.cairo.LinearGradient;
6 | import org.freedesktop.cairo.Status;
7 | import org.junit.jupiter.api.Test;
8 |
9 | class LinearGradientTest {
10 |
11 | @Test
12 | void testCreate() {
13 | LinearGradient gradient = LinearGradient.create(0, 0, 10, 10);
14 | assertEquals(Status.SUCCESS, gradient.status());
15 | }
16 |
17 | @Test
18 | void testGetLinearPoints() {
19 | LinearGradient gradient = LinearGradient.create(0, 1, 10, 11);
20 | var points = gradient.getLinearPoints();
21 | assertEquals(2, points.length);
22 | assertEquals(0, points[0].x());
23 | assertEquals(1, points[0].y());
24 | assertEquals(10, points[1].x());
25 | assertEquals(11, points[1].y());
26 | assertEquals(Status.SUCCESS, gradient.status());
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/io/github/jwharm/cairobindings/package-info.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2024 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | /**
21 | * This package contains functionality that the cairo java bindings
22 | * need to load native libraries and call native functions.
23 | */
24 | package io.github.jwharm.cairobindings;
25 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/SolidPatternTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import static org.junit.jupiter.api.Assertions.*;
4 |
5 | import org.freedesktop.cairo.SolidPattern;
6 | import org.freedesktop.cairo.Status;
7 | import org.junit.jupiter.api.Test;
8 |
9 | class SolidPatternTest {
10 |
11 | @Test
12 | void testCreateRGB() {
13 | SolidPattern pattern = SolidPattern.createRGB(0.1, 0.2, 0.3);
14 | assertEquals(Status.SUCCESS, pattern.status());
15 | }
16 |
17 | @Test
18 | void testCreateRGBA() {
19 | SolidPattern pattern = SolidPattern.createRGBA(0.1, 0.2, 0.3, 0.4);
20 | assertEquals(Status.SUCCESS, pattern.status());
21 | }
22 |
23 | @Test
24 | void testGetRGBA() {
25 | SolidPattern pattern = SolidPattern.createRGBA(0.1, 0.2, 0.3, 0.4);
26 | double[] rgba = pattern.getRGBA();
27 | assertEquals(4, rgba.length);
28 | assertEquals(0.1, rgba[0]);
29 | assertEquals(0.2, rgba[1]);
30 | assertEquals(0.3, rgba[2]);
31 | assertEquals(0.4, rgba[3]);
32 | assertEquals(Status.SUCCESS, pattern.status());
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/RadialGradientTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 |
5 | import org.freedesktop.cairo.Circle;
6 | import org.freedesktop.cairo.RadialGradient;
7 | import org.freedesktop.cairo.Status;
8 | import org.junit.jupiter.api.Test;
9 |
10 | class RadialGradientTest {
11 |
12 | @Test
13 | void testCreate() {
14 | RadialGradient gradient = RadialGradient.create(100, 100, 50, 200, 100, 60);
15 | assertEquals(Status.SUCCESS, gradient.status());
16 | }
17 |
18 | @Test
19 | void testGetRadialCircles() {
20 | RadialGradient gradient = RadialGradient.create(100, 100, 50, 200, 100, 60);
21 | Circle[] circles = gradient.getRadialCircles();
22 | assertEquals(circles.length, 2);
23 | assertEquals(circles[0].x(), 100);
24 | assertEquals(circles[0].y(), 100);
25 | assertEquals(circles[0].radius(), 50);
26 | assertEquals(circles[1].x(), 200);
27 | assertEquals(circles[1].y(), 100);
28 | assertEquals(circles[1].radius(), 60);
29 | assertEquals(Status.SUCCESS, gradient.status());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/Point.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | /**
23 | * A Point defined by its x and y coordinates.
24 | *
25 | * @param x the X coordinate of the point
26 | * @param y the Y coordinate of the point
27 | * @since 1.16
28 | */
29 | public record Point(double x, double y) {
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/io/github/jwharm/cairobindings/Flag.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package io.github.jwharm.cairobindings;
21 |
22 | /**
23 | * Base class for flag types (enumerations that can be combined into bitfields)
24 | */
25 | public interface Flag {
26 |
27 | /**
28 | * Get the integer value for an enum member
29 | * @return the integer value
30 | */
31 | int getValue();
32 | }
33 |
--------------------------------------------------------------------------------
/.github/workflows/publish-pages.yml:
--------------------------------------------------------------------------------
1 | name: Publish Pages
2 |
3 | on:
4 | release:
5 | types: [created]
6 | push:
7 | branches:
8 | - main
9 |
10 | jobs:
11 | publish:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Setup Java
15 | uses: actions/setup-java@v4
16 | with:
17 | distribution: 'temurin'
18 | java-version: 22
19 | - name: Checkout
20 | uses: actions/checkout@v4
21 | - name: Setup Gradle
22 | uses: gradle/actions/setup-gradle@v3
23 | - name: Create javadoc with Gradle Wrapper
24 | run: ./gradlew javadoc
25 | - name: Create Site Artifact
26 | run: |
27 | mkdir site
28 | mv build/docs/javadoc site/
29 | - name: Upload Site Artifact
30 | uses: actions/upload-pages-artifact@v3
31 | with:
32 | path: 'site'
33 | pages:
34 | runs-on: ubuntu-latest
35 | needs: publish
36 | if: github.event_name == 'push'
37 | permissions:
38 | pages: write
39 | id-token: write
40 | environment:
41 | name: github-pages
42 | url: ${{ steps.deployment.outputs.page_url }}
43 | steps:
44 | - name: Deploy to GitHub Pages
45 | id: deployment
46 | uses: actions/deploy-pages@v4
47 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/Circle.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | /**
23 | * A circle defined by the x and y coordinates of the center and the radius.
24 | *
25 | * @param x x coordinate of the center
26 | * @param y y coordinate of the center
27 | * @param radius radius of the circle
28 | * @since 1.16
29 | */
30 | public record Circle(double x, double y, double radius) {
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/RGBA.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | /**
23 | * A color with red, green, blue and alpha components
24 | *
25 | * @param red red component of color
26 | * @param green green component of color
27 | * @param blue blue component of color
28 | * @param alpha alpha component of color
29 | * @since 1.18
30 | */
31 | public record RGBA(double red, double green, double blue, double alpha) {
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/module-info.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2024 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | /**
21 | * This module contains Java language bindings for the cairo
22 | * graphics library using the JEP-454 Panama FFI. The bindings are based on cairo 1.18
23 | * and work with JDK 22 or later.
24 | */
25 | module org.freedesktop.cairo {
26 | requires static org.gnome.glib; // Optional dependency on java-gi when cairo-gobject is used
27 | exports org.freedesktop.cairo;
28 | exports org.freedesktop.freetype;
29 | exports io.github.jwharm.cairobindings;
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/io/github/jwharm/cairobindings/ArenaCloseAction.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 | package io.github.jwharm.cairobindings;
20 |
21 | import java.lang.foreign.Arena;
22 | import java.lang.ref.Cleaner;
23 |
24 | /**
25 | * Helper class to separate the cleanup logic from the object being cleaned
26 | *
27 | * @param arena the Arena that will be closed
28 | * @since 1.18.1
29 | */
30 | public record ArenaCloseAction(Arena arena) implements Runnable {
31 |
32 | // Cleaner used to close the arena
33 | public static final Cleaner CLEANER = Cleaner.create();
34 |
35 | @Override
36 | public void run() {
37 | arena.close();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/ToyFontFaceTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 |
5 | import org.freedesktop.cairo.FontSlant;
6 | import org.freedesktop.cairo.FontWeight;
7 | import org.freedesktop.cairo.Status;
8 | import org.freedesktop.cairo.ToyFontFace;
9 | import org.junit.jupiter.api.Test;
10 |
11 | class ToyFontFaceTest {
12 |
13 | @Test
14 | void testCreate() {
15 | ToyFontFace f = ToyFontFace.create();
16 | assertEquals(Status.SUCCESS, f.status());
17 | }
18 |
19 | @Test
20 | void testCreateStringFontSlantFontWeight() {
21 | ToyFontFace f = ToyFontFace.create("Arial", FontSlant.NORMAL, FontWeight.NORMAL);
22 | assertEquals(Status.SUCCESS, f.status());
23 | }
24 |
25 | @Test
26 | void testGetFamily() {
27 | ToyFontFace f = ToyFontFace.create("Arial", FontSlant.NORMAL, FontWeight.NORMAL);
28 | assertEquals("Arial", f.getFamily());
29 | assertEquals(Status.SUCCESS, f.status());
30 | }
31 |
32 | @Test
33 | void testGetSlant() {
34 | ToyFontFace f = ToyFontFace.create("Arial", FontSlant.ITALIC, FontWeight.BOLD);
35 | assertEquals(FontSlant.ITALIC, f.getSlant());
36 | assertEquals(Status.SUCCESS, f.status());
37 | }
38 |
39 | @Test
40 | void testGetWeight() {
41 | ToyFontFace f = ToyFontFace.create("Arial", FontSlant.ITALIC, FontWeight.BOLD);
42 | assertEquals(FontWeight.BOLD, f.getWeight());
43 | assertEquals(Status.SUCCESS, f.status());
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ##############################
2 | ## Java
3 | ##############################
4 | .mtj.tmp/
5 | *.class
6 | *.jar
7 | *.war
8 | *.ear
9 | *.nar
10 | hs_err_pid*
11 | replay_pid*
12 |
13 | ##############################
14 | ## Maven
15 | ##############################
16 | target/
17 | pom.xml.tag
18 | pom.xml.releaseBackup
19 | pom.xml.versionsBackup
20 | pom.xml.next
21 | pom.xml.bak
22 | release.properties
23 | dependency-reduced-pom.xml
24 | buildNumber.properties
25 | .mvn/timing.properties
26 | .mvn/wrapper/maven-wrapper.jar
27 |
28 | ##############################
29 | ## Gradle
30 | ##############################
31 | bin/
32 | build/
33 | .gradle
34 | .gradletasknamecache
35 | gradle-app.setting
36 | !gradle-wrapper.jar
37 |
38 | ##############################
39 | ## IntelliJ
40 | ##############################
41 | out/
42 | .idea/
43 | .idea_modules/
44 | *.iml
45 | *.ipr
46 | *.iws
47 |
48 | ##############################
49 | ## Eclipse
50 | ##############################
51 | .settings/
52 | bin/
53 | tmp/
54 | .metadata
55 | .classpath
56 | .project
57 | *.tmp
58 | *.bak
59 | *.swp
60 | *~.nib
61 | local.properties
62 | .loadpath
63 | .factorypath
64 |
65 | ##############################
66 | ## NetBeans
67 | ##############################
68 | nbproject/private/
69 | build/
70 | nbbuild/
71 | dist/
72 | nbdist/
73 | nbactions.xml
74 | nb-configuration.xml
75 |
76 | ##############################
77 | ## Visual Studio Code
78 | ##############################
79 | .vscode/
80 | .code-workspace
81 |
82 | ##############################
83 | ## OS X
84 | ##############################
85 | .DS_Store
86 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/GradientTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 |
5 | import org.freedesktop.cairo.Gradient;
6 | import org.freedesktop.cairo.LinearGradient;
7 | import org.freedesktop.cairo.Status;
8 | import org.junit.jupiter.api.Test;
9 |
10 | class GradientTest {
11 |
12 | @Test
13 | void testAddColorStopRGB() {
14 | Gradient gradient = LinearGradient.create(0, 0, 10, 10);
15 | gradient.addColorStopRGB(0, 1, 1, 1);
16 | assertEquals(Status.SUCCESS, gradient.status());
17 | }
18 |
19 | @Test
20 | void testAddColorStopRGBA() {
21 | Gradient gradient = LinearGradient.create(0, 0, 10, 10);
22 | gradient.addColorStopRGBA(0, 1, 1, 1, 1);
23 | assertEquals(Status.SUCCESS, gradient.status());
24 | }
25 |
26 | @Test
27 | void testGetColorStopCount() {
28 | Gradient gradient = LinearGradient.create(0, 0, 10, 10);
29 | gradient.addColorStopRGB(0, 1, 1, 1);
30 | assertEquals(1, gradient.getColorStopCount());
31 | assertEquals(Status.SUCCESS, gradient.status());
32 | }
33 |
34 | @Test
35 | void testGetColorStopRGBA() {
36 | Gradient gradient = LinearGradient.create(0, 0, 10, 10);
37 | gradient.addColorStopRGBA(0, 0.5, 0.6, 0.7, 0.8);
38 | var color = gradient.getColorStopRGBA(0);
39 | assertEquals(0, color[0]);
40 | assertEquals(0.5, color[1]);
41 | assertEquals(0.6, color[2]);
42 | assertEquals(0.7, color[3]);
43 | assertEquals(0.8, color[4]);
44 | assertEquals(Status.SUCCESS, gradient.status());
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/Rect.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | /**
23 | * A rectangle.
24 | *
25 | * This is one of several helper classes in Java (see also {@link RGBA} and
26 | * {@link Point}), that do not exist in the native cairo API. The difference between
27 | * {@code Rect} and {@link Rectangle} is that the latter class is part of the native
28 | * cairo API and stores its values in native memory, while {@code Rect} instances
29 | * only exist in the JVM.
30 | *
31 | * @param x X coordinate of the left side of the rectangle
32 | * @param y Y coordinate of the top side of the rectangle
33 | * @param width width of the rectangle
34 | * @param height height of the rectangle
35 | * @since 1.18.1
36 | */
37 | public record Rect(double x, double y, double width, double height) {
38 | }
39 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/PathTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 |
5 | import org.freedesktop.cairo.Context;
6 | import org.freedesktop.cairo.Format;
7 | import org.freedesktop.cairo.ImageSurface;
8 | import org.freedesktop.cairo.Path;
9 | import org.freedesktop.cairo.PathElement;
10 | import org.junit.jupiter.api.Test;
11 |
12 | public class PathTest {
13 |
14 | @Test
15 | public void testPath() throws Exception {
16 | Context cr = Context.create(ImageSurface.create(Format.ARGB32, 120, 120));
17 |
18 | cr.moveTo(10, 20);
19 | cr.lineTo(30, 40);
20 | cr.curveTo(50, 60, 70, 80, 90, 100);
21 | cr.closePath(); // also adds an explicit move_to to the path
22 |
23 | var result = new StringBuilder();
24 |
25 | Path path = cr.copyPath();
26 | for (PathElement element : path) {
27 | switch (element) {
28 | case PathElement.MoveTo(double x, double y) -> result.append(String.format("move %.0f %.0f", x, y));
29 | case PathElement.LineTo(double x, double y) -> result.append(String.format("line %.0f %.0f", x, y));
30 | case PathElement.CurveTo(double x1, double y1, double x2, double y2, double x3, double y3) ->
31 | result.append(String.format("curve %.0f %.0f %.0f %.0f %.0f %.0f", x1, y1, x2, y2, x3, y3));
32 | case PathElement.ClosePath() -> result.append(String.format("close"));
33 | }
34 | }
35 |
36 | assertEquals("move 10 20" + "line 30 40" + "curve 50 60 70 80 90 100" + "close" + "move 10 20",
37 | result.toString());
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/freetype/FreeType2.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.freetype;
21 |
22 | import io.github.jwharm.cairobindings.LibLoad;
23 | import io.github.jwharm.cairobindings.Platform;
24 |
25 | /**
26 | * This class contains global declarations that do not belong in a specific
27 | * FreeType class definition.
28 | */
29 | public class FreeType2 {
30 |
31 | static {
32 | switch (Platform.getRuntimePlatform()) {
33 | case "linux" -> LibLoad.loadLibrary("libfreetype.so.6");
34 | case "windows" -> LibLoad.loadLibrary("libfreetype-6.dll");
35 | case "macos" -> LibLoad.loadLibrary("libfreetype.6.dylib");
36 | }
37 | }
38 |
39 | /**
40 | * Ensures the class initializer has loaded the freetype library.
41 | */
42 | public static void ensureInitialized() {
43 | }
44 |
45 | // Prohibit instantiation
46 | private FreeType2() {
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/UserScaledFontTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import org.freedesktop.cairo.*;
4 | import org.junit.jupiter.api.Test;
5 |
6 | import java.io.IOException;
7 | import java.util.concurrent.atomic.AtomicBoolean;
8 |
9 | import static org.junit.jupiter.api.Assertions.assertEquals;
10 | import static org.junit.jupiter.api.Assertions.assertTrue;
11 |
12 | public class UserScaledFontTest {
13 |
14 | @Test
15 | void testForegroundMarker() throws IOException {
16 | UserFontFace uf = UserFontFace.create();
17 | AtomicBoolean flag = new AtomicBoolean(false);
18 | uf.setRenderColorGlyphFunc((font, glyph, cr, extents) -> {
19 | Pattern p = font.getForegroundMarker();
20 | flag.set(Status.SUCCESS.equals(p.status()));
21 | });
22 | try (SVGSurface s = SVGSurface.create((String) null, 120, 120)) {
23 | Context cr = Context.create(s);
24 | cr.setFontFace(uf);
25 | cr.showText("test");
26 | assertTrue(flag.get());
27 | assertEquals(Status.SUCCESS, uf.status());
28 | }
29 | }
30 |
31 | @Test
32 | void testForegroundSource() throws IOException {
33 | UserFontFace uf = UserFontFace.create();
34 | AtomicBoolean flag = new AtomicBoolean(false);
35 | uf.setRenderColorGlyphFunc((font, glyph, cr, extents) -> {
36 | Pattern p = font.getForegroundSource();
37 | flag.set(Status.SUCCESS.equals(p.status()));
38 | });
39 | try (SVGSurface s = SVGSurface.create((String) null, 120, 120)) {
40 | Context cr = Context.create(s);
41 | cr.setFontFace(uf);
42 | cr.showText("test");
43 | assertTrue(flag.get());
44 | assertEquals(Status.SUCCESS, uf.status());
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/freetype/package-info.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2024 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | /**
21 | * Minimal wrapper for FreeType, for use with cairo FTFontFace and FTScaledFont.
22 | *
23 | * To use this wrapper, make sure that FreeType is installed and in the Java library path.
24 | *
25 | *
26 | * - {@code libfreetype.6.so} on Linux
27 | *
- {@code freetype-6.dll} on Windows
28 | *
- {@code libfreetype.6.dylib} on MacOS
29 | *
30 | *
31 | * Example usage of the wrapper, using a Windows-style path to load {@code arial.ttf}:
32 | *
33 | * {@code
34 | * Library ftLib = Library.initFreeType();
35 | * Face ftFace = new Face(ftLib, "C:\\Windows\\Fonts\\arial.ttf", 0);
36 | *
37 | * // Create a font face for FreeType
38 | * FTFontFace face = FTFontFace.create(ftFace, 0);
39 | *
40 | * // Create a scaled font from the FreeType font backend
41 | * FTScaledFont scaledFont = FTScaledFont.create(face, matrix, ctm, options);
42 | * }
43 | */
44 | package org.freedesktop.freetype;
45 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/ScriptMode.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | /**
23 | * A set of script output variants.
24 | *
25 | * @since 1.12
26 | */
27 | public enum ScriptMode {
28 |
29 | /**
30 | * the output will be in readable text (default).
31 | *
32 | * @since 1.12
33 | */
34 | ASCII,
35 |
36 | /**
37 | * the output will use byte codes.
38 | *
39 | * @since 1.12
40 | */
41 | BINARY;
42 |
43 | /**
44 | * Return the value of this enum
45 | * @return the value
46 | */
47 | public int getValue() {
48 | return ordinal();
49 | }
50 |
51 | /**
52 | * Returns the enum constant for the given ordinal (its position in the enum
53 | * declaration).
54 | *
55 | * @param ordinal the position in the enum declaration, starting from zero
56 | * @return the enum constant for the given ordinal
57 | */
58 | public static ScriptMode of(int ordinal) {
59 | return values()[ordinal];
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/SurfaceObserverMode.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | /**
23 | * Whether operations should be recorded.
24 | *
25 | * @see SurfaceObserver
26 | * @see Surface
27 | */
28 | public enum SurfaceObserverMode {
29 |
30 | /**
31 | * no recording is done
32 | *
33 | * @since 1.12
34 | */
35 | NORMAL,
36 |
37 | /**
38 | * operations are recorded
39 | *
40 | * @since 1.12
41 | */
42 | RECORD_OPERATIONS;
43 |
44 | /**
45 | * Return the value of this enum
46 | * @return the value
47 | */
48 | public int getValue() {
49 | return ordinal();
50 | }
51 |
52 | /**
53 | * Returns the enum constant for the given ordinal (its position in the enum
54 | * declaration).
55 | *
56 | * @param ordinal the position in the enum declaration, starting from zero
57 | * @return the enum constant for the given ordinal
58 | */
59 | public static SurfaceObserverMode of(int ordinal) {
60 | return values()[ordinal];
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/io/github/jwharm/cairobindings/Platform.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package io.github.jwharm.cairobindings;
21 |
22 | /**
23 | * The Platform class provides utility functions to retrieve the runtime platform
24 | * and check if a function is supported on the runtime platform.
25 | */
26 | public final class Platform {
27 |
28 | private static String runtimePlatform = null;
29 |
30 | // Prevent instantiation
31 | private Platform() {}
32 |
33 | /**
34 | * Determine the runtime platform
35 | * @return the runtime platform: "windows", "linux" or "macos"
36 | */
37 | public static String getRuntimePlatform() {
38 | if (runtimePlatform == null) {
39 | String osName = System.getProperty("os.name").toLowerCase();
40 | if (osName.contains("windows")) {
41 | runtimePlatform = "windows";
42 | } else if (osName.contains("linux")) {
43 | runtimePlatform = "linux";
44 | } else {
45 | runtimePlatform = "macos";
46 | }
47 | }
48 | return runtimePlatform;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/SVGSurfaceTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import org.freedesktop.cairo.*;
4 | import org.junit.jupiter.api.Test;
5 |
6 | import java.io.IOException;
7 | import java.io.OutputStream;
8 | import java.util.concurrent.atomic.AtomicBoolean;
9 |
10 | import static org.junit.jupiter.api.Assertions.*;
11 |
12 | class SVGSurfaceTest {
13 |
14 | @Test
15 | void testCreateStringIntInt() {
16 | try (SVGSurface s = SVGSurface.create((String) null, 120, 120)) {
17 | assertEquals(Status.SUCCESS, s.status());
18 | }
19 | }
20 |
21 | @Test
22 | void testCreateOutputStreamIntInt() throws IOException {
23 | AtomicBoolean success = new AtomicBoolean();
24 | OutputStream stream = new OutputStream() {
25 | @Override
26 | public void write(int b) {
27 | success.set(true);
28 | }
29 | };
30 | try (SVGSurface s = SVGSurface.create(stream, 120, 120)) {
31 | Context cr = Context.create(s);
32 | cr.rectangle(10, 10, 20, 20);
33 | cr.fill();
34 | assertEquals(Status.SUCCESS, s.status());
35 | }
36 | assertTrue(success.get());
37 | }
38 |
39 | @Test
40 | void testGetDocumentUnit() {
41 | try (SVGSurface s = SVGSurface.create((String) null, 120, 120)) {
42 | s.getDocumentUnit();
43 | assertEquals(Status.SUCCESS, s.status());
44 | }
45 | }
46 |
47 | @Test
48 | void testSetDocumentUnit() {
49 | try (SVGSurface s = SVGSurface.create((String) null, 120, 120)) {
50 | s.setDocumentUnit(SVGUnit.CM);
51 | assertEquals(Status.SUCCESS, s.status());
52 | }
53 | }
54 |
55 | @Test
56 | void testRestrictToVersion() {
57 | try (SVGSurface s = SVGSurface.create((String) null, 120, 120)) {
58 | s.restrictToVersion(SVGVersion.VERSION_1_2);
59 | assertEquals(Status.SUCCESS, s.status());
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/ScriptSurface.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import java.lang.foreign.MemorySegment;
23 |
24 | /**
25 | * The script surface provides the ability to render to a native script that
26 | * matches the cairo drawing model. The scripts can be replayed using tools
27 | * under the util/cairo-script directory, or with cairo-perf-trace.
28 | *
29 | * @see Surface
30 | * @see Script
31 | * @since 1.12
32 | */
33 | public final class ScriptSurface extends Surface {
34 |
35 | static {
36 | Cairo.ensureInitialized();
37 | }
38 |
39 | /*
40 | * Keep a reference to the Script and the wrapped Surface instances during the
41 | * lifetime of the ScriptSurface.
42 | */
43 | Script script;
44 | Surface target;
45 |
46 | /**
47 | * Constructor used internally to instantiate a java ScriptSurface object for a
48 | * native {@code cairo_surface_t} instance
49 | *
50 | * @param address the memory address of the native {@code cairo_surface_t}
51 | * instance
52 | */
53 | public ScriptSurface(MemorySegment address) {
54 | super(address);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/UserDataKey.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Proxy;
23 |
24 | import java.lang.foreign.*;
25 |
26 | /**
27 | * UserDataKey is used for attaching user data to cairo data structures.
28 | *
29 | * @since 1.0
30 | */
31 | public final class UserDataKey extends Proxy {
32 |
33 | static MemoryLayout getMemoryLayout() {
34 | return MemoryLayout.structLayout(
35 | ValueLayout.JAVA_INT.withName("unused")
36 | ).withName("cairo_user_data_key_t");
37 | }
38 |
39 | /**
40 | * Constructor used internally to instantiate a java UserDataKey object for a
41 | * native {@code UserDataKey} instance
42 | *
43 | * @param address the memory address of the native {@code UserDataKey} instance
44 | */
45 | public UserDataKey(MemorySegment address) {
46 | super(address);
47 | }
48 |
49 | /**
50 | * Create a new UserDataKey
51 | *
52 | * @param arena the arena in which the returned UserDataKey will be allocated
53 | * @return the newly created UserDataKey
54 | */
55 | public static UserDataKey create(Arena arena) {
56 | return new UserDataKey(arena.allocate(getMemoryLayout()));
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/RecordingSurfaceTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import org.freedesktop.cairo.*;
4 | import org.junit.jupiter.api.Test;
5 |
6 | import java.io.IOException;
7 | import java.lang.foreign.Arena;
8 |
9 | import static org.junit.jupiter.api.Assertions.*;
10 |
11 | class RecordingSurfaceTest {
12 |
13 | @Test
14 | void testCreate() throws IOException {
15 | try (Arena arena = Arena.ofConfined();
16 | Surface s = ImageSurface.create(Format.ARGB32, 120, 120);
17 | RecordingSurface r = RecordingSurface.create(Content.COLOR_ALPHA, Rectangle.create(arena, 20, 20, 50, 50))) {
18 | assertEquals(Status.SUCCESS, s.status());
19 | assertEquals(Status.SUCCESS, r.status());
20 | }
21 | }
22 |
23 | @Test
24 | void testInkExtents() throws IOException {
25 | try (Surface s = ImageSurface.create(Format.ARGB32, 120, 120);
26 | RecordingSurface r = RecordingSurface.create(Content.COLOR_ALPHA, null)) {
27 | Context.create(r)
28 | .rectangle(12, 14, 16, 18)
29 | .fill();
30 | Rect rect = r.inkExtents();
31 | assertEquals(12, rect.x());
32 | assertEquals(14, rect.y());
33 | assertEquals(16, rect.width());
34 | assertEquals(18, rect.height());
35 | assertEquals(Status.SUCCESS, s.status());
36 | assertEquals(Status.SUCCESS, r.status());
37 | }
38 | }
39 |
40 | @Test
41 | void testGetExtents() {
42 | try (Arena arena = Arena.ofConfined();
43 | Surface s = ImageSurface.create(Format.ARGB32, 120, 120);
44 | RecordingSurface r = RecordingSurface.create(Content.COLOR_ALPHA, Rectangle.create(arena, 20, 30, 50, 60))) {
45 | Rectangle rect = Rectangle.create(arena, 0, 0, 0, 0);
46 | r.getExtents(rect);
47 | assertEquals(20, rect.x());
48 | assertEquals(30, rect.y());
49 | assertEquals(50, rect.width());
50 | assertEquals(60, rect.height());
51 | assertEquals(Status.SUCCESS, s.status());
52 | assertEquals(Status.SUCCESS, r.status());
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/DeviceTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import org.freedesktop.cairo.*;
4 | import org.junit.jupiter.api.Test;
5 | import org.junit.jupiter.api.io.TempDir;
6 |
7 | import java.lang.foreign.Arena;
8 | import java.nio.file.Path;
9 |
10 | import static org.junit.jupiter.api.Assertions.*;
11 |
12 | class DeviceTest {
13 |
14 | @TempDir
15 | Path tempDir;
16 |
17 | @Test
18 | void status() {
19 | try (Device d = Script.create(tempDir.resolve("test.script").toString())) {
20 | assertEquals(Status.SUCCESS, d.status());
21 | }
22 | }
23 |
24 | @Test
25 | void finish() {
26 | try (Device d = Script.create(tempDir.resolve("test.script").toString())) {
27 | d.finish();
28 | assertEquals(Status.SUCCESS, d.status());
29 | }
30 | }
31 |
32 | @Test
33 | void flush() {
34 | try (Device d = Script.create(tempDir.resolve("test.script").toString())) {
35 | d.flush();
36 | assertEquals(Status.SUCCESS, d.status());
37 | }
38 | }
39 |
40 | @Test
41 | void getDeviceType() {
42 | try (Device d = Script.create(tempDir.resolve("test.script").toString())) {
43 | DeviceType type = d.getDeviceType();
44 | assertEquals(DeviceType.SCRIPT, type);
45 | assertEquals(Status.SUCCESS, d.status());
46 | }
47 | }
48 |
49 | @Test
50 | void acquireAndRelease() {
51 | try (Device d = Script.create(tempDir.resolve("test.script").toString())) {
52 | d.acquire();
53 | d.release();
54 | assertEquals(d.status(), Status.SUCCESS);
55 | }
56 | }
57 |
58 | @Test
59 | void testUserData() {
60 | try (Arena arena = Arena.ofConfined();
61 | Device device = Script.create(tempDir.resolve("test.script").toString())) {
62 | Rectangle input = Rectangle.create(arena, 0, 0, 10, 10);
63 | UserDataKey key = UserDataKey.create(arena);
64 | device.setUserData(key, input.handle());
65 | Rectangle output = new Rectangle(device.getUserData(key));
66 | assertEquals(input, output);
67 | assertEquals(device.status(), Status.SUCCESS);
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/PatternTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import static org.junit.jupiter.api.Assertions.*;
4 |
5 | import org.freedesktop.cairo.*;
6 | import org.junit.jupiter.api.Disabled;
7 | import org.junit.jupiter.api.Test;
8 |
9 | import java.lang.foreign.Arena;
10 |
11 | class PatternTest {
12 |
13 | @Test
14 | void testStatus() {
15 | Gradient pattern = LinearGradient.create(0, 0, 10, 10);
16 | assertEquals(Status.SUCCESS, pattern.status());
17 | }
18 |
19 | @Test
20 | void testExtend() {
21 | Gradient pattern = LinearGradient.create(0, 0, 10, 10);
22 | pattern.setExtend(Extend.PAD);
23 | Extend e = pattern.getExtend();
24 | assertEquals(Extend.PAD, e);
25 | assertEquals(Status.SUCCESS, pattern.status());
26 | }
27 |
28 | @Test
29 | void testFilter() {
30 | Gradient pattern = LinearGradient.create(0, 0, 10, 10);
31 | pattern.setFilter(Filter.NEAREST);
32 | Filter f = pattern.getFilter();
33 | assertEquals(Filter.NEAREST, f);
34 | assertEquals(Status.SUCCESS, pattern.status());
35 | }
36 |
37 | @Test
38 | void testMatrix() {
39 | try (Arena arena = Arena.ofConfined()) {
40 | Gradient pattern = LinearGradient.create(0, 0, 10, 10);
41 | Matrix scale = Matrix.create(arena).initIdentity();
42 | scale.scale(2, 2);
43 | pattern.setMatrix(scale);
44 | Matrix m = Matrix.create(arena).init(0, 0, 0, 0, 0, 0);
45 | pattern.getMatrix(m);
46 | assertEquals(Status.SUCCESS, pattern.status());
47 | }
48 | }
49 |
50 | @Test
51 | void testGetPatternType() {
52 | Gradient pattern = LinearGradient.create(0, 0, 10, 10);
53 | assertEquals(PatternType.LINEAR, pattern.getPatternType());
54 | assertEquals(Status.SUCCESS, pattern.status());
55 | }
56 |
57 | @Disabled("Does not work with cairo 1.17.8 (Fedora 38, Gnome 45 Flatpak SDK)")
58 | @Test
59 | void testDither() {
60 | Pattern pattern = LinearGradient.create(0, 0, 10, 10);
61 | pattern.setDither(Dither.FAST);
62 | assertEquals(Dither.FAST, pattern.getDither());
63 | assertEquals(Status.SUCCESS, pattern.status());
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/PDFOutlineFlags.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Flag;
23 |
24 | /**
25 | * {@code PDFOutlineFlags} is used by the cairo_pdf_surface_add_outline()
26 | * function specify the attributes of an outline item. These flags may be
27 | * bitwise-or'd to produce any combination of flags.
28 | *
29 | * @since 1.16
30 | */
31 | public enum PDFOutlineFlags implements Flag {
32 |
33 | /**
34 | * The outline item defaults to open in the PDF viewer
35 | *
36 | * @since 1.16
37 | */
38 | OPEN,
39 |
40 | /**
41 | * The outline item is displayed by the viewer in bold text
42 | *
43 | * @since 1.16
44 | */
45 | BOLD,
46 |
47 | /**
48 | * The outline item is displayed by the viewer in italic text
49 | *
50 | * @since 1.16
51 | */
52 | ITALIC;
53 |
54 | /**
55 | * Return the value of this enum
56 | * @return the value
57 | */
58 | public int getValue() {
59 | return ordinal();
60 | }
61 |
62 | /**
63 | * Returns the enum constant for the given ordinal (its position in the enum
64 | * declaration).
65 | *
66 | * @param ordinal the position in the enum declaration, starting from zero
67 | * @return the enum constant for the given ordinal
68 | */
69 | public static PDFOutlineFlags of(int ordinal) {
70 | return values()[ordinal];
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/ColorMode.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | /**
23 | * Specifies if color fonts are to be rendered using the color glyphs or
24 | * outline glyphs. Glyphs that do not have a color presentation, and
25 | * non-color fonts are not affected by this font option.
26 | *
27 | * @since 1.18
28 | */
29 | public enum ColorMode {
30 |
31 | /**
32 | * Use the default color mode for font backend and target device
33 | *
34 | * @since 1.18
35 | */
36 | DEFAULT,
37 |
38 | /**
39 | * Disable rendering color glyphs. Glyphs are always rendered as outline
40 | * glyphs
41 | *
42 | * @since 1.18
43 | */
44 | NO_COLOR,
45 |
46 | /**
47 | * Enable rendering color glyphs. If the font contains a color presentation
48 | * for a glyph, and when supported by the font backend, the glyph will be
49 | * rendered in color
50 | *
51 | * @since 1.18
52 | */
53 | COLOR;
54 |
55 | /**
56 | * Return the value of this enum
57 | *
58 | * @return the value
59 | */
60 | public int getValue() {
61 | return ordinal();
62 | }
63 |
64 | /**
65 | * Returns the enum constant for the given ordinal (its position in the enum
66 | * declaration).
67 | *
68 | * @param ordinal the position in the enum declaration, starting from zero
69 | * @return the enum constant for the given ordinal
70 | */
71 | public static ColorMode of(int ordinal) {
72 | return values()[ordinal];
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/io/github/jwharm/cairobindings/Proxy.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package io.github.jwharm.cairobindings;
21 |
22 | import java.lang.foreign.MemorySegment;
23 |
24 | /**
25 | * Base type for a Java proxy object to an instance in native memory.
26 | */
27 | public class Proxy {
28 |
29 | private final MemorySegment address;
30 |
31 | /**
32 | * Create a new {@code Proxy} object for an instance in native memory.
33 | * @param address the memory address of the instance
34 | */
35 | public Proxy(MemorySegment address) {
36 | this.address = address;
37 | MemoryCleaner.register(this);
38 | }
39 |
40 | /**
41 | * Get the memory address of the instance
42 | * @return the memory address of the instance
43 | */
44 | public MemorySegment handle() {
45 | return address;
46 | }
47 |
48 | /**
49 | * Returns the hashcode of the memory address
50 | * @return the hashcode of the memory address
51 | * @see MemorySegment#hashCode()
52 | */
53 | public int hashCode() {
54 | return address.hashCode();
55 | }
56 |
57 | /**
58 | * Checks whether the other object is a Proxy instance and the memory
59 | * addresses are equal.
60 | * @param obj another object
61 | * @return true when the other object is a Proxy instance and the memory
62 | * addresses are equal, otherwise false.
63 | * @see MemorySegment#equals(Object)
64 | */
65 | @Override
66 | public boolean equals(Object obj) {
67 | return obj instanceof Proxy other
68 | && address.equals(other.address);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/FTFontFaceTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 |
5 | import org.freedesktop.cairo.FTFontFace;
6 | import org.freedesktop.cairo.FTSynthesize;
7 | import org.freedesktop.cairo.Status;
8 | import org.freedesktop.freetype.Face;
9 | import org.freedesktop.freetype.Library;
10 | import org.junit.jupiter.api.BeforeAll;
11 | import org.junit.jupiter.api.Test;
12 |
13 | import io.github.jwharm.cairobindings.Platform;
14 |
15 | import java.io.File;
16 | import java.util.Set;
17 |
18 | class FTFontFaceTest {
19 |
20 | private static String TTF_FILE;
21 |
22 | @BeforeAll
23 | static void setup() {
24 | // These files are going to be in different locations depending on your system.
25 | switch (Platform.getRuntimePlatform()) {
26 | case "linux" -> {
27 | // Fedora
28 | TTF_FILE = "/usr/share/fonts/liberation-serif/LiberationSerif-Regular.ttf";
29 | if (! new File(TTF_FILE).exists()) {
30 | // Ubuntu
31 | TTF_FILE = "/usr/share/fonts/truetype/liberation/LiberationSerif-Regular.ttf";
32 | }
33 | if (! new File(TTF_FILE).exists()) {
34 | // OpenSUSE
35 | TTF_FILE = "/usr/share/fonts/truetype/LiberationSerif-Regular.ttf";
36 | }
37 | }
38 | case "windows" -> TTF_FILE = "C:\\Windows\\Fonts\\arial.ttf";
39 | case "macos" -> TTF_FILE = "/Library/Fonts/Arial Unicode.ttf";
40 | }
41 | }
42 |
43 | @Test
44 | void testCreate() {
45 | Library ftLib = Library.initFreeType();
46 | Face ftFace = Face.newFace(ftLib, TTF_FILE, 0);
47 | FTFontFace face = FTFontFace.create(ftFace, 0);
48 | assertEquals(Status.SUCCESS, face.status());
49 | ftFace.doneFace();
50 | ftLib.doneFreeType();
51 | }
52 |
53 | @Test
54 | void testSynthesize() {
55 | Library ftLib = Library.initFreeType();
56 | Face ftFace = Face.newFace(ftLib, TTF_FILE, 0);
57 | FTFontFace face = FTFontFace.create(ftFace, 0);
58 | face.setSynthesize(Set.of(FTSynthesize.BOLD, FTSynthesize.OBLIQUE));
59 | face.unsetSynthesize(Set.of(FTSynthesize.BOLD));
60 | assertEquals(Set.of(FTSynthesize.OBLIQUE), face.getSynthesize());
61 | assertEquals(Status.SUCCESS, face.status());
62 | ftFace.doneFace();
63 | ftLib.doneFreeType();
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/PDFMetadata.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | /**
23 | * {@code PDFMetadata} is used by the cairo_pdf_surface_set_metadata() function
24 | * specify the metadata to set.
25 | *
26 | * @since 1.16
27 | */
28 | public enum PDFMetadata {
29 |
30 | /**
31 | * The document title
32 | *
33 | * @since 1.16
34 | */
35 | TITLE,
36 |
37 | /**
38 | * The document author
39 | *
40 | * @since 1.16
41 | */
42 | AUTHOR,
43 |
44 | /**
45 | * The document subject
46 | *
47 | * @since 1.16
48 | */
49 | SUBJECT,
50 |
51 | /**
52 | * The document keywords
53 | *
54 | * @since 1.16
55 | */
56 | KEYWORDS,
57 |
58 | /**
59 | * The document creator
60 | *
61 | * @since 1.16
62 | */
63 | CREATOR,
64 |
65 | /**
66 | * The document creation date
67 | *
68 | * @since 1.16
69 | */
70 | CREATE_DATE,
71 |
72 | /**
73 | * The document modification date
74 | *
75 | * @since 1.16
76 | */
77 | MOD_DATE;
78 |
79 | /**
80 | * Return the value of this enum
81 | * @return the value
82 | */
83 | public int getValue() {
84 | return ordinal();
85 | }
86 |
87 | /**
88 | * Returns the enum constant for the given ordinal (its position in the enum
89 | * declaration).
90 | *
91 | * @param ordinal the position in the enum declaration, starting from zero
92 | * @return the enum constant for the given ordinal
93 | */
94 | public static PDFMetadata of(int ordinal) {
95 | return values()[ordinal];
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/RasterSourceTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 |
5 | import org.freedesktop.cairo.Content;
6 | import org.freedesktop.cairo.RasterSource;
7 | import org.freedesktop.cairo.RasterSourceAcquireFunc;
8 | import org.freedesktop.cairo.RasterSourceCopyFunc;
9 | import org.freedesktop.cairo.RasterSourceFinishFunc;
10 | import org.freedesktop.cairo.RasterSourceReleaseFunc;
11 | import org.freedesktop.cairo.RasterSourceSnapshotFunc;
12 | import org.freedesktop.cairo.Status;
13 | import org.junit.jupiter.api.Test;
14 |
15 | class RasterSourceTest {
16 |
17 | @Test
18 | void testCreate() {
19 | RasterSource source = RasterSource.create(Content.COLOR_ALPHA, 100, 100);
20 | assertEquals(Status.SUCCESS, source.status());
21 | }
22 |
23 | @Test
24 | void testAcquireAndRelease() {
25 | RasterSource source = RasterSource.create(Content.COLOR_ALPHA, 100, 100);
26 | RasterSourceAcquireFunc acquireFunc = (pattern, target, extents) -> null;
27 | RasterSourceReleaseFunc releaseFunc = (pattern, target) -> {};
28 | source.setAcquire(acquireFunc, releaseFunc);
29 | assertEquals(acquireFunc, source.getAcquire());
30 | assertEquals(releaseFunc, source.getRelease());
31 | assertEquals(Status.SUCCESS, source.status());
32 | }
33 |
34 | @Test
35 | void testSnapshot() {
36 | RasterSource source = RasterSource.create(Content.COLOR_ALPHA, 100, 100);
37 | RasterSourceSnapshotFunc s1 = (pattern) -> null;
38 | source.setSnapshot(s1);
39 | RasterSourceSnapshotFunc s2 = source.getSnapshot();
40 | assertEquals(s1, s2);
41 | assertEquals(Status.SUCCESS, source.status());
42 | }
43 |
44 | @Test
45 | void testCopy() {
46 | RasterSource source = RasterSource.create(Content.COLOR_ALPHA, 100, 100);
47 | RasterSourceCopyFunc c1 = (pattern, other) -> null;
48 | source.setCopy(c1);
49 | RasterSourceCopyFunc c2 = source.getCopy();
50 | assertEquals(c1, c2);
51 | assertEquals(Status.SUCCESS, source.status());
52 | }
53 |
54 | @Test
55 | void testFinish() {
56 | RasterSource source = RasterSource.create(Content.COLOR_ALPHA, 100, 100);
57 | RasterSourceFinishFunc f1 = (pattern) -> {};
58 | source.setFinish(f1);
59 | RasterSourceFinishFunc f2 = source.getFinish();
60 | assertEquals(f1, f2);
61 | assertEquals(Status.SUCCESS, source.status());
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/FontOptionsTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import org.freedesktop.cairo.*;
4 | import org.junit.jupiter.api.Test;
5 |
6 | import static org.junit.jupiter.api.Assertions.assertEquals;
7 |
8 | class FontOptionsTest {
9 |
10 | @Test
11 | void testAntialias() {
12 | FontOptions fo = FontOptions.create();
13 | fo.setAntialias(Antialias.FAST);
14 | assertEquals(Antialias.FAST, fo.getAntialias());
15 | assertEquals(Status.SUCCESS, fo.status());
16 | }
17 |
18 | @Test
19 | void testSubpixelOrder() {
20 | FontOptions fo = FontOptions.create();
21 | fo.setSubpixelOrder(SubpixelOrder.BGR);
22 | assertEquals(SubpixelOrder.BGR, fo.getSubpixelOrder());
23 | assertEquals(Status.SUCCESS, fo.status());
24 | }
25 |
26 | @Test
27 | void testHintStyle() {
28 | FontOptions fo = FontOptions.create();
29 | fo.setHintStyle(HintStyle.SLIGHT);
30 | assertEquals(HintStyle.SLIGHT, fo.getHintStyle());
31 | assertEquals(Status.SUCCESS, fo.status());
32 | }
33 |
34 | @Test
35 | void testHintMetrics() {
36 | FontOptions fo = FontOptions.create();
37 | fo.setHintMetrics(HintMetrics.OFF);
38 | assertEquals(HintMetrics.OFF, fo.getHintMetrics());
39 | assertEquals(Status.SUCCESS, fo.status());
40 | }
41 |
42 | @Test
43 | void testVariations() {
44 | FontOptions fo = FontOptions.create();
45 | fo.setVariations("wght=200,wdth=140.5");
46 | assertEquals("wght=200,wdth=140.5", fo.getVariations());
47 | assertEquals(Status.SUCCESS, fo.status());
48 | }
49 |
50 | @Test
51 | void testColorMode() {
52 | FontOptions fo = FontOptions.create();
53 | fo.setColorMode(ColorMode.NO_COLOR);
54 | assertEquals(ColorMode.NO_COLOR, fo.getColorMode());
55 | assertEquals(Status.SUCCESS, fo.status());
56 | }
57 |
58 | @Test
59 | void testColorPalette() {
60 | FontOptions fo = FontOptions.create();
61 | fo.setColorPalette(FontOptions.COLOR_PALETTE_DEFAULT);
62 | assertEquals(FontOptions.COLOR_PALETTE_DEFAULT, fo.getColorPalette());
63 | assertEquals(Status.SUCCESS, fo.status());
64 | }
65 |
66 | @Test
67 | void testCustomColorPalette() {
68 | FontOptions fo = FontOptions.create();
69 | fo.setCustomPaletteColor(0, 10.0, 20.0, 30.0, 40.5);
70 | assertEquals(new RGBA(10.0, 20.0, 30.0, 40.5), fo.getCustomPaletteColor(0));
71 | assertEquals(Status.SUCCESS, fo.status());
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/FTSynthesize.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Flag;
23 |
24 | /**
25 | * A set of synthesis options to control how FreeType renders the glyphs for a particular font face.
26 | *
27 | * Individual synthesis features of a {@link FTFontFace} can be set using
28 | * {@link FTFontFace#setSynthesize}, or disabled using {@link FTFontFace#unsetSynthesize}.
29 | * The currently enabled set of synthesis options can be queried with {@link FTFontFace#getSynthesize}.
30 | *
31 | * Note that when synthesizing glyphs, the font metrics returned will only be estimates.
32 | *
33 | * @since 1.12
34 | */
35 | public enum FTSynthesize implements Flag {
36 | /**
37 | * Embolden the glyphs (redraw with a pixel offset)
38 | */
39 | BOLD(1),
40 |
41 | /**
42 | * Slant the glyph outline by 12 degrees to the right.
43 | */
44 | OBLIQUE(1 << 1);
45 |
46 | private final int value;
47 |
48 | /**
49 | * Create a new FTSynthesize enum value
50 | *
51 | * @param value {@link #BOLD}, {@link #OBLIQUE} or a combination of both
52 | */
53 | FTSynthesize(int value) {
54 | this.value = value;
55 | }
56 |
57 | /**
58 | * Get the value of this FTSynthesize enum
59 | *
60 | * @return {@link #BOLD}, {@link #OBLIQUE} or a combination of both
61 | */
62 | public int getValue() {
63 | return value;
64 | }
65 |
66 | /**
67 | * Create an FTSynthesize enum for this value
68 | *
69 | * @param value the value of the enum
70 | * @return a new FTSynthesize enum member
71 | */
72 | public static FTSynthesize of(int value) {
73 | return value == 1 ? BOLD : OBLIQUE;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/ScriptTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import org.freedesktop.cairo.*;
4 | import org.junit.jupiter.api.Test;
5 | import org.junit.jupiter.api.io.TempDir;
6 |
7 | import java.io.OutputStream;
8 | import java.nio.file.Path;
9 | import java.util.concurrent.atomic.AtomicBoolean;
10 |
11 | import static org.junit.jupiter.api.Assertions.*;
12 |
13 | class ScriptTest {
14 |
15 | @TempDir
16 | Path tempDir;
17 |
18 | @Test
19 | void testCreateString() {
20 | try (Script s = Script.create(tempDir.resolve("test.script").toString())) {
21 | assertEquals(Status.SUCCESS, s.status());
22 | }
23 | }
24 |
25 | @Test
26 | void testCreateOutputStream() {
27 | AtomicBoolean success = new AtomicBoolean();
28 | OutputStream stream = new OutputStream() {
29 | @Override
30 | public void write(int b) {
31 | success.set(true);
32 | }
33 | };
34 | try (Script s = Script.create(stream)) {
35 | assertEquals(Status.SUCCESS, s.status());
36 | }
37 | assertTrue(success.get());
38 | }
39 |
40 | @Test
41 | void testFrom() {
42 | try (Script s = Script.create(tempDir.resolve("test.script").toString())) {
43 | s.from(RecordingSurface.create(Content.COLOR_ALPHA, null));
44 | assertEquals(Status.SUCCESS, s.status());
45 | }
46 | }
47 |
48 | @Test
49 | void testMode() {
50 | try (Script s = Script.create(tempDir.resolve("test.script").toString())) {
51 | s.setMode(ScriptMode.ASCII);
52 | assertEquals(ScriptMode.ASCII, s.getMode());
53 | assertEquals(Status.SUCCESS, s.status());
54 | }
55 | }
56 |
57 | @Test
58 | void testCreateScriptSurface() {
59 | try (Script s = Script.create(tempDir.resolve("test.script").toString())) {
60 | s.createScriptSurface(Content.COLOR, 30, 30);
61 | assertEquals(Status.SUCCESS, s.status());
62 | }
63 | }
64 |
65 | @Test
66 | void testCreateScriptSurfaceForTarget() {
67 | try (Script s = Script.create(tempDir.resolve("test.script").toString())) {
68 | s.createScriptSurfaceForTarget(ImageSurface.create(Format.ARGB32, 120, 120));
69 | assertEquals(Status.SUCCESS, s.status());
70 | }
71 | }
72 |
73 | @Test
74 | void testWriteComment() {
75 | try (Script s = Script.create(tempDir.resolve("test.script").toString())) {
76 | s.writeComment("test");
77 | assertEquals(Status.SUCCESS, s.status());
78 | }
79 | }
80 | }
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/PSSurfaceTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import org.freedesktop.cairo.PSLevel;
4 | import org.freedesktop.cairo.PSSurface;
5 | import org.freedesktop.cairo.Status;
6 | import org.junit.jupiter.api.Test;
7 |
8 | import java.io.OutputStream;
9 | import java.util.concurrent.atomic.AtomicBoolean;
10 |
11 | import static org.junit.jupiter.api.Assertions.*;
12 |
13 | class PSSurfaceTest {
14 |
15 | @Test
16 | void testCreateStringIntInt() {
17 | try (PSSurface s = PSSurface.create((String) null, 120, 120)) {
18 | assertEquals(Status.SUCCESS, s.status());
19 | }
20 | }
21 |
22 | @Test
23 | void testCreateOutputStreamIntInt() {
24 | AtomicBoolean success = new AtomicBoolean();
25 | OutputStream stream = new OutputStream() {
26 | @Override
27 | public void write(int b) {
28 | success.set(true);
29 | }
30 | };
31 | try (PSSurface s = PSSurface.create(stream, 120, 120)) {
32 | s.showPage();
33 | assertEquals(Status.SUCCESS, s.status());
34 | }
35 | assertTrue(success.get());
36 | }
37 |
38 | @Test
39 | void testRestrictToLevel() {
40 | try (PSSurface s = PSSurface.create((String) null, 120, 120)) {
41 | s.restrictToLevel(PSLevel.LEVEL_3);
42 | assertEquals(Status.SUCCESS, s.status());
43 | }
44 | }
45 |
46 | @Test
47 | void testEPS() {
48 | try (PSSurface s = PSSurface.create((String) null, 120, 120)) {
49 | s.setEPS(true);
50 | assertTrue(s.getEPS());
51 | assertEquals(Status.SUCCESS, s.status());
52 | }
53 | }
54 |
55 | @Test
56 | void testSetSize() {
57 | try (PSSurface s = PSSurface.create((String) null, 120, 120)) {
58 | s.setSize(140, 140);
59 | assertEquals(Status.SUCCESS, s.status());
60 | }
61 | }
62 |
63 | @Test
64 | void testDscBeginSetup() {
65 | try (PSSurface s = PSSurface.create((String) null, 120, 120)) {
66 | s.dscBeginSetup();
67 | assertEquals(Status.SUCCESS, s.status());
68 | }
69 | }
70 |
71 | @Test
72 | void testDscBeginPageSetup() {
73 | try (PSSurface s = PSSurface.create((String) null, 120, 120)) {
74 | s.dscBeginPageSetup();
75 | assertEquals(Status.SUCCESS, s.status());
76 | }
77 | }
78 |
79 | @Test
80 | void testDscComment() {
81 | try (PSSurface s = PSSurface.create((String) null, 120, 120)) {
82 | s.dscComment("%%Title: Test");
83 | assertEquals(Status.SUCCESS, s.status());
84 | }
85 | }
86 | }
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/Dither.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | /**
23 | * Dither is an intentionally applied form of noise used to randomize
24 | * quantization error, preventing large-scale patterns such as color banding in
25 | * images (e.g. for gradients). Ordered dithering applies a precomputed
26 | * threshold matrix to spread the errors smoothly.
27 | *
28 | * {@link Dither} is modeled on pixman dithering algorithm choice. As of
29 | * Pixman 0.40, FAST corresponds to a 8x8 ordered bayer noise and GOOD and BEST
30 | * use an ordered 64x64 precomputed blue noise.
31 | *
32 | * @since 1.18
33 | */
34 | public enum Dither {
35 |
36 | /**
37 | * No dithering.
38 | *
39 | * @since 1.18
40 | */
41 | NONE,
42 |
43 | /**
44 | * Default choice at cairo compile time. Currently NONE.
45 | *
46 | * @since 1.18
47 | */
48 | DEFAULT,
49 |
50 | /**
51 | * Fastest dithering algorithm supported by the backend
52 | *
53 | * @since 1.18
54 | */
55 | FAST,
56 |
57 | /**
58 | * An algorithm with smoother dithering than FAST
59 | *
60 | * @since 1.18
61 | */
62 | GOOD,
63 |
64 | /**
65 | * Best algorithm available in the backend
66 | *
67 | * @since 1.18
68 | */
69 | BEST;
70 |
71 | /**
72 | * Return the value of this enum
73 | *
74 | * @return the value
75 | */
76 | public int getValue() {
77 | return ordinal();
78 | }
79 |
80 | /**
81 | * Returns the enum constant for the given ordinal (its position in the enum
82 | * declaration).
83 | *
84 | * @param ordinal the position in the enum declaration, starting from zero
85 | * @return the enum constant for the given ordinal
86 | */
87 | public static Dither of(int ordinal) {
88 | return values()[ordinal];
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/DestroyFunc.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import java.lang.foreign.*;
23 | import java.lang.invoke.MethodHandle;
24 | import java.lang.invoke.MethodHandles;
25 |
26 | /**
27 | * DestroyFunc the type of function which is called when a data element is
28 | * destroyed. It is passed the pointer to the data element and should free any
29 | * memory and resources allocated for it.
30 | *
31 | * @since 1.0
32 | */
33 | @FunctionalInterface
34 | public interface DestroyFunc {
35 |
36 | /**
37 | * The function to implement as callback in a destroy operation.
38 | *
39 | * @param data the data element being destroyed.
40 | * @since 1.0
41 | */
42 | void destroy(MemorySegment data);
43 |
44 | /**
45 | * The callback that is executed by native code. This method marshals the
46 | * parameters and calls {@link #destroy}.
47 | *
48 | * @param data the data element being destroyed.
49 | * @since 1.0
50 | */
51 | default void upcall(MemorySegment data) {
52 | destroy(data);
53 | }
54 |
55 | /**
56 | * Generates an upcall stub, a C function pointer that will call
57 | * {@link #upcall}.
58 | *
59 | * @param arena the arena in which the upcall stub will be allocated
60 | * @return the function pointer of the upcall stub
61 | * @since 1.0
62 | */
63 | default MemorySegment toCallback(Arena arena) {
64 | try {
65 | FunctionDescriptor fdesc = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS);
66 | MethodHandle handle = MethodHandles.lookup().findVirtual(DestroyFunc.class, "upcall", fdesc.toMethodType());
67 | return Linker.nativeLinker().upcallStub(handle.bindTo(this), fdesc, arena);
68 | } catch (NoSuchMethodException | IllegalAccessException e) {
69 | throw new RuntimeException(e);
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/FontWeight.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 |
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.ValueLayout;
26 | import java.lang.invoke.MethodHandle;
27 |
28 | /**
29 | * Specifies variants of a font face based on their weight.
30 | *
31 | * @since 1.0
32 | */
33 | public enum FontWeight {
34 |
35 | /**
36 | * Normal font weight
37 | *
38 | * @since 1.0
39 | */
40 | NORMAL,
41 |
42 | /**
43 | * Bold font weight
44 | *
45 | * @since 1.0
46 | */
47 | BOLD;
48 |
49 | static {
50 | Cairo.ensureInitialized();
51 | }
52 |
53 | /**
54 | * Return the value of this enum
55 | *
56 | * @return the value
57 | */
58 | public int getValue() {
59 | return ordinal();
60 | }
61 |
62 | /**
63 | * Returns the enum constant for the given ordinal (its position in the enum
64 | * declaration).
65 | *
66 | * @param ordinal the position in the enum declaration, starting from zero
67 | * @return the enum constant for the given ordinal
68 | */
69 | public static FontWeight of(int ordinal) {
70 | return values()[ordinal];
71 | }
72 |
73 | /**
74 | * Get the CairoFontWeight GType
75 | * @return the GType
76 | */
77 | public static org.gnome.glib.Type getType() {
78 | try {
79 | long result = (long) cairo_gobject_font_weight_get_type.invoke();
80 | return new org.gnome.glib.Type(result);
81 | } catch (Throwable e) {
82 | throw new RuntimeException(e);
83 | }
84 | }
85 |
86 | private static final MethodHandle cairo_gobject_font_weight_get_type = Interop.downcallHandle(
87 | "cairo_gobject_font_weight_get_type", FunctionDescriptor.of(ValueLayout.JAVA_LONG));
88 | }
89 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/TeeSurfaceTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import io.github.jwharm.cairobindings.Interop;
4 | import org.freedesktop.cairo.*;
5 | import org.junit.jupiter.api.Test;
6 |
7 | import java.lang.foreign.FunctionDescriptor;
8 | import java.lang.foreign.MemorySegment;
9 | import java.lang.foreign.ValueLayout;
10 | import java.lang.invoke.MethodHandle;
11 |
12 | import static org.junit.jupiter.api.Assertions.assertEquals;
13 |
14 | public class TeeSurfaceTest {
15 |
16 | @Test
17 | void testCreate() {
18 | try (Surface primary = ImageSurface.create(Format.ARGB32, 120, 120)) {
19 | TeeSurface tee = TeeSurface.create(primary);
20 | assertEquals(Status.SUCCESS, tee.status());
21 | }
22 | }
23 |
24 | @Test
25 | void testIndex() {
26 | try (Surface primary = ImageSurface.create(Format.ARGB32, 120, 120);
27 | Surface target1 = ImageSurface.create(Format.ARGB32, 120, 120);
28 | Surface target2 = ImageSurface.create(Format.ARGB32, 120, 120)) {
29 | TeeSurface tee = TeeSurface.create(primary);
30 | tee.add(target1);
31 | tee.add(target2);
32 |
33 | assertEquals(primary, tee.index(0));
34 | assertEquals(target1, tee.index(1));
35 | assertEquals(target2, tee.index(2));
36 |
37 | /* We don't actually call `cairo_tee_surface_index` in the bindings,
38 | * but we call it in the method below, to assert that the results
39 | * are the same.
40 | */
41 | assertEquals(tee.index(0).handle(), cairo_tee_surface_index(tee, 0));
42 | assertEquals(tee.index(1).handle(), cairo_tee_surface_index(tee, 1));
43 | assertEquals(tee.index(2).handle(), cairo_tee_surface_index(tee, 2));
44 |
45 | assertEquals(Status.SUCCESS, tee.status());
46 | }
47 | }
48 |
49 | private MemorySegment cairo_tee_surface_index(Surface tee, int index) {
50 | MethodHandle cairo_tee_surface_index = Interop.downcallHandle("cairo_tee_surface_index",
51 | FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.JAVA_INT));
52 | try {
53 | return (MemorySegment) cairo_tee_surface_index.invoke(tee.handle(), index);
54 | } catch (Throwable e) {
55 | throw new RuntimeException(e);
56 | }
57 | }
58 |
59 | @Test
60 | void testAddAndRemove() {
61 | try (Surface primary = ImageSurface.create(Format.ARGB32, 120, 120);
62 | Surface target = ImageSurface.create(Format.ARGB32, 120, 120)) {
63 | TeeSurface tee = TeeSurface.create(primary);
64 | tee.add(target);
65 | tee.remove(target);
66 | assertEquals(Status.SUCCESS, tee.status());
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/SurfaceObserverCallback.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import java.lang.foreign.*;
23 | import java.lang.invoke.MethodHandle;
24 | import java.lang.invoke.MethodHandles;
25 |
26 | /**
27 | * A generic callback function for surface operations.
28 | *
29 | * @since 1.12
30 | */
31 | @FunctionalInterface
32 | public interface SurfaceObserverCallback {
33 |
34 | /**
35 | * A generic callback function for surface operations.
36 | *
37 | * @param target the observed surface
38 | * @since 1.12
39 | */
40 | void run(Surface target);
41 |
42 | /**
43 | * The callback that is executed by native code. This method marshals the
44 | * parameters and calls {@link #run}.
45 | *
46 | * @param observer the {@link SurfaceObserver}, ignored
47 | * @param target the observed surface
48 | * @param data ignored
49 | * @since 1.12
50 | */
51 | default void upcall(MemorySegment observer, MemorySegment target, MemorySegment data) {
52 | run(new Surface(target));
53 | }
54 |
55 | /**
56 | * Generates an upcall stub, a C function pointer that will call
57 | * {@link #upcall}.
58 | *
59 | * @param arena the arena in which the upcall stub will be allocated
60 | * @return the function pointer of the upcall stub
61 | * @since 1.12
62 | */
63 | default MemorySegment toCallback(Arena arena) {
64 | try {
65 | FunctionDescriptor fdesc = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS,
66 | ValueLayout.ADDRESS, ValueLayout.ADDRESS);
67 | MethodHandle handle = MethodHandles.lookup().findVirtual(
68 | SurfaceObserverCallback.class, "upcall", fdesc.toMethodType());
69 | return Linker.nativeLinker().upcallStub(handle.bindTo(this), fdesc, arena);
70 | } catch (NoSuchMethodException | IllegalAccessException e) {
71 | throw new RuntimeException(e);
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/FontSlant.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 |
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.ValueLayout;
26 | import java.lang.invoke.MethodHandle;
27 |
28 | /**
29 | * Specifies variants of a font face based on their slant.
30 | *
31 | * @since 1.0
32 | */
33 | public enum FontSlant {
34 |
35 | /**
36 | * Upright font style
37 | *
38 | * @since 1.0
39 | */
40 | NORMAL,
41 |
42 | /**
43 | * Italic font style
44 | *
45 | * @since 1.0
46 | */
47 | ITALIC,
48 |
49 | /**
50 | * Oblique font style
51 | *
52 | * @since 1.0
53 | */
54 | OBLIQUE;
55 |
56 | static {
57 | Cairo.ensureInitialized();
58 | }
59 |
60 | /**
61 | * Return the value of this enum
62 | *
63 | * @return the value
64 | */
65 | public int getValue() {
66 | return ordinal();
67 | }
68 |
69 | /**
70 | * Returns the enum constant for the given ordinal (its position in the enum
71 | * declaration).
72 | *
73 | * @param ordinal the position in the enum declaration, starting from zero
74 | * @return the enum constant for the given ordinal
75 | */
76 | public static FontSlant of(int ordinal) {
77 | return values()[ordinal];
78 | }
79 |
80 | /**
81 | * Get the CairoFontSlant GType
82 | * @return the GType
83 | */
84 | public static org.gnome.glib.Type getType() {
85 | try {
86 | long result = (long) cairo_gobject_font_slant_get_type.invoke();
87 | return new org.gnome.glib.Type(result);
88 | } catch (Throwable e) {
89 | throw new RuntimeException(e);
90 | }
91 | }
92 |
93 | private static final MethodHandle cairo_gobject_font_slant_get_type = Interop.downcallHandle(
94 | "cairo_gobject_font_slant_get_type", FunctionDescriptor.of(ValueLayout.JAVA_LONG));
95 | }
96 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/RasterSourceFinishFunc.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import java.lang.foreign.*;
23 | import java.lang.invoke.MethodHandle;
24 | import java.lang.invoke.MethodHandles;
25 |
26 | /**
27 | * RasterSourceFinishFunc is the type of function which is called when the
28 | * pattern (or a copy thereof) is no longer required.
29 | *
30 | * @since 1.12
31 | */
32 | @FunctionalInterface
33 | public interface RasterSourceFinishFunc {
34 |
35 | /**
36 | * Called when the pattern (or a copy thereof) is no longer required.
37 | *
38 | * @param pattern the pattern being rendered from
39 | * @since 1.12
40 | */
41 | void finish(RasterSource pattern);
42 |
43 | /**
44 | * The callback that is executed by native code. This method marshals the
45 | * parameters and calls {@link #finish(RasterSource)}.
46 | *
47 | * @param pattern the pattern being rendered from
48 | * @param callbackData ignored
49 | * @since 1.12
50 | */
51 | default void upcall(MemorySegment pattern, MemorySegment callbackData) {
52 | finish(new RasterSource(pattern));
53 | }
54 |
55 | /**
56 | * Generates an upcall stub, a C function pointer that will call
57 | * {@link #upcall}.
58 | *
59 | * @param arena the arena in which the upcall stub will be allocated
60 | * @return the function pointer of the upcall stub
61 | * @since 1.12
62 | */
63 | default MemorySegment toCallback(Arena arena) {
64 | try {
65 | FunctionDescriptor fdesc = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.ADDRESS);
66 | MethodHandle handle = MethodHandles.lookup().findVirtual(RasterSourceFinishFunc.class, "upcall",
67 | fdesc.toMethodType());
68 | return Linker.nativeLinker().upcallStub(handle.bindTo(this), fdesc, arena);
69 | } catch (NoSuchMethodException | IllegalAccessException e) {
70 | throw new RuntimeException(e);
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/TextClusterFlags.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 |
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.ValueLayout;
26 | import java.lang.invoke.MethodHandle;
27 |
28 | /**
29 | * Specifies properties of a text cluster mapping.
30 | *
31 | * @since 1.8
32 | */
33 | public enum TextClusterFlags {
34 |
35 | /**
36 | * The clusters in the cluster array map to glyphs in the glyph array from end
37 | * to start.
38 | *
39 | * @since 1.8
40 | */
41 | BACKWARD(0x00000001);
42 |
43 | static {
44 | Cairo.ensureInitialized();
45 | }
46 |
47 | private final int value;
48 |
49 | TextClusterFlags(int value) {
50 | this.value = value;
51 | }
52 |
53 | /**
54 | * Return the value of this enum
55 | *
56 | * @return the value
57 | */
58 | public int getValue() {
59 | return value;
60 | }
61 |
62 | /**
63 | * Returns the enum member for the given value.
64 | *
65 | * @param value the value of the enum member
66 | * @return the enum member for the given value
67 | */
68 | public static TextClusterFlags of(int value) {
69 | if (value == 0x00000001) {
70 | return BACKWARD;
71 | } else {
72 | throw new IllegalArgumentException("No TextClusterFlags enum with value " + value);
73 | }
74 | }
75 |
76 | /**
77 | * Get the CairoTextClusterFlags GType
78 | * @return the GType
79 | */
80 | public static org.gnome.glib.Type getType() {
81 | try {
82 | long result = (long) cairo_gobject_text_cluster_flags_get_type.invoke();
83 | return new org.gnome.glib.Type(result);
84 | } catch (Throwable e) {
85 | throw new RuntimeException(e);
86 | }
87 | }
88 |
89 | private static final MethodHandle cairo_gobject_text_cluster_flags_get_type = Interop.downcallHandle(
90 | "cairo_gobject_text_cluster_flags_get_type", FunctionDescriptor.of(ValueLayout.JAVA_LONG));
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/RegionOverlap.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 |
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.ValueLayout;
26 | import java.lang.invoke.MethodHandle;
27 |
28 | /**
29 | * Used as the return value for cairo_region_contains_rectangle().
30 | *
31 | * @since 1.10
32 | */
33 | public enum RegionOverlap {
34 |
35 | /**
36 | * The contents are entirely inside the region.
37 | *
38 | * @since 1.10
39 | */
40 | IN,
41 |
42 | /**
43 | * The contents are entirely outside the region.
44 | *
45 | * @since 1.10
46 | */
47 | OUT,
48 |
49 | /**
50 | * The contents are partially inside and partially outside the region.
51 | *
52 | * @since 1.10
53 | */
54 | PART;
55 |
56 | static {
57 | Cairo.ensureInitialized();
58 | }
59 |
60 | /**
61 | * Return the value of this enum
62 | * @return the value
63 | */
64 | public int getValue() {
65 | return ordinal();
66 | }
67 |
68 | /**
69 | * Returns the enum constant for the given ordinal (its position in the enum
70 | * declaration).
71 | *
72 | * @param ordinal the position in the enum declaration, starting from zero
73 | * @return the enum constant for the given ordinal
74 | */
75 | public static RegionOverlap of(int ordinal) {
76 | return values()[ordinal];
77 | }
78 |
79 | /**
80 | * Get the CairoRegionOverlap GType
81 | * @return the GType
82 | */
83 | public static org.gnome.glib.Type getType() {
84 | try {
85 | long result = (long) cairo_gobject_region_overlap_get_type.invoke();
86 | return new org.gnome.glib.Type(result);
87 | } catch (Throwable e) {
88 | throw new RuntimeException(e);
89 | }
90 | }
91 |
92 | private static final MethodHandle cairo_gobject_region_overlap_get_type = Interop.downcallHandle(
93 | "cairo_gobject_region_overlap_get_type", FunctionDescriptor.of(ValueLayout.JAVA_LONG));
94 | }
95 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/FTScaledFontTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 |
5 | import io.github.jwharm.cairobindings.Platform;
6 | import org.freedesktop.cairo.FTFontFace;
7 | import org.freedesktop.cairo.FTScaledFont;
8 | import org.freedesktop.cairo.FontOptions;
9 | import org.freedesktop.cairo.Matrix;
10 | import org.freedesktop.cairo.Status;
11 | import org.freedesktop.freetype.Face;
12 | import org.freedesktop.freetype.Library;
13 | import org.junit.jupiter.api.BeforeAll;
14 | import org.junit.jupiter.api.Test;
15 |
16 | import java.io.File;
17 | import java.lang.foreign.Arena;
18 |
19 | class FTScaledFontTest {
20 |
21 | private static String TTF_FILE;
22 |
23 | @BeforeAll
24 | static void setup() {
25 | // These files are going to be in different locations depending on your system.
26 | switch (Platform.getRuntimePlatform()) {
27 | case "linux" -> {
28 | // Fedora
29 | TTF_FILE = "/usr/share/fonts/liberation-serif/LiberationSerif-Regular.ttf";
30 | if (! new File(TTF_FILE).exists()) {
31 | // Ubuntu
32 | TTF_FILE = "/usr/share/fonts/truetype/liberation/LiberationSerif-Regular.ttf";
33 | }
34 | if (! new File(TTF_FILE).exists()) {
35 | // OpenSUSE
36 | TTF_FILE = "/usr/share/fonts/truetype/LiberationSerif-Regular.ttf";
37 | }
38 | }
39 | case "windows" -> TTF_FILE = "C:\\Windows\\Fonts\\arial.ttf";
40 | case "macos" -> TTF_FILE = "/Library/Fonts/Arial Unicode.ttf";
41 | }
42 | }
43 |
44 | @Test
45 | void testCreate() {
46 | try (Arena arena = Arena.ofConfined()) {
47 | Library ftLib = Library.initFreeType();
48 | Face ftFace = Face.newFace(ftLib, TTF_FILE, 0);
49 | FTFontFace face = FTFontFace.create(ftFace, 0);
50 | FTScaledFont scaledFont = FTScaledFont.create(face, Matrix.create(arena).initIdentity(), Matrix.create(arena).initIdentity(), FontOptions.create());
51 | assertEquals(Status.SUCCESS, scaledFont.status());
52 | ftFace.doneFace();
53 | ftLib.doneFreeType();
54 | }
55 | }
56 |
57 | @Test
58 | void testLockAndUnlockFace() {
59 | try (Arena arena = Arena.ofConfined()) {
60 | Library ftLib = Library.initFreeType();
61 | Face ftFace = Face.newFace(ftLib, TTF_FILE, 0);
62 | FTFontFace face = FTFontFace.create(ftFace, 0);
63 | FTScaledFont scaledFont = FTScaledFont.create(face, Matrix.create(arena).initIdentity(), Matrix.create(arena).initIdentity(), FontOptions.create());
64 | scaledFont.lockFace();
65 | scaledFont.unlockFace();
66 | assertEquals(Status.SUCCESS, scaledFont.status());
67 | ftFace.doneFace();
68 | ftLib.doneFreeType();
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/LineCap.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 |
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.ValueLayout;
26 | import java.lang.invoke.MethodHandle;
27 |
28 | /**
29 | * Specifies how to render the endpoints of the path when stroking.
30 | *
31 | * The default line cap style is CAIRO_LINE_CAP_BUTT.
32 | */
33 | public enum LineCap {
34 |
35 | /**
36 | * start(stop) the line exactly at the start(end) point
37 | *
38 | * @since 1.0
39 | */
40 | BUTT,
41 |
42 | /**
43 | * use a round ending, the center of the circle is the end point
44 | *
45 | * @since 1.0
46 | */
47 | ROUND,
48 |
49 | /**
50 | * use a squared ending, the center of the square is the end point
51 | *
52 | * @since 1.0
53 | */
54 | SQUARE;
55 |
56 | static {
57 | Cairo.ensureInitialized();
58 | }
59 |
60 | /**
61 | * Return the value of this enum
62 | * @return the value
63 | */
64 | public int getValue() {
65 | return ordinal();
66 | }
67 |
68 | /**
69 | * Returns the enum constant for the given ordinal (its position in the enum
70 | * declaration).
71 | *
72 | * @param ordinal the position in the enum declaration, starting from zero
73 | * @return the enum constant for the given ordinal
74 | */
75 | public static LineCap of(int ordinal) {
76 | return values()[ordinal];
77 | }
78 |
79 | /**
80 | * Get the CairoLineCap GType
81 | * @return the GType
82 | */
83 | public static org.gnome.glib.Type getType() {
84 | try {
85 | long result = (long) cairo_gobject_line_cap_get_type.invoke();
86 | return new org.gnome.glib.Type(result);
87 | } catch (Throwable e) {
88 | throw new RuntimeException(e);
89 | }
90 | }
91 |
92 | private static final MethodHandle cairo_gobject_line_cap_get_type = Interop.downcallHandle(
93 | "cairo_gobject_line_cap_get_type", FunctionDescriptor.of(ValueLayout.JAVA_LONG));
94 | }
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/PathDataType.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 |
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.ValueLayout;
26 | import java.lang.invoke.MethodHandle;
27 |
28 | /**
29 | * Describes the type of one portion of a path when represented as a
30 | * {@link Path}. See {@link PathData} for details.
31 | *
32 | * @since 1.0
33 | */
34 | public enum PathDataType {
35 |
36 | /**
37 | * A move-to operation
38 | * @since 1.0
39 | */
40 | MOVE_TO,
41 |
42 | /**
43 | * A line-to operation
44 | * @since 1.0
45 | */
46 | LINE_TO,
47 |
48 | /**
49 | * A curve-to operation
50 | * @since 1.0
51 | */
52 | CURVE_TO,
53 |
54 | /**
55 | * A close-path operation
56 | * @since 1.0
57 | */
58 | CLOSE_PATH;
59 |
60 | static {
61 | Cairo.ensureInitialized();
62 | }
63 |
64 | /**
65 | * Return the value of this enum
66 | * @return the value
67 | */
68 | public int getValue() {
69 | return ordinal();
70 | }
71 |
72 | /**
73 | * Returns the enum constant for the given ordinal (its position in the enum
74 | * declaration).
75 | *
76 | * @param ordinal the position in the enum declaration, starting from zero
77 | * @return the enum constant for the given ordinal
78 | */
79 | public static PathDataType of(int ordinal) {
80 | return values()[ordinal];
81 | }
82 |
83 | /**
84 | * Get the CairoPathDataType GType
85 | * @return the GType
86 | */
87 | public static org.gnome.glib.Type getType() {
88 | try {
89 | long result = (long) cairo_gobject_path_data_type_get_type.invoke();
90 | return new org.gnome.glib.Type(result);
91 | } catch (Throwable e) {
92 | throw new RuntimeException(e);
93 | }
94 | }
95 |
96 | private static final MethodHandle cairo_gobject_path_data_type_get_type = Interop.downcallHandle(
97 | "cairo_gobject_path_data_type_get_type", FunctionDescriptor.of(ValueLayout.JAVA_LONG));
98 | }
99 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/LineJoin.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 |
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.ValueLayout;
26 | import java.lang.invoke.MethodHandle;
27 |
28 | /**
29 | * Specifies how to render the junction of two lines when stroking.
30 | *
31 | * The default line join style is CAIRO_LINE_JOIN_MITER.
32 | */
33 | public enum LineJoin {
34 |
35 | /**
36 | * use a sharp (angled) corner, see cairo_set_miter_limit()
37 | *
38 | * @since 1.0
39 | */
40 | MITER,
41 |
42 | /**
43 | * use a rounded join, the center of the circle is the joint point
44 | *
45 | * @since 1.0
46 | */
47 | ROUND,
48 |
49 | /**
50 | * use a cut-off join, the join is cut off at half the line width from the joint
51 | * point
52 | *
53 | * @since 1.0
54 | */
55 | BEVEL;
56 |
57 | static {
58 | Cairo.ensureInitialized();
59 | }
60 |
61 | /**
62 | * Return the value of this enum
63 | * @return the value
64 | */
65 | public int getValue() {
66 | return ordinal();
67 | }
68 |
69 | /**
70 | * Returns the enum constant for the given ordinal (its position in the enum
71 | * declaration).
72 | *
73 | * @param ordinal the position in the enum declaration, starting from zero
74 | * @return the enum constant for the given ordinal
75 | */
76 | public static LineJoin of(int ordinal) {
77 | return values()[ordinal];
78 | }
79 |
80 | /**
81 | * Get the CairoLineJoin GType
82 | * @return the GType
83 | */
84 | public static org.gnome.glib.Type getType() {
85 | try {
86 | long result = (long) cairo_gobject_line_join_get_type.invoke();
87 | return new org.gnome.glib.Type(result);
88 | } catch (Throwable e) {
89 | throw new RuntimeException(e);
90 | }
91 | }
92 |
93 | private static final MethodHandle cairo_gobject_line_join_get_type = Interop.downcallHandle(
94 | "cairo_gobject_line_join_get_type", FunctionDescriptor.of(ValueLayout.JAVA_LONG));
95 | }
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/PathElement.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | /**
23 | * The PathElement interface is a sealed type that models Path elements. It permits four records:
24 | *
25 | *
26 | * - {@link PathElement.MoveTo} that corresponds with {@link Context#moveTo(double, double)}
27 | *
- {@link PathElement.LineTo} that corresponds with {@link Context#lineTo(double, double)}
28 | *
- {@link PathElement.CurveTo} that corresponds with {@link Context#curveTo(double, double, double, double, double, double)}
29 | *
- {@link PathElement.ClosePath} that corresponds with {@link Context#closePath()}
30 | *
31 | *
32 | * See {@link Path} for more information about working with paths.
33 | */
34 | public sealed interface PathElement
35 | permits PathElement.MoveTo, PathElement.LineTo, PathElement.CurveTo, PathElement.ClosePath {
36 |
37 | /**
38 | * A {@link PathDataType#MOVE_TO} path element
39 | *
40 | * @param x the X coordinate of the new position
41 | * @param y the Y coordinate of the new position
42 | */
43 | record MoveTo(double x, double y) implements PathElement {
44 | }
45 |
46 | /**
47 | * A {@link PathDataType#LINE_TO} path element
48 | *
49 | * @param x the X coordinate of the end of the new line
50 | * @param y the Y coordinate of the end of the new line
51 | */
52 | record LineTo(double x, double y) implements PathElement {
53 | }
54 |
55 | /**
56 | * A {@link PathDataType#CURVE_TO} path element
57 | *
58 | * @param x1 the X coordinate of the first control point
59 | * @param y1 the Y coordinate of the first control point
60 | * @param x2 the X coordinate of the second control point
61 | * @param y2 the Y coordinate of the second control point
62 | * @param x3 the X coordinate of the end of the curve
63 | * @param y3 the Y coordinate of the end of the curve
64 | */
65 | record CurveTo(double x1, double y1, double x2, double y2, double x3, double y3) implements PathElement {
66 | }
67 |
68 | /**
69 | * A {@link PathDataType#CLOSE_PATH} path element
70 | */
71 | record ClosePath() implements PathElement {
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/PDFSurfaceTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 | import static org.junit.jupiter.api.Assertions.assertTrue;
5 |
6 | import java.io.OutputStream;
7 | import java.util.Set;
8 | import java.util.concurrent.atomic.AtomicBoolean;
9 |
10 | import org.freedesktop.cairo.*;
11 | import org.junit.jupiter.api.Test;
12 |
13 | class PDFSurfaceTest {
14 |
15 | @Test
16 | void testCreateStringIntInt() {
17 | try (PDFSurface s = PDFSurface.create((String) null, 120, 120)) {
18 | assertEquals(Status.SUCCESS, s.status());
19 | }
20 | }
21 |
22 | @Test
23 | void testCreateOutputStreamIntInt() {
24 | AtomicBoolean success = new AtomicBoolean();
25 | OutputStream stream = new OutputStream() {
26 | @Override
27 | public void write(int b) {
28 | success.set(true);
29 | }
30 | };
31 | try (PDFSurface s = PDFSurface.create(stream, 120, 120)) {
32 | s.showPage();
33 | assertEquals(Status.SUCCESS, s.status());
34 | }
35 | assertTrue(success.get());
36 | }
37 |
38 | @Test
39 | void testRestrictToVersion() {
40 | try (PDFSurface s = PDFSurface.create((String) null, 120, 120)) {
41 | s.restrictToVersion(PDFVersion.VERSION_1_4);
42 | assertEquals(Status.SUCCESS, s.status());
43 | }
44 | }
45 |
46 | @Test
47 | void testSetSize() {
48 | try (PDFSurface s = PDFSurface.create((String) null, 120, 120)) {
49 | s.setSize(100, 100);
50 | assertEquals(Status.SUCCESS, s.status());
51 | }
52 | }
53 |
54 | @Test
55 | void testAddOutline() {
56 | try (PDFSurface s = PDFSurface.create((String) null, 120, 120)) {
57 | // This verifies the method call runs, but the result will not be successful
58 | s.addOutline(PDFSurface.CAIRO_PDF_OUTLINE_ROOT, "test", "test", Set.of(PDFOutlineFlags.ITALIC));
59 | }
60 | }
61 |
62 | @Test
63 | void testSetMetadata() {
64 | try (PDFSurface s = PDFSurface.create((String) null, 120, 120)) {
65 | s.setMetadata(PDFMetadata.TITLE, "test document");
66 | assertEquals(Status.SUCCESS, s.status());
67 | }
68 | }
69 |
70 | @Test
71 | void testSetCustomMetadata() {
72 | try (PDFSurface s = PDFSurface.create((String) null, 120, 120)) {
73 | s.setCustomMetadata("ISBN", "978-0123456789");
74 | assertEquals(Status.SUCCESS, s.status());
75 | }
76 | }
77 |
78 | @Test
79 | void testSetPageLabel() {
80 | try (PDFSurface s = PDFSurface.create((String) null, 120, 120)) {
81 | s.setPageLabel("label");
82 | assertEquals(Status.SUCCESS, s.status());
83 | }
84 | }
85 |
86 | @Test
87 | void testSetThumbnailSize() {
88 | try (PDFSurface s = PDFSurface.create((String) null, 120, 120)) {
89 | s.setThumbnailSize(30, 30);
90 | assertEquals(Status.SUCCESS, s.status());
91 | }
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/HintMetrics.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 |
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.ValueLayout;
26 | import java.lang.invoke.MethodHandle;
27 |
28 | /**
29 | * Specifies whether to hint font metrics; hinting font metrics means quantizing
30 | * them so that they are integer values in device space. Doing this improves the
31 | * consistency of letter and line spacing, however it also means that text will
32 | * be laid out differently at different zoom factors.
33 | *
34 | * @since 1.0
35 | */
36 | public enum HintMetrics {
37 |
38 | /**
39 | * Hint metrics in the default manner for the font backend and target device
40 | *
41 | * @since 1.0
42 | */
43 | DEFAULT,
44 |
45 | /**
46 | * Do not hint font metrics
47 | *
48 | * @since 1.0
49 | */
50 | OFF,
51 |
52 | /**
53 | * Hint font metrics
54 | *
55 | * @since 1.0
56 | */
57 | ON;
58 |
59 | static {
60 | Cairo.ensureInitialized();
61 | }
62 |
63 | /**
64 | * Return the value of this enum
65 | *
66 | * @return the value
67 | */
68 | public int getValue() {
69 | return ordinal();
70 | }
71 |
72 | /**
73 | * Returns the enum constant for the given ordinal (its position in the enum
74 | * declaration).
75 | *
76 | * @param ordinal the position in the enum declaration, starting from zero
77 | * @return the enum constant for the given ordinal
78 | */
79 | public static HintMetrics of(int ordinal) {
80 | return values()[ordinal];
81 | }
82 |
83 | /**
84 | * Get the CairoHintMetrics GType
85 | * @return the GType
86 | */
87 | public static org.gnome.glib.Type getType() {
88 | try {
89 | long result = (long) cairo_gobject_hint_metrics_get_type.invoke();
90 | return new org.gnome.glib.Type(result);
91 | } catch (Throwable e) {
92 | throw new RuntimeException(e);
93 | }
94 | }
95 |
96 | private static final MethodHandle cairo_gobject_hint_metrics_get_type = Interop.downcallHandle(
97 | "cairo_gobject_hint_metrics_get_type", FunctionDescriptor.of(ValueLayout.JAVA_LONG));
98 | }
99 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
74 |
75 |
76 | @rem Execute Gradle
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
78 |
79 | :end
80 | @rem End local scope for the variables with windows NT shell
81 | if %ERRORLEVEL% equ 0 goto mainEnd
82 |
83 | :fail
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
85 | rem the _cmd.exe /c_ return code!
86 | set EXIT_CODE=%ERRORLEVEL%
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
89 | exit /b %EXIT_CODE%
90 |
91 | :mainEnd
92 | if "%OS%"=="Windows_NT" endlocal
93 |
94 | :omega
95 |
--------------------------------------------------------------------------------
/src/main/java/io/github/jwharm/cairobindings/LibLoad.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package io.github.jwharm.cairobindings;
21 |
22 | import java.io.File;
23 | import java.nio.file.Files;
24 | import java.nio.file.Path;
25 | import java.util.stream.Stream;
26 |
27 | /**
28 | * The LibLoad class is used internally to load native libraries by name
29 | */
30 | public final class LibLoad {
31 |
32 | static {
33 | String javagiPath = System.getProperty("javagi.path");
34 | String javaPath = System.getProperty("java.library.path");
35 | if (javagiPath != null) {
36 | if (javaPath == null) {
37 | System.setProperty("java.library.path", javagiPath);
38 | } else {
39 | System.setProperty("java.library.path", javaPath + File.pathSeparator + javagiPath);
40 | }
41 | }
42 | }
43 |
44 | // Prevent instantiation
45 | private LibLoad() {}
46 |
47 | /**
48 | * Load the native library with the provided name
49 | * @param name the name of the library
50 | */
51 | public static void loadLibrary(String name) {
52 | RuntimeException fail = new RuntimeException("Could not load library " + name);
53 | try {
54 | System.loadLibrary(name);
55 | return;
56 | } catch (Throwable t) {
57 | fail.addSuppressed(t);
58 | }
59 | for (String s : System.getProperty("java.library.path").split(File.pathSeparator)) {
60 | if (s.isBlank()) {
61 | continue;
62 | }
63 |
64 | Path pk = Path.of(s).toAbsolutePath().normalize();
65 | if (!Files.isDirectory(pk)) {
66 | continue;
67 | }
68 |
69 | Path[] paths;
70 | try (Stream p = Files.list(pk)) {
71 | paths = p.toArray(Path[]::new);
72 | } catch (Throwable t) {
73 | fail.addSuppressed(t);
74 | continue;
75 | }
76 |
77 | for (Path path : paths) {
78 | try {
79 | String fn = path.getFileName().toString();
80 | if (fn.equals(name)) {
81 | System.load(path.toString());
82 | return;
83 | }
84 | } catch (Throwable t) {
85 | fail.addSuppressed(t);
86 | }
87 | }
88 | }
89 | throw fail;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/RasterSourceReleaseFunc.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import java.lang.foreign.*;
23 | import java.lang.invoke.MethodHandle;
24 | import java.lang.invoke.MethodHandles;
25 |
26 | /**
27 | * RasterSourceReleaseFunc is the type of function which is called when the
28 | * pixel data is no longer being access by the pattern for the rendering
29 | * operation. Typically this function will simply destroy the surface created
30 | * during acquire.
31 | *
32 | * @since 1.12
33 | */
34 | @FunctionalInterface
35 | public interface RasterSourceReleaseFunc {
36 |
37 | /**
38 | * Called when the pixel data is no longer being access by the pattern for the
39 | * rendering operation. Typically this function will simply destroy the surface
40 | * created during acquire.
41 | *
42 | * @param pattern the pattern being rendered from
43 | * @param target the surface created during acquire
44 | * @since 1.12
45 | */
46 | void release(RasterSource pattern, Surface target);
47 |
48 | /**
49 | * The callback that is executed by native code. This method marshals the
50 | * parameters and calls {@link #release(RasterSource, Surface)}.
51 | *
52 | * @param pattern the pattern being rendered from
53 | * @param callbackData ignored
54 | * @param target the surface created during acquire
55 | * @since 1.12
56 | */
57 | default void upcall(MemorySegment pattern, MemorySegment callbackData, MemorySegment target) {
58 | release(new RasterSource(pattern), new Surface(target));
59 | }
60 |
61 | /**
62 | * Generates an upcall stub, a C function pointer that will call
63 | * {@link #upcall}.
64 | *
65 | * @param arena the arena in which the upcall stub will be allocated
66 | * @return the function pointer of the upcall stub
67 | * @since 1.12
68 | */
69 | default MemorySegment toCallback(Arena arena) {
70 | try {
71 | FunctionDescriptor fdesc = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.ADDRESS,
72 | ValueLayout.ADDRESS);
73 | MethodHandle handle = MethodHandles.lookup().findVirtual(RasterSourceReleaseFunc.class, "upcall",
74 | fdesc.toMethodType());
75 | return Linker.nativeLinker().upcallStub(handle.bindTo(this), fdesc, arena);
76 | } catch (NoSuchMethodException | IllegalAccessException e) {
77 | throw new RuntimeException(e);
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/TextCluster.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Proxy;
23 |
24 | import java.lang.foreign.MemoryLayout;
25 | import java.lang.foreign.MemorySegment;
26 | import java.lang.foreign.ValueLayout;
27 | import java.lang.invoke.VarHandle;
28 |
29 | /**
30 | * The TextCluster structure holds information about a single text
31 | * cluster. A text cluster is a minimal mapping of some glyphs corresponding
32 | * to some UTF-8 text.
33 | *
34 | * For a cluster to be valid, both {@code numBytes} and {@code numGlyphs} should
35 | * be non-negative, and at least one should be non-zero. Note that clusters with
36 | * zero glyphs are not as well supported as normal clusters. For example, PDF
37 | * rendering applications typically ignore those clusters when PDF text is being
38 | * selected.
39 | *
40 | * See cairo_show_text_glyphs() for how clusters are used in advanced text
41 | * operations.
42 | *
43 | * @since 1.8
44 | */
45 | public class TextCluster extends Proxy {
46 |
47 | /**
48 | * The memory layout of the native C struct
49 | *
50 | * @return the memory layout of the native C struct
51 | */
52 | static MemoryLayout getMemoryLayout() {
53 | return MemoryLayout.structLayout(
54 | ValueLayout.JAVA_INT.withName("num_bytes"),
55 | ValueLayout.JAVA_INT.withName("num_glyphs"))
56 | .withName("cairo_text_cluster_t");
57 | }
58 |
59 | private static final VarHandle NUM_BYTES = getMemoryLayout().varHandle(MemoryLayout.PathElement.groupElement("num_bytes"));
60 | private static final VarHandle NUM_GLYPHS = getMemoryLayout().varHandle(MemoryLayout.PathElement.groupElement("num_glyphs"));
61 |
62 | /**
63 | * The number of bytes of UTF-8 text covered by the cluster
64 | *
65 | * @return the number of bytes of UTF-8 text
66 | */
67 | public int numBytes() {
68 | return (int) NUM_BYTES.get(handle(), 0);
69 | }
70 |
71 | /**
72 | * The number of glyphs covered by cluster
73 | *
74 | * @return the number of glyphs covered by cluster
75 | */
76 | public int numGlyphs() {
77 | return (int) NUM_GLYPHS.get(handle(), 0);
78 | }
79 |
80 | /**
81 | * Constructor used internally to instantiate a java TextCluster object for a
82 | * native {@code cairo_text_cluster_t} instance
83 | *
84 | * @param address the memory address of the native {@code cairo_text_cluster_t}
85 | * instance
86 | */
87 | public TextCluster(MemorySegment address) {
88 | super(address);
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/SubpixelOrder.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 |
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.ValueLayout;
26 | import java.lang.invoke.MethodHandle;
27 |
28 | /**
29 | * The subpixel order specifies the order of color elements within each pixel on
30 | * the display device when rendering with an antialiasing mode of
31 | * {@link Antialias#SUBPIXEL}.
32 | *
33 | * @since 1.0
34 | */
35 | public enum SubpixelOrder {
36 |
37 | /**
38 | * Use the default subpixel order for for the target device
39 | *
40 | * @since 1.0
41 | */
42 | DEFAULT,
43 |
44 | /**
45 | * Subpixel elements are arranged horizontally with red at the left
46 | *
47 | * @since 1.0
48 | */
49 | RGB,
50 |
51 | /**
52 | * Subpixel elements are arranged horizontally with blue at the left
53 | *
54 | * @since 1.0
55 | */
56 | BGR,
57 |
58 | /**
59 | * Subpixel elements are arranged vertically with red at the top
60 | *
61 | * @since 1.0
62 | */
63 | VRGB,
64 |
65 | /**
66 | * Subpixel elements are arranged vertically with blue at the top
67 | *
68 | * @since 1.0
69 | */
70 | VBGR;
71 |
72 | static {
73 | Cairo.ensureInitialized();
74 | }
75 |
76 | /**
77 | * Return the value of this enum
78 | * @return the value
79 | */
80 | public int getValue() {
81 | return ordinal();
82 | }
83 |
84 | /**
85 | * Returns the enum constant for the given ordinal (its position in the enum
86 | * declaration).
87 | *
88 | * @param ordinal the position in the enum declaration, starting from zero
89 | * @return the enum constant for the given ordinal
90 | */
91 | public static SubpixelOrder of(int ordinal) {
92 | return values()[ordinal];
93 | }
94 |
95 | /**
96 | * Get the CairoSubpixelOrder GType
97 | * @return the GType
98 | */
99 | public static org.gnome.glib.Type getType() {
100 | try {
101 | long result = (long) cairo_gobject_subpixel_order_get_type.invoke();
102 | return new org.gnome.glib.Type(result);
103 | } catch (Throwable e) {
104 | throw new RuntimeException(e);
105 | }
106 | }
107 |
108 | private static final MethodHandle cairo_gobject_subpixel_order_get_type = Interop.downcallHandle(
109 | "cairo_gobject_subpixel_order_get_type", FunctionDescriptor.of(ValueLayout.JAVA_LONG));
110 | }
111 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/SVGUnit.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | /**
23 | * SVGUnit is used to describe the units valid for coordinates and lengths in
24 | * the SVG specification.
25 | *
26 | * See also:
27 | *
35 | *
36 | * @see Surface
37 | * @since 1.16
38 | */
39 | public enum SVGUnit {
40 |
41 | /**
42 | * User unit, a value in the current coordinate system. If used in the root
43 | * element for the initial coordinate systems it corresponds to pixels.
44 | *
45 | * @since 1.16
46 | */
47 | USER,
48 |
49 | /**
50 | * The size of the element's font.
51 | *
52 | * @since 1.16
53 | */
54 | EM,
55 |
56 | /**
57 | * The x-height of the element’s font.
58 | *
59 | * @since 1.16
60 | */
61 | EX,
62 |
63 | /**
64 | * Pixels (1px = 1/96th of 1in).
65 | *
66 | * @since 1.16
67 | */
68 | PX,
69 |
70 | /**
71 | * Inches (1in = 2.54cm = 96px).
72 | *
73 | * @since 1.16
74 | */
75 | IN,
76 |
77 | /**
78 | * Centimeters (1cm = 96px/2.54).
79 | *
80 | * @since 1.16
81 | */
82 | CM,
83 |
84 | /**
85 | * Millimeters (1mm = 1/10th of 1cm).
86 | *
87 | * @since 1.16
88 | */
89 | MM,
90 |
91 | /**
92 | * Points (1pt = 1/72th of 1in).
93 | *
94 | * @since 1.16
95 | */
96 | PT,
97 |
98 | /**
99 | * Picas (1pc = 1/6th of 1in).
100 | *
101 | * @since 1.16
102 | */
103 | PC,
104 |
105 | /**
106 | * Percent, a value that is some fraction of another reference value.
107 | *
108 | * @since 1.16
109 | */
110 | PERCENT;
111 |
112 | /**
113 | * Return the value of this enum
114 | * @return the value
115 | */
116 | public int getValue() {
117 | return ordinal();
118 | }
119 |
120 | /**
121 | * Returns the enum constant for the given ordinal (its position in the enum
122 | * declaration).
123 | *
124 | * @param ordinal the position in the enum declaration, starting from zero
125 | * @return the enum constant for the given ordinal
126 | */
127 | public static SVGUnit of(int ordinal) {
128 | return values()[ordinal];
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/Content.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2024 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 |
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.ValueLayout;
26 | import java.lang.invoke.MethodHandle;
27 |
28 | /**
29 | * Content is used to describe the content that a surface will contain,
30 | * whether color information, alpha information (translucence vs. opacity), or
31 | * both.
32 | *
33 | * Note: The large values here are designed to keep Content values
34 | * distinct from Format values so that the implementation can detect the
35 | * error if users confuse the two types.
36 | *
37 | * @since 1.0
38 | */
39 | public enum Content {
40 |
41 | /**
42 | * The surface will hold color content only.
43 | *
44 | * @since 1.0
45 | */
46 | COLOR(0x1000),
47 |
48 | /**
49 | * The surface will hold alpha content only.
50 | *
51 | * @since 1.0
52 | */
53 | ALPHA(0x2000),
54 |
55 | /**
56 | * The surface will hold color and alpha content.
57 | *
58 | * @since 1.0
59 | */
60 | COLOR_ALPHA(0x3000);
61 |
62 | static {
63 | Cairo.ensureInitialized();
64 | }
65 |
66 | private final int value;
67 |
68 | Content(int value) {
69 | this.value = value;
70 | }
71 |
72 | /**
73 | * Return the value of this enum
74 | * @return the value
75 | */
76 | public int getValue() {
77 | return value;
78 | }
79 |
80 | /**
81 | * Returns the enum member for the given value.
82 | *
83 | * @param value the value of the enum member
84 | * @return the enum member for the given value
85 | */
86 | public static Content of(int value) {
87 | if (value == 0x1000) {
88 | return COLOR;
89 | } else if (value == 0x2000) {
90 | return ALPHA;
91 | } else if (value == 0x3000) {
92 | return COLOR_ALPHA;
93 | } else {
94 | throw new IllegalArgumentException("No Content enum with value " + value);
95 | }
96 | }
97 |
98 | /**
99 | * Get the CairoContent GType
100 | * @return the GType
101 | */
102 | public static org.gnome.glib.Type getType() {
103 | try {
104 | long result = (long) cairo_gobject_content_get_type.invoke();
105 | return new org.gnome.glib.Type(result);
106 | } catch (Throwable e) {
107 | throw new RuntimeException(e);
108 | }
109 | }
110 |
111 | private static final MethodHandle cairo_gobject_content_get_type = Interop.downcallHandle(
112 | "cairo_gobject_content_get_type", FunctionDescriptor.of(ValueLayout.JAVA_LONG));
113 | }
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/Extend.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 |
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.ValueLayout;
26 | import java.lang.invoke.MethodHandle;
27 |
28 | /**
29 | * Extend is used to describe how pattern color/alpha will be determined for
30 | * areas "outside" the pattern's natural area, (for example, outside the surface
31 | * bounds or outside the gradient geometry).
32 | *
33 | * Mesh patterns are not affected by the extend mode.
34 | *
35 | * The default extend mode is {@link #NONE} for surface patterns and
36 | * {@link #PAD} for gradient patterns.
37 | *
38 | * New entries may be added in future versions.
39 | *
40 | * @since 1.0
41 | */
42 | public enum Extend {
43 |
44 | /**
45 | * pixels outside of the source pattern are fully transparent
46 | *
47 | * @since 1.0
48 | */
49 | NONE,
50 |
51 | /**
52 | * the pattern is tiled by repeating
53 | *
54 | * @since 1.0
55 | */
56 | REPEAT,
57 |
58 | /**
59 | * the pattern is tiled by reflecting at the edges
60 | *
61 | * @since 1.0; but only implemented for surface patterns since 1.6
62 | */
63 | REFLECT,
64 |
65 | /**
66 | * pixels outside of the pattern copy the closest pixel from the source
67 | *
68 | * @since 1.2; but only implemented for surface patterns since 1.6
69 | */
70 | PAD;
71 |
72 | static {
73 | Cairo.ensureInitialized();
74 | }
75 |
76 | /**
77 | * Return the value of this enum
78 | * @return the value
79 | */
80 | public int getValue() {
81 | return ordinal();
82 | }
83 |
84 | /**
85 | * Returns the enum constant for the given ordinal (its position in the enum
86 | * declaration).
87 | *
88 | * @param ordinal the position in the enum declaration, starting from zero
89 | * @return the enum constant for the given ordinal
90 | */
91 | public static Extend of(int ordinal) {
92 | return values()[ordinal];
93 | }
94 |
95 | /**
96 | * Get the CairoExtend GType
97 | * @return the GType
98 | */
99 | public static org.gnome.glib.Type getType() {
100 | try {
101 | long result = (long) cairo_gobject_extend_get_type.invoke();
102 | return new org.gnome.glib.Type(result);
103 | } catch (Throwable e) {
104 | throw new RuntimeException(e);
105 | }
106 | }
107 |
108 | private static final MethodHandle cairo_gobject_extend_get_type = Interop.downcallHandle(
109 | "cairo_gobject_extend_get_type", FunctionDescriptor.of(ValueLayout.JAVA_LONG));
110 | }
111 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/MeshTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 | import static org.junit.jupiter.api.Assertions.assertNotNull;
5 |
6 | import org.freedesktop.cairo.Mesh;
7 | import org.freedesktop.cairo.Path;
8 | import org.freedesktop.cairo.Point;
9 | import org.freedesktop.cairo.Status;
10 | import org.junit.jupiter.api.Test;
11 |
12 | class MeshTest {
13 |
14 | @Test
15 | void testCreate() {
16 | Mesh mesh = Mesh.create();
17 | assertEquals(Status.SUCCESS, mesh.status());
18 | }
19 |
20 | @Test
21 | void testBeginAndEndPatch() {
22 | Mesh mesh = Mesh.create();
23 | mesh.beginPatch();
24 | mesh.moveTo(10, 10);
25 | mesh.endPatch();
26 | assertEquals(Status.SUCCESS, mesh.status());
27 | }
28 |
29 | @Test
30 | void testMoveTo() {
31 | Mesh mesh = Mesh.create();
32 | mesh.beginPatch();
33 | mesh.moveTo(10, 10);
34 | assertEquals(Status.SUCCESS, mesh.status());
35 | }
36 |
37 | @Test
38 | void testLineTo() {
39 | Mesh mesh = Mesh.create();
40 | mesh.beginPatch();
41 | mesh.lineTo(10, 10);
42 | assertEquals(Status.SUCCESS, mesh.status());
43 | }
44 |
45 | @Test
46 | void testCurveTo() {
47 | Mesh mesh = Mesh.create();
48 | mesh.beginPatch();
49 | mesh.curveTo(30, -30, 60, 30, 100, 0);
50 | assertEquals(Status.SUCCESS, mesh.status());
51 | }
52 |
53 | @Test
54 | void testSetCornerColorRGB() {
55 | Mesh mesh = Mesh.create();
56 | mesh.beginPatch()
57 | .moveTo(10, 10)
58 | .lineTo(20, 20)
59 | .lineTo(30, 30)
60 | .setCornerColorRGB(0, 0.5, 0.5, 0.5);
61 | assertEquals(Status.SUCCESS, mesh.status());
62 | }
63 |
64 | @Test
65 | void testGetPatchCount() {
66 | Mesh mesh = Mesh.create();
67 | assertEquals(0, mesh.getPatchCount());
68 | mesh.beginPatch();
69 | mesh.moveTo(10, 10);
70 | mesh.endPatch();
71 | assertEquals(1, mesh.getPatchCount());
72 | assertEquals(Status.SUCCESS, mesh.status());
73 | }
74 |
75 | @Test
76 | void testGetPath() {
77 | Mesh mesh = Mesh.create();
78 | mesh.beginPatch();
79 | mesh.moveTo(10, 10);
80 | mesh.endPatch();
81 | Path path = mesh.getPath(0);
82 | assertNotNull(path);
83 | assertEquals(Status.SUCCESS, mesh.status());
84 | }
85 |
86 | @Test
87 | void testControlPoint() {
88 | Mesh mesh = Mesh.create();
89 | mesh.beginPatch();
90 | mesh.setControlPoint(0, 10, 15);
91 | mesh.moveTo(20, 30);
92 | mesh.endPatch();
93 | Point point = mesh.getControlPoint(0, 0);
94 | assertEquals(10, point.x());
95 | assertEquals(15, point.y());
96 | assertEquals(Status.SUCCESS, mesh.status());
97 | }
98 |
99 | @Test
100 | void testCornerColorRGBA() {
101 | Mesh mesh = Mesh.create();
102 | mesh.beginPatch()
103 | .moveTo(10, 10)
104 | .lineTo(20, 20)
105 | .lineTo(30, 30)
106 | .setCornerColorRGBA(0, 0.5, 0.6, 0.7, 0.8)
107 | .endPatch();
108 | double[] color = mesh.getCornerColorRGBA(0, 0);
109 | assertEquals(color.length, 4);
110 | assertEquals(0.5, color[0]);
111 | assertEquals(0.6, color[1]);
112 | assertEquals(0.7, color[2]);
113 | assertEquals(0.8, color[3]);
114 | assertEquals(Status.SUCCESS, mesh.status());
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/Filter.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 |
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.ValueLayout;
26 | import java.lang.invoke.MethodHandle;
27 |
28 | /**
29 | * Filter is used to indicate what filtering should be applied when reading
30 | * pixel values from patterns. See {@link Pattern#setFilter} for indicating the
31 | * desired filter to be used with a particular pattern.
32 | *
33 | * @since 1.0
34 | */
35 | public enum Filter {
36 |
37 | /**
38 | * A high-performance filter, with quality similar to {@link #NEAREST}
39 | *
40 | * @since 1.0
41 | */
42 | FAST,
43 |
44 | /**
45 | * A reasonable-performance filter, with quality similar to {@link #BILINEAR}
46 | *
47 | * @since 1.0
48 | */
49 | GOOD,
50 |
51 | /**
52 | * The highest-quality available, performance may not be suitable for
53 | * interactive use.
54 | *
55 | * @since 1.0
56 | */
57 | BEST,
58 |
59 | /**
60 | * Nearest-neighbor filtering
61 | *
62 | * @since 1.0
63 | */
64 | NEAREST,
65 |
66 | /**
67 | * Linear interpolation in two dimensions
68 | *
69 | * @since 1.0
70 | */
71 | BILINEAR,
72 |
73 | /**
74 | * This filter value is currently unimplemented, and should not be used in
75 | * current code.
76 | *
77 | * @since 1.0
78 | */
79 | GAUSSIAN;
80 |
81 | static {
82 | Cairo.ensureInitialized();
83 | }
84 |
85 | /**
86 | * Return the value of this enum
87 | * @return the value
88 | */
89 | public int getValue() {
90 | return ordinal();
91 | }
92 |
93 | /**
94 | * Returns the enum constant for the given ordinal (its position in the enum
95 | * declaration).
96 | *
97 | * @param ordinal the position in the enum declaration, starting from zero
98 | * @return the enum constant for the given ordinal
99 | */
100 | public static Filter of(int ordinal) {
101 | return values()[ordinal];
102 | }
103 |
104 | /**
105 | * Get the CairoFilter GType
106 | * @return the GType
107 | */
108 | public static org.gnome.glib.Type getType() {
109 | try {
110 | long result = (long) cairo_gobject_filter_get_type.invoke();
111 | return new org.gnome.glib.Type(result);
112 | } catch (Throwable e) {
113 | throw new RuntimeException(e);
114 | }
115 | }
116 |
117 | private static final MethodHandle cairo_gobject_filter_get_type = Interop.downcallHandle(
118 | "cairo_gobject_filter_get_type", FunctionDescriptor.of(ValueLayout.JAVA_LONG));
119 | }
120 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/RasterSourceCopyFunc.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import java.lang.foreign.*;
23 | import java.lang.invoke.MethodHandle;
24 | import java.lang.invoke.MethodHandles;
25 |
26 | /**
27 | * RasterSourceCopyFunc is the type of function which is called when the pattern
28 | * gets copied as a normal part of rendering.
29 | *
30 | * @since 1.12
31 | */
32 | @FunctionalInterface
33 | public interface RasterSourceCopyFunc {
34 |
35 | /**
36 | * Called when the pattern gets copied as a normal part of rendering.
37 | *
38 | * @param pattern the pattern that was copied to
39 | * @param other the pattern being used as the source for the copy
40 | * @return {@link Status#SUCCESS} on success, or one of the {@link Status} error
41 | * codes for failure.
42 | * @since 1.12
43 | */
44 | Status copy(RasterSource pattern, RasterSource other);
45 |
46 | /**
47 | * The callback that is executed by native code. This method marshals the
48 | * parameters and calls {@link #copy(RasterSource, RasterSource)}.
49 | *
50 | * @param pattern the pattern being rendered from
51 | * @param callbackData ignored
52 | * @param other the pattern being used as the source for the copy
53 | * @return {@link Status#SUCCESS} on success, or one of the {@link Status} error
54 | * codes for failure.
55 | * @since 1.12
56 | */
57 | default int upcall(MemorySegment pattern, MemorySegment callbackData, MemorySegment other) {
58 | Status result = copy(new RasterSource(pattern), new RasterSource(other));
59 | /*
60 | * Will throw a NPE if the callback function returns null. This is deliberate:
61 | * The snapshot function must always return a Status enum member; failing to do
62 | * so is a programming error that should fail fast and obvious.
63 | */
64 | return result.getValue();
65 | }
66 |
67 | /**
68 | * Generates an upcall stub, a C function pointer that will call
69 | * {@link #upcall}.
70 | *
71 | * @param arena the arena in which the upcall stub will be allocated
72 | * @return the function pointer of the upcall stub
73 | * @since 1.12
74 | */
75 | default MemorySegment toCallback(Arena arena) {
76 | try {
77 | FunctionDescriptor fdesc = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS,
78 | ValueLayout.ADDRESS, ValueLayout.ADDRESS);
79 | MethodHandle handle = MethodHandles.lookup().findVirtual(RasterSourceCopyFunc.class, "upcall",
80 | fdesc.toMethodType());
81 | return Linker.nativeLinker().upcallStub(handle.bindTo(this), fdesc, arena);
82 | } catch (NoSuchMethodException | IllegalAccessException e) {
83 | throw new RuntimeException(e);
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/HintStyle.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 |
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.ValueLayout;
26 | import java.lang.invoke.MethodHandle;
27 |
28 | /**
29 | * Specifies the type of hinting to do on font outlines. Hinting is the process
30 | * of fitting outlines to the pixel grid in order to improve the appearance of
31 | * the result. Since hinting outlines involves distorting them, it also reduces
32 | * the faithfulness to the original outline shapes. Not all of the outline
33 | * hinting styles are supported by all font backends.
34 | *
35 | * New entries may be added in future versions.
36 | *
37 | * @since 1.0
38 | */
39 | public enum HintStyle {
40 |
41 | /**
42 | * Use the default hint style for font backend and target device
43 | *
44 | * @since 1.0
45 | */
46 | DEFAULT,
47 |
48 | /**
49 | * Do not hint outlines
50 | *
51 | * @since 1.0
52 | */
53 | NONE,
54 |
55 | /**
56 | * Hint outlines slightly to improve contrast while retaining good fidelity to
57 | * the original shapes
58 | *
59 | * @since 1.0
60 | */
61 | SLIGHT,
62 |
63 | /**
64 | * Hint outlines with medium strength giving a compromise between fidelity to
65 | * the original shapes and contrast
66 | *
67 | * @since 1.0
68 | */
69 | MEDIUM,
70 |
71 | /**
72 | * Hint outlines to maximize contrast
73 | *
74 | * @since 1.0
75 | */
76 | FULL;
77 |
78 | static {
79 | Cairo.ensureInitialized();
80 | }
81 |
82 | /**
83 | * Return the value of this enum
84 | *
85 | * @return the value
86 | */
87 | public int getValue() {
88 | return ordinal();
89 | }
90 |
91 | /**
92 | * Returns the enum constant for the given ordinal (its position in the enum
93 | * declaration).
94 | *
95 | * @param ordinal the position in the enum declaration, starting from zero
96 | * @return the enum constant for the given ordinal
97 | */
98 | public static HintStyle of(int ordinal) {
99 | return values()[ordinal];
100 | }
101 |
102 | /**
103 | * Get the CairoHintStyle GType
104 | * @return the GType
105 | */
106 | public static org.gnome.glib.Type getType() {
107 | try {
108 | long result = (long) cairo_gobject_hint_style_get_type.invoke();
109 | return new org.gnome.glib.Type(result);
110 | } catch (Throwable e) {
111 | throw new RuntimeException(e);
112 | }
113 | }
114 |
115 | private static final MethodHandle cairo_gobject_hint_style_get_type = Interop.downcallHandle(
116 | "cairo_gobject_hint_style_get_type", FunctionDescriptor.of(ValueLayout.JAVA_LONG));
117 | }
118 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/SurfacePattern.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 | import io.github.jwharm.cairobindings.MemoryCleaner;
24 |
25 | import java.lang.foreign.Arena;
26 | import java.lang.foreign.FunctionDescriptor;
27 | import java.lang.foreign.MemorySegment;
28 | import java.lang.foreign.ValueLayout;
29 | import java.lang.invoke.MethodHandle;
30 |
31 | /**
32 | * A pattern based on a surface (an image).
33 | */
34 | public class SurfacePattern extends Pattern {
35 |
36 | static {
37 | Cairo.ensureInitialized();
38 | }
39 |
40 | // Keep a reference to the target surface during the lifetime of this pattern
41 | Surface surface;
42 |
43 | /**
44 | * Constructor used internally to instantiate a java SurfacePattern object for a
45 | * native {@code cairo_pattern_t} instance
46 | *
47 | * @param address the memory address of the native {@code cairo_pattern_t}
48 | * instance
49 | */
50 | public SurfacePattern(MemorySegment address) {
51 | super(address);
52 | }
53 |
54 | /**
55 | * Create a new {@link Pattern} for the given surface.
56 | *
57 | * @param surface the surface
58 | * @return the newly created {@link SurfacePattern}
59 | * @since 1.0
60 | */
61 | public static SurfacePattern create(Surface surface) {
62 | try {
63 | MemorySegment result = (MemorySegment) cairo_pattern_create_for_surface
64 | .invoke(surface == null ? MemorySegment.NULL : surface.handle());
65 | SurfacePattern pattern = new SurfacePattern(result);
66 | MemoryCleaner.takeOwnership(pattern.handle());
67 | pattern.surface = surface;
68 | return pattern;
69 | } catch (Throwable e) {
70 | throw new RuntimeException(e);
71 | }
72 | }
73 |
74 | private static final MethodHandle cairo_pattern_create_for_surface = Interop.downcallHandle(
75 | "cairo_pattern_create_for_surface", FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS));
76 |
77 | /**
78 | * Gets the surface of a surface pattern.
79 | *
80 | * @return surface of pattern
81 | * @since 1.4
82 | */
83 | public Surface getSurface() {
84 | try {
85 | try (Arena arena = Arena.ofConfined()) {
86 | MemorySegment surfacePtr = arena.allocate(ValueLayout.ADDRESS);
87 | cairo_pattern_get_surface.invoke(handle(), surfacePtr);
88 | return new Surface(surfacePtr.get(ValueLayout.ADDRESS, 0));
89 | }
90 | } catch (Throwable e) {
91 | throw new RuntimeException(e);
92 | }
93 | }
94 |
95 | private static final MethodHandle cairo_pattern_get_surface = Interop.downcallHandle("cairo_pattern_get_surface",
96 | FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.ADDRESS));
97 |
98 | }
99 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/RasterSourceSnapshotFunc.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import java.lang.foreign.*;
23 | import java.lang.invoke.MethodHandle;
24 | import java.lang.invoke.MethodHandles;
25 |
26 | /**
27 | * RasterSourceSnapshotFunc is the type of function which is called when the
28 | * pixel data needs to be preserved for later use during printing. This pattern
29 | * will be accessed again later, and it is expected to provide the pixel data
30 | * that was current at the time of snapshotting.
31 | *
32 | * @since 1.12
33 | */
34 | @FunctionalInterface
35 | public interface RasterSourceSnapshotFunc {
36 |
37 | /**
38 | * Called when the pixel data needs to be preserved for later use during
39 | * printing. This pattern will be accessed again later, and it is expected to
40 | * provide the pixel data that was current at the time of snapshotting.
41 | *
42 | * @param pattern the pattern being rendered from
43 | * @return {@link Status#SUCCESS} on success, or one of the {@link Status} error
44 | * codes for failure.
45 | * @since 1.12
46 | */
47 | Status snapshot(RasterSource pattern);
48 |
49 | /**
50 | * The callback that is executed by native code. This method marshals the
51 | * parameters and calls {@link #snapshot(RasterSource)}.
52 | *
53 | * @param pattern the pattern being rendered from
54 | * @param callbackData ignored
55 | * @return {@link Status#SUCCESS} on success, or one of the {@link Status} error
56 | * codes for failure.
57 | * @since 1.12
58 | */
59 | default int upcall(MemorySegment pattern, MemorySegment callbackData) {
60 | Status result = snapshot(new RasterSource(pattern));
61 | /*
62 | * Will throw a NPE if the callback function returns null. This is deliberate:
63 | * The snapshot function must always return a Status enum member; failing to do
64 | * so is a programming error that should fail fast and obvious.
65 | */
66 | return result.getValue();
67 | }
68 |
69 | /**
70 | * Generates an upcall stub, a C function pointer that will call
71 | * {@link #upcall}.
72 | *
73 | * @param arena the arena in which the upcall stub will be allocated
74 | * @return the function pointer of the upcall stub
75 | * @since 1.12
76 | */
77 | default MemorySegment toCallback(Arena arena) {
78 | try {
79 | FunctionDescriptor fdesc = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS,
80 | ValueLayout.ADDRESS);
81 | MethodHandle handle = MethodHandles.lookup().findVirtual(RasterSourceSnapshotFunc.class, "upcall",
82 | fdesc.toMethodType());
83 | return Linker.nativeLinker().upcallStub(handle.bindTo(this), fdesc, arena);
84 | } catch (NoSuchMethodException | IllegalAccessException e) {
85 | throw new RuntimeException(e);
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/FillRule.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 |
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.ValueLayout;
26 | import java.lang.invoke.MethodHandle;
27 |
28 | /**
29 | * cairo_fill_rule_t is used to select how paths are filled. For both fill
30 | * rules, whether or not a point is included in the fill is determined by taking
31 | * a ray from that point to infinity and looking at intersections with the path.
32 | * The ray can be in any direction, as long as it doesn't pass through the end
33 | * point of a segment or have a tricky intersection such as intersecting tangent
34 | * to the path. (Note that filling is not actually implemented in this way. This
35 | * is just a description of the rule that is applied.)
36 | *
37 | * The default fill rule is CAIRO_FILL_RULE_WINDING.
38 | *
39 | * New entries may be added in future versions.
40 | *
41 | * @since 1.0
42 | */
43 | public enum FillRule {
44 |
45 | /**
46 | * If the path crosses the ray from left-to-right, counts +1. If the path
47 | * crosses the ray from right to left, counts -1. (Left and right are determined
48 | * from the perspective of looking along the ray from the starting point.) If
49 | * the total count is non-zero, the point will be filled.
50 | *
51 | * @since 1.0
52 | */
53 | WINDING,
54 |
55 | /**
56 | * Counts the total number of intersections, without regard to the orientation
57 | * of the contour. If the total number of intersections is odd, the point will
58 | * be filled.
59 | *
60 | * @since 1.0
61 | */
62 | EVEN_ODD;
63 |
64 | static {
65 | Cairo.ensureInitialized();
66 | }
67 |
68 | /**
69 | * Return the value of this enum
70 | * @return the value
71 | */
72 | public int getValue() {
73 | return ordinal();
74 | }
75 |
76 | /**
77 | * Returns the enum constant for the given ordinal (its position in the enum
78 | * declaration).
79 | *
80 | * @param ordinal the position in the enum declaration, starting from zero
81 | * @return the enum constant for the given ordinal
82 | */
83 | public static FillRule of(int ordinal) {
84 | return values()[ordinal];
85 | }
86 |
87 | /**
88 | * Get the CairoFillRule GType
89 | * @return the GType
90 | */
91 | public static org.gnome.glib.Type getType() {
92 | try {
93 | long result = (long) cairo_gobject_fill_rule_get_type.invoke();
94 | return new org.gnome.glib.Type(result);
95 | } catch (Throwable e) {
96 | throw new RuntimeException(e);
97 | }
98 | }
99 |
100 | private static final MethodHandle cairo_gobject_fill_rule_get_type = Interop.downcallHandle(
101 | "cairo_gobject_fill_rule_get_type", FunctionDescriptor.of(ValueLayout.JAVA_LONG));
102 | }
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/MatrixTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 | import static org.junit.jupiter.api.Assertions.assertNotNull;
5 |
6 | import org.freedesktop.cairo.Matrix;
7 | import org.freedesktop.cairo.Point;
8 | import org.junit.jupiter.api.Test;
9 |
10 | import java.lang.foreign.Arena;
11 |
12 | class MatrixTest {
13 |
14 | @Test
15 | void testInit() {
16 | try (Arena arena = Arena.ofConfined()) {
17 | Matrix matrix = Matrix.create(arena).init(1, 0, 0, 1, 0, 0);
18 | matrix.init(2, 0, 0, 2, 0, 0);
19 | }
20 | }
21 |
22 | @Test
23 | void testCreateIdentity() {
24 | try (Arena arena = Arena.ofConfined()) {
25 | Matrix matrix = Matrix.create(arena).initIdentity();
26 | assertNotNull(matrix);
27 | }
28 | }
29 |
30 | @Test
31 | void testCreateTranslate() {
32 | try (Arena arena = Arena.ofConfined()) {
33 | Matrix matrix = Matrix.create(arena).initTranslate(20, 20);
34 | assertNotNull(matrix);
35 | }
36 | }
37 |
38 | @Test
39 | void testCreateScale() {
40 | try (Arena arena = Arena.ofConfined()) {
41 | Matrix matrix = Matrix.create(arena).initIdentity();
42 | matrix.scale(2, 2);
43 | assertNotNull(matrix);
44 | }
45 | }
46 |
47 | @Test
48 | void testCreateRotate() {
49 | try (Arena arena = Arena.ofConfined()) {
50 | Matrix matrix = Matrix.create(arena).initIdentity();
51 | matrix.rotate(90);
52 | assertNotNull(matrix);
53 | }
54 | }
55 |
56 | @Test
57 | void testTranslate() {
58 | try (Arena arena = Arena.ofConfined()) {
59 | Matrix matrix = Matrix.create(arena).initIdentity();
60 | matrix.translate(10, 10);
61 | }
62 | }
63 |
64 | @Test
65 | void testScale() {
66 | try (Arena arena = Arena.ofConfined()) {
67 | Matrix matrix = Matrix.create(arena).initTranslate(20, 20);
68 | matrix.scale(0.5, 0.5);
69 | }
70 | }
71 |
72 | @Test
73 | void testRotate() {
74 | try (Arena arena = Arena.ofConfined()) {
75 | Matrix matrix = Matrix.create(arena).initTranslate(20, 20);
76 | matrix.rotate(180);
77 | }
78 | }
79 |
80 | @Test
81 | void testInvert() {
82 | try (Arena arena = Arena.ofConfined()) {
83 | Matrix matrix = Matrix.create(arena).initTranslate(20, 20);
84 | matrix.invert();
85 | }
86 | }
87 |
88 | @Test
89 | void testMultiply() {
90 | try (Arena arena = Arena.ofConfined()) {
91 | Matrix matrix1 = Matrix.create(arena).initIdentity();
92 | matrix1.rotate(90);
93 | Matrix matrix2 = Matrix.create(arena).initTranslate(20, 20);
94 | Matrix matrix3 = Matrix.create(arena).initIdentity();
95 | matrix3.multiply(matrix1, matrix2);
96 | }
97 | }
98 |
99 | @Test
100 | void testTransformDistance() {
101 | try (Arena arena = Arena.ofConfined()) {
102 | Matrix matrix = Matrix.create(arena).initIdentity();
103 | matrix.scale(3, 2);
104 | Point point = matrix.transformDistance(new Point(10, 10));
105 | assertEquals(30, point.x());
106 | assertEquals(20, point.y());
107 | }
108 | }
109 |
110 | @Test
111 | void testTransformPoint() {
112 | try (Arena arena = Arena.ofConfined()) {
113 | Matrix matrix = Matrix.create(arena).initTranslate(20, 30);
114 | Point point = matrix.transformPoint(new Point(30, 40));
115 | assertEquals(50, point.x());
116 | assertEquals(70, point.y());
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/WriteFunc.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import java.io.IOException;
23 | import java.lang.foreign.Arena;
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.Linker;
26 | import java.lang.foreign.MemorySegment;
27 | import java.lang.foreign.ValueLayout;
28 | import java.lang.invoke.MethodHandle;
29 | import java.lang.invoke.MethodHandles;
30 |
31 | /**
32 | * WriteFunc is the type of function which is called when a backend needs to
33 | * write data to an output stream. It is passed the closure which was specified
34 | * by the user at the time the write function was registered, the data to write
35 | * and the length of the data in bytes. The write function should throw
36 | * {@link IOException} if all the data was not successfully written.
37 | *
38 | * @since 1.0
39 | */
40 | @FunctionalInterface
41 | public interface WriteFunc {
42 |
43 | /**
44 | * The function to implement as callback in a write operation to an output
45 | * stream.
46 | *
47 | * @param data the data to write to the output stream
48 | * @throws IOException to be thrown when an error occurs during the write
49 | * operation
50 | * @since 1.0
51 | */
52 | void write(byte[] data) throws IOException;
53 |
54 | /**
55 | * The callback that is executed by native code. This method marshals the
56 | * parameters and calls {@link #write(byte[])}.
57 | *
58 | * @param closure ignored
59 | * @param data the buffer from which to read the data
60 | * @param length the amount of data to write
61 | * @return {@link Status#SUCCESS} on success, or {@link Status#WRITE_ERROR} if
62 | * an IOException occured.
63 | * @since 1.0
64 | */
65 | default int upcall(MemorySegment closure, MemorySegment data, int length) {
66 | if (length <= 0) {
67 | return Status.SUCCESS.getValue();
68 | }
69 | byte[] bytes = data.reinterpret(length).toArray(ValueLayout.JAVA_BYTE);
70 | try {
71 | write(bytes);
72 | return Status.SUCCESS.getValue();
73 | } catch (IOException ioe) {
74 | return Status.WRITE_ERROR.getValue();
75 | }
76 | }
77 |
78 | /**
79 | * Generates an upcall stub, a C function pointer that will call
80 | * {@link #upcall}.
81 | *
82 | * @param arena the arena in which the upcall stub will be allocated
83 | * @return the function pointer of the upcall stub
84 | * @since 1.0
85 | */
86 | default MemorySegment toCallback(Arena arena) {
87 | try {
88 | FunctionDescriptor fdesc = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS,
89 | ValueLayout.ADDRESS, ValueLayout.JAVA_INT);
90 | MethodHandle handle = MethodHandles.lookup().findVirtual(WriteFunc.class, "upcall", fdesc.toMethodType());
91 | return Linker.nativeLinker().upcallStub(handle.bindTo(this), fdesc, arena);
92 | } catch (NoSuchMethodException | IllegalAccessException e) {
93 | throw new RuntimeException(e);
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/FontType.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 |
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.ValueLayout;
26 | import java.lang.invoke.MethodHandle;
27 |
28 | /**
29 | * FontType is used to describe the type of a given font face or scaled font.
30 | * The font types are also known as "font backends" within cairo.
31 | *
32 | * The type of a font face is determined by the function used to create it,
33 | * which will generally be of the form {@code FontFaceClass.create()}. The font
34 | * face type can be queried with {@link FontFace#getType()}.
35 | *
36 | * The various {@link FontFace} functions can be used with a font face of any
37 | * type.
38 | *
39 | * The type of a scaled font is determined by the type of the font face passed
40 | * to {@link ScaledFont#create(FontFace, Matrix, Matrix, FontOptions)}. The
41 | * scaled font type can be queried with {@link ScaledFont#getType()}.
42 | *
43 | * New entries may be added in future versions.
44 | *
45 | * @since 1.2
46 | */
47 | public enum FontType {
48 |
49 | /**
50 | * The font was created using cairo's toy font api
51 | *
52 | * @since 1.2
53 | */
54 | TOY,
55 |
56 | /**
57 | * The font is of type FreeType
58 | *
59 | * @since 1.2
60 | */
61 | FT,
62 |
63 | /**
64 | * The font is of type Win32
65 | *
66 | * @since 1.2
67 | */
68 | WIN32,
69 |
70 | /**
71 | * The font is of type Quartz
72 | *
73 | * @since 1.6, in 1.2 and 1.4 it was named ATSUI
74 | */
75 | QUARTZ,
76 |
77 | /**
78 | * The font was create using cairo's user font api
79 | *
80 | * @since 1.8
81 | */
82 | USER,
83 |
84 | /**
85 | * The font is of type Win32 DWrite
86 | *
87 | * @since 1.18
88 | */
89 | DWRITE;
90 |
91 | static {
92 | Cairo.ensureInitialized();
93 | }
94 |
95 | /**
96 | * Return the value of this enum
97 | *
98 | * @return the value
99 | */
100 | public int getValue() {
101 | return ordinal();
102 | }
103 |
104 | /**
105 | * Returns the enum constant for the given ordinal (its position in the enum
106 | * declaration).
107 | *
108 | * @param ordinal the position in the enum declaration, starting from zero
109 | * @return the enum constant for the given ordinal
110 | */
111 | public static FontType of(int ordinal) {
112 | return values()[ordinal];
113 | }
114 |
115 | /**
116 | * Get the CairoFontType GType
117 | * @return the GType
118 | */
119 | public static org.gnome.glib.Type getType() {
120 | try {
121 | long result = (long) cairo_gobject_font_type_get_type.invoke();
122 | return new org.gnome.glib.Type(result);
123 | } catch (Throwable e) {
124 | throw new RuntimeException(e);
125 | }
126 | }
127 |
128 | private static final MethodHandle cairo_gobject_font_type_get_type = Interop.downcallHandle(
129 | "cairo_gobject_font_type_get_type", FunctionDescriptor.of(ValueLayout.JAVA_LONG));
130 | }
131 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/PatternType.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 |
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.ValueLayout;
26 | import java.lang.invoke.MethodHandle;
27 |
28 | /**
29 | * PatternType is used to describe the type of a given pattern.
30 | *
31 | * The type of a pattern is determined by the function used to create it. The
32 | * cairo_pattern_create_rgb() and cairo_pattern_create_rgba() functions create
33 | * SOLID patterns. The remaining cairo_pattern_create functions map to pattern
34 | * types in obvious ways.
35 | *
36 | * The pattern type can be queried with cairo_pattern_get_type()
37 | *
38 | * Most Pattern functions can be called with a pattern of any type, (though
39 | * trying to change the extend or filter for a solid pattern will have no
40 | * effect). A notable exception is cairo_pattern_add_color_stop_rgb() and
41 | * cairo_pattern_add_color_stop_rgba() which must only be called with gradient
42 | * patterns (either LINEAR or RADIAL). Otherwise the pattern will be shutdown
43 | * and put into an error state.
44 | *
45 | * New entries may be added in future versions.
46 | *
47 | * @since 1.2
48 | */
49 | public enum PatternType {
50 |
51 | /**
52 | * The pattern is a solid (uniform) color. It may be opaque or translucent
53 | * @since 1.2
54 | */
55 | SOLID,
56 |
57 | /**
58 | * The pattern is a based on a surface (an image)
59 | * @since 1.2
60 | */
61 | SURFACE,
62 |
63 | /**
64 | * The pattern is a linear gradient
65 | * @since 1.2
66 | */
67 | LINEAR,
68 |
69 | /**
70 | * The pattern is a radial gradient
71 | * @since 1.2
72 | */
73 | RADIAL,
74 |
75 | /**
76 | * The pattern is a mesh
77 | * @since 1.2
78 | */
79 | MESH,
80 |
81 | /**
82 | * The pattern is a user pattern providing raster data
83 | * @since 1.2
84 | */
85 | RASTER_SOURCE;
86 |
87 | static {
88 | Cairo.ensureInitialized();
89 | }
90 |
91 | /**
92 | * Return the value of this enum
93 | * @return the value
94 | */
95 | public int getValue() {
96 | return ordinal();
97 | }
98 |
99 | /**
100 | * Returns the enum constant for the given ordinal (its position in the enum
101 | * declaration).
102 | *
103 | * @param ordinal the position in the enum declaration, starting from zero
104 | * @return the enum constant for the given ordinal
105 | */
106 | public static PatternType of(int ordinal) {
107 | return values()[ordinal];
108 | }
109 |
110 | /**
111 | * Get the CairoPatternType GType
112 | * @return the GType
113 | */
114 | public static org.gnome.glib.Type getType() {
115 | try {
116 | long result = (long) cairo_gobject_pattern_type_get_type.invoke();
117 | return new org.gnome.glib.Type(result);
118 | } catch (Throwable e) {
119 | throw new RuntimeException(e);
120 | }
121 | }
122 |
123 | private static final MethodHandle cairo_gobject_pattern_type_get_type = Interop.downcallHandle(
124 | "cairo_gobject_pattern_type_get_type", FunctionDescriptor.of(ValueLayout.JAVA_LONG));
125 | }
126 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/ReadFunc.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import java.io.IOException;
23 | import java.lang.foreign.Arena;
24 | import java.lang.foreign.FunctionDescriptor;
25 | import java.lang.foreign.Linker;
26 | import java.lang.foreign.MemorySegment;
27 | import java.lang.foreign.ValueLayout;
28 | import java.lang.invoke.MethodHandle;
29 | import java.lang.invoke.MethodHandles;
30 |
31 | /**
32 | * ReadFunc is the type of function which is called when a backend needs to read
33 | * data from an input stream. It is passed the closure which was specified by
34 | * the user at the time the read function was registered, the buffer to read the
35 | * data into and the length of the data in bytes. The read function should throw
36 | * {@link IOException} if all the data was not successfully read.
37 | *
38 | * @since 1.0
39 | */
40 | @FunctionalInterface
41 | public interface ReadFunc {
42 |
43 | /**
44 | * The function to implement as callback in a read operation from an input
45 | * stream.
46 | *
47 | * @param length the amount of data to read
48 | * @return data the data read from the input stream
49 | * @throws IOException to be thrown when an error occurs during the read
50 | * operation
51 | * @since 1.0
52 | */
53 | byte[] read(int length) throws IOException;
54 |
55 | /**
56 | * The callback that is executed by native code. This method marshals the
57 | * parameters and calls {@link #read(int)}.
58 | *
59 | * @param closure ignored
60 | * @param data the buffer into which to read the data
61 | * @param length the amount of data to read
62 | * @return {@link Status#SUCCESS} on success, or {@link Status#READ_ERROR} if an
63 | * IOException occured or 0 bytes (or null) was returned from
64 | * {@code read()}.
65 | * @since 1.0
66 | */
67 | default int upcall(MemorySegment closure, MemorySegment data, int length) {
68 | if (length <= 0) {
69 | return Status.SUCCESS.getValue();
70 | }
71 | try {
72 | byte[] bytes = read(length);
73 | if (bytes == null || bytes.length == 0) {
74 | return Status.READ_ERROR.getValue();
75 | }
76 | data.reinterpret(length).asByteBuffer().put(bytes);
77 | return Status.SUCCESS.getValue();
78 | } catch (IOException ioe) {
79 | return Status.READ_ERROR.getValue();
80 | }
81 | }
82 |
83 | /**
84 | * Generates an upcall stub, a C function pointer that will call
85 | * {@link #upcall}.
86 | *
87 | * @param arena the arena in which the upcall stub will be allocated
88 | * @return the function pointer of the upcall stub
89 | * @since 1.0
90 | */
91 | default MemorySegment toCallback(Arena arena) {
92 | try {
93 | FunctionDescriptor fdesc = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS,
94 | ValueLayout.ADDRESS, ValueLayout.JAVA_INT);
95 | MethodHandle handle = MethodHandles.lookup().findVirtual(ReadFunc.class, "upcall", fdesc.toMethodType());
96 | return Linker.nativeLinker().upcallStub(handle.bindTo(this), fdesc, arena);
97 | } catch (NoSuchMethodException | IllegalAccessException e) {
98 | throw new RuntimeException(e);
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/Glyph.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 | import io.github.jwharm.cairobindings.Proxy;
24 |
25 | import java.lang.foreign.MemoryLayout;
26 | import java.lang.foreign.MemorySegment;
27 | import java.lang.foreign.ValueLayout;
28 | import java.lang.invoke.VarHandle;
29 |
30 | /**
31 | * The Glyph structure holds information about a single glyph when drawing or
32 | * measuring text. A font is (in simple terms) a collection of shapes used to
33 | * draw text. A glyph is one of these shapes. There can be multiple glyphs for a
34 | * single character (alternates to be used in different contexts, for example),
35 | * or a glyph can be a ligature of multiple characters. Cairo doesn't
36 | * expose any way of converting input text into glyphs, so in order to use the
37 | * Cairo interfaces that take arrays of glyphs, you must directly access the
38 | * appropriate underlying font system.
39 | *
40 | * Note that the offsets given by {@code x} and {@code y} are not cumulative.
41 | * When drawing or measuring text, each glyph is individually positioned with
42 | * respect to the overall origin.
43 | *
44 | * @since 1.0
45 | */
46 | public class Glyph extends Proxy {
47 |
48 | /**
49 | * The memory layout of the native C struct
50 | *
51 | * @return the memory layout of the native C struct
52 | */
53 | static MemoryLayout getMemoryLayout() {
54 | return MemoryLayout.structLayout(
55 | ValueLayout.JAVA_LONG.withName("index"),
56 | ValueLayout.JAVA_DOUBLE.withName("x"),
57 | ValueLayout.JAVA_DOUBLE.withName("y"))
58 | .withName("cairo_glyph_t");
59 | }
60 |
61 | private static final VarHandle INDEX = getMemoryLayout().varHandle(MemoryLayout.PathElement.groupElement("index"));
62 | private static final VarHandle X = getMemoryLayout().varHandle(MemoryLayout.PathElement.groupElement("x"));
63 | private static final VarHandle Y = getMemoryLayout().varHandle(MemoryLayout.PathElement.groupElement("y"));
64 |
65 | /**
66 | * Glyph index in the font. The exact interpretation of the glyph index depends
67 | * on the font technology being used.
68 | *
69 | * @return glyph index in the font
70 | */
71 | public long index() {
72 | return (long) INDEX.get(handle(), 0);
73 | }
74 |
75 | /**
76 | * The offset in the X direction between the origin used for drawing or
77 | * measuring the string and the origin of this glyph.
78 | *
79 | * @return the offset in the X direction
80 | */
81 | public double x() {
82 | return (double) X.get(handle(), 0);
83 | }
84 |
85 | /**
86 | * The offset in the Y direction between the origin used for drawing or
87 | * measuring the string and the origin of this glyph.
88 | *
89 | * @return the offset in the Y direction
90 | */
91 | public double y() {
92 | return (double) Y.get(handle(), 0);
93 | }
94 |
95 | /**
96 | * Constructor used internally to instantiate a java Glyph object for a native
97 | * {@code cairo_glyph_t} instance
98 | *
99 | * @param address the memory address of the native {@code cairo_glyph_t}
100 | * instance
101 | */
102 | public Glyph(MemorySegment address) {
103 | super(address.reinterpret(getMemoryLayout().byteSize()));
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/java/io/github/jwharm/cairobindings/Interop.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package io.github.jwharm.cairobindings;
21 |
22 | import java.lang.foreign.*;
23 | import java.lang.invoke.*;
24 | import java.util.EnumSet;
25 | import java.util.Set;
26 | import java.util.function.Function;
27 |
28 | /**
29 | * The Interop class contains functionality for interoperability with native code.
30 | */
31 | public final class Interop {
32 |
33 | private final static SymbolLookup symbolLookup;
34 | private final static Linker linker = Linker.nativeLinker();
35 |
36 | static {
37 | SymbolLookup loaderLookup = SymbolLookup.loaderLookup();
38 | symbolLookup = name -> loaderLookup.find(name).or(() -> linker.defaultLookup().find(name));
39 | }
40 |
41 | // Prevent instantiation
42 | private Interop() {}
43 |
44 | /**
45 | * Creates a method handle that is used to call the native function with
46 | * the provided name and function descriptor. The method handle is cached
47 | * and reused in subsequent lookups.
48 | * @param name Name of the native function
49 | * @param fdesc Function descriptor of the native function
50 | * @return the MethodHandle
51 | */
52 | public static MethodHandle downcallHandle(String name, FunctionDescriptor fdesc) {
53 | return symbolLookup
54 | .find(name)
55 | .map(addr -> linker.downcallHandle(addr, fdesc))
56 | .orElse(null);
57 | }
58 |
59 | /**
60 | * Allocate a native string using SegmentAllocator.allocateUtf8String(String).
61 | * @param string the string to allocate as a native string (utf8 char*)
62 | * @param allocator the segment allocator to use
63 | * @return the allocated MemorySegment
64 | */
65 | public static MemorySegment allocateNativeString(String string, SegmentAllocator allocator) {
66 | return string == null ? MemorySegment.NULL : allocator.allocateFrom(string);
67 | }
68 |
69 | /**
70 | * Create an EnumSet of class `cls` from the provided bitfield
71 | *
72 | * @param an enum implementing the Java-GI Enumeration interface
73 | * @param cls the class of the enum
74 | * @param make function that will construct an enum from one flag value
75 | * @param bitfield the integer containing the bitfield
76 | * @return an EnumSet containing the enum values as set in the bitfield
77 | */
78 | public static & Flag>
79 | EnumSet intToEnumSet(Class cls,
80 | Function make,
81 | int bitfield) {
82 | int n = bitfield;
83 | EnumSet enumSet = EnumSet.noneOf(cls);
84 | int position = 0;
85 | while (n != 0) {
86 | if ((n & 1) == 1)
87 | enumSet.add(make.apply(1 << position));
88 | position++;
89 | n >>= 1;
90 | }
91 | return enumSet;
92 | }
93 |
94 | /**
95 | * Create a bitfield from the provided Set of enums
96 | *
97 | * @param an enum implementing the Java-GI Enumeration interface
98 | * @param set the set of enums
99 | * @return the resulting bitfield
100 | */
101 | public static & Flag>
102 | int enumSetToInt(Set set) {
103 | int bitfield = 0;
104 | for (T element : set)
105 | bitfield |= element.getValue();
106 | return bitfield;
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/test/java/org/freedesktop/cairo/test/UserFontFaceTest.java:
--------------------------------------------------------------------------------
1 | package org.freedesktop.cairo.test;
2 |
3 | import org.freedesktop.cairo.*;
4 | import org.junit.jupiter.api.Test;
5 |
6 | import java.io.IOException;
7 | import java.util.concurrent.atomic.AtomicBoolean;
8 |
9 | import static org.junit.jupiter.api.Assertions.*;
10 |
11 | public class UserFontFaceTest {
12 |
13 | private Context createContext() {
14 | try {
15 | return Context.create(ImageSurface.create(Format.ARGB32, 120, 120));
16 | } catch (IOException ioe) {
17 | fail(ioe);
18 | throw new RuntimeException(ioe);
19 | }
20 | }
21 |
22 | @Test
23 | void testCreate() {
24 | UserFontFace uf = UserFontFace.create();
25 | assertEquals(Status.SUCCESS, uf.status());
26 | }
27 |
28 | @Test
29 | void testInit() {
30 | UserFontFace uf = UserFontFace.create();
31 | AtomicBoolean flag = new AtomicBoolean(false);
32 | UserScaledFontInitFunc func = (font, cr, extents) -> flag.set(true);
33 | uf.setInitFunc(func);
34 | Context cr = createContext();
35 | cr.setFontFace(uf);
36 | cr.showText("test");
37 | assertTrue(flag.get());
38 | assertEquals(func, uf.getInitFunc());
39 | assertEquals(Status.SUCCESS, uf.status());
40 | }
41 |
42 | @Test
43 | void testRenderGlyph() {
44 | UserFontFace uf = UserFontFace.create();
45 | AtomicBoolean flag = new AtomicBoolean(false);
46 | UserScaledFontRenderGlyphFunc func = (font, glyph, cr, extents) -> flag.set(true);
47 | uf.setRenderGlyphFunc(func);
48 | Context cr = createContext();
49 | cr.setFontFace(uf);
50 | cr.showText("test");
51 | assertTrue(flag.get());
52 | assertEquals(func, uf.getRenderGlyphFunc());
53 | assertEquals(Status.SUCCESS, uf.status());
54 | }
55 |
56 | @Test
57 | void testRenderColorGlyph() {
58 | UserFontFace uf = UserFontFace.create();
59 | AtomicBoolean flag = new AtomicBoolean(false);
60 | UserScaledFontRenderGlyphFunc func = (font, glyph, cr, extents) -> flag.set(true);
61 | uf.setRenderColorGlyphFunc(func);
62 | Context cr = createContext();
63 | cr.setFontFace(uf);
64 | cr.showText("test");
65 | assertTrue(flag.get());
66 | assertEquals(func, uf.getRenderColorGlyphFunc());
67 | assertEquals(Status.SUCCESS, uf.status());
68 | }
69 |
70 | @Test
71 | void testRenderColorGlyph_Fallback() {
72 | UserFontFace uf = UserFontFace.create();
73 | AtomicBoolean flag = new AtomicBoolean(false);
74 | UserScaledFontRenderGlyphFunc renderColorFunc = (font, glyph, cr, extents) -> {
75 | throw new UnsupportedOperationException(); // should redirect to renderFunc
76 | };
77 | UserScaledFontRenderGlyphFunc renderFunc = (font, glyph, cr, extents) -> flag.set(true);
78 | uf.setRenderColorGlyphFunc(renderColorFunc);
79 | uf.setRenderGlyphFunc(renderFunc);
80 | Context cr = createContext();
81 | cr.setFontFace(uf);
82 | cr.showText("test");
83 | assertTrue(flag.get());
84 | assertEquals(Status.SUCCESS, uf.status());
85 | }
86 |
87 | @Test
88 | void testUnicodeToGlyph() {
89 | UserFontFace uf = UserFontFace.create();
90 | AtomicBoolean flag = new AtomicBoolean(false);
91 | UserScaledFontUnicodeToGlyphFunc func = (font, unicode) -> {
92 | flag.set(true);
93 | return 0;
94 | };
95 | uf.setUnicodeToGlyphFunc(func);
96 | Context cr = createContext();
97 | cr.setFontFace(uf);
98 | cr.showText("test");
99 | assertTrue(flag.get());
100 | assertEquals(func, uf.getUnicodeToGlyphFunc());
101 | assertEquals(Status.SUCCESS, uf.status());
102 | }
103 |
104 | @Test
105 | void testTextToGlyphs() {
106 | UserFontFace uf = UserFontFace.create();
107 | AtomicBoolean flag = new AtomicBoolean(false);
108 | UserScaledFontTextToGlyphsFunc func = (font, string, glyphs) -> {
109 | flag.set(true);
110 | };
111 | uf.setTextToGlyphsFunc(func);
112 | Context cr = createContext();
113 | cr.setFontFace(uf);
114 | cr.showText("test");
115 | assertTrue(flag.get());
116 | assertEquals(func, uf.getTextToGlyphsFunc());
117 | assertEquals(Status.SUCCESS, uf.status());
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/MimeType.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | /**
23 | * MIME types defined as constants in Cairo.
24 | */
25 | public enum MimeType {
26 |
27 | /**
28 | * Group 3 or Group 4 CCITT facsimile encoding (International Telecommunication
29 | * Union, Recommendations T.4 and T.6.)
30 | *
31 | * @since 1.16
32 | */
33 | CCITT_FAX("image/g3fax"),
34 |
35 | /**
36 | * Decode parameters for Group 3 or Group 4 CCITT facsimile encoding. See
37 | * CCITT
39 | * Fax Images.
40 | *
41 | * @since 1.16
42 | */
43 | CCITT_FAX_PARAMS("application/x-cairo.ccitt.params"),
44 |
45 | /**
46 | * Encapsulated PostScript file. Encapsulated
48 | * PostScript File Format Specification
49 | *
50 | * @since 1.16
51 | */
52 | TYPE_EPS("application/postscript"),
53 |
54 | /**
55 | * Embedding parameters Encapsulated PostScript data. See Embedding
57 | * EPS files.
58 | *
59 | * @since 1.16
60 | */
61 | EPS_PARAMS("application/x-cairo.eps.params"),
62 |
63 | /**
64 | * Joint Bi-level Image Experts Group image coding standard (ISO/IEC 11544).
65 | *
66 | * @since 1.14
67 | */
68 | JBIG2("application/x-cairo.jbig2"),
69 |
70 | /**
71 | * Joint Bi-level Image Experts Group image coding standard (ISO/IEC 11544)
72 | * global segment.
73 | *
74 | * @since 1.14
75 | */
76 | JBIG2_GLOBAL("application/x-cairo.jbig2-global"),
77 |
78 | /**
79 | * An unique identifier shared by a JBIG2 global segment and all JBIG2 images
80 | * that depend on the global segment.
81 | *
82 | * @since 1.14
83 | */
84 | JBIG2_GLOBAL_ID("application/x-cairo.jbig2-global-id"),
85 |
86 | /**
87 | * The Joint Photographic Experts Group (JPEG) 2000 image coding standard
88 | * (ISO/IEC 15444-1).
89 | *
90 | * @since 1.10
91 | */
92 | JP2("image/jp2"),
93 |
94 | /**
95 | * The Joint Photographic Experts Group (JPEG) image coding standard (ISO/IEC
96 | * 10918-1).
97 | *
98 | * @since 1.10
99 | */
100 | JPEG("image/jpeg"),
101 |
102 | /**
103 | * The Portable Network Graphics image file format (ISO/IEC 15948).
104 | *
105 | * @since 1.10
106 | */
107 | PNG("image/png"),
108 |
109 | /**
110 | * URI for an image file (unofficial MIME type).
111 | *
112 | * @since 1.10
113 | */
114 | URI("text/x-uri"),
115 |
116 | /**
117 | * Unique identifier for a surface (cairo specific MIME type). All surfaces with
118 | * the same unique identifier will only be embedded once.
119 | *
120 | * @since 1.12
121 | */
122 | UNIQUE_ID("application/x-cairo.uuid");
123 |
124 | private final String name;
125 |
126 | MimeType(String name) {
127 | this.name = name;
128 | }
129 |
130 | @Override
131 | public String toString() {
132 | return this.name;
133 | }
134 |
135 | /**
136 | * Returns the enum constant for the given ordinal (its position in the enum
137 | * declaration).
138 | *
139 | * @param ordinal the position in the enum declaration, starting from zero
140 | * @return the enum constant for the given ordinal
141 | */
142 | public static MimeType of(int ordinal) {
143 | return values()[ordinal];
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/freetype/Face.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.freetype;
21 |
22 | import io.github.jwharm.cairobindings.Proxy;
23 | import io.github.jwharm.cairobindings.Interop;
24 |
25 | import java.lang.foreign.Arena;
26 | import java.lang.foreign.FunctionDescriptor;
27 | import java.lang.foreign.MemorySegment;
28 | import java.lang.foreign.ValueLayout;
29 | import java.lang.invoke.MethodHandle;
30 |
31 | /**
32 | * A handle to a typographic face object. A face object models a given typeface,
33 | * in a given style.
34 | */
35 | public class Face extends Proxy {
36 |
37 | static {
38 | FreeType2.ensureInitialized();
39 | }
40 |
41 | // The Arena in which the handle to the Face object was allocated.
42 | private Arena allocator = null;
43 |
44 | /**
45 | * Constructor used internally to instantiate a java Face object for a native
46 | * {@code FT_Face} instance
47 | *
48 | * @param address the memory address of the native {@code FT_Face} instance
49 | */
50 | public Face(MemorySegment address) {
51 | super(address);
52 | }
53 |
54 | /**
55 | * Call {@code FT_Open_Face} to open a font by its pathname.
56 | *
57 | * The resulting Face instance must be cleaned up manually with a call to
58 | * {@link #doneFace()}.
59 | *
60 | * @param library the library resource
61 | * @param filepathname path to the font file
62 | * @param faceIndex See FT_Open_Face
64 | * for a detailed description of this parameter.
65 | * @return the newly created Face instance
66 | * @throws UnsupportedOperationException when {@code FT_Init_FreeType} returns a
67 | * non-zero error code
68 | */
69 | public static Face newFace(Library library, String filepathname, long faceIndex) {
70 | Arena allocator = Arena.ofConfined();
71 | try {
72 | MemorySegment pointer = allocator.allocate(ValueLayout.ADDRESS.withTargetLayout(ValueLayout.ADDRESS));
73 | try (Arena arena = Arena.ofConfined()) {
74 | MemorySegment utf8 = Interop.allocateNativeString(filepathname, arena);
75 | int result = (int) FT_New_Face.invoke(library.handle(), utf8, faceIndex, pointer);
76 | if (result != 0) {
77 | throw new UnsupportedOperationException(
78 | "Error " + result + " occurred during FreeType FT_Face initialization");
79 | }
80 | Face face = new Face(pointer.get(ValueLayout.ADDRESS, 0));
81 | face.allocator = allocator;
82 | return face;
83 | }
84 | } catch (Throwable e) {
85 | throw new RuntimeException(e);
86 | }
87 | }
88 |
89 | private static final MethodHandle FT_New_Face = Interop.downcallHandle("FT_New_Face",
90 | FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.JAVA_LONG,
91 | ValueLayout.ADDRESS));
92 |
93 | /**
94 | * Discard a given face object, as well as all of its child slots and sizes.
95 | */
96 | public void doneFace() {
97 | try {
98 | int ignored = (int) FT_Done_Face.invoke(handle());
99 | } catch (Throwable e) {
100 | throw new RuntimeException(e);
101 | }
102 | if (allocator != null) {
103 | allocator.close();
104 | allocator = null;
105 | }
106 | }
107 |
108 | private static final MethodHandle FT_Done_Face = Interop.downcallHandle("FT_Done_Face",
109 | FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS));
110 | }
111 |
--------------------------------------------------------------------------------
/src/main/java/org/freedesktop/cairo/PSLevel.java:
--------------------------------------------------------------------------------
1 | /* cairo-java-bindings - Java language bindings for cairo
2 | * Copyright (C) 2023 Jan-Willem Harmannij
3 | *
4 | * SPDX-License-Identifier: LGPL-2.1-or-later
5 | *
6 | * This library is free software; you can redistribute it and/or
7 | * modify it under the terms of the GNU Lesser General Public
8 | * License as published by the Free Software Foundation; either
9 | * version 2.1 of the License, or (at your option) any later version.
10 | *
11 | * This library is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 | * Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public
17 | * License along with this library; if not, see .
18 | */
19 |
20 | package org.freedesktop.cairo;
21 |
22 | import io.github.jwharm.cairobindings.Interop;
23 |
24 | import java.lang.foreign.Arena;
25 | import java.lang.foreign.FunctionDescriptor;
26 | import java.lang.foreign.MemorySegment;
27 | import java.lang.foreign.ValueLayout;
28 | import java.lang.invoke.MethodHandle;
29 |
30 | /**
31 | * PSLevel is used to describe the language level of the PostScript
32 | * Language Reference that a generated PostScript file will conform to.
33 | *
34 | * @since 1.6
35 | */
36 | public enum PSLevel {
37 |
38 | /**
39 | * The language level 2 of the PostScript specification.
40 | *
41 | * @since 1.6
42 | */
43 | LEVEL_2,
44 |
45 | /**
46 | * The language level 3 of the PostScript specification.
47 | *
48 | * @since 1.6
49 | */
50 | LEVEL_3;
51 |
52 | /**
53 | * Return the value of this enum
54 | * @return the value
55 | */
56 | public int getValue() {
57 | return ordinal();
58 | }
59 |
60 | /**
61 | * Returns the enum constant for the given ordinal (its position in the enum
62 | * declaration).
63 | *
64 | * @param ordinal the position in the enum declaration, starting from zero
65 | * @return the enum constant for the given ordinal
66 | */
67 | public static PSLevel of(int ordinal) {
68 | return values()[ordinal];
69 | }
70 |
71 | static {
72 | Cairo.ensureInitialized();
73 | }
74 |
75 | /**
76 | * Used to retrieve the list of supported levels. See
77 | * {@link PSSurface#restrictToLevel(PSLevel)}.
78 | *
79 | * @return supported level list
80 | * @since 1.6
81 | */
82 | public static PSLevel[] getLevels() {
83 | try {
84 | try (Arena arena = Arena.ofConfined()) {
85 | MemorySegment levelsPtr = arena.allocate(ValueLayout.ADDRESS);
86 | MemorySegment numLevelsPtr = arena.allocate(ValueLayout.JAVA_INT);
87 | cairo_ps_get_levels.invoke(levelsPtr, numLevelsPtr);
88 | int numLevels = numLevelsPtr.get(ValueLayout.JAVA_INT, 0);
89 | int[] levelInts = levelsPtr.reinterpret(ValueLayout.JAVA_INT.byteSize() * numLevels).toArray(ValueLayout.JAVA_INT);
90 | PSLevel[] levels = new PSLevel[numLevels];
91 | for (int i = 0; i < levelInts.length; i++) {
92 | levels[i] = PSLevel.of(levelInts[i]);
93 | }
94 | return levels;
95 | }
96 | } catch (Throwable e) {
97 | throw new RuntimeException(e);
98 | }
99 | }
100 |
101 | private static final MethodHandle cairo_ps_get_levels = Interop.downcallHandle("cairo_ps_get_levels",
102 | FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS));
103 |
104 | /**
105 | * Get the string representation of this level. This function will return
106 | * {@code null} if the level isn't valid. See {@link #getLevels()} for a way to
107 | * get the list of valid levels.
108 | *
109 | * @return the string associated to this level.
110 | * @since 1.6
111 | */
112 | @Override
113 | public String toString() {
114 | try {
115 | MemorySegment result = (MemorySegment) cairo_ps_level_to_string.invoke(getValue());
116 | if (MemorySegment.NULL.equals(result)) {
117 | return null;
118 | }
119 | return result.reinterpret(Integer.MAX_VALUE).getString(0);
120 | } catch (Throwable e) {
121 | throw new RuntimeException(e);
122 | }
123 | }
124 |
125 | private static final MethodHandle cairo_ps_level_to_string = Interop.downcallHandle("cairo_ps_level_to_string",
126 | FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.JAVA_INT));
127 | }
128 |
--------------------------------------------------------------------------------