Code Monkey home page Code Monkey logo

rust-skia's Introduction

Safe Rust bindings for the Skia Graphics Library.

crates.io license Windows QA Linux QA macOS QA

Skia Submodule Status: chrome/m124 (upstream changes, our changes).

About

This project provides up to date safe bindings that bridge idiomatic Rust with Skia's C++ API on desktop and mobile platforms, including GPU rendering backends for Vulkan, Metal, OpenGL, and Direct3D.

Status

Documentation

Because we can't build on docs.rs, the cargo doc output for skia-safe is manually created and uploaded to rust-skia.github.io.

We (slowly) add more documentation by converting Skia's Doxygen comments to Rust.

Crate

A prerelease crate is available from crates.io and invoking

cargo add skia-safe

in your project's folder should get you started. And you might want to take a look at the gl-window example if you plan to render to a window.

On Linux you may run into trouble when OpenSSL libraries are missing. On Debian and Ubuntu they can be installed with:

sudo apt-get install pkg-config libssl-dev

For other platforms, more information is available at the OpenSSL crate documentation.

Platform Support, Build Targets, and Prebuilt Binaries

Because building Skia takes a lot of time and needs tools that may be missing, the skia-bindings crate's build.rs attempts to download prebuilt binaries from the skia-binaries repository using the curl command line tool.

Platform Binaries
Windows x86_64-pc-windows-msvc
Linux Ubuntu 16+
CentOS 7, 8
x86_64-unknown-linux-gnu
aarch64-unknown-linux-gnu
macOS x86_64-apple-darwin
aarch64-apple-darwin
Android aarch64-linux-android
x86_64-linux-android
iOS aarch64-apple-ios
x86_64-apple-ios
WebAssembly wasm32-unknown-emscripten

Wrappers & Codecs & Supported Features

The supported wrappers, Skia codecs, and additional Skia features are documented in the skia-safe package's readme. Prebuilt binaries are available for most feature combinations.

Building

If the target platform or feature configuration is not available as a prebuilt binary, skia-bindings' build.rs will try to build Skia and generate the Rust bindings.

To prepare for that, LLVM and Python 3 are needed:

LLVM

We recommend the version that comes preinstalled with your platform, or, if not available, the latest official LLVM release. To see which version of LLVM/Clang is installed on your system, use clang --version.

Python 3

The build script probes for python --version and python3 --version and uses the first one that looks like a version 3 executable for building Skia.

On macOS

  • Install the Command Line Tools for Xcode with

    xcode-select --install

    or download and install the Command Line Tools for Xcode.

  • macOS Mojave only: install the SDK headers:

    sudo open /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg

    If not installed, the Skia build may fail to build SkJpegUtility.cpp and the binding generation will fail with 'TargetConditionals.h' file not found . Also note that the Command Line Tools and SDK headers should be reinstalled after an update of XCode.

  • As an alternative to Apple's XCode LLVM, install LLVM via brew install llvm or brew install llvm and then set PATH, CPPFLAGS, and LDFLAGS like instructed.

    If the environment variables are not set, bindgen will most likely use the wrong libclang.dylib and cause confusing compilation errors (see #228).

On Windows

  • Have the latest versions of git and Rust ready.

  • Install Visual Studio 2022 Build Tools or one of the other IDE editions. If you installed the IDE, make sure that the Desktop Development with C++ workload is installed.

  • Install the latest LLVM distribution.

    If the environment variable LLVM_HOME is not defined, the build script will look for LLVM installations located at C:\Program Files\LLVM\, C:\LLVM\, and %USERPROFILE%\scoop\apps\llvm\current\.

  • MSYS2:

    • Install Python 3 with pacman -S python.
  • Windows Shell (Cmd.exe):

  • Install and select the MSVC toolchain:

    rustup default stable-msvc

On Linux

Ubuntu 16+

  • LLVM/Clang should be available already, if not, install the latest version.
  • If OpenGL libraries are missing, install the drivers for you graphics card, or a mesa package like libgl1-mesa-dev.
  • For X11, build with feature x11.
  • For Wayland, install libwayland-dev and build with the wayland feature.

CentOS 7

CentOS 8

  • Install the following packages:

    sudo yum install gcc openssl-devel libX11-devel python3 clang fontconfig-devel mesa-libGL-devel
  • Set /usr/bin/python3 as the default python command:

    sudo alternatives --set python /usr/bin/python3

For Android

Cross compilation to Android is supported for targeting 64 bit ARM and Intel x86 architectures (aarch64 and x86_64) for API Level 26 (Oreo, Android 8):

We recommend to use cargo apk, but if that does not work for you, following are some instructions on how we build Android targets with GitHub Actions:

For example, to compile for aarch64:

  1. Install the Rust target:
    rustup target install aarch64-linux-android
  2. Download the r25b NDK (or newer) for your host architecture and unzip it.
  3. Compile your package for the aarch64-linux-android target:

On macOS:

export ANDROID_NDK=:path-to-android-ndk-r25b
export PATH=$PATH:$ANDROID_NDK/toolchains/llvm/prebuilt/darwin-x86_64/bin
export CC_aarch64_linux_android=aarch64-linux-android26-clang
export CXX_aarch64_linux_android=aarch64-linux-android26-clang++
export AR_aarch64_linux_android=llvm-ar
export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=aarch64-linux-android26-clang

cargo build -vv --target aarch64-linux-android

We don't support Apple's Clang to build for Android on macOS, so you need to install LLVM and set the PATH like instructed.

On Linux:

export ANDROID_NDK=:path-to-android-ndk-r25b
export PATH=$PATH:$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin
export CC_aarch64_linux_android=aarch64-linux-android26-clang
export CXX_aarch64_linux_android=aarch64-linux-android26-clang++
export AR_aarch64_linux_android=llvm-ar
export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=aarch64-linux-android26-clang

cargo build -vv --target aarch64-linux-android

On Windows the Android NDK Clang executable must be invoked through .cmd scripts:

export ANDROID_NDK=:path-to-android-ndk-r25b
export PATH=$PATH:$ANDROID_NDK/toolchains/llvm/prebuilt/windows-x86_64/bin
export CC_aarch64_linux_android=aarch64-linux-android26-clang.cmd
export CXX_aarch64_linux_android=aarch64-linux-android26-clang++.cmd
export AR_aarch64_linux_android=llvm-ar
export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=aarch64-linux-android26-clang.cmd

cargo build -vv --target aarch64-linux-android

Notes:

  • At the time of this writing, the Rust compiler will automatically add a -lgcc argument to the linker, which results in a linker error, because newer NDKs do not contain libgcc.a anymore. To fix this, we created a workaround and copy libunwind.a over to libgcc.a. Cargo apk does something similar.
  • The CARGO_TARGET_${TARGET}_LINKER environment variable name needs to be all uppercase.
  • In some older shells (for example macOS High Sierra), environment variable replacement can not be used when the variable was defined on the same line. Therefore the ANDROID_NDK variable must be defined before it's used in the PATH variable.
  • Rebuilding skia-bindings with a different target may cause linker errors, in that case touch skia-bindings/build.rs will force a rebuild (#10).

For iOS

Compilation to iOS is supported on macOS targeting the iOS simulator (--target x86_64-apple-ios) and 64 bit ARM devices (--target aarch64-apple-ios). The ARM64e architecture is not supported yet.

For WebAssembly

Install emscripten version 3.1.1 or superior. In the examples below, we assume emsdk version 3.1.1 was installed with asdf.

Build with the wasm32-unknown-emscripten target (wasm32-unknown-unknown is unsupported because it is fundamentally incompatible with linking C code:

export EMSDK=~/.asdf/installs/emsdk/3.1.1
export EMCC_CFLAGS="-s ERROR_ON_UNDEFINED_SYMBOLS=0"

cargo build --target wasm32-unknown-emscripten

The EMSDK environment variable must be set to the root of your emscripten SDK.

In EMCC_CFLAGS, -s ERROR_ON_UNDEFINED_SYMBOLS is a workaround to build with emscripten > 2.0.9.

If you want to enable WebGL, you will also have to set MAX_WEBGL_VERSION=2:

export EMSDK=~/.asdf/installs/emsdk/3.1.1
export EMCC_CFLAGS="-s ERROR_ON_UNDEFINED_SYMBOLS=0 -s MAX_WEBGL_VERSION=2"

cargo build --target wasm32-unknown-emscripten --features gl

On MacOS there is a problem with the OS version of ar so you will have to install the GNU version from homebrew:

brew install binutils

Then prepend binutils path for the build. The path depends on your CPU architecture, and can be retrieved with brew info binutils. Here is an example for Apple silicon:

export EMSDK=~/.asdf/installs/emsdk/3.1.1
export EMCC_CFLAGS="-s ERROR_ON_UNDEFINED_SYMBOLS=0"
export PATH="/opt/homebrew/opt/binutils/bin:$PATH"

cargo build --target wasm32-unknown-emscripten

Skia

For situations in which Skia does not build or needs to be configured differently, we support some customization support in skia-bindings/build.rs. For more details take a look at the README of the skia-bindings package.

Please share your build experience so that we can try to automate the build and get to the point where cargo build is sufficient to build the bindings including Skia, and if that is not possible, clearly prompts to what's missing.

Example Applications

icon

The icon example generates the rust-skia icon in the current directory. It computes the position of all the gear teeth etc. based on parameters such as the number of teeth and wheel radius.

If you were able to build the project, run

cargo run --example icon 512

It has a single optional parameter which is the size in pixels for the PNG file. Without parameters, it’ll produce PNG frames for the animated version.

skia-org

The other examples are taken from Skia's website and ported to the Rust API.

cargo run -- [OUTPUT_DIR]

to generate some Skia drawn PNG images in the directory OUTPUT_DIR. To render with OpenGL, use

cargo run -- [OUTPUT_DIR] --driver opengl

And to show the drivers that are supported

cargo run -- --help

gl-window

An example that opens an OpenGL Window and draws the rust-skia icon with skia-safe (contributed by @nornagon).

cargo run --example gl-window --features gl

On Linux the feature x11 needs to be enabled:

cargo run --example gl-window --features gl,x11

Example Images

Fill, Radial Gradients, Stroke, Stroke with Gradient, Transparency: Rust-skia icon

Fill, Stroke, Text:

Fill, Stroke, Text

Sweep Gradient:

Sweep Gradient

Dash Path Effect:

Dash Path Effect

For more, you may take a look at the rust-skia.github.io repository.

This project needs contributions!

If you'd like to help with the bindings, take a look at the Wiki to get started and create an issue to prevent duplicate work. For smaller tasks, grep for "TODO"s in the source code. And for heroic work, check out the label help wanted. And if you like to help making the Rust API nicer to use, look out for open issues with the label api ergonomics.

More details can be found at CONTRIBUTING.md.

Notable Contributions

  • Denis Kolodin (@DenisKolodin) contributed build support for Android.
  • Alberto González Palomo (@AlbertoGP) designed the Rust-Skia Logo and the example program that renders it.
  • Luper Rouch (@flupke, sponsored by Jitter) added build support for the wasm32-unknown-emscripten target.
  • Osei Fortune (@triniwiz) contributed rendering SVG files.

Maintainers

License

MIT

rust-skia's People

Contributors

antonsmetanin avatar brooooooklyn avatar coderedart avatar ctrlcctrlv avatar dependabot-preview[bot] avatar dependabot[bot] avatar eira-fransham avatar eywek avatar fledgexu avatar flupke avatar freqmod avatar hack3ric avatar hpmason avatar j4qfrost avatar katyo avatar kethku avatar marc2332 avatar messense avatar namse avatar pragmatrix avatar romanzes avatar samizdatco avatar stringke avatar superwhiskers avatar syrel avatar tfemby avatar tomb-msft avatar triniwiz avatar tronical avatar upsuper avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rust-skia's Issues

Try to avoid prefixes for wrapped, nested C++ types.

Currently we do represent a number of nested C++ types by prefixing them with the class they are contained in. For example, SkPaint::Style is represented as PaintStyle, but I would rather prefer to use it as Paint::Style, which is AFAIK not possible in Rust, because a module can not be defined with the same name as a type.

So, as an alternative, I'd then prefer paint::Style, which feels a bit more like idiomatic Rust.

Our Skia file structure defines Paint inside a module name paint.rs which we do not export, and - as I just found out - if that is the case, it seems to be possible to export a nested module with the same name, for example:

File core/paint.rs:

struct Paint {};

pub mod paint {
    enum Style {};
}

In core.rs:

// makes core::paint accessible inside the crate (required for `lib.rs`).
pub(crate) mod paint;
// makes core::paint::Paint accessible as core::Paint, but _does not_ make the nested `paint` module accessible in `core`, because it would conflict with the already existing one.
pub use self::paint::*;

In lib.rs

// makes core::Paint accessible as crate::Paint and `core::paint` (the file) as `crate::paint`.
pub use crate::core::*;
// makes core::paint::paint accessible as crate::paint and so makes the nested paint::Style accessible.
pub use crate::core::paint::paint;

with the result that Paint is accessible via skia_safe::Paint and paint::Style via skia_safe::paint::Style.

So instead of importing use skia_safe::{Paint, PaintStyle} we can now use use skia_safe::{Paint, paint} which imports Paint, and the module that contains all nested types.

I am kind of a purist when it comes to naming things, which means that I am not sure if this is actually a change that leads to an improvement for anyone except me. Here is an example taken vom skpaint_overview.rs:

Before:

    use skia_safe::{Paint, PaintStyle, Color}
    ...
    paint1.set_anti_alias(true);
    paint1.set_color(Color::from_rgb(255, 0, 0));
    paint1.set_style(PaintStyle::Fill);

    paint2.set_anti_alias(true);
    paint2.set_color(Color::from_rgb(0, 136, 0));
    paint2.set_style(PaintStyle::Stroke);
    paint2.set_stroke_width(3.0);

After:

    use skia_safe::{Paint, paint, Color}
    ...
    paint1.set_anti_alias(true);
    paint1.set_color(Color::from_rgb(255, 0, 0));
    paint1.set_style(paint::Style::Fill);

    paint2.set_anti_alias(true);
    paint2.set_color(Color::from_rgb(0, 136, 0));
    paint2.set_style(paint::Style::Stroke);
    paint2.set_stroke_width(3.0);

One obvious advantage would be that when a type contains multiple nested types, they don't need to be imported individually.

A disadvantage may be the metal step one must make to locate nested types through a module that is named as the containing type in lowercase.

Update: While trying to actually implement this I am hitting internal compilers error with Rust 1.34 (achievement unlocked, 🥇). So I guess this is blocked for now anyways.

URLs in PDF are missing the last character

I'm using the following code to add a clickable URL area to a PDF I'm rendering:

    fn add_url(&mut self, rect: &SkRect, url: &str) {
        self.canvas.draw_annotation(
            rect.to_skia(),
            "SkAnnotationKey_URL",
            &mut Data::new_copy(url.as_bytes())
        );
    }

However, the clickable area in the resulting PDF is missing the last character. For example, if url was "http://google.com", it would become "http://google.co".

Reenable binding layout tests and compare the failures against what we can tolerate.

Right now, the bindgen generated tests result in a number of failed layout tests we have to tolerate. For the types related, skia-safe does not access their members and never allocates memory for them in Rust.

But the layout of these types depend on the platform and probably on the C++ compiler that is used, so we must provide a facility that runs these tests automatically and compares the result with our expectations.

Safe Rust API Conventions & Implementation Strategy

I finally got around to port the canvas example to a safe API according to my limited knowledge of Rust.

What I learned so far is, that the bindgen bindings are not always usable, specifically when C++ classes, like smartpointers sk_sp are returned (or passed?) by value, the calling conventions break apart, so all C++ methods that utilize that, need to be wrapped before the can be used in Rust.

This ticket should clarify the implementation strategy for the safe Rust API and eventually form a wiki page.

C Naming conventions

  • The extern "C" functions that we need to add to the bindings should begin with extern "C" C_, this way we can whitelist them all with one match pattern C_.* in bindgen. They include the class / struct name they are interfacing with and then the method's name. Name parts are separated by _.

Rust naming conventions

I would like to avoid any abbrevations that are appearing in struct names, like Sk or something like that. For the skia binding Surface, for example, I would prefer to use the name skia::Surface. A GrContext should be named GraphicsContext or graphics::Context.

Static "constructor" functions that begin in Skia with Make should begin with new_ in Rust, abbrevations that indicate function parameter variants may be used (Rect::new_iwh(), (i)int (w)idth (h)eight for example) . In general, the naming should be very similar to the original API but when possible be Rust idiomatic, so that a Rust user can use the original Skia documentation without much mental translation.

Smartpointers / Ref counting base classes

  • Classes with reference counters that need to be used in Rust are transported as native pointers, the function .release() can be used for that.
  • If a pointer derives from a smartpointer base class, like SkRefCntBase or SkNVRefCnt, the unref() function has to be called in the related Drop trait. If we need to use smart pointers in Rust, we can interface with ref() and unref() later on, although I would like to avoid that at first and see how far we can go with Rust's ownership system.

For example:

extern "C" SkSurface* C_SkSurface_MakeRasterN32Premul(int width, int height, const SkSurfaceProps* surfaceProps) {
    return SkSurface::MakeRasterN32Premul(width, height, surfaceProps).release();
}

In Rust:

pub struct Surface {
    native: *mut SkSurface
}

impl Drop for Surface {
    fn drop(&mut self) {
        unsafe { (*self.native)._base._base.unref() }
    }
}

impl Surface {
    pub fn new_raster_n32_premul(width: i32, height: i32) -> Surface {
        Surface {
            native: unsafe { C_SkSurface_MakeRasterN32Premul(width, height, ptr::null()) }
        }
    }
}

C++ Structures (like SkPaint and SkPath) for which the constructor / destructor must be called.

Here bindgen generates new() and destruct() functions. If possible, I would prefer not to use pointers for these in Rust. From what I can see now, the new() function can be called from Rust, but I had no luck linking the destruct() functions. May be this is an error in bindgen or some tree shaking process removes them. So to fix that we can interface a destructor like this:

extern "C" void C_SkPaint_destruct(const SkPaint* self) {
    self->~SkPaint();
}

Overloaded Functions

A lot of Skia functions offer overloads with different abstraction levels, so for example, a draw_rect function may exist with an overloaded function that takes

  • 4 scalar values.
  • 2 points.
  • a Rect struct.

Since Rust does not support overloading functions, I see the following options:

  • We support each of them, but name the function differently.

  • We support a rich set of .into traits that convert more granular types into more abstract types. For example a Rect supports the following From traits (implicitly providing the .into() function):

    • From<(f32, f32, f32, f32)>
    • From<(Point, Point)>

    So a draw_rect can be called with draw_rect((x1, y1, x2, y2).into()), or draw_rect((p1, p2).into()) or just draw_rect(rect).

    ... I am not sure if this even works, or if that is even a Rust idiomatic way to support something like overloaded functions.

  • Use enums for the variants?

Enumeration constants.

TBD

Default parameters.

TBD: Option, Builder pattern?

Try to provide pre-built binaries of Skia.

@Brooooooklyn Can you outline your plan on how you want to do this exactly?

I see these two options (as discussed briefly before):

  1. Build them on Azure, deploy them to some hosting service, where they can be stored permanently, and then download them in via build.rs for cargo builds that match the hash of our repository and the platform.
  2. Include them into the crate and use the facility provided here: https://doc.rust-lang.org/cargo/reference/build-scripts.html#overriding-build-scripts. For that I assume we would need to provide different crates for different platforms (we could name them skia-[platform]-sys (#14)).

Note that I think it's absolutely necessary to provide reproducible builds and not binaries that are built on our machines, because I wouldn't trust anyone else's binaries, so why should anyone trust us.

LLVM 8 binding generation fails on macOS

This happens on the Azure build server which currently runs on Mac OS X 10.13 and on Mojave 10.14 when LLVM 8 is installed via brew install llvm.

rust-skia/skia-bindings/skia/include/private/../private/SkOnce.h:11:10: fatal error: 'atomic' file not found

Not sure why, the Skia build is successful.

gpu::SurfaceOrigin::BottomLeft / TopLeft inverted

It appears that the values of skia_safe::gpu::SurfaceOrigin::BottomLeft and skia_safe::gpu::SurfaceOrigin::TopLeft are the wrong way round.

I want TopLeft and was puzzled about the positions of what I drew on a canvas. On a whim I tried BottomLeft, and the origin behaves as though it is TopLeft.

I'm depending on commit 38396d0.

(Awesome project by the way.)

Build with feature `vulkan` on the CI.

A recent PR damaged the build of the skia-org example when the feature vulkan is enabled in master (again).

I suggest to extend the CI matrix with the feature vulkan.

Don't manage the memory of Skia types with interior pointers in Rust.

We are wrapping opaque Skia types with Handle<T> and NativeTransmutable<T> by utilizing Rust's memory management for performance reasons. Some of them may contain pointers that point into itself or to other Rust allocated types, which is unsafe because Rust moves them to other memory locations if needed. Instances of these types need to be guaranteed to never move after they were initialized.

I suggest to tackle this the following way:

  • Locate all types that contain pointers wrapped with Handle<T> or NativeTransmutable<T>.
  • If a type is potentially unsafe, write a test case that most likely crashes by forcing Rust to move an instance before it's being used.
  • Make these test cases pass by allocating and freeing them on the Skia's side and wrapping them into a pointer in Rust.

Currently, I have no idea how many of these potential unsafe wrapper types do exist.

Rust-format skia-safe, add an Azure job to check the formatting, and also verify all code with clippy.

Although I don't always agree with the output of rustfmt, I think we should use it throughout the repository. IDE support should be readily available and the formatting process will also clean up a number of ugly leftovers (for example automatically generated use constructs).

Also I would like to check the formatting with Azure running cargo fmt -- --check. And while we are at it, do a verification run with clippy, too. I bet this will be annoying sometimes, but overall think that the quality of the repository will improve.

Because of the cruel effects on the git commit history and pending merges, this is blocked until all open PRs are merged into master, so it will be most likely the next thing to do after the repository is updated to the Chrome 75 branch (#86).

BTW: With #97 landing in master, skia-bindings is already formatted with rustfmt.

Build, verify, and deploy cargo crates of skia-bindings and skia-safe to rust-skia.

Now that #97 has landed, the next step to prepare for official crate releases is to build and verify the crates on the CI server and release them to the skia-binariesrust-skia repository. The resulting .crate files are platform and feature independent, so we can create and verify them without an initial build in a separate Azure Pipelines job, but I would rather create them after a binaries package was created so that the verification already pulls in the previously built binary from the regular build and indirectly so tests the binary package downloader with each CI build.

For a first setup, I think we should limit the crate generation to "Linux stable" for now.

Rust-format bindings.rs on the CI server.

Seems that the rustfmt that bindgen invokes, does not work on the CI. I am often opening bindings.rs for taking a look of some function's signatures and would appreciate if it's formatted properly. So even though Rust formatting the bindings adds a lot of time to the overall binding generation process, I think bindings.rs should be formatted before it gets packaged into the binaries.

Better Enum representation.

There are some situations for which it would be convenient to pass a mutable pointer to an enum handle to a native function.

Add SkFontMgr and related wrappers

Skia font wrappers are incomplete, to complete them, we need to wrap some more header files:

  • core/SkFontArguments.h
  • core/SkFontMgr.h
  • core/SkFontParameters.h
  • core/SkTypeface.h
    • getVariationDesignPosition()
    • getVariationDesignParameters()
    • impl NativePartialEq
    • makeClone(),
    • remove maySupportKerning()
    • createFamilyNameIterator()
    • getFamilyName()

Complete SkCanvas Bindings

For that we need a number of binding types to be created, exact progress is in the related PR.

Regarding SkPoint, SkVector, SkRect, SkMatrix, etc. we might consider to use an alternative math / vector 2D library if there is one that fits exactly and is popular in the Rust community, for example https://github.com/servo/euclid.

I took the liberty to postpone some additional types and their related functions like Allocator, SkMetadata, SkString, SkStreamAsset, SkStream, etc.

License, please.

Hi, first, great work!, I am quite surprised to see that the binding generation works for C++ header files, and I would like to give that a shot for creating up to date Skia bindings, primarily I am interested in the Vulkan backend.

With a few hurdles, I was able to generate the bindings (including Vulkan support) on Ubuntu 18 after I failed to get everything working on Windows via msys (my primary development environment): clang 7.0.1 was not be to consume the Skia header files, many spurious errors were popping up, and I got confused about the include directories and their order, so I postponed that, and now I try to just use the Ubuntu generated bindings on windows.

Anyway, that's just to offer a bit of my motivational ground and progress, but to continue I'd like to see a license to be on the safe side, thanks.

non-compiled

hello,Can you provide a non-compiled version? I now have the dynamic library of skia and the header file of skia. How can I change it?

Wrap useful classes in include/utils/

I suggest to wrap at least the following utilily classes in include/utils/ for reaching the API Complete milestone:

  • Sk3D.h, SkCamera.h, because ... I want this 😎!
  • SkInterpolator.h for creating nice transitions.
  • SkNullCanvas.h for performance testing.
  • SkParsePath.h for converting Paths to SVG and back.
  • SkShadowUtils.h to draw shadows on a Canvas.
  • SkTextUtils.h for drawing aligned text, though I suspect that we need to support the SkShaper module as a separate feature anyway.

Everything else looks very implementation / Chrome specific (SkCanvasStateUtils.h, SkEventTracer.h, SkFrontBufferedStream.h, SkNoDrawCanvas.h, SkNWayCanvas.h, SkParse.h, SkTraceEventPhase.h), or better suited to be pulled in as a native Rust library (SkBase64.h, SkRandom.h).

SkAnimCodecPlayer.h must be postponed until we wrap codec/ and I don't think that we need to support Lua for now.

Dont generate the bindings in src/bindings.rs

This messes up compilation dependency tracking and also - I think - produces stale IDE results in dependent projects when cargo check is used and INIT_SKIA is not set, because the cargo project is always out of date after the bindings are regenerated. I also assume that's why the check for INIT_SKIA exists in the build.rs script.

I've tried the following:

Next step is to patch mtime of the generated file src/bindings.rs in the build.rs script. This can only be a temporary solution primarily targeted for IDE support, because AFAIK we can not write in the src directory for cargo package generation anyway.

[Android] Cannot locate symbol

Hi lovely work btw I've been monitoring this repo for a while now ...... so I'm building for android an I only get missing symbol errors if I try setting another font other than using the default values ... any help will be appreciated
java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_ZN11SkFontStyle6NormalEv" referenced by "/data/app/com.github.triniwiz.canvasdemo-IUBq5oT_0-heYZaI1jYbLg==/lib/arm64/libcanvasnative.so"

[IOS] Undefined symbols for architecture x86_64

I'm trying to run following run on ios sim (also tried on an ipad before had a similar error)

use skia_safe::{ Surface, SurfaceProps, PixelGeometry, ColorType, Paint, Rect, SurfacePropsFlags};
use skia_safe::gpu::gl;
use skia_safe::paint::Style;
use std::os::raw::{c_int, c_uint};
use skia_safe::gpu::{Context, BackendRenderTarget, SurfaceOrigin};

#[no_mangle]
pub extern fn native_init(width: *const c_int, height: *const c_int, buffer: *const c_uint) {
    let interface = gl::Interface::new_native().unwrap();
    let mut context = Context::new_gl(Some(&interface));
    let frame_buffer = gl::FramebufferInfo::from_fboid(buffer as u32);
    let target = BackendRenderTarget::new_gl((width as i32, height as i32), Some(0), 0, frame_buffer);
    let surface_props = SurfaceProps::new(SurfacePropsFlags::default(), PixelGeometry::Unknown);
    let surface_holder = Surface::from_backend_render_target(&mut context.unwrap(), &target, SurfaceOrigin::TopLeft, ColorType::RGBA8888, None, Some(&surface_props));
    let mut surface = surface_holder.unwrap();
    let canvas = surface.canvas();
    let mut paint = Paint::default();
    paint.set_style(Style::Fill);
    let rect = Rect::new(0.0, 0.0, 100.0, 100.0);
    canvas.draw_rect(rect, &paint);
}

Xcode output

Undefined symbols for architecture x86_64:
  "SkFontParameters::Variation::Axis::setHidden(bool)", referenced from:
      skia_bindings::bindings::SkFontParameters_Variation_Axis::setHidden::h3732f0e5568a7c90 in libcanvasnative.a(skia_safe-37d69c1bedbf10ce.skia_safe.91mkqjfv-cgu.1.rcgu.o)
  "typeinfo for SkShader", referenced from:
      _C_SkShader_Deserialize in libcanvasnative.a(bindings.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Any pointer(s) will be appreciated 😃

Turn mutating functions that return value `bool` into `Option<&mut Self>`

Several functions in Bitmap for example return a bool value which need to be checked to be sure that the function did what it is supposed to (for example set_info).

I'd suggested we support method chaining and turn all bool returns that confirm the mutation to the caller into Option<&mut Self>. This way method chaining can continue uninterrupted with .unwrap() or .expect(), for example.

Build error

I am getting the following error when trying to build the latest master on MacOS Mojave 10.14.5

rust-skia/skia-bindings/skia/include/private/SkNx_sse.h:525:24: error: useof undeclared identifier '__builtin_ia32_psrldqi128_byteshift', err: true
thread 'main' panicked at 'Unable to generate bindings: ()', src/libcore/result.rs:999:5

I was able to build an older commit ac8b54d7b9fad479b1a473978b346c5c1a6a35f7
I tried cargo clean, but no luck
Thanks

Building on MacOS with libjpeg-turbo compile errors.

Hey,

I had some compile errors related to libjpeg (you can see other people getting the same errors here: aseprite/aseprite#1981).

I tried brew install libjpeg-turbo but that didn't work, in the end I had to put ("skia_use_libjpeg_turbo", no()), into build.rs to get it building.

I'm not sure if that's a change you want to include unconditionally, but I thought I should mention it in case someone else has the same issue.

Wrap remaining effects.

The effects/ API is nearly feature complete, what's missing are wrappers for the following header files:

  • SkBlurMaskFilter.h

    deprecated, under a legacy guard

  • SkColorMatrix.h (optional, included in SkColorMatrixFilter.h but unused) (update: comes with the m76 bindings #122)
  • SkColorMatrixFilter.h
  • SkHighContrastFilter.h
  • SkLumaColorFilter.h
  • SkOpPathEffect.h
  • SkOverdrawColorFilter.h
  • SkShaderMaskFilter.h
  • SkTableMaskFilter.h
  • SkTrimPathEffect.h

Integrate depot_tools

I think we should integrate depot_tools into the project, probably as a submodule.

This way, we can run ninja from build.rs and it will be a bit easier to compile this library.

In addition to that we can pin down the exact version of the depot_tools that we support, currently we are pulling the master branch for the CI builds.

Interesting enough, I've never installed depot_tools on my machine, so it should actually be enough to pull in ninja only.

/cc @Brooooooklyn
Related to #3

Function Level Documentation

The binding generator already generates attribute based doc comments based on the original Skia documentation, so it would be great if we are able to reuse them.

Is it possible to build a macro for that?

Say something #[docref(OriginalFunctionName)] that looks for the function's doc attributes and copies its docs into the attribute list of the current function?

NativeTransmutable needs to implicitly implement NativeAccess

The trait NativeTransmutable overlaps somewhat NativeAccess, and it seems impossible to implement NativeAccess for all types that are NativeTransmutable without creating a conflict, this in turn causes a duplication of a number of traits that are based on the two functions native() and native_mut() that are defined by both of these traits.

One solution would be to create a derive macro that implements NativeAccess for transmutable structs.

Try to match the Skia include hierarchy in skia-safe.

I think that the directory hierarchy should match the include hierarchy of Skia, which means that we need to rename skia/ to core/, graphics/ to gpu/, graphics/gl/ to gpu/gl/, and graphics/vulkan/ to gpu/vk/.

I wrongly assumed that the Gr prefix stands for graphics, but it is most likely an abbreviation for "GPU Rasterization".

Consolidating all that, the Skia prefixes should match the Rust modules the following way:

  • Sk -> skia_safe (exported from core::* and effects::*).
  • Gr -> skia_safe::gpu
  • GrVk -> skia_safe::gpu::vk
  • GrGL -> skia_safe::gpu::gl

`get_points` not working as expected

Hey,

Is there an example showcasing how to use get_points?

let count = self.path.count_points();
let mut points = Vec::with_capacity(count);
let c = self.path.get_points(&mut points);

I can't get it to update the array I am passing with points.
Probably I am doing something wrong, sorry 🤷‍♀️

[Android] skia-safe test failures

When compiling for the Android target aarch64-linux-android and running skia-safe tests with --nocapture on my Android device, I get one test-failure:

thread 'core::typeface::serialize_and_deserialize_default_typeface' panicked at 'assertion failed: `(left == right)`
  left: `"sans-serif"`,
 right: `"Roboto"`', skia-safe/src/core/typeface.rs:315:5

Which is probably a false negative, because Roboto is actually the default sans-serif font on Android.

And suspiciously, there are no style names printed, for example:

font_family: hwchinese-bold
  style:
  style:

And the last font family name looks a bit like a garbage string:

font_family: chnfzxh

bit it seems that it is actually a font family name of a font named RobotoXianBlack (https://github.com/search?q=chnfzxh&type=Code).

Suggestion: Distribute the raw bindings as a crate and continue to use them as dependency.

I did an experiment and separated the canvas implementation and the hello.rs into a another dependent project and it went along fine, Rust seems to be awesome in this regard, the skia.lib and the skiabinding.lib were all included into the resulting rlib, and the linker flags were propagated.

The improvements I seek are:

  • To separate the the evolution of the raw binding generation (including feature control!) from the future safe bindings or other simplified bindings like the already existing canvas implementation.
  • To simplify IDE support and development. For example, CLion completely freaks out with the included raw bindings inside the same project, it shows errors and the IDE completion does not work, but as soon they are in a dependent create, everything is fine.
  • To reduce build times for creating dependent crates, running build.rs for every change seems to be too heavy.
  • To simplify builds. We could run the binding generation every time (i.e remove the INIT_SKIA switch). Cargo seems to be intelligent enough to build the project only once for dependent projects as long there are no changes affecting it, though I don't know how reliable that is.
  • To avoid waiting for and using azure-pipelines for uncountable hours and heating up our planet even more.

Note that I am a Rust beginner, and some of the points above may be speculative and based on naive assumptions.

Naming suggestions for the resulting crates and projects:

  • skia-raw, for the raw bindings (we just export everything that binding.rs produces).
  • skia-canvas, for the simplified canvas drawing implementation.
  • skia-safe, for the safe bindings which should closely resemble the Skia API.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.