Skip to content

Commit

Permalink
Merge #110
Browse files Browse the repository at this point in the history
110: No std support r=Ogeon a=mb64

Adds support for using palette without the standard library, as discussed in issue #108.

Fixes #108.

One tiny question: because this would be in a future release (not 0.4.0), what version should be in the README example Cargo.toml for `#![no_std]`?  I put 0.4, but was unsure about if it should be something different.

Co-authored-by: Mark Barbone <mark.l.barbone@gmail.com>
  • Loading branch information
bors[bot] and mb64 committed Aug 28, 2018
2 parents 941de7a + c729c30 commit 961b58e
Show file tree
Hide file tree
Showing 42 changed files with 359 additions and 175 deletions.
29 changes: 26 additions & 3 deletions README.md
Expand Up @@ -20,16 +20,27 @@ Add the following lines to your `Cargo.toml` file:
palette = "0.4"
```

### Optional Features
### Features

These features are enabled by default:

* `"named"` - Enables color constants, located in the `named` module.
* `"named_from_str"` - Enables the `named::from_str`, which maps name string to colors.
* `"named_from_str"` - Enables the `named::from_str`, which maps name string to colors. This requires the standard library.
* `"std"` - Enables use of the standard library.

These features are disabled by default:

* `"serde"` - Enables color serializing and deserializing.
* `"serializing"` - Enables color serializing and deserializing using `serde`.

### Without the standard library

Here is an example `Cargo.toml` entry for using palette on `#![no_std]`:

```toml
[dependencies.palette]
version = "0.4"
default-features = false
```

## It's Never "Just RGB"

Expand Down Expand Up @@ -113,6 +124,18 @@ This library is only meant for color manipulation and conversion. It's not a ful

[pixel_module]: https://ogeon.github.io/docs/palette/master/palette/pixel/index.html

## Using palette in an embedded environment

Palette supports `#![no_std]` environments by disabling the `"std"` feature. However, there are some things that are unavailable without the standard library:

* Gradients are unavailable, because they depend heavily on Vectors
* The `"named_from_str"` feature requires the standard library as well
* Serialization using `serde` is unavailable

It uses [`libm`] to provide the floating-point operations that are typically in `std`.

[`libm`]: https://github.com/japaric/libm

## Contributing

All sorts of contributions are welcome, no matter how huge or tiny, so take a look at [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines, if you are interested.
Expand Down
12 changes: 7 additions & 5 deletions palette/Cargo.toml
Expand Up @@ -13,24 +13,26 @@ license = "MIT OR Apache-2.0"
build = "build/main.rs"

[features]
default = ["named_from_str"]
named_from_str = ["named", "phf", "phf_codegen"]
default = ["named_from_str", "std"]
named_from_str = ["named", "phf", "phf_codegen", "std"]
named = []
std = ["approx/std", "num-traits/std"]
serializing = ["serde", "std"]

#internal
strict = []

[dependencies]
palette_derive = {version = "0.4.1", path = "../palette_derive"}
num-traits = "0.2"
approx = "0.2"
num-traits = {version = "0.2", default-features = false}
approx = {version = "0.2", default-features = false}
libm = "0.1.2"

[dependencies.phf]
version = "0.7"
optional = true

[dependencies.serde]
#feature
version = "1"
features = ["serde_derive"]
optional = true
Expand Down
33 changes: 27 additions & 6 deletions palette/README.md
Expand Up @@ -20,16 +20,27 @@ Add the following lines to your `Cargo.toml` file:
palette = "0.4"
```

### Optional Features
### Features

These features are enabled by default:

* `"named"` - Enables color constants, located in the `named` module.
* `"named_from_str"` - Enables the `named::from_str`, which maps name string to colors.
* `"named_from_str"` - Enables the `named::from_str`, which maps name string to colors. This requires the standard library.
* `"std"` - Enables use of the standard library.

These features are disabled by default:

* `"serde"` - Enables color serializing and deserializing.
* `"serializing"` - Enables color serializing and deserializing using `serde`.

### Without the standard library

Here is an example `Cargo.toml` entry for using palette on `#![no_std]`:

```toml
[dependencies.palette]
version = "0.4"
default-features = false
```

## It's Never "Just RGB"

Expand Down Expand Up @@ -109,12 +120,22 @@ The RGB gradient goes through gray, while the HSV gradients changes only the hue

## What It Isn't

This library is only meant for color manipulation and conversion. It's not a fully features image manipulation library. It will only handle colors, and not whole images.

These are meant to work as bridges between Palette and other graphical libraries, but it has been limited only focus on single pixel operations to keep the scope at a manageable size.
This library is only meant for color manipulation and conversion. It's not a fully features image manipulation library. It will only handle colors, and not whole images. There are features that are meant to work as bridges between Palette and other graphical libraries, but the main features are limited to only focus on single pixel operations, to keep the scope at a manageable size.

[pixel_module]: https://ogeon.github.io/docs/palette/master/palette/pixel/index.html

## Using palette in an embedded environment

Palette supports `#![no_std]` environments by disabling the `"std"` feature. However, there are some things that are unavailable without the standard library:

* Gradients are unavailable, because they depend heavily on Vectors
* The `"named_from_str"` feature requires the standard library as well
* Serialization using `serde` is unavailable

It uses [`libm`] to provide the floating-point operations that are typically in `std`.

[`libm`]: https://github.com/japaric/libm

## Contributing

All sorts of contributions are welcome, no matter how huge or tiny, so take a look at [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines, if you are interested.
Expand Down
2 changes: 1 addition & 1 deletion palette/build/named.rs
Expand Up @@ -32,7 +32,7 @@ pub fn build() {
.expect(&format!("couldn't get blue for {}", name));

writeln!(writer, "\n///<div style=\"display: inline-block; width: 3em; height: 1em; border: 1px solid black; background: {0};\"></div>", name).unwrap();
writeln!(writer, "pub const {}: ::rgb::Srgb<u8> = ::rgb::Srgb {{ red: {}, green: {}, blue: {}, standard: ::std::marker::PhantomData }};", name.to_uppercase(), red, green, blue).unwrap();
writeln!(writer, "pub const {}: ::rgb::Srgb<u8> = ::rgb::Srgb {{ red: {}, green: {}, blue: {}, standard: ::core::marker::PhantomData }};", name.to_uppercase(), red, green, blue).unwrap();

entries.push((name.to_owned(), name.to_uppercase()));
}
Expand Down
12 changes: 9 additions & 3 deletions palette/examples/gradient.rs
@@ -1,11 +1,17 @@
extern crate image;
extern crate palette;

use palette::{Gradient, Lch, LinSrgb, Pixel, Srgb};

use image::{GenericImage, RgbImage};
#[cfg(not(feature = "std"))]
fn main() {
println!("You can't use gradients without the standard library");
}

#[cfg(feature = "std")]
fn main() {
use palette::{Gradient, Lch, LinSrgb, Pixel, Srgb};

use image::{GenericImage, RgbImage};

//A gradient of evenly spaced colors
let grad1 = Gradient::new(vec![
LinSrgb::new(1.0, 0.1, 0.1),
Expand Down
7 changes: 6 additions & 1 deletion palette/examples/readme_examples.rs
Expand Up @@ -4,7 +4,9 @@ extern crate palette;

use image::{GenericImage, RgbImage};

use palette::{Gradient, LinSrgb, Mix, Pixel, Srgb};
use palette::{Pixel, Srgb};
#[cfg(feature = "std")]
use palette::{Gradient, LinSrgb, Mix};

mod color_spaces {
use palette::{Hue, Lch, LinSrgb, Srgb};
Expand Down Expand Up @@ -44,6 +46,7 @@ mod manipulation {
}
}

#[cfg(feature = "std")]
mod gradients {
use palette::{Gradient, Hsv, LinSrgb};
use display_gradients;
Expand Down Expand Up @@ -81,6 +84,7 @@ fn display_colors(filename: &str, colors: &[Srgb<u8>]) {
}
}

#[cfg(feature = "std")]
fn display_gradients<A: Mix<Scalar = f32> + Clone, B: Mix<Scalar = f32> + Clone>(
filename: &str,
grad1: Gradient<A>,
Expand Down Expand Up @@ -127,5 +131,6 @@ fn display_gradients<A: Mix<Scalar = f32> + Clone, B: Mix<Scalar = f32> + Clone>
fn main() {
color_spaces::run();
manipulation::run();
#[cfg(feature = "std")]
gradients::run();
}
18 changes: 9 additions & 9 deletions palette/src/alpha.rs
@@ -1,7 +1,7 @@
use std::ops::{Add, Deref, DerefMut, Div, Mul, Sub};
use std::fmt;
use core::ops::{Add, Deref, DerefMut, Div, Mul, Sub};
use core::fmt;

use num_traits::Float;
use float::Float;

use approx::{AbsDiffEq, RelativeEq, UlpsEq};

Expand All @@ -11,11 +11,11 @@ use encoding::pixel::RawPixel;

///An alpha component wrapper for colors.
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serializing", derive(Serialize, Deserialize))]
#[repr(C)]
pub struct Alpha<C, T> {
///The color.
#[cfg_attr(feature = "serde", serde(flatten))]
#[cfg_attr(feature = "serializing", serde(flatten))]
pub color: C,

///The transparency component. 0.0 is fully transparent and 1.0 is fully
Expand Down Expand Up @@ -338,7 +338,7 @@ where
C: fmt::LowerHex,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let size = f.width().unwrap_or(::std::mem::size_of::<T>() * 2);
let size = f.width().unwrap_or(::core::mem::size_of::<T>() * 2);
write!(
f,
"{:0width$x}{:0width$x}",
Expand All @@ -355,7 +355,7 @@ where
C: fmt::UpperHex,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let size = f.width().unwrap_or(::std::mem::size_of::<T>() * 2);
let size = f.width().unwrap_or(::core::mem::size_of::<T>() * 2);
write!(
f,
"{:0width$X}{:0width$X}",
Expand Down Expand Up @@ -467,7 +467,7 @@ mod test {
);
}

#[cfg(feature = "serde")]
#[cfg(feature = "serializing")]
#[test]
fn serialize() {
let serialized = ::serde_json::to_string(&Rgba::<Srgb>::new(0.3, 0.8, 0.1, 0.5)).unwrap();
Expand All @@ -478,7 +478,7 @@ mod test {
);
}

#[cfg(feature = "serde")]
#[cfg(feature = "serializing")]
#[test]
fn deserialize() {
let deserialized: Rgba<Srgb> =
Expand Down
5 changes: 4 additions & 1 deletion palette/src/blend/blend.rs
@@ -1,4 +1,7 @@
use num_traits::{Float, One, Zero};
use num_traits::{One, Zero};
use float::Float;
#[cfg(feature = "libm_works")]
use num_traits::float::FloatCore;

use {cast, clamp, ComponentWise};
use blend::{BlendFunction, PreAlpha};
Expand Down
4 changes: 3 additions & 1 deletion palette/src/blend/equations.rs
@@ -1,4 +1,6 @@
use num_traits::Float;
use float::Float;
#[cfg(feature = "libm_works")]
use num_traits::float::FloatCore;

use {Blend, ComponentWise};
use blend::{BlendFunction, PreAlpha};
Expand Down
2 changes: 1 addition & 1 deletion palette/src/blend/mod.rs
Expand Up @@ -36,7 +36,7 @@
//!which may result in loss of some color information in some cases. One such
//!case is that a completely transparent resultant color will become black.

use num_traits::Float;
use float::Float;

use ComponentWise;

Expand Down
14 changes: 7 additions & 7 deletions palette/src/blend/pre_alpha.rs
@@ -1,6 +1,6 @@
use std::ops::{Add, Deref, DerefMut, Div, Mul, Sub};
use core::ops::{Add, Deref, DerefMut, Div, Mul, Sub};
use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use num_traits::Float;
use float::Float;

use {clamp, Alpha, Blend, ComponentWise, Mix, Pixel};
use encoding::pixel::RawPixel;
Expand All @@ -27,11 +27,11 @@ use encoding::pixel::RawPixel;
///Note that converting to and from premultiplied alpha will cause the alpha
///component to be clamped to [0.0, 1.0].
#[derive(Clone, Copy, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serializing", derive(Serialize, Deserialize))]
#[repr(C)]
pub struct PreAlpha<C, T: Float> {
///The premultiplied color components (`original.color * original.alpha`).
#[cfg_attr(feature = "serde", serde(flatten))]
#[cfg_attr(feature = "serializing", serde(flatten))]
pub color: C,

///The transparency component. 0.0 is fully transparent and 1.0 is fully
Expand Down Expand Up @@ -319,13 +319,13 @@ impl<C, T: Float> DerefMut for PreAlpha<C, T> {
}

#[cfg(test)]
#[cfg(feature = "serde")]
#[cfg(feature = "serializing")]
mod test {
use super::PreAlpha;
use rgb::Rgb;
use encoding::Srgb;

#[cfg(feature = "serde")]
#[cfg(feature = "serializing")]
#[test]
fn serialize() {
let color = PreAlpha {
Expand All @@ -338,7 +338,7 @@ mod test {
assert_eq!(serialized, r#"{"red":0.3,"green":0.8,"blue":0.1,"alpha":0.5}"#);
}

#[cfg(feature = "serde")]
#[cfg(feature = "serializing")]
#[test]
fn deserialize() {
let expected = PreAlpha {
Expand Down
2 changes: 1 addition & 1 deletion palette/src/chromatic_adaptation.rs
Expand Up @@ -22,7 +22,7 @@
//!//Should print {x: 0.257963, y: 0.139776,z: 0.058825}
//!println!("{:?}", c)
//!```
use num_traits::Float;
use float::Float;

use {cast, Component, FromColor, IntoColor, Xyz};
use white_point::WhitePoint;
Expand Down

0 comments on commit 961b58e

Please sign in to comment.