Giter Club home page Giter Club logo

blend2d-rs's Introduction

blend2d-rs

Build Status Crates.io Docs.rs

This crate provides rust bindings to the blend2d lib.

  • This project is currently WIP and therefor incomplete, due to this the crate will most likely go through breaking changes until a proper api has been figured out. Bear in mind that blend2d itself is also still in beta, meaning changes in their api will most likely be reflected in this crate as well in one way or another. This also means that some functionality is currently not correctly(or at all) implemented, for example, filling a context with an image will currently return an InvalidValue error.

  • Almost nothing is documented at this point so if confusion arises it might help to check out the C++ docs. This will hopefully change in the near future.

  • Not everything has been tested, so bugs might occur.

Setup

This crate requires CMake to be installed and available on PATH.

Also make sure to initialize the submodules after cloning the repository(git submodule update --init).

Examples

You can find the examples here.

rust_bl_logo

Current Design Decision

  • The Clone Trait is currently implemented in such a way that it does weak clones by using the underlying ref-counting of blend2d. Deep clones can be achieved by using the corresponding DeepClone Trait.
  • OutOfMemory errors returned by blend2d will as of now panic the program by default.

License

Licensed under either of

at your option.

The Rust logo is owned by Mozilla and distributed under the terms of the Creative Commons Attribution license (CC-BY).

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

blend2d-rs's People

Contributors

malthe avatar tillsten avatar veykril avatar

Stargazers

 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

Forkers

malthe tillsten

blend2d-rs's Issues

Refactor Gradient constructors

The way gradient's constructors work rn forces one to specify the generic GradientType since the compiler cant infer which type comes from the given ValuesType since a GradientType defines what ValuesType it takes. Due to this the public type definitions like LinearGradient have been created to avoid having to write out the generic parameter everytime. This doesn't solve the problem though.

Implement DeepClone for Array<T>

For some reason it is not currently possible to implement DeepClone for Array generically either due to a compiler bug or me overlooking something.

blend2d-rs/src/variant.rs

Lines 322 to 332 in f1f116c

// Fails to compile on rust stable but works fine on nightly(E0277). I believe
// this might be related to https://github.com/rust-lang/rust/issues/24159,
// but im unsure as to how one could circumvent it
/*impl<T> DeepClone for Array<T>
where
T: ArrayType,
Array<T>: WrappedBlCore,
<Array<T> as WrappedBlCore>::Core: Copy + 'static,
{
const ASSIGN_DEEP: BlAssignDeep<Self::Core> = ffi::blArrayAssignDeep;
}*/

We can obviously circumvent this by changing the array_type macro to implement DeepClone for each of the types for Array instead. It's not nice but it would solve the problem for the time being

blend2d-rs/src/array.rs

Lines 448 to 504 in f1f116c

macro_rules! impl_array_type {
($( $append:ident, $insert:ident, $replace:ident for $( ($ty:ty = $idx:expr) ),+);*$(;)*) => {
$(
$(
impl ArrayType for $ty {
const IMPL_IDX: usize = $idx as usize;
#[inline]
unsafe fn push(core: &mut ffi::BLArrayCore, item: Self) -> Result<()> {
errcode_to_result(ffi::$append(core, item as _))
}
#[inline]
unsafe fn insert(core: &mut ffi::BLArrayCore, index: usize, item: Self) -> Result<()> {
errcode_to_result(ffi::$insert(core, index, item as _))
}
#[inline]
unsafe fn replace(core: &mut ffi::BLArrayCore, index: usize, item: Self) -> Result<()> {
errcode_to_result(ffi::$replace(core, index, item as _))
}
}
)+
)*
};
($( ( $( $ty:ty ),+ = $idx:expr) );* $(;)*) => {
$(
$(
impl ArrayType for $ty {
const IMPL_IDX: usize = $idx as usize;
}
)+
)*
}
}
impl_array_type! {
blArrayAppendU8, blArrayInsertU8, blArrayInsertU8 for (i8 = ImplType::ArrayI8), (u8 = ImplType::ArrayU8);
blArrayAppendU16, blArrayInsertU16, blArrayInsertU16 for (i16 = ImplType::ArrayI16), (u16 = ImplType::ArrayU16);
blArrayAppendU32, blArrayInsertU32, blArrayInsertU32 for (i32 = ImplType::ArrayI32), (u32 = ImplType::ArrayU32);
blArrayAppendU64, blArrayInsertU64, blArrayInsertU64 for (i64 = ImplType::ArrayI64), (u64 = ImplType::ArrayU64);
blArrayAppendF32, blArrayInsertF32, blArrayInsertF32 for (f32 = ImplType::ArrayF32);
blArrayAppendF64, blArrayInsertF64, blArrayInsertF64 for (f64 = ImplType::ArrayF32);
}
#[cfg(target_pointer_width = "32")]
impl_array_type!(blArrayAppendU32, blArrayInsertU32, blArrayInsertU32 for (isize = ImplType::ArrayI32), (usize = ImplType::ArrayU32));
#[cfg(target_pointer_width = "64")]
impl_array_type!(blArrayAppendU64, blArrayInsertU64, blArrayInsertU64 for (isize = ImplType::ArrayI64), (usize = ImplType::ArrayU64));
mod scope {
use crate::{array::ArrayType, font_defs::*, geometry::*, variant::ImplType, Tag};
impl_array_type! {
(Tag = ImplType::ArrayStruct4);
(PointD, PointI, SizeD, SizeI, FontFeature, FontVariation = ImplType::ArrayStruct8);
(Circle = ImplType::ArrayStruct12);
(BoxD, BoxI, Ellipse, Line, RectD, RectI = ImplType::ArrayStruct16);
(Arc, Chord, Pie, RoundRect, Triangle = ImplType::ArrayStruct24);
}
}
.

Make functions that return an OutOfMemory error panic

Currently almost every method returns a Result even the ones that are infallible internally to stay consistent. A lot of methods actually only return an OutOfMemory error, so panicking on those by default would make it possible to have a slightly better to use api while also sticking to what current Rust does when it encounters OOM situations.

Integrate std::fs

Currently most things that can make use of I/O do so through the C side of blend2d. It would be nice if these things could also maybe offer an api that allows to pass Read/Write instances and similar things for example. Maybe it would be beneficial to also wrap the BLFileCore struct to allow I/O stuff to be used in a more idiomatic manner.

Implement external data constructors

Some objects can be constructed with external data, those functions take a function pointer to clean up the data when it isnt needed anymore. I am not sure how one could properly implement this yet.
As of now the following functions exist:

Array: https://github.com/blend2d/blend2d/blob/69141350b5a654f328c8529ae301aa1e6bad5342/src/blend2d/blapi.h#L1388
FontLoader: https://github.com/blend2d/blend2d/blob/69141350b5a654f328c8529ae301aa1e6bad5342/src/blend2d/blapi.h#L1589
Image: https://github.com/blend2d/blend2d/blob/69141350b5a654f328c8529ae301aa1e6bad5342/src/blend2d/blapi.h#L1651

Consider keeping the BL prefix?

Currently all the bl structs are named the same as their C/C++ counterparts just without the BL prefix. I chose to do this since everything in Rust is namespaced anyways, though I now noticed the problems this could make in terms of clashing names when importing structs from different crates/std that have similar names. Mainly speaking BLBox and BLString. To avoid this I renamed BLBox to BoxD like BLBoxI became BoxI. While this is fine for BLBox, there is no similar way to avoid the confusion with BLString becoming just String. On a different note, is it idiomatic for Rust ffi libs to keep prefixes like this or not?

Remove lifetime dependencies wiith the blend2d internal refcounting

Blend2D uses reference counting to ensure that objects aren't being destroyed until they aren't needed anymore. This is somewhat equal to an Rc<RefCell<T>> in Rust. Currently the wrapper only allows deep clones of objects that support it, while trying to not have multiple objects that point to the same implementation. As I wrap more of the library I slowly notice that this approach seems like a bad choice, making it difficult to create a sound api that sticks to rust's lifetime rules.

As it turns out, the external image object can currently cause a use after free by creating a pattern from it, handing that over to a context and then dropping the pattern, image and then the data.
A possible prevention for this would be to make a wrapper struct for an external image that panics if it drops while not being the only ref counted object

Enhance the error type

The current error implementation just wraps the C error codes and thats it. The display implementation currently just returns the variant names, it would be nicer to have proper descriptions of what might have happened instead since some variant names arent really that descriptive on their own.

#6 is related to this as well.

Offer an actual color api

Regarding color things, we currently just use u32s and u64s which isnt that nice to use in most cases. It would be nice if we had something to the C versions rgba things. I am also considering adding optional support for the palette crate.

Remove objects none constructor

Currently objects can be none implementation objects which is fine for some types but types that have a virtual function table do not function due to the none implementations function table just returning an invalid state error. I dont think it makes much sense to have this available on the rust side so all objects that have a virtual function table should be stripped of their empty constructor instead, replacing it with a properly initializing constructor.

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.