Skip to content

Commit

Permalink
Merge pull request #82 from rust-skia/svg
Browse files Browse the repository at this point in the history
SVG Support
  • Loading branch information
Brooooooklyn committed Apr 17, 2019
2 parents 0705887 + 18e0d12 commit 38396d0
Show file tree
Hide file tree
Showing 14 changed files with 205 additions and 36 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -97,7 +97,7 @@ We do support most of the SkCanvas, SkPaint, and SkPath and related APIs and are
- [x] Basic Drawing: Surface, Canvas, Paint, Path.
- [x] Basic Effects and Shaders.
- [x] PDF
- [ ] SVG
- [x] SVG
- [ ] Animation
- [x] Vulkan
- [x] OpenGL
Expand Down
20 changes: 9 additions & 11 deletions azure-pipelines-template.yml
Expand Up @@ -5,16 +5,20 @@ jobs:
stable:
toolchain: stable
features: ''
exampleArgs: '--driver cpu --driver pdf'
beta:
toolchain: beta
features: ''
stable-vulkan:
toolchain: stable
features: 'vulkan'
stable-svg:
toolchain: stable
features: 'svg'
exampleArgs: '--driver svg'
variables:
platform: ${{ parameters.platform }}
image: ${{ parameters.image }}
exampleArgs: '--driver cpu --driver pdf'
pool:
vmImage: $(image)

Expand Down Expand Up @@ -62,18 +66,12 @@ jobs:
- script: cd skia-safe && cargo test --release --features "$(features)" -vv
displayName: Test skia-safe

- ${{ if ne(parameters.platform, 'Windows') }}:
- script: cargo run --release --example skia-org ${BUILD_ARTIFACTSTAGINGDIRECTORY}/skia-org $(exampleArgs)
displayName: Generate skia-org Example Images
condition: eq(variables['features'], '')

- ${{ if eq(parameters.platform, 'Windows') }}:
- script: cargo run --release --example skia-org %BUILD_ARTIFACTSTAGINGDIRECTORY%/skia-org $(exampleArgs)
displayName: Generate skia-org Example Images
condition: eq(variables['features'], '')
- script: cd skia-safe && cargo run --release --features "$(features)" --example skia-org "$(Build.ArtifactStagingDirectory)/skia-org" $(exampleArgs)
displayName: Generate skia-org Example Images
condition: ne(variables['exampleArgs'], '')

- task: PublishBuildArtifacts@1
inputs:
pathtoPublish: '$(Build.ArtifactStagingDirectory)/skia-org'
artifactName: 'skia-org-examples-$(platform)-$(toolchain)'
condition: eq(variables['features'], '')
condition: ne(variables['exampleArgs'], '')
2 changes: 2 additions & 0 deletions skia-bindings/CMakeLists.txt
Expand Up @@ -7,5 +7,7 @@ include_directories("skia/include/core")
include_directories("skia/include/docs")
include_directories("skia/include/effects")
include_directories("skia/include/gpu")
include_directories("skia/include/svg")
include_directories("skia/src/xml")

add_library(skiabindings src/bindings.cpp)
1 change: 1 addition & 0 deletions skia-bindings/Cargo.toml
Expand Up @@ -10,6 +10,7 @@ include = [ "Cargo.toml", "build.rs", "src/**/*.cpp", "src/lib.rs", "skia/includ
[features]
default = []
vulkan = []
svg = []

[dependencies]

Expand Down
33 changes: 24 additions & 9 deletions skia-bindings/build.rs
Expand Up @@ -5,7 +5,7 @@ extern crate cc;

use std::env;
use std::fs;
use std::path::PathBuf;
use std::path::{PathBuf, Path};
use std::process::{Command, Stdio};
use bindgen::EnumVariation;
use cc::Build;
Expand All @@ -24,6 +24,9 @@ mod build {

/// Build with Vulkan support?
pub const VULKAN: bool = cfg!(feature = "vulkan");

/// Build with SVG support?
pub const SVG: bool = cfg!(feature = "svg");
}

fn main() {
Expand Down Expand Up @@ -72,7 +75,8 @@ fn main() {

let mut args: Vec<(&str, String)> = vec![
("is_official_build", if build::SKIA_RELEASE { yes() } else { no() }),
("skia_use_expat", no()),
("skia_use_expat", if build::SVG { yes() } else { no() }),
("skia_use_system_expat", no()),
("skia_use_icu", no()),
("skia_use_system_libjpeg_turbo", no()),
("skia_use_system_libpng", no()),
Expand Down Expand Up @@ -175,15 +179,14 @@ fn main() {
.success(), "`ninja` returned an error, please check the output for details.");

let current_dir = env::current_dir().unwrap();
let current_dir_name = current_dir.to_str().unwrap();

println!("cargo:rustc-link-search={}", &skia_out_dir);
cargo::add_link_libs(&["static=skia", "static=skiabinding"]);
cargo::add_link_lib("static=skia");

bindgen_gen(&current_dir_name, &skia_out_dir)
bindgen_gen(&current_dir, &skia_out_dir)
}

fn bindgen_gen(current_dir_name: &str, skia_out_dir: &str) {
fn bindgen_gen(current_dir: &Path, skia_out_dir: &str) {

let mut builder = bindgen::Builder::default()
.generate_inline_functions(true)
Expand Down Expand Up @@ -225,9 +228,11 @@ fn bindgen_gen(current_dir_name: &str, skia_out_dir: &str) {
.whitelist_type("SkGradientShader")
.whitelist_type("SkPerlinNoiseShader")
.whitelist_type("SkTableColorFilter")

.whitelist_type("SkDocument")

.whitelist_type("SkDynamicMemoryWStream")
.whitelist_type("SkXMLStreamWriter")

.whitelist_type("GrGLBackendState")

Expand All @@ -251,9 +256,9 @@ fn bindgen_gen(current_dir_name: &str, skia_out_dir: &str) {
for include_dir in fs::read_dir("skia/include").expect("Unable to read skia/include") {
let dir = include_dir.unwrap();
cargo::add_dependent_path(dir.path().to_str().unwrap());
let include_path = format!("{}/{}", &current_dir_name, &dir.path().to_str().unwrap());
builder = builder.clang_arg(format!("-I{}", &include_path));
cc_build.include(&include_path);
let include_path = current_dir.join(dir.path());
builder = builder.clang_arg(format!("-I{}", include_path.display()));
cc_build.include(include_path);
}

if build::VULKAN {
Expand All @@ -263,6 +268,16 @@ fn bindgen_gen(current_dir_name: &str, skia_out_dir: &str) {
builder = builder.clang_arg("-DSKIA_IMPLEMENTATION=1");
}

if build::SVG {
cc_build.define("SK_XML", "1");
builder = builder.clang_arg("-DSK_XML");

// SkXMLWriter.h
let include_path = current_dir.join(Path::new("skia/src/xml"));
builder = builder.clang_arg(format!("-I{}", include_path.display()));
cc_build.include(include_path);
}

if build::SKIA_RELEASE {
cc_build.define("NDEBUG", "1");
builder = builder.clang_arg("-DNDEBUG=1")
Expand Down
22 changes: 21 additions & 1 deletion skia-bindings/src/bindings.cpp
Expand Up @@ -38,14 +38,18 @@
#include "GrContext.h"
// gpu/gl
#include "gl/GrGLInterface.h"
#include "SkRect.h"

#if defined(SK_VULKAN)

#include "vk/GrVkVulkan.h"
#include "vk/GrVkTypes.h"
#include "vk/GrVkBackendContext.h"
#include "GrBackendSurface.h"
#endif

#if defined(SK_XML)
#include "SkSVGCanvas.h"
#include "SkXMLWriter.h"
#endif

template<typename T>
Expand Down Expand Up @@ -1358,3 +1362,19 @@ extern "C" bool C_GrVkImageInfo_Equals(const GrVkImageInfo* lhs, const GrVkImage
}

#endif

#if defined(SK_XML)

// Note, we can't use the SkWStream* implementation, because its implementation creates
// an SkXMLWriter and destroys it before returning (this bug is fixed in Skia master, and
// so may be available in a future update).

extern "C" SkCanvas* C_SkSVGCanvas_Make(const SkRect* bounds, SkXMLWriter* writer) {
return SkSVGCanvas::Make(*bounds, writer).release();
}

extern "C" void C_SkXMLStreamWriter_destruct(SkXMLStreamWriter* self) {
self->~SkXMLStreamWriter();
}

#endif
1 change: 1 addition & 0 deletions skia-safe/Cargo.toml
Expand Up @@ -7,6 +7,7 @@ edition = "2018"
[features]
default = []
vulkan = ["skia-bindings/vulkan"]
svg = ["skia-bindings/svg"]

[dependencies]
bitflags = "1.0.4"
Expand Down
45 changes: 34 additions & 11 deletions skia-safe/examples/skia-org/main.rs
Expand Up @@ -52,10 +52,13 @@ pub(crate) mod artifact {
}

pub enum CPU {}
pub enum PDF {}
#[cfg(feature = "svg")]
pub enum SVG {}

pub enum OpenGL {}
#[cfg(feature = "vulkan")]
pub enum Vulkan {}
pub enum PDF {}

impl DrawingDriver for CPU {

Expand All @@ -79,6 +82,19 @@ pub(crate) mod artifact {
}
}

#[cfg(feature = "svg")]
impl DrawingDriver for SVG {
const NAME: &'static str = "svg";

fn draw_image<F>(size: (i32, i32), path: &PathBuf, name: &str, func: F) -> () where F: Fn(&mut Canvas) -> () {
use skia_safe::Rect;
let mut canvas = skia_safe::svg::Canvas::new(Rect::from_size(size));
func(&mut canvas);
let data = canvas.end();
write_file(data.bytes(), path, name, "svg");
}
}

impl DrawingDriver for OpenGL {

const NAME: &'static str = "opengl";
Expand Down Expand Up @@ -195,7 +211,7 @@ fn main() {
.arg(Arg::with_name(DRIVER)
.long(DRIVER)
.takes_value(true)
.possible_values(get_possible_drivers())
.possible_values(get_possible_drivers().as_slice())
.multiple(true)
.help("In addition to the CPU, render with the given driver.")
)
Expand Down Expand Up @@ -225,6 +241,13 @@ fn main() {
draw_all::<artifact::PDF>(&out_path);
}

#[cfg(feature = "svg")]
{
if drivers.contains(&artifact::SVG::NAME) {
draw_all::<artifact::SVG>(&out_path);
}
}

if drivers.contains(&artifact::OpenGL::NAME) {
let context =
GLContext::<NativeGLContext>::create(
Expand Down Expand Up @@ -262,13 +285,13 @@ fn main() {
}
}

#[cfg(not(feature = "vulkan"))]
fn get_possible_drivers() -> &'static [&'static str] {
["cpu", "pdf", "opengl"].as_ref()
}

#[cfg(feature = "vulkan")]
fn get_possible_drivers() -> &'static [&'static str] {
["cpu", "pdf", "opengl", "vulkan"].as_ref()
fn get_possible_drivers() -> Vec<&'static str> {
let mut drivers = vec!["cpu", "pdf", "opengl"];
if cfg!(feature = "vulkan") {
drivers.push("vulkan")
}
if cfg!(feature = "svg") {
drivers.push("svg");
}
drivers
}

2 changes: 1 addition & 1 deletion skia-safe/src/core/canvas.rs
Expand Up @@ -145,7 +145,7 @@ impl NativeAccess<SkCanvas> for Canvas {
}
}

/// This is the type representing a canvas that is owned and destructed
/// This is the type representing a canvas that is owned and dropped
/// when it goes out of scope _and_ is bound to a the lifetime of another
/// instance. Function resolvement is done via the Deref trait.
pub struct OwnedCanvas<'lt>(*mut Canvas, PhantomData<&'lt ()>);
Expand Down
2 changes: 1 addition & 1 deletion skia-safe/src/interop/stream.rs
Expand Up @@ -13,7 +13,7 @@ pub type DynamicMemoryWStream = Handle<SkDynamicMemoryWStream>;
impl NativeDrop for SkDynamicMemoryWStream {
fn drop(&mut self) {
unsafe {
C_SkDynamicMemoryWStream_destruct(self)
C_SkDynamicMemoryWStream_destruct(self);
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions skia-safe/src/lib.rs
Expand Up @@ -4,6 +4,8 @@ mod docs;
mod effects;
mod interop;
pub mod gpu;
#[cfg(feature = "svg")]
pub mod svg;

#[macro_use]
extern crate bitflags;
Expand Down
2 changes: 1 addition & 1 deletion skia-safe/src/prelude.rs
Expand Up @@ -231,7 +231,7 @@ impl<H, N> IntoHandle<H> for N
}

/// Wraps a native type that can be represented as a value
/// and needs a destructor.
/// and needs a Drop trait.
#[repr(transparent)]
pub struct Handle<N: NativeDrop>(N);

Expand Down
3 changes: 3 additions & 0 deletions skia-safe/src/svg.rs
@@ -0,0 +1,3 @@
mod canvas;
pub use self::canvas::*;

0 comments on commit 38396d0

Please sign in to comment.