Skip to content

Commit

Permalink
1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
micycle1 committed Nov 20, 2020
1 parent 9879371 commit cf50dfc
Show file tree
Hide file tree
Showing 6 changed files with 246 additions and 1 deletion.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
target/
.settings/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
Expand All @@ -9,3 +10,6 @@ buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
.project
.classpath
.checkstyle
56 changes: 55 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,56 @@
# processing-skia
Wraps Skija (Skia for Java) for easy interoperability with Processing

**Skia** is an open source 2D graphics library which provides common APIs that work across a variety of hardware and software platforms.

**Skija** provides high-quality Java bindings for Skia.

**processing-skia** does the backend work of setting Skija's render target to Processing, so you can easily use any Skija [bindings](https://github.com/JetBrains/skija/blob/master/docs/Getting%20Started.md) to draw into a Processing sketch.

## Requirements
* Java 11+
* A Processing sketch using either the `P2D` or `P3D` renderer.

## Download
Download the processing-skia *jar* from [releases](https://github.com/micycle1/processing-skia/releases/).

## Example
### Code

```
import micycle.processingSkia.SkiaCanvas;
import org.jetbrains.skija.*;
Canvas skiaCanvas;
@Override
public void settings() {
size(800, 800, P2D);
}
@Override
public void setup() {
skiaCanvas = SkiaCanvas.getSkiaCanvas(this);
}
@Override
public void draw() {
background(255);
Paint fill = new Paint().setShader(Shader.makeLinearGradient(400, 300, 400, 500, new int[] {0xFFFFA500, 0xFF4CA387}));
skiaCanvas.drawCircle(400, 400, 200, fill);
}
```
### Result
<p align="center">
<img src="resources/result_example.png" alt="Example" width="400"squares_examplesquares_example/></a><br></p>

## Further Work
Further work would wrap the Skija library itself, creating something like a `PSurfaceSkia` interface leading to a dedicated Skia-based renderer in Processing.

## Another Example

This is the [squares example](https://github.com/JetBrains/skija/blob/master/examples/lwjgl/src/main/java/org/jetbrains/skija/examples/lwjgl/SquaresScene.java) as rendered in a Processing sketch. Here, the gradient fill and square-circle morphing provide features that are not easily attained in vanilla Processing, but are easily attained with the Skia renderer.

<p align="center">
<img src="resources/squares_example.gif" alt="Example"/></a><br></p>
68 changes: 68 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>micycle</groupId>
<artifactId>processing-skia</artifactId>
<version>1.0</version>

<repositories>
<repository>
<id>space-maven</id>
<url>https://packages.jetbrains.team/maven/p/skija/maven</url>
</repository>
</repositories>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>org.jetbrains.skija</groupId>
<artifactId>skija-windows</artifactId> <!--NOTE windows version -->
<version>0.6.10</version>
</dependency>
<dependency>
<groupId>org.jogamp.gluegen</groupId>
<artifactId>gluegen-rt-main</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>org.jogamp.jogl</groupId>
<artifactId>jogl-all-main</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>org.processing</groupId>
<artifactId>core</artifactId>
<version>3.3.7</version>
</dependency>
</dependencies>

</project>
Binary file added resources/result_example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/squares_example.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
119 changes: 119 additions & 0 deletions src/main/java/micycle/processingSkia/SkiaCanvas.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package micycle.processingSkia;

import java.nio.IntBuffer;

import org.jetbrains.skija.BackendRenderTarget;
import org.jetbrains.skija.Canvas;
import org.jetbrains.skija.ColorSpace;
import org.jetbrains.skija.DirectContext;
import org.jetbrains.skija.FramebufferFormat;
import org.jetbrains.skija.Surface;
import org.jetbrains.skija.SurfaceColorFormat;
import org.jetbrains.skija.SurfaceOrigin;

import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.event.WindowListener;
import com.jogamp.newt.event.WindowUpdateEvent;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.GL;

import processing.core.PApplet;
import processing.opengl.PSurfaceJOGL;

public class SkiaCanvas {

private static SkiaCanvas wrapper;

/**
* Call this to get a Skia Canvas whose render target is the sketch provided.
* Calling Skija drawing methods on this canvas will draw the output to your
* Processing sketch.
*
* @param p Your Processing sketch
* @return
*/
public static Canvas getSkiaCanvas(PApplet p) {
if (!(p.sketchRenderer() == "processing.opengl.PGraphics3D" || p.sketchRenderer() == "processing.opengl.PGraphics2D")) {
System.err.println("SkiaRenderer requires processing using P2D or P3D (JOGL) renderer.");
return null;
}

if (wrapper == null) { // singleton pattern
wrapper = new SkiaCanvas(p);
}

return wrapper.canvas;
}

private Canvas canvas;

private DirectContext context;
private BackendRenderTarget renderTarget;
private Surface surface;

private GL gl;

private PApplet p;

private SkiaCanvas(PApplet p) {

PSurfaceJOGL pSurface = (PSurfaceJOGL) p.getSurface();
GLWindow window = (GLWindow) pSurface.getNative();
gl = window.getGL();

final IntBuffer intBuffer = IntBuffer.allocate(1);
gl.glGetIntegerv(GL.GL_DRAW_FRAMEBUFFER_BINDING, intBuffer);
final int fbId = intBuffer.get(0);

renderTarget = BackendRenderTarget.makeGL(p.width, p.height, 0, 8, fbId, FramebufferFormat.GR_GL_RGBA8);

context = DirectContext.makeGL();

surface = Surface.makeFromBackendRenderTarget(context, renderTarget, SurfaceOrigin.BOTTOM_LEFT, SurfaceColorFormat.RGBA_8888,
ColorSpace.getSRGB());

canvas = surface.getCanvas();

window.addWindowListener(new WindowListener() {

@Override
public void windowResized(WindowEvent e) {
renderTarget = BackendRenderTarget.makeGL(window.getWidth(), window.getHeight(), 0, 8, fbId, FramebufferFormat.GR_GL_RGBA8);
surface = Surface.makeFromBackendRenderTarget(context, renderTarget, SurfaceOrigin.BOTTOM_LEFT,
SurfaceColorFormat.RGBA_8888, ColorSpace.getSRGB());
canvas = surface.getCanvas();
}

// @formatter:off
public void windowRepaint(WindowUpdateEvent e) {}
public void windowMoved(WindowEvent e) {}
public void windowLostFocus(WindowEvent e) {}
public void windowGainedFocus(WindowEvent e) {}
public void windowDestroyed(WindowEvent e) {}
public void windowDestroyNotify(WindowEvent e) {}
// @formatter:on
});

this.p = p;

p.registerMethod("pre", this);
p.registerMethod("post", this);
}

/**
* Calling Skija's {@link Canvas#clear(int) canvas.clear()} breaks it for some
* unknown reason; without calling clear() on the PApplet, skia doesn't update
* (again, for some unknown reason...).
*/
public void pre() {
p.clear();
}

/**
* Flushes Skia graphics to the screen.
*/
public void post() {
context.flush();
}

}

0 comments on commit cf50dfc

Please sign in to comment.