Skip to content

Commit 265e781

Browse files
authored
Auto merge of #365 - pcwalton:c-svg, r=pcwalton
Expose `pathfinder_svg` to the C API Closes #357.
2 parents 9816779 + 9e67028 commit 265e781

File tree

8 files changed

+65
-19
lines changed

8 files changed

+65
-19
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

c/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ font-kit = "0.6"
1212
foreign-types = "0.3"
1313
gl = "0.14"
1414
libc = "0.2"
15+
usvg = "0.9"
1516

1617
[dependencies.pathfinder_canvas]
1718
features = ["pf-text"]
@@ -41,6 +42,9 @@ path = "../resources"
4142
[dependencies.pathfinder_simd]
4243
path = "../simd"
4344

45+
[dependencies.pathfinder_svg]
46+
path = "../svg"
47+
4448
[target.'cfg(target_os = "macos")'.dependencies]
4549
metal = "0.17"
4650

c/src/lib.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,14 @@ use pathfinder_renderer::gpu::renderer::Renderer;
3434
use pathfinder_renderer::options::{BuildOptions, RenderTransform};
3535
use pathfinder_renderer::scene::Scene;
3636
use pathfinder_simd::default::F32x4;
37+
use pathfinder_svg::SVGScene;
3738
use std::ffi::CString;
3839
use std::os::raw::{c_char, c_void};
3940
use std::path::PathBuf;
41+
use std::ptr;
4042
use std::slice;
4143
use std::str;
44+
use usvg::{Options, Tree};
4245

4346
#[cfg(all(target_os = "macos", not(feature = "pf-gl")))]
4447
use metal::{self, CAMetalLayer, CoreAnimationLayerRef};
@@ -204,6 +207,9 @@ pub type PFBuildOptionsRef = *mut BuildOptions;
204207
pub type PFRenderTransformRef = *mut RenderTransform;
205208
pub type PFRendererLevel = u8;
206209

210+
// `svg`
211+
pub type PFSVGSceneRef = *mut SVGScene;
212+
207213
// `canvas`
208214

209215
/// This function internally adds a reference to the font context. Therefore, if you created the
@@ -735,6 +741,40 @@ pub unsafe extern "C" fn PFSceneProxyDestroy(scene_proxy: PFSceneProxyRef) {
735741
drop(Box::from_raw(scene_proxy))
736742
}
737743

744+
// `svg`
745+
746+
/// Returns `NULL` on failure.
747+
#[no_mangle]
748+
pub unsafe extern "C" fn PFSVGSceneCreateWithMemory(bytes: *const c_char, byte_len: usize)
749+
-> PFSVGSceneRef {
750+
let data = slice::from_raw_parts(bytes as *const _, byte_len);
751+
let tree = match Tree::from_data(data, &Options::default()) {
752+
Ok(tree) => tree,
753+
Err(_) => return ptr::null_mut(),
754+
};
755+
let svg_scene = SVGScene::from_tree(&tree);
756+
Box::into_raw(Box::new(svg_scene))
757+
}
758+
759+
/// Returns `NULL` on failure.
760+
#[no_mangle]
761+
pub unsafe extern "C" fn PFSVGSceneCreateWithPath(path: *const c_char) -> PFSVGSceneRef {
762+
let string = to_rust_string(&path, 0);
763+
let path = PathBuf::from(string);
764+
let tree = match Tree::from_file(path, &Options::default()) {
765+
Ok(tree) => tree,
766+
Err(_) => return ptr::null_mut(),
767+
};
768+
let svg_scene = SVGScene::from_tree(&tree);
769+
Box::into_raw(Box::new(svg_scene))
770+
}
771+
772+
/// Destroys the SVG and returns the scene.
773+
#[no_mangle]
774+
pub unsafe extern "C" fn PFSVGSceneIntoScene(svg: PFSVGSceneRef) -> PFSceneRef {
775+
Box::into_raw(Box::new((*Box::from_raw(svg)).scene))
776+
}
777+
738778
// Helpers for `canvas`
739779

740780
unsafe fn to_rust_string(ptr: &*const c_char, mut len: usize) -> &str {

demo/common/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use pathfinder_renderer::options::{BuildOptions, RenderTransform};
4242
use pathfinder_renderer::paint::Paint;
4343
use pathfinder_renderer::scene::{DrawPath, RenderTarget, Scene};
4444
use pathfinder_resources::ResourceLoader;
45-
use pathfinder_svg::BuiltSVG;
45+
use pathfinder_svg::SVGScene;
4646
use pathfinder_ui::{MousePosition, UIEvent};
4747
use std::fs::File;
4848
use std::io::{BufWriter, Read};
@@ -759,7 +759,7 @@ fn load_scene(resource_loader: &dyn ResourceLoader,
759759
input_path: &SVGPath,
760760
viewport_size: Vector2I,
761761
filter: Option<PatternFilter>)
762-
-> (BuiltSVG, Tree) {
762+
-> (SVGScene, Tree) {
763763
let mut data;
764764
match *input_path {
765765
SVGPath::Default => data = resource_loader.slurp(DEFAULT_SVG_VIRTUAL_PATH).unwrap(),
@@ -778,7 +778,7 @@ fn load_scene(resource_loader: &dyn ResourceLoader,
778778
// FIXME(pcwalton): Rework how transforms work in the demo. The transform affects the final
779779
// composite steps, breaking this approach.
780780
fn build_svg_tree(tree: &Tree, viewport_size: Vector2I, filter: Option<PatternFilter>)
781-
-> BuiltSVG {
781+
-> SVGScene {
782782
let mut scene = Scene::new();
783783
let filter_info = filter.map(|filter| {
784784
let scale = match filter {
@@ -792,7 +792,7 @@ fn build_svg_tree(tree: &Tree, viewport_size: Vector2I, filter: Option<PatternFi
792792
FilterInfo { filter, render_target_id, render_target_size }
793793
});
794794

795-
let mut built_svg = BuiltSVG::from_tree_and_scene(&tree, scene);
795+
let mut built_svg = SVGScene::from_tree_and_scene(&tree, scene);
796796
if let Some(FilterInfo { filter, render_target_id, render_target_size }) = filter_info {
797797
let mut pattern = Pattern::from_render_target(render_target_id, render_target_size);
798798
pattern.set_filter(Some(filter));
@@ -818,7 +818,7 @@ fn center_of_window(window_size: &WindowSize) -> Vector2F {
818818
window_size.device_size().to_f32() * 0.5
819819
}
820820

821-
fn get_svg_building_message(built_svg: &BuiltSVG) -> String {
821+
fn get_svg_building_message(built_svg: &SVGScene) -> String {
822822
if built_svg.result_flags.is_empty() {
823823
return String::new();
824824
}

demo/magicleap/src/immersive.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use pathfinder_geometry::transform3d::Transform4F32;
2424
use pathfinder_geometry::transform3d::Perspective;
2525
use pathfinder_gpu::Device;
2626
use pathfinder_simd::default::F32x4;
27-
use pathfinder_svg::BuiltSVG;
27+
use pathfinder_svg::SVGScene;
2828
use pathfinder_renderer::scene::Scene;
2929
use pathfinder_renderer::builder::RenderTransform;
3030

@@ -58,7 +58,7 @@ impl<D: Display> ImmersiveDemo<D> {
5858
let options = Options::get();
5959
let svg_data = resources.slurp(DEFAULT_SVG_VIRTUAL_PATH)?;
6060
let tree = usvg::Tree::from_data(&svg_data[..], &usvg::Options::default())?;
61-
let svg = BuiltSVG::from_tree(tree);
61+
let svg = SVGScene::from_tree(tree);
6262
let svg_size = svg.scene.view_box.size();
6363
let scene_thread_proxy = SceneThreadProxy::new(svg.scene, options);
6464
let _ = scene_thread_proxy.sender.send(MainToSceneMsg::SetDrawableSize(display.size()));

demo/magicleap/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ use pathfinder_renderer::options::RenderTransform;
4848
use pathfinder_resources::ResourceLoader;
4949
use pathfinder_resources::fs::FilesystemResourceLoader;
5050
use pathfinder_simd::default::F32x4;
51-
use pathfinder_svg::BuiltSVG;
51+
use pathfinder_svg::SVGScene;
5252

5353
use std::collections::HashMap;
5454
use std::ffi::CStr;
@@ -135,7 +135,7 @@ pub unsafe extern "C" fn magicleap_pathfinder_demo_load(app: *mut c_void, svg_fi
135135

136136
struct MagicLeapPathfinder {
137137
renderers: HashMap<(EGLSurface, EGLDisplay), Renderer<GLDevice>>,
138-
svgs: HashMap<String, BuiltSVG>,
138+
svgs: HashMap<String, SVGScene>,
139139
resources: FilesystemResourceLoader,
140140
}
141141

@@ -185,7 +185,7 @@ pub unsafe extern "C" fn magicleap_pathfinder_render(pf: *mut c_void, options: *
185185
let svg_filename = CStr::from_ptr(options.svg_filename).to_string_lossy();
186186
let data = resources.slurp(&*svg_filename).unwrap();
187187
let tree = Tree::from_data(&data, &UsvgOptions::default()).unwrap();
188-
BuiltSVG::from_tree(tree)
188+
SVGScene::from_tree(tree)
189189
});
190190

191191
let mut width = 0;

svg/src/lib.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use usvg::{Transform as UsvgTransform, Tree, Visibility};
3737

3838
const HAIRLINE_STROKE_WIDTH: f32 = 0.0333;
3939

40-
pub struct BuiltSVG {
40+
pub struct SVGScene {
4141
pub scene: Scene,
4242
pub result_flags: BuildResultFlags,
4343
pub clip_paths: HashMap<String, ClipPathId>,
@@ -60,18 +60,18 @@ bitflags! {
6060
}
6161
}
6262

63-
impl BuiltSVG {
63+
impl SVGScene {
6464
// TODO(pcwalton): Allow a global transform to be set.
6565
#[inline]
66-
pub fn from_tree(tree: &Tree) -> BuiltSVG {
67-
BuiltSVG::from_tree_and_scene(tree, Scene::new())
66+
pub fn from_tree(tree: &Tree) -> SVGScene {
67+
SVGScene::from_tree_and_scene(tree, Scene::new())
6868
}
6969

7070
// TODO(pcwalton): Allow a global transform to be set.
71-
pub fn from_tree_and_scene(tree: &Tree, scene: Scene) -> BuiltSVG {
71+
pub fn from_tree_and_scene(tree: &Tree, scene: Scene) -> SVGScene {
7272
// TODO(pcwalton): Maybe have a `SVGBuilder` type to hold the clip path IDs and other
73-
// transient data separate from `BuiltSVG`?
74-
let mut built_svg = BuiltSVG {
73+
// transient data separate from `SVGScene`?
74+
let mut built_svg = SVGScene {
7575
scene,
7676
result_flags: BuildResultFlags::empty(),
7777
clip_paths: HashMap::new(),

utils/convert/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::fs::File;
22
use std::io::{Read, BufWriter};
33
use std::error::Error;
44
use std::path::PathBuf;
5-
use pathfinder_svg::BuiltSVG;
5+
use pathfinder_svg::SVGScene;
66
use pathfinder_export::{Export, FileFormat};
77
use usvg::{Tree, Options};
88

@@ -13,7 +13,7 @@ fn main() -> Result<(), Box<dyn Error>> {
1313

1414
let mut data = Vec::new();
1515
File::open(input)?.read_to_end(&mut data)?;
16-
let svg = BuiltSVG::from_tree(&Tree::from_data(&data, &Options::default()).unwrap());
16+
let svg = SVGScene::from_tree(&Tree::from_data(&data, &Options::default()).unwrap());
1717

1818
let scene = &svg.scene;
1919
let mut writer = BufWriter::new(File::create(&output)?);

0 commit comments

Comments
 (0)