Compare commits

..

No commits in common. "5fa9e8f88337cca2495cee71967fd4c1c10b5642" and "a29dd979c196a00756749d06c61f7bf6978c9dc7" have entirely different histories.

11 changed files with 717 additions and 1490 deletions

1939
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -4,8 +4,11 @@ version = "0.1.0"
authors = ["Patrick Walton <pcwalton@mimiga.net>"] authors = ["Patrick Walton <pcwalton@mimiga.net>"]
edition = "2018" edition = "2018"
[features]
capi = []
[lib] [lib]
crate-type = ["staticlib", "cdylib"] crate-type = ["staticlib"]
name = "pathfinder" name = "pathfinder"
[dependencies] [dependencies]
@ -13,13 +16,8 @@ font-kit = "0.6"
foreign-types = "0.3" foreign-types = "0.3"
gl = "0.14" gl = "0.14"
libc = "0.2" libc = "0.2"
simple_logger = "4.3"
usvg = "0.9" usvg = "0.9"
[dependencies.log]
version = "0.4"
features = ["max_level_info"]
[dependencies.pathfinder_canvas] [dependencies.pathfinder_canvas]
features = ["pf-text"] features = ["pf-text"]
path = "../canvas" path = "../canvas"

View File

@ -10,7 +10,6 @@
//! C bindings to Pathfinder. //! C bindings to Pathfinder.
use font_kit::font::Font;
use font_kit::handle::Handle; use font_kit::handle::Handle;
use gl; use gl;
use pathfinder_canvas::{Canvas, CanvasFontContext, CanvasRenderingContext2D, FillStyle, LineJoin}; use pathfinder_canvas::{Canvas, CanvasFontContext, CanvasRenderingContext2D, FillStyle, LineJoin};
@ -28,7 +27,6 @@ use pathfinder_gpu::Device;
use pathfinder_resources::ResourceLoader; use pathfinder_resources::ResourceLoader;
use pathfinder_resources::fs::FilesystemResourceLoader; use pathfinder_resources::fs::FilesystemResourceLoader;
use pathfinder_resources::embedded::EmbeddedResourceLoader; use pathfinder_resources::embedded::EmbeddedResourceLoader;
use pathfinder_renderer::concurrent::executor::SequentialExecutor;
use pathfinder_renderer::concurrent::rayon::RayonExecutor; use pathfinder_renderer::concurrent::rayon::RayonExecutor;
use pathfinder_renderer::concurrent::scene_proxy::SceneProxy; use pathfinder_renderer::concurrent::scene_proxy::SceneProxy;
use pathfinder_renderer::gpu::options::{DestFramebuffer, RendererLevel}; use pathfinder_renderer::gpu::options::{DestFramebuffer, RendererLevel};
@ -41,7 +39,7 @@ use pathfinder_svg::SVGScene;
use std::ffi::CString; use std::ffi::CString;
use std::os::raw::{c_char, c_void}; use std::os::raw::{c_char, c_void};
use std::path::PathBuf; use std::path::PathBuf;
use std::ptr::{self, NonNull}; use std::ptr;
use std::slice; use std::slice;
use std::str; use std::str;
use usvg::{Options, Tree}; use usvg::{Options, Tree};
@ -53,11 +51,6 @@ use metal::{self, CoreAnimationDrawableRef, DeviceRef as NativeMetalDeviceRef};
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] #[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
use pathfinder_metal::MetalDevice; use pathfinder_metal::MetalDevice;
#[no_mangle]
pub extern "system" fn init_logging() {
simple_logger::init_with_env().unwrap();
}
// Constants // Constants
// `canvas` // `canvas`
@ -109,7 +102,6 @@ pub type FKHandleRef = *mut Handle;
pub type PFCanvasRef = *mut CanvasRenderingContext2D; pub type PFCanvasRef = *mut CanvasRenderingContext2D;
pub type PFPathRef = *mut Path2D; pub type PFPathRef = *mut Path2D;
pub type PFCanvasFontContextRef = *mut CanvasFontContext; pub type PFCanvasFontContextRef = *mut CanvasFontContext;
pub type FKFontRef = NonNull<Font>;
pub type PFFillStyleRef = *mut FillStyle; pub type PFFillStyleRef = *mut FillStyle;
pub type PFLineCap = u8; pub type PFLineCap = u8;
pub type PFLineJoin = u8; pub type PFLineJoin = u8;
@ -280,13 +272,6 @@ pub unsafe extern "C" fn PFCanvasCreateScene(canvas: PFCanvasRef) -> PFSceneRef
Box::into_raw(Box::new(Box::from_raw(canvas).into_canvas().into_scene())) Box::into_raw(Box::new(Box::from_raw(canvas).into_canvas().into_scene()))
} }
// Extensions
#[no_mangle]
pub unsafe extern "C" fn PFCanvasClear(canvas: PFCanvasRef) {
(*canvas).clear()
}
// Drawing rectangles // Drawing rectangles
#[no_mangle] #[no_mangle]
@ -299,11 +284,6 @@ pub unsafe extern "C" fn PFCanvasStrokeRect(canvas: PFCanvasRef, rect: *const PF
(*canvas).stroke_rect((*rect).to_rust()) (*canvas).stroke_rect((*rect).to_rust())
} }
#[no_mangle]
pub unsafe extern "C" fn PFCanvasClearRect(canvas: PFCanvasRef, rect: *const PFRectF) {
(*canvas).clear_rect((*rect).to_rust())
}
// Drawing text // Drawing text
#[no_mangle] #[no_mangle]
@ -326,8 +306,9 @@ pub unsafe extern "C" fn PFCanvasStrokeText(canvas: PFCanvasRef,
pub unsafe extern "C" fn PFCanvasMeasureText(canvas: PFCanvasRef, pub unsafe extern "C" fn PFCanvasMeasureText(canvas: PFCanvasRef,
string: *const c_char, string: *const c_char,
string_len: usize, string_len: usize,
out_text_metrics: NonNull<PFTextMetrics>) { out_text_metrics: *mut PFTextMetrics) {
out_text_metrics.write((*canvas).measure_text(to_rust_string(&string, string_len)).to_c()) debug_assert!(!out_text_metrics.is_null());
*out_text_metrics = (*canvas).measure_text(to_rust_string(&string, string_len)).to_c()
} }
#[no_mangle] #[no_mangle]
@ -394,33 +375,10 @@ pub unsafe extern "C" fn PFCanvasSetLineDashOffset(canvas: PFCanvasRef, new_offs
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn PFCanvasFontContextGetFontByPostScriptName(context: PFCanvasFontContextRef, pub unsafe extern "C" fn PFCanvasSetFontByPostScriptName(canvas: PFCanvasRef,
postscript_name: *const c_char, postscript_name: *const c_char,
postscript_name_len: usize) -> Option<FKFontRef> { postscript_name_len: usize) {
let name = to_rust_string(&postscript_name, postscript_name_len); (*canvas).set_font(to_rust_string(&postscript_name, postscript_name_len))
match (*context).get_font_by_postscript_name(name) {
Ok(font) => NonNull::new(Box::into_raw(Box::new(font))),
Err(e) => {
log::error!("Failed to get font {:?}: {:?}", name, e);
None
}
}
}
#[no_mangle]
pub unsafe extern "C" fn FKFontDestroy(font: FKFontRef) {
drop(Box::from_raw(font.as_ptr()))
}
#[no_mangle]
pub unsafe extern "C" fn PFCanvasSetFont(canvas: PFCanvasRef, font: FKFontRef) -> i32 {
match (*canvas).set_font(font.as_ref().clone()) {
Ok(_) => 0,
Err(e) => {
log::error!("Failed to set font: {:?}", e);
1
}
}
} }
#[no_mangle] #[no_mangle]
@ -663,33 +621,6 @@ pub unsafe extern "C" fn PFGLRendererGetDevice(renderer: PFGLRendererRef) -> PFG
(*renderer).device_mut() (*renderer).device_mut()
} }
#[no_mangle]
pub unsafe extern "C" fn PFGLRendererSetViewport(renderer: PFGLRendererRef, new_viewport: PFRectI) -> i32 {
match (*renderer).options_mut().dest {
DestFramebuffer::Default { ref mut viewport, .. } => {
*viewport = new_viewport.to_rust();
0
}
DestFramebuffer::Other(_) => 1,
}
}
#[no_mangle]
pub unsafe extern "C" fn PFGLRendererSetWindowSize(renderer: PFGLRendererRef, new_window_size: PFVector2I) -> i32 {
match (*renderer).options_mut().dest {
DestFramebuffer::Default { ref mut window_size, .. } => {
*window_size = new_window_size.to_rust();
0
}
DestFramebuffer::Other(_) => 1,
}
}
#[no_mangle]
pub unsafe extern "C" fn PFGLRendererDestFramebufferSizeChanged(renderer: PFGLRendererRef) {
(*renderer).dest_framebuffer_size_changed()
}
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))] #[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn PFMetalDestFramebufferCreateFullWindow(window_size: *const PFVector2I) pub unsafe extern "C" fn PFMetalDestFramebufferCreateFullWindow(window_size: *const PFVector2I)
@ -854,18 +785,12 @@ pub unsafe extern "C" fn PFSceneDestroy(scene: PFSceneRef) {
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn PFSceneProxyCreateWithSequentialExecutor(level: PFRendererLevel) -> PFSceneProxyRef { pub unsafe extern "C" fn PFSceneProxyCreateFromSceneAndRayonExecutor(scene: PFSceneRef,
Box::into_raw(Box::new(SceneProxy::new(to_rust_renderer_level(level), SequentialExecutor))) level: PFRendererLevel)
} -> PFSceneProxyRef {
Box::into_raw(Box::new(SceneProxy::from_scene(*Box::from_raw(scene),
#[no_mangle] to_rust_renderer_level(level),
pub unsafe extern "C" fn PFSceneProxyCreateWithRayonExecutor(level: PFRendererLevel) -> PFSceneProxyRef { RayonExecutor)))
Box::into_raw(Box::new(SceneProxy::new(to_rust_renderer_level(level), RayonExecutor)))
}
#[no_mangle]
pub unsafe extern "C" fn PFSceneProxyReplaceScene(scene_proxy: PFSceneProxyRef, scene: PFSceneRef) {
(*scene_proxy).replace_scene(*Box::from_raw(scene))
} }
#[no_mangle] #[no_mangle]

View File

@ -10,7 +10,6 @@
use crate::{CanvasRenderingContext2D, State, TextAlign, TextBaseline}; use crate::{CanvasRenderingContext2D, State, TextAlign, TextBaseline};
use font_kit::canvas::RasterizationOptions; use font_kit::canvas::RasterizationOptions;
use font_kit::error::{FontLoadingError, SelectionError};
use font_kit::family_name::FamilyName; use font_kit::family_name::FamilyName;
use font_kit::handle::Handle; use font_kit::handle::Handle;
use font_kit::hinting::HintingOptions; use font_kit::hinting::HintingOptions;
@ -104,10 +103,9 @@ impl CanvasRenderingContext2D {
} }
#[inline] #[inline]
pub fn set_font<FC>(&mut self, font_collection: FC) -> Result<(), FontError> where FC: IntoFontCollection { pub fn set_font<FC>(&mut self, font_collection: FC) where FC: IntoFontCollection {
let font_collection = font_collection.into_font_collection(&self.canvas_font_context)?; let font_collection = font_collection.into_font_collection(&self.canvas_font_context);
self.current_state.font_collection = font_collection; self.current_state.font_collection = font_collection;
Ok(())
} }
#[inline] #[inline]
@ -154,7 +152,13 @@ pub trait ToTextLayout {
impl ToTextLayout for str { impl ToTextLayout for str {
fn layout(&self, state: CanvasState) -> Cow<TextMetrics> { fn layout(&self, state: CanvasState) -> Cow<TextMetrics> {
Cow::Owned(TextMetrics::layout(self, &state.0.font_collection, state.0.font_size, state.0.text_align, state.0.text_baseline)) let skribo_layout = Rc::new(skribo::layout(&TextStyle { size: state.0.font_size },
&state.0.font_collection,
self));
Cow::Owned(TextMetrics::new(skribo_layout,
state.0.font_size,
state.0.text_align,
state.0.text_baseline))
} }
} }
@ -184,13 +188,6 @@ impl ToTextLayout for TextMetrics {
#[derive(Clone)] #[derive(Clone)]
pub struct CanvasFontContext(pub(crate) Rc<RefCell<CanvasFontContextData>>); pub struct CanvasFontContext(pub(crate) Rc<RefCell<CanvasFontContextData>>);
/// The reason a font could not be loaded
#[derive(Debug)]
pub enum FontError {
NotFound(SelectionError),
LoadError(FontLoadingError),
}
pub(super) struct CanvasFontContextData { pub(super) struct CanvasFontContextData {
pub(super) font_context: FontContext<Font>, pub(super) font_context: FontContext<Font>,
#[allow(dead_code)] #[allow(dead_code)]
@ -227,15 +224,16 @@ impl CanvasFontContext {
CanvasFontContext::new(Arc::new(MemSource::from_fonts(fonts).unwrap())) CanvasFontContext::new(Arc::new(MemSource::from_fonts(fonts).unwrap()))
} }
pub fn get_font_by_postscript_name(&self, postscript_name: &str) -> Result<Font, FontError> { fn get_font_by_postscript_name(&self, postscript_name: &str) -> Font {
let this = self.0.borrow(); let this = self.0.borrow();
if let Some(cached_font) = this.font_context.get_cached_font(postscript_name) { if let Some(cached_font) = this.font_context.get_cached_font(postscript_name) {
return Ok((*cached_font).clone()); return (*cached_font).clone();
} }
this.font_source this.font_source
.select_by_postscript_name(postscript_name) .select_by_postscript_name(postscript_name)
.map_err(FontError::NotFound)? .expect("Couldn't find a font with that PostScript name!")
.load().map_err(FontError::LoadError) .load()
.expect("Failed to load the font!")
} }
} }
@ -316,13 +314,6 @@ impl TextMetrics {
} }
} }
pub fn layout(string: &str, font_collection: &FontCollection, font_size: f32, text_align: TextAlign, text_baseline: TextBaseline) -> TextMetrics {
let skribo_layout = Rc::new(skribo::layout(&TextStyle { size: font_size },
font_collection,
string));
TextMetrics::new(skribo_layout, font_size, text_align, text_baseline)
}
pub fn text_x_offset(&self) -> f32 { pub fn text_x_offset(&self) -> f32 {
if self.text_x_offset.get().is_none() { if self.text_x_offset.get().is_none() {
self.text_x_offset.set(Some(match self.align { self.text_x_offset.set(Some(match self.align {
@ -532,46 +523,46 @@ impl VerticalMetrics {
/// Various things that can be conveniently converted into font collections for use with /// Various things that can be conveniently converted into font collections for use with
/// `CanvasRenderingContext2D::set_font()`. /// `CanvasRenderingContext2D::set_font()`.
pub trait IntoFontCollection { pub trait IntoFontCollection {
fn into_font_collection(self, font_context: &CanvasFontContext) -> Result<Arc<FontCollection>, FontError>; fn into_font_collection(self, font_context: &CanvasFontContext) -> Arc<FontCollection>;
} }
impl IntoFontCollection for Arc<FontCollection> { impl IntoFontCollection for Arc<FontCollection> {
#[inline] #[inline]
fn into_font_collection(self, _: &CanvasFontContext) -> Result<Arc<FontCollection>, FontError> { fn into_font_collection(self, _: &CanvasFontContext) -> Arc<FontCollection> {
Ok(self) self
} }
} }
impl IntoFontCollection for FontFamily { impl IntoFontCollection for FontFamily {
#[inline] #[inline]
fn into_font_collection(self, _: &CanvasFontContext) -> Result<Arc<FontCollection>, FontError> { fn into_font_collection(self, _: &CanvasFontContext) -> Arc<FontCollection> {
let mut font_collection = FontCollection::new(); let mut font_collection = FontCollection::new();
font_collection.add_family(self); font_collection.add_family(self);
Ok(Arc::new(font_collection)) Arc::new(font_collection)
} }
} }
impl IntoFontCollection for Vec<FontFamily> { impl IntoFontCollection for Vec<FontFamily> {
#[inline] #[inline]
fn into_font_collection(self, _: &CanvasFontContext) -> Result<Arc<FontCollection>, FontError> { fn into_font_collection(self, _: &CanvasFontContext) -> Arc<FontCollection> {
let mut font_collection = FontCollection::new(); let mut font_collection = FontCollection::new();
for family in self { for family in self {
font_collection.add_family(family); font_collection.add_family(family);
} }
Ok(Arc::new(font_collection)) Arc::new(font_collection)
} }
} }
impl IntoFontCollection for Font { impl IntoFontCollection for Font {
#[inline] #[inline]
fn into_font_collection(self, context: &CanvasFontContext) -> Result<Arc<FontCollection>, FontError> { fn into_font_collection(self, context: &CanvasFontContext) -> Arc<FontCollection> {
Ok(FontFamily::new_from_font(self).into_font_collection(context)?) FontFamily::new_from_font(self).into_font_collection(context)
} }
} }
impl<'a> IntoFontCollection for &'a [Font] { impl<'a> IntoFontCollection for &'a [Font] {
#[inline] #[inline]
fn into_font_collection(self, context: &CanvasFontContext) -> Result<Arc<FontCollection>, FontError> { fn into_font_collection(self, context: &CanvasFontContext) -> Arc<FontCollection> {
let mut family = FontFamily::new(); let mut family = FontFamily::new();
for font in self { for font in self {
family.add_font(FontRef::new((*font).clone())) family.add_font(FontRef::new((*font).clone()))
@ -582,19 +573,19 @@ impl<'a> IntoFontCollection for &'a [Font] {
impl<'a> IntoFontCollection for &'a str { impl<'a> IntoFontCollection for &'a str {
#[inline] #[inline]
fn into_font_collection(self, context: &CanvasFontContext) -> Result<Arc<FontCollection>, FontError> { fn into_font_collection(self, context: &CanvasFontContext) -> Arc<FontCollection> {
context.get_font_by_postscript_name(self)?.into_font_collection(context) context.get_font_by_postscript_name(self).into_font_collection(context)
} }
} }
impl<'a, 'b> IntoFontCollection for &'a [&'b str] { impl<'a, 'b> IntoFontCollection for &'a [&'b str] {
#[inline] #[inline]
fn into_font_collection(self, context: &CanvasFontContext) -> Result<Arc<FontCollection>, FontError> { fn into_font_collection(self, context: &CanvasFontContext) -> Arc<FontCollection> {
let mut font_collection = FontCollection::new(); let mut font_collection = FontCollection::new();
for postscript_name in self { for postscript_name in self {
let font = context.get_font_by_postscript_name(postscript_name)?; let font = context.get_font_by_postscript_name(postscript_name);
font_collection.add_family(FontFamily::new_from_font(font)); font_collection.add_family(FontFamily::new_from_font(font));
} }
Ok(Arc::new(font_collection)) Arc::new(font_collection)
} }
} }

View File

@ -367,14 +367,14 @@ impl Contour {
return Contour::from_rect(rect); return Contour::from_rect(rect);
} }
let radius = radius.min(rect.size() * 0.5); let radius = radius.min(rect.size() * 0.5);
let control_point_offset = radius * QUARTER_ARC_CP_FROM_OUTSIDE; let contol_point_offset = radius * QUARTER_ARC_CP_FROM_OUTSIDE;
let mut contour = Contour::with_capacity(8); let mut contour = Contour::with_capacity(8);
// upper left corner // upper left corner
{ {
let p0 = rect.origin(); let p0 = rect.origin();
let p1 = p0 + control_point_offset; let p1 = p0 + contol_point_offset;
let p2 = p0 + radius; let p2 = p0 + radius;
contour.push_endpoint(vec2f(p0.x(), p2.y())); contour.push_endpoint(vec2f(p0.x(), p2.y()));
contour.push_cubic( contour.push_cubic(
@ -387,7 +387,7 @@ impl Contour {
// upper right // upper right
{ {
let p0 = rect.upper_right(); let p0 = rect.upper_right();
let p1 = p0 + control_point_offset * vec2f(-1.0, 1.0); let p1 = p0 + contol_point_offset * vec2f(-1.0, 1.0);
let p2 = p0 + radius * vec2f(-1.0, 1.0); let p2 = p0 + radius * vec2f(-1.0, 1.0);
contour.push_endpoint(vec2f(p2.x(), p0.y())); contour.push_endpoint(vec2f(p2.x(), p0.y()));
contour.push_cubic( contour.push_cubic(
@ -400,7 +400,7 @@ impl Contour {
// lower right // lower right
{ {
let p0 = rect.lower_right(); let p0 = rect.lower_right();
let p1 = p0 + control_point_offset * vec2f(-1.0, -1.0); let p1 = p0 + contol_point_offset * vec2f(-1.0, -1.0);
let p2 = p0 + radius * vec2f(-1.0, -1.0); let p2 = p0 + radius * vec2f(-1.0, -1.0);
contour.push_endpoint(vec2f(p0.x(), p2.y())); contour.push_endpoint(vec2f(p0.x(), p2.y()));
contour.push_cubic( contour.push_cubic(
@ -413,7 +413,7 @@ impl Contour {
// lower left // lower left
{ {
let p0 = rect.lower_left(); let p0 = rect.lower_left();
let p1 = p0 + control_point_offset * vec2f(1.0, -1.0); let p1 = p0 + contol_point_offset * vec2f(1.0, -1.0);
let p2 = p0 + radius * vec2f(1.0, -1.0); let p2 = p0 + radius * vec2f(1.0, -1.0);
contour.push_endpoint(vec2f(p2.x(), p0.y())); contour.push_endpoint(vec2f(p2.x(), p0.y()));
contour.push_cubic( contour.push_cubic(

View File

@ -50,8 +50,8 @@ use std::path::PathBuf;
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use usvg::{Options as UsvgOptions, Tree as SvgTree}; use usvg::{Options as UsvgOptions, Tree as SvgTree};
use pdf::file::{CachedFile, FileOptions}; use pdf::file::File as PdfFile;
use pdf_render::{Cache as PdfRenderCache, SceneBackend}; use pdf_render::Cache as PdfRenderCache;
#[cfg(any(not(target_os = "macos"), feature = "pf-gl"))] #[cfg(any(not(target_os = "macos"), feature = "pf-gl"))]
use pathfinder_gl::GLDevice as DeviceImpl; use pathfinder_gl::GLDevice as DeviceImpl;
@ -86,7 +86,7 @@ mod ui;
enum Content { enum Content {
Svg(SvgTree), Svg(SvgTree),
Pdf { Pdf {
file: CachedFile<Vec<u8>>, file: PdfFile<Vec<u8>>,
cache: PdfRenderCache, cache: PdfRenderCache,
page_nr: u32 page_nr: u32
} }
@ -773,9 +773,8 @@ impl Content {
} }
Content::Pdf { ref file, ref mut cache, page_nr } => { Content::Pdf { ref file, ref mut cache, page_nr } => {
let page = file.get_page(page_nr).expect("no such page"); let page = file.get_page(page_nr).expect("no such page");
let mut backend = SceneBackend::new(cache); let (scene, _) = cache.render_page(file, &page, Transform2F::default()).unwrap();
pdf_render::render_page(&mut backend, &file.resolver(), &page, Transform2F::default()).unwrap(); (scene, String::new())
(backend.finish(), String::new())
} }
} }
} }
@ -792,7 +791,7 @@ fn load_scene(resource_loader: &dyn ResourceLoader,
if let Ok(tree) = SvgTree::from_data(&data, &UsvgOptions::default()) { if let Ok(tree) = SvgTree::from_data(&data, &UsvgOptions::default()) {
Content::Svg(tree) Content::Svg(tree)
} else if let Ok(file) = FileOptions::cached().load(data) { } else if let Ok(file) = PdfFile::from_data(data) {
Content::Pdf { file, cache: PdfRenderCache::new(), page_nr: 0 } Content::Pdf { file, cache: PdfRenderCache::new(), page_nr: 0 }
} else { } else {
panic!("can't load data"); panic!("can't load data");

View File

@ -25,7 +25,6 @@ use sdl2::keyboard::Keycode;
use sdl2::video::GLProfile; use sdl2::video::GLProfile;
use std::iter; use std::iter;
use std::sync::Arc; use std::sync::Arc;
use std::time::{Duration, Instant};
fn main() { fn main() {
// Set up SDL2. // Set up SDL2.
@ -35,10 +34,7 @@ fn main() {
// Make sure we have at least a GL 3.0 context. Pathfinder requires this. // Make sure we have at least a GL 3.0 context. Pathfinder requires this.
let gl_attributes = video.gl_attr(); let gl_attributes = video.gl_attr();
gl_attributes.set_context_profile(GLProfile::Core); gl_attributes.set_context_profile(GLProfile::Core);
gl_attributes.set_context_version(4, 1); gl_attributes.set_context_version(3, 3);
gl_attributes.set_context_flags()
.forward_compatible()
.set();
// Open a window. // Open a window.
let window_size = vec2i(640, 480); let window_size = vec2i(640, 480);
@ -70,32 +66,17 @@ fn main() {
// Wait for a keypress. // Wait for a keypress.
let mut event_pump = sdl_context.event_pump().unwrap(); let mut event_pump = sdl_context.event_pump().unwrap();
let mut n = 0;
let mut last_update = Instant::now();
let mut fps_buf = String::new();
loop { loop {
match event_pump.poll_event() { match event_pump.wait_event() {
Some(Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. }) => return, Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => return,
Some(Event::Window { win_event: WindowEvent::Exposed, .. }) | None => { Event::Window { win_event: WindowEvent::Exposed, .. } => {
// Make a canvas. // Make a canvas.
let mut canvas = Canvas::new(window_size.to_f32()).get_context_2d(font_context.clone()); let mut canvas = Canvas::new(window_size.to_f32()).get_context_2d(font_context.clone());
// Draw the text. // Draw the text.
canvas.set_font("Overpass-Regular").unwrap(); canvas.set_font("Overpass-Regular");
canvas.set_font_size(32.0); canvas.set_font_size(32.0);
let now = Instant::now();
let elapsed = now.duration_since(last_update);
if elapsed >= Duration::from_millis(50) {
last_update = now;
let fps = (n as f64) * ((Duration::from_secs(1).as_micros() as f64) / (elapsed.as_micros() as f64));
fps_buf.clear();
fps_buf.push_str("FPS: ");
use std::fmt::Write;
write!(fps_buf, "{fps:.2}").unwrap();
n = 0;
}
canvas.fill_text("Hello Pathfinder!", vec2f(32.0, 48.0)); canvas.fill_text("Hello Pathfinder!", vec2f(32.0, 48.0));
canvas.fill_text(&fps_buf, vec2f(32.0, 96.0));
canvas.set_text_align(TextAlign::Right); canvas.set_text_align(TextAlign::Right);
canvas.stroke_text("Goodbye Pathfinder!", vec2f(608.0, 464.0)); canvas.stroke_text("Goodbye Pathfinder!", vec2f(608.0, 464.0));
@ -105,8 +86,6 @@ fn main() {
RayonExecutor); RayonExecutor);
scene.build_and_render(&mut renderer, BuildOptions::default()); scene.build_and_render(&mut renderer, BuildOptions::default());
window.gl_swap_window(); window.gl_swap_window();
n += 1;
}, },
_ => {} _ => {}
} }

View File

@ -31,5 +31,5 @@ export SPIRVCROSS=spirv-cross.exe
Note: the Windows versions of `glslangValidator` and `spirv-cross` may change Note: the Windows versions of `glslangValidator` and `spirv-cross` may change
the line endings of the generated output. Please take care to ensure that the line endings of the generated output. Please take care to ensure that
unintended line ending changes aren't accidentally committed, for instance by unintended line ending changes aren't accidentally commited, for instance by
[configuring Git to automatically handle line endings](https://docs.github.com/en/github/using-git/configuring-git-to-handle-line-endings#global-settings-for-line-endings). [configuring Git to automatically handle line endings](https://docs.github.com/en/github/using-git/configuring-git-to-handle-line-endings#global-settings-for-line-endings).

View File

@ -1,6 +1,6 @@
[package] [package]
name = "pathfinder_simd" name = "pathfinder_simd"
version = "0.5.3" version = "0.5.2"
edition = "2018" edition = "2018"
authors = ["Patrick Walton <pcwalton@mimiga.net>"] authors = ["Patrick Walton <pcwalton@mimiga.net>"]
build = "build.rs" build = "build.rs"

View File

@ -10,7 +10,6 @@
use std::arch::aarch64::{self, float32x2_t, float32x4_t, int32x2_t, int32x4_t}; use std::arch::aarch64::{self, float32x2_t, float32x4_t, int32x2_t, int32x4_t};
use std::arch::aarch64::{uint32x2_t, uint32x4_t}; use std::arch::aarch64::{uint32x2_t, uint32x4_t};
use std::intrinsics::simd::*;
use std::f32; use std::f32;
use std::fmt::{self, Debug, Formatter}; use std::fmt::{self, Debug, Formatter};
use std::mem; use std::mem;
@ -870,6 +869,33 @@ impl Index<usize> for U32x4 {
} }
} }
// Intrinsics
extern "platform-intrinsic" {
fn simd_add<T>(x: T, y: T) -> T;
fn simd_div<T>(x: T, y: T) -> T;
fn simd_mul<T>(x: T, y: T) -> T;
fn simd_sub<T>(x: T, y: T) -> T;
fn simd_shr<T>(x: T, y: T) -> T;
fn simd_and<T>(x: T, y: T) -> T;
fn simd_or<T>(x: T, y: T) -> T;
fn simd_xor<T>(x: T, y: T) -> T;
fn simd_fmin<T>(x: T, y: T) -> T;
fn simd_fmax<T>(x: T, y: T) -> T;
fn simd_eq<T, U>(x: T, y: T) -> U;
fn simd_gt<T, U>(x: T, y: T) -> U;
fn simd_le<T, U>(x: T, y: T) -> U;
fn simd_lt<T, U>(x: T, y: T) -> U;
fn simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U;
fn simd_cast<T, U>(x: T) -> U;
}
extern "C" { extern "C" {
#[link_name = "llvm.fabs.v2f32"] #[link_name = "llvm.fabs.v2f32"]
fn fabs_v2f32(a: float32x2_t) -> float32x2_t; fn fabs_v2f32(a: float32x2_t) -> float32x2_t;

View File

@ -8,8 +8,8 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#![cfg_attr(pf_rustc_nightly, allow(internal_features))] #![cfg_attr(pf_rustc_nightly, feature(link_llvm_intrinsics, platform_intrinsics))]
#![cfg_attr(pf_rustc_nightly, feature(link_llvm_intrinsics, core_intrinsics))] #![cfg_attr(all(target_arch = "aarch64", pf_rustc_nightly), feature(stdarch_arm_crc32))]
#![cfg_attr(pf_rustc_nightly, feature(simd_ffi))] #![cfg_attr(pf_rustc_nightly, feature(simd_ffi))]
//! A minimal SIMD abstraction, usable outside of Pathfinder. //! A minimal SIMD abstraction, usable outside of Pathfinder.