-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
246 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
|
||
} |