parent
009f78ba26
commit
e04cc273ee
|
@ -5,6 +5,7 @@ target
|
|||
/site/package-lock.json
|
||||
/site/dist
|
||||
node_modules
|
||||
/examples/c_canvas_minimal/build
|
||||
|
||||
# Editors
|
||||
*.swp
|
||||
|
|
|
@ -1184,6 +1184,19 @@ dependencies = [
|
|||
"pathfinder_gpu 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathfinder_c"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"gl 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pathfinder_canvas 0.1.0",
|
||||
"pathfinder_geometry 0.3.0",
|
||||
"pathfinder_gl 0.1.0",
|
||||
"pathfinder_gpu 0.1.0",
|
||||
"pathfinder_renderer 0.1.0",
|
||||
"pathfinder_simd 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathfinder_canvas"
|
||||
version = "0.1.0"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"c",
|
||||
"canvas",
|
||||
"demo/android/rust",
|
||||
"demo/common",
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
[package]
|
||||
name = "pathfinder_c"
|
||||
version = "0.1.0"
|
||||
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[dependencies]
|
||||
gl = "0.6"
|
||||
|
||||
[dependencies.pathfinder_canvas]
|
||||
path = "../canvas"
|
||||
|
||||
[dependencies.pathfinder_geometry]
|
||||
path = "../geometry"
|
||||
|
||||
[dependencies.pathfinder_gl]
|
||||
path = "../gl"
|
||||
|
||||
[dependencies.pathfinder_gpu]
|
||||
path = "../gpu"
|
||||
|
||||
[dependencies.pathfinder_renderer]
|
||||
path = "../renderer"
|
||||
|
||||
[dependencies.pathfinder_simd]
|
||||
path = "../simd"
|
|
@ -0,0 +1,158 @@
|
|||
// pathfinder/c/include/pathfinder/pathfinder.h
|
||||
//
|
||||
// Copyright © 2019 The Pathfinder Project Developers.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#ifndef PF_PATHFINDER_H
|
||||
#define PF_PATHFINDER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Macros
|
||||
|
||||
// `gl`
|
||||
|
||||
#define PF_GL_VERSION_GL3 0
|
||||
#define PF_GL_VERSION_GLES3 1
|
||||
|
||||
// `gpu`
|
||||
|
||||
#define PF_CLEAR_FLAGS_HAS_COLOR 0x1
|
||||
#define PF_CLEAR_FLAGS_HAS_DEPTH 0x2
|
||||
#define PF_CLEAR_FLAGS_HAS_STENCIL 0x4
|
||||
#define PF_CLEAR_FLAGS_HAS_RECT 0x8
|
||||
|
||||
// Types
|
||||
|
||||
// `canvas`
|
||||
|
||||
struct PFCanvas;
|
||||
typedef struct PFCanvas *PFCanvasRef;
|
||||
struct PFPath;
|
||||
typedef struct PFPath *PFPathRef;
|
||||
|
||||
// `geometry`
|
||||
|
||||
struct PFColorF {
|
||||
float r, g, b, a;
|
||||
};
|
||||
typedef struct PFColorF PFColorF;
|
||||
struct PFPoint2DF {
|
||||
float x, y;
|
||||
};
|
||||
typedef struct PFPoint2DF PFPoint2DF;
|
||||
struct PFPoint2DI {
|
||||
int32_t x, y;
|
||||
};
|
||||
typedef struct PFPoint2DI PFPoint2DI;
|
||||
struct PFRectF {
|
||||
PFPoint2DF origin, lower_right;
|
||||
};
|
||||
typedef struct PFRectF PFRectF;
|
||||
struct PFRectI {
|
||||
PFPoint2DI origin, lower_right;
|
||||
};
|
||||
typedef struct PFRectI PFRectI;
|
||||
|
||||
// `gl`
|
||||
|
||||
struct PFGLDevice;
|
||||
typedef struct PFGLDevice *PFGLDeviceRef;
|
||||
struct PFGLDestFramebuffer;
|
||||
typedef struct PFGLDestFramebuffer *PFGLDestFramebufferRef;
|
||||
typedef const void *(*PFGLFunctionLoader)(const char *data, void *userdata);
|
||||
struct PFGLRenderer;
|
||||
typedef struct PFGLRenderer *PFGLRendererRef;
|
||||
typedef uint32_t PFGLVersion;
|
||||
|
||||
// `gpu`
|
||||
|
||||
typedef uint8_t PFClearFlags;
|
||||
struct PFClearParams {
|
||||
PFColorF color;
|
||||
float depth;
|
||||
uint8_t stencil;
|
||||
PFRectI rect;
|
||||
PFClearFlags flags;
|
||||
};
|
||||
typedef struct PFClearParams PFClearParams;
|
||||
struct PFResourceLoader;
|
||||
typedef struct PFResourceLoader *PFResourceLoaderRef;
|
||||
|
||||
// `renderer`
|
||||
|
||||
struct PFRenderOptions {
|
||||
uint32_t placeholder;
|
||||
};
|
||||
typedef struct PFRenderOptions PFRenderOptions;
|
||||
struct PFScene;
|
||||
typedef struct PFScene *PFSceneRef;
|
||||
struct PFSceneProxy;
|
||||
typedef struct PFSceneProxy *PFSceneProxyRef;
|
||||
|
||||
// Functions
|
||||
|
||||
// `canvas`
|
||||
|
||||
PFCanvasRef PFCanvasCreate(const PFPoint2DF *size);
|
||||
void PFCanvasDestroy(PFCanvasRef canvas);
|
||||
PFSceneRef PFCanvasCreateScene(PFCanvasRef canvas);
|
||||
void PFCanvasFillRect(PFCanvasRef canvas, const PFRectF *rect);
|
||||
void PFCanvasStrokeRect(PFCanvasRef canvas, const PFRectF *rect);
|
||||
void PFCanvasSetLineWidth(PFCanvasRef canvas, float new_line_width);
|
||||
void PFCanvasFillPath(PFCanvasRef canvas, PFPathRef path);
|
||||
void PFCanvasStrokePath(PFCanvasRef canvas, PFPathRef path);
|
||||
PFPathRef PFPathCreate();
|
||||
void PFPathDestroy(PFPathRef path);
|
||||
PFPathRef PFPathClone(PFPathRef path);
|
||||
void PFPathMoveTo(PFPathRef path, const PFPoint2DF *to);
|
||||
void PFPathLineTo(PFPathRef path, const PFPoint2DF *to);
|
||||
void PFPathQuadraticCurveTo(PFPathRef path, const PFPoint2DF *ctrl, const PFPoint2DF *to);
|
||||
void PFPathBezierCurveTo(PFPathRef path,
|
||||
const PFPoint2DF *ctrl0,
|
||||
const PFPoint2DF *ctrl1,
|
||||
const PFPoint2DF *to);
|
||||
void PFPathClosePath(PFPathRef path);
|
||||
|
||||
// `gl`
|
||||
|
||||
PFGLDestFramebufferRef PFGLDestFramebufferCreateFullWindow(const PFPoint2DI *window_size);
|
||||
void PFGLDestFramebufferDestroy(PFGLDestFramebufferRef dest_framebuffer);
|
||||
PFGLDeviceRef PFGLDeviceCreate(PFGLVersion version, uint32_t default_framebuffer);
|
||||
void PFGLDeviceDestroy(PFGLDeviceRef device);
|
||||
void PFGLDeviceClear(PFGLDeviceRef device, const PFClearParams *params);
|
||||
void PFGLLoadWith(PFGLFunctionLoader loader, void *userdata);
|
||||
PFGLRendererRef PFGLRendererCreate(PFGLDeviceRef device,
|
||||
PFResourceLoaderRef resources,
|
||||
PFGLDestFramebufferRef dest_framebuffer);
|
||||
void PFGLRendererDestroy(PFGLRendererRef renderer);
|
||||
/// Returns a borrowed reference to the device.
|
||||
PFGLDeviceRef PFGLRendererGetDevice(PFGLRendererRef renderer);
|
||||
void PFSceneProxyBuildAndRenderGL(PFSceneProxyRef scene_proxy,
|
||||
PFGLRendererRef renderer,
|
||||
const PFRenderOptions *options);
|
||||
|
||||
// `gpu`
|
||||
|
||||
PFResourceLoaderRef PFFilesystemResourceLoaderLocate();
|
||||
void PFResourceLoaderDestroy(PFResourceLoaderRef loader);
|
||||
|
||||
// `renderer`
|
||||
|
||||
PFSceneProxyRef PFSceneProxyCreateFromSceneAndRayonExecutor(PFSceneRef scene);
|
||||
void PFSceneProxyDestroy(PFSceneProxyRef scene_proxy);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,360 @@
|
|||
// pathfinder/c/src/lib.rs
|
||||
//
|
||||
// Copyright © 2019 The Pathfinder Project Developers.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! C bindings to Pathfinder.
|
||||
|
||||
use gl;
|
||||
use pathfinder_canvas::{CanvasRenderingContext2D, Path2D};
|
||||
use pathfinder_geometry::basic::point::{Point2DF32, Point2DI32};
|
||||
use pathfinder_geometry::basic::rect::{RectF32, RectI32};
|
||||
use pathfinder_geometry::color::ColorF;
|
||||
use pathfinder_gl::{GLDevice, GLVersion};
|
||||
use pathfinder_gpu::resources::{FilesystemResourceLoader, ResourceLoader};
|
||||
use pathfinder_gpu::{ClearParams, Device};
|
||||
use pathfinder_renderer::concurrent::rayon::RayonExecutor;
|
||||
use pathfinder_renderer::concurrent::scene_proxy::SceneProxy;
|
||||
use pathfinder_renderer::gpu::renderer::{DestFramebuffer, Renderer};
|
||||
use pathfinder_renderer::options::RenderOptions;
|
||||
use pathfinder_renderer::scene::Scene;
|
||||
use pathfinder_simd::default::F32x4;
|
||||
use std::ffi::CString;
|
||||
use std::os::raw::{c_char, c_void};
|
||||
|
||||
// Constants
|
||||
|
||||
pub const PF_CLEAR_FLAGS_HAS_COLOR: u8 = 0x1;
|
||||
pub const PF_CLEAR_FLAGS_HAS_DEPTH: u8 = 0x2;
|
||||
pub const PF_CLEAR_FLAGS_HAS_STENCIL: u8 = 0x4;
|
||||
pub const PF_CLEAR_FLAGS_HAS_RECT: u8 = 0x8;
|
||||
|
||||
// Types
|
||||
|
||||
// `canvas`
|
||||
pub type PFCanvasRef = *mut CanvasRenderingContext2D;
|
||||
pub type PFPathRef = *mut Path2D;
|
||||
|
||||
// `geometry`
|
||||
#[repr(C)]
|
||||
pub struct PFPoint2DF {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct PFPoint2DI {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct PFRectF {
|
||||
pub origin: PFPoint2DF,
|
||||
pub lower_right: PFPoint2DF,
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct PFRectI {
|
||||
pub origin: PFPoint2DI,
|
||||
pub lower_right: PFPoint2DI,
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct PFColorF {
|
||||
pub r: f32,
|
||||
pub g: f32,
|
||||
pub b: f32,
|
||||
pub a: f32,
|
||||
}
|
||||
|
||||
// `gl`
|
||||
pub type PFGLDeviceRef = *mut GLDevice;
|
||||
pub type PFGLVersion = GLVersion;
|
||||
pub type PFGLFunctionLoader = extern "C" fn(name: *const c_char, userdata: *mut c_void)
|
||||
-> *const c_void;
|
||||
// `gpu`
|
||||
pub type PFGLDestFramebufferRef = *mut DestFramebuffer<GLDevice>;
|
||||
pub type PFGLRendererRef = *mut Renderer<GLDevice>;
|
||||
// FIXME(pcwalton): Double-boxing is unfortunate. Remove this when `std::raw::TraitObject` is
|
||||
// stable?
|
||||
pub type PFResourceLoaderRef = *mut Box<dyn ResourceLoader>;
|
||||
#[repr(C)]
|
||||
pub struct PFClearParams {
|
||||
pub color: PFColorF,
|
||||
pub depth: f32,
|
||||
pub stencil: u8,
|
||||
pub rect: PFRectI,
|
||||
pub flags: PFClearFlags,
|
||||
}
|
||||
pub type PFClearFlags = u8;
|
||||
|
||||
// `renderer`
|
||||
pub type PFSceneRef = *mut Scene;
|
||||
pub type PFSceneProxyRef = *mut SceneProxy;
|
||||
// TODO(pcwalton)
|
||||
#[repr(C)]
|
||||
pub struct PFRenderOptions {
|
||||
pub placeholder: u32,
|
||||
}
|
||||
|
||||
// `canvas`
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFCanvasCreate(size: *const PFPoint2DF) -> PFCanvasRef {
|
||||
Box::into_raw(Box::new(CanvasRenderingContext2D::new((*size).to_rust())))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFCanvasDestroy(canvas: PFCanvasRef) {
|
||||
drop(Box::from_raw(canvas))
|
||||
}
|
||||
|
||||
/// Consumes the canvas.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFCanvasCreateScene(canvas: PFCanvasRef) -> PFSceneRef {
|
||||
Box::into_raw(Box::new(Box::from_raw(canvas).into_scene()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFCanvasFillRect(canvas: PFCanvasRef, rect: *const PFRectF) {
|
||||
(*canvas).fill_rect((*rect).to_rust())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFCanvasStrokeRect(canvas: PFCanvasRef, rect: *const PFRectF) {
|
||||
(*canvas).stroke_rect((*rect).to_rust())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFCanvasSetLineWidth(canvas: PFCanvasRef, new_line_width: f32) {
|
||||
(*canvas).set_line_width(new_line_width)
|
||||
}
|
||||
|
||||
/// Consumes the path.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFCanvasFillPath(canvas: PFCanvasRef, path: PFPathRef) {
|
||||
(*canvas).fill_path(*Box::from_raw(path))
|
||||
}
|
||||
|
||||
/// Consumes the path.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFCanvasStrokePath(canvas: PFCanvasRef, path: PFPathRef) {
|
||||
(*canvas).stroke_path(*Box::from_raw(path))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFPathCreate() -> PFPathRef {
|
||||
Box::into_raw(Box::new(Path2D::new()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFPathDestroy(path: PFPathRef) {
|
||||
drop(Box::from_raw(path))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFPathClone(path: PFPathRef) -> PFPathRef {
|
||||
Box::into_raw(Box::new((*path).clone()))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFPathMoveTo(path: PFPathRef, to: *const PFPoint2DF) {
|
||||
(*path).move_to((*to).to_rust())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFPathLineTo(path: PFPathRef, to: *const PFPoint2DF) {
|
||||
(*path).line_to((*to).to_rust())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFPathQuadraticCurveTo(path: PFPathRef,
|
||||
ctrl: *const PFPoint2DF,
|
||||
to: *const PFPoint2DF) {
|
||||
(*path).quadratic_curve_to((*ctrl).to_rust(), (*to).to_rust())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFPathBezierCurveTo(path: PFPathRef,
|
||||
ctrl0: *const PFPoint2DF,
|
||||
ctrl1: *const PFPoint2DF,
|
||||
to: *const PFPoint2DF) {
|
||||
(*path).bezier_curve_to((*ctrl0).to_rust(), (*ctrl1).to_rust(), (*to).to_rust())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFPathClosePath(path: PFPathRef) {
|
||||
(*path).close_path()
|
||||
}
|
||||
|
||||
// `gl`
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFFilesystemResourceLoaderLocate() -> PFResourceLoaderRef {
|
||||
let loader = Box::new(FilesystemResourceLoader::locate());
|
||||
Box::into_raw(Box::new(loader as Box<dyn ResourceLoader>))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFGLLoadWith(loader: PFGLFunctionLoader, userdata: *mut c_void) {
|
||||
gl::load_with(|name| {
|
||||
let name = CString::new(name).unwrap();
|
||||
loader(name.as_ptr(), userdata)
|
||||
});
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFGLDeviceCreate(version: PFGLVersion, default_framebuffer: u32)
|
||||
-> PFGLDeviceRef {
|
||||
Box::into_raw(Box::new(GLDevice::new(version, default_framebuffer)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFGLDeviceDestroy(device: PFGLDeviceRef) {
|
||||
drop(Box::from_raw(device))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFGLDeviceClear(device: PFGLDeviceRef, params: *const PFClearParams) {
|
||||
(*device).clear(&(*params).to_rust())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFResourceLoaderDestroy(loader: PFResourceLoaderRef) {
|
||||
drop(Box::from_raw(loader))
|
||||
}
|
||||
|
||||
// `gpu`
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFGLDestFramebufferCreateFullWindow(window_size: *const PFPoint2DI)
|
||||
-> PFGLDestFramebufferRef {
|
||||
Box::into_raw(Box::new(DestFramebuffer::full_window((*window_size).to_rust())))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFGLDestFramebufferDestroy(dest_framebuffer: PFGLDestFramebufferRef) {
|
||||
drop(Box::from_raw(dest_framebuffer))
|
||||
}
|
||||
|
||||
/// Takes ownership of `device` and `dest_framebuffer`, but not `resources`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFGLRendererCreate(device: PFGLDeviceRef,
|
||||
resources: PFResourceLoaderRef,
|
||||
dest_framebuffer: PFGLDestFramebufferRef)
|
||||
-> PFGLRendererRef {
|
||||
Box::into_raw(Box::new(Renderer::new(*Box::from_raw(device),
|
||||
&**resources,
|
||||
*Box::from_raw(dest_framebuffer))))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFGLRendererDestroy(renderer: PFGLRendererRef) {
|
||||
drop(Box::from_raw(renderer))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFGLRendererGetDevice(renderer: PFGLRendererRef) -> PFGLDeviceRef {
|
||||
&mut (*renderer).device
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFSceneProxyBuildAndRenderGL(scene_proxy: PFSceneProxyRef,
|
||||
renderer: PFGLRendererRef,
|
||||
options: *const PFRenderOptions) {
|
||||
(*scene_proxy).build_and_render(&mut *renderer, (*options).to_rust())
|
||||
}
|
||||
|
||||
// `renderer`
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFSceneDestroy(scene: PFSceneRef) {
|
||||
drop(Box::from_raw(scene))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFSceneProxyCreateFromSceneAndRayonExecutor(scene: PFSceneRef)
|
||||
-> PFSceneProxyRef {
|
||||
Box::into_raw(Box::new(SceneProxy::from_scene(*Box::from_raw(scene), RayonExecutor)))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn PFSceneProxyDestroy(scene_proxy: PFSceneProxyRef) {
|
||||
drop(Box::from_raw(scene_proxy))
|
||||
}
|
||||
|
||||
// Helpers for `geometry`
|
||||
|
||||
impl PFColorF {
|
||||
#[inline]
|
||||
pub fn to_rust(&self) -> ColorF {
|
||||
ColorF(F32x4::new(self.r, self.g, self.b, self.a))
|
||||
}
|
||||
}
|
||||
|
||||
impl PFRectF {
|
||||
#[inline]
|
||||
pub fn to_rust(&self) -> RectF32 {
|
||||
RectF32::from_points(self.origin.to_rust(), self.lower_right.to_rust())
|
||||
}
|
||||
}
|
||||
|
||||
impl PFRectI {
|
||||
#[inline]
|
||||
pub fn to_rust(&self) -> RectI32 {
|
||||
RectI32::from_points(self.origin.to_rust(), self.lower_right.to_rust())
|
||||
}
|
||||
}
|
||||
|
||||
impl PFPoint2DF {
|
||||
#[inline]
|
||||
pub fn to_rust(&self) -> Point2DF32 {
|
||||
Point2DF32::new(self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl PFPoint2DI {
|
||||
#[inline]
|
||||
pub fn to_rust(&self) -> Point2DI32 {
|
||||
Point2DI32::new(self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers for `gpu`
|
||||
|
||||
impl PFClearParams {
|
||||
pub fn to_rust(&self) -> ClearParams {
|
||||
ClearParams {
|
||||
color: if (self.flags & PF_CLEAR_FLAGS_HAS_COLOR) != 0 {
|
||||
Some(self.color.to_rust())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
rect: if (self.flags & PF_CLEAR_FLAGS_HAS_RECT) != 0 {
|
||||
Some(self.rect.to_rust())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
depth: if (self.flags & PF_CLEAR_FLAGS_HAS_DEPTH) != 0 {
|
||||
Some(self.depth)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
stencil: if (self.flags & PF_CLEAR_FLAGS_HAS_STENCIL) != 0 {
|
||||
Some(self.stencil)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers for `renderer`
|
||||
|
||||
impl PFRenderOptions {
|
||||
pub fn to_rust(&self) -> RenderOptions {
|
||||
RenderOptions::default()
|
||||
}
|
||||
}
|
|
@ -4,6 +4,9 @@ version = "0.1.0"
|
|||
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["rlib", "staticlib"]
|
||||
|
||||
[dependencies]
|
||||
font-kit = "0.1"
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
OBJ_DIR?=build
|
||||
TARGET_DIR?=build
|
||||
SRC_DIR?=.
|
||||
RUST_TARGET_DIR?=../../target
|
||||
RUST_SRC_DIR?=../../c
|
||||
RUSTFLAGS?=-C target-cpu=native
|
||||
|
||||
CFLAGS?=-Wall -g -I../../c/include
|
||||
LIBS?=-lpathfinder_c
|
||||
MKDIR?=mkdir -p
|
||||
RM?=rm
|
||||
CARGO?=cargo
|
||||
|
||||
UNAME=$(shell uname -s)
|
||||
ifeq ($(UNAME),Darwin)
|
||||
# FIXME(pcwalton): Don't link against HarfBuzz!!
|
||||
LIBS+=-framework OpenGL -framework CoreFoundation -framework CoreGraphics -framework CoreText
|
||||
LIBS+=-lharfbuzz
|
||||
else
|
||||
LIBS+=-lGL
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG),)
|
||||
CFLAGS+=-O2
|
||||
LDFLAGS?=-L$(RUST_TARGET_DIR)/release
|
||||
CARGOFLAGS?=--release
|
||||
else
|
||||
CFLAGS+=-O0
|
||||
LDFLAGS?=-L$(RUST_TARGET_DIR)/debug
|
||||
CARGOFLAGS?=
|
||||
endif
|
||||
|
||||
all: $(TARGET_DIR)/c_canvas_minimal
|
||||
|
||||
.PHONY: clean rustlib
|
||||
|
||||
$(TARGET_DIR)/c_canvas_minimal: $(OBJ_DIR)/c_canvas_minimal.o rustlib
|
||||
$(MKDIR) $(TARGET_DIR) && $(CC) $(LDFLAGS) $(LIBS) `sdl2-config --libs` -o $@ $<
|
||||
|
||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
|
||||
$(MKDIR) $(OBJ_DIR) && $(CC) -c $(CFLAGS) `sdl2-config --cflags` -o $@ $<
|
||||
|
||||
rustlib:
|
||||
cd $(RUST_SRC_DIR) && RUSTFLAGS="$(RUSTFLAGS)" $(CARGO) build $(CARGOFLAGS)
|
||||
|
||||
clean:
|
||||
$(RM) -rf $(TARGET_DIR) && $(RM) -rf $(OBJ_DIR)
|
|
@ -0,0 +1,117 @@
|
|||
// pathfinder/examples/c_canvas_minimal/c_canvas_minimal.c
|
||||
//
|
||||
// Copyright © 2019 The Pathfinder Project Developers.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_opengl.h>
|
||||
#include <pathfinder/pathfinder.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static const void *LoadGLFunction(const char *name, void *userdata);
|
||||
static void SDLFailed(const char *msg);
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
// Set up SDL2.
|
||||
if (SDL_Init(SDL_INIT_EVENTS | SDL_INIT_VIDEO) != 0)
|
||||
SDLFailed("Failed to initialize SDL");
|
||||
|
||||
// Make sure we have at least a GL 3.0 context. Pathfinder requires this.
|
||||
if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3) != 0)
|
||||
SDLFailed("Failed to set GL major version");
|
||||
if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2) != 0)
|
||||
SDLFailed("Failed to set GL minor version");
|
||||
if (SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE) != 0)
|
||||
SDLFailed("Failed to set GL profile");
|
||||
if (SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1) != 0)
|
||||
SDLFailed("Failed to make GL context double-buffered");
|
||||
|
||||
// Open a window.
|
||||
SDL_Window *window = SDL_CreateWindow("Minimal canvas example (C API)",
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
SDL_WINDOWPOS_CENTERED,
|
||||
640,
|
||||
480,
|
||||
SDL_WINDOW_OPENGL);
|
||||
if (window == NULL)
|
||||
SDLFailed("Failed to create SDL window");
|
||||
|
||||
// Create the GL context, and make it current.
|
||||
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
|
||||
if (gl_context == NULL)
|
||||
SDLFailed("Failed to create GL context");
|
||||
|
||||
// Put the window on screen.
|
||||
SDL_ShowWindow(window);
|
||||
|
||||
// Create a Pathfinder renderer.
|
||||
PFGLLoadWith(LoadGLFunction, NULL);
|
||||
PFGLDestFramebufferRef dest_framebuffer =
|
||||
PFGLDestFramebufferCreateFullWindow(&(PFPoint2DI){640, 480});
|
||||
PFGLRendererRef renderer = PFGLRendererCreate(PFGLDeviceCreate(PF_GL_VERSION_GL3, 0),
|
||||
PFFilesystemResourceLoaderLocate(),
|
||||
dest_framebuffer);
|
||||
|
||||
// Clear to white.
|
||||
PFGLDeviceClear(PFGLRendererGetDevice(renderer), &(PFClearParams){
|
||||
(PFColorF){1.0, 1.0, 1.0, 1.0}, 0.0, 0, {0}, PF_CLEAR_FLAGS_HAS_COLOR
|
||||
});
|
||||
|
||||
// Make a canvas. We're going to draw a house.
|
||||
PFCanvasRef canvas = PFCanvasCreate(&(PFPoint2DF){640.0f, 480.0f});
|
||||
|
||||
// Set line width.
|
||||
PFCanvasSetLineWidth(canvas, 10.0f);
|
||||
|
||||
// Draw walls.
|
||||
PFCanvasStrokeRect(canvas, &(PFRectF){{75.0f, 140.0f}, {225.0f, 250.0f}});
|
||||
|
||||
// Draw door.
|
||||
PFCanvasFillRect(canvas, &(PFRectF){{130.0f, 190.0f}, {170.0f, 250.0f}});
|
||||
|
||||
// Draw roof.
|
||||
PFPathRef path = PFPathCreate();
|
||||
PFPathMoveTo(path, &(PFPoint2DF){50.0, 140.0});
|
||||
PFPathLineTo(path, &(PFPoint2DF){150.0, 60.0});
|
||||
PFPathLineTo(path, &(PFPoint2DF){250.0, 140.0});
|
||||
PFPathClosePath(path);
|
||||
PFCanvasStrokePath(canvas, path);
|
||||
|
||||
// Render the canvas to screen.
|
||||
PFSceneRef scene = PFCanvasCreateScene(canvas);
|
||||
PFSceneProxyRef scene_proxy = PFSceneProxyCreateFromSceneAndRayonExecutor(scene);
|
||||
PFSceneProxyBuildAndRenderGL(scene_proxy, renderer, &(PFRenderOptions){0});
|
||||
SDL_GL_SwapWindow(window);
|
||||
|
||||
// Wait for a keypress.
|
||||
while (true) {
|
||||
SDL_Event event;
|
||||
if (SDL_WaitEvent(&event) == 0)
|
||||
SDLFailed("Failed to get SDL event");
|
||||
if (event.type == SDL_QUIT ||
|
||||
(event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Finish up.
|
||||
SDL_Quit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const void *LoadGLFunction(const char *name, void *userdata) {
|
||||
return SDL_GL_GetProcAddress(name);
|
||||
}
|
||||
|
||||
static void SDLFailed(const char *msg) {
|
||||
fprintf(stderr, "%s: %s\n", msg, SDL_GetError());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
|
@ -4,6 +4,9 @@ version = "0.1.0"
|
|||
edition = "2018"
|
||||
authors = ["Patrick Walton <pcwalton@mimiga.net>"]
|
||||
|
||||
[lib]
|
||||
crate-type = ["rlib", "staticlib"]
|
||||
|
||||
[dependencies]
|
||||
gl = "0.6"
|
||||
rustache = "0.1"
|
||||
|
|
|
@ -859,11 +859,13 @@ impl VertexAttrTypeExt for VertexAttrType {
|
|||
}
|
||||
|
||||
/// The version/dialect of OpenGL we should render with.
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(u32)]
|
||||
pub enum GLVersion {
|
||||
/// OpenGL 3.0+, core profile.
|
||||
GL3,
|
||||
GL3 = 0,
|
||||
/// OpenGL ES 3.0+.
|
||||
GLES3,
|
||||
GLES3 = 1,
|
||||
}
|
||||
|
||||
impl GLVersion {
|
||||
|
|
Loading…
Reference in New Issue