Skip to content

Commit 4b2f9c5

Browse files
authored
Add support color mode. (#96)
1 parent bbb5501 commit 4b2f9c5

File tree

8 files changed

+525
-122
lines changed

8 files changed

+525
-122
lines changed

crates/processing_ffi/src/color.rs

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,33 @@
11
use bevy::color::{LinearRgba, Srgba};
2+
use processing::prelude::color::{ColorMode, ColorSpace};
23

3-
/// A sRGB (?) color
4+
/// A color with 4 float components and its color space.
45
#[repr(C)]
56
#[derive(Debug, Clone, Copy)]
67
pub struct Color {
7-
pub r: f32,
8-
pub g: f32,
9-
pub b: f32,
8+
pub c1: f32,
9+
pub c2: f32,
10+
pub c3: f32,
1011
pub a: f32,
12+
pub space: u8,
1113
}
1214

13-
impl From<Color> for bevy::color::Color {
14-
fn from(color: Color) -> Self {
15-
bevy::color::Color::srgba(color.r, color.g, color.b, color.a)
15+
impl Color {
16+
pub fn resolve(self, mode: &ColorMode) -> bevy::color::Color {
17+
let c1 = mode.scale(self.c1, 0);
18+
let c2 = mode.scale(self.c2, 1);
19+
let c3 = mode.scale(self.c3, 2);
20+
let ca = mode.scale(self.a, 3);
21+
mode.space.color(c1, c2, c3, ca)
1622
}
17-
}
18-
19-
impl From<LinearRgba> for Color {
20-
fn from(lin: LinearRgba) -> Self {
21-
let srgb: Srgba = lin.into();
22-
srgb.into()
23-
}
24-
}
2523

26-
impl From<Srgba> for Color {
27-
fn from(srgb: Srgba) -> Self {
24+
pub fn from_linear(lin: LinearRgba) -> Self {
2825
Color {
29-
r: srgb.red,
30-
g: srgb.green,
31-
b: srgb.blue,
32-
a: srgb.alpha,
26+
c1: lin.red,
27+
c2: lin.green,
28+
c3: lin.blue,
29+
a: lin.alpha,
30+
space: ColorSpace::Linear as u8,
3331
}
3432
}
3533
}

crates/processing_ffi/src/lib.rs

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,9 @@ pub extern "C" fn processing_background_color(graphics_id: u64, color: Color) {
173173
error::clear_error();
174174
let graphics_entity = Entity::from_bits(graphics_id);
175175
error::check(|| {
176-
graphics_record_command(graphics_entity, DrawCommand::BackgroundColor(color.into()))
176+
let mode = graphics_get_color_mode(graphics_entity)?;
177+
let color = color.resolve(&mode);
178+
graphics_record_command(graphics_entity, DrawCommand::BackgroundColor(color))
177179
});
178180
}
179181

@@ -244,17 +246,46 @@ pub extern "C" fn processing_exit(exit_code: u8) {
244246
error::check(|| exit(exit_code));
245247
}
246248

249+
/// Set the color mode for a graphics context.
250+
///
251+
/// SAFETY:
252+
/// - graphics_id is a valid ID returned from graphics_create.
253+
/// - This is called from the same thread as init.
254+
#[unsafe(no_mangle)]
255+
pub extern "C" fn processing_color_mode(
256+
graphics_id: u64,
257+
space: u8,
258+
max1: f32,
259+
max2: f32,
260+
max3: f32,
261+
max_alpha: f32,
262+
) {
263+
error::clear_error();
264+
let graphics_entity = Entity::from_bits(graphics_id);
265+
error::check(|| {
266+
let space = processing::prelude::color::ColorSpace::from_u8(space).ok_or_else(|| {
267+
processing::prelude::error::ProcessingError::InvalidArgument(format!(
268+
"unknown color space: {space}"
269+
))
270+
})?;
271+
let mode = processing::prelude::color::ColorMode::new(space, max1, max2, max3, max_alpha);
272+
graphics_set_color_mode(graphics_entity, mode)
273+
});
274+
}
275+
247276
/// Set the fill color.
248277
///
249278
/// SAFETY:
250279
/// - graphics_id is a valid ID returned from graphics_create.
251280
/// - This is called from the same thread as init.
252281
#[unsafe(no_mangle)]
253-
pub extern "C" fn processing_set_fill(graphics_id: u64, r: f32, g: f32, b: f32, a: f32) {
282+
pub extern "C" fn processing_set_fill(graphics_id: u64, color: Color) {
254283
error::clear_error();
255284
let graphics_entity = Entity::from_bits(graphics_id);
256-
let color = bevy::color::Color::srgba(r, g, b, a);
257-
error::check(|| graphics_record_command(graphics_entity, DrawCommand::Fill(color)));
285+
error::check(|| {
286+
let mode = graphics_get_color_mode(graphics_entity)?;
287+
graphics_record_command(graphics_entity, DrawCommand::Fill(color.resolve(&mode)))
288+
});
258289
}
259290

260291
/// Set the stroke color.
@@ -263,11 +294,16 @@ pub extern "C" fn processing_set_fill(graphics_id: u64, r: f32, g: f32, b: f32,
263294
/// - graphics_id is a valid ID returned from graphics_create.
264295
/// - This is called from the same thread as init.
265296
#[unsafe(no_mangle)]
266-
pub extern "C" fn processing_set_stroke_color(graphics_id: u64, r: f32, g: f32, b: f32, a: f32) {
297+
pub extern "C" fn processing_set_stroke_color(graphics_id: u64, color: Color) {
267298
error::clear_error();
268299
let graphics_entity = Entity::from_bits(graphics_id);
269-
let color = bevy::color::Color::srgba(r, g, b, a);
270-
error::check(|| graphics_record_command(graphics_entity, DrawCommand::StrokeColor(color)));
300+
error::check(|| {
301+
let mode = graphics_get_color_mode(graphics_entity)?;
302+
graphics_record_command(
303+
graphics_entity,
304+
DrawCommand::StrokeColor(color.resolve(&mode)),
305+
)
306+
});
271307
}
272308

273309
/// Set the stroke weight.
@@ -565,7 +601,7 @@ pub unsafe extern "C" fn processing_image_readback(
565601
unsafe {
566602
let buffer_slice = std::slice::from_raw_parts_mut(buffer, buffer_len);
567603
for (i, color) in colors.iter().enumerate() {
568-
buffer_slice[i] = Color::from(*color);
604+
buffer_slice[i] = Color::from_linear(*color);
569605
}
570606
}
571607

@@ -1154,9 +1190,12 @@ pub extern "C" fn processing_light_create_directional(
11541190
) -> u64 {
11551191
error::clear_error();
11561192
let graphics_entity = Entity::from_bits(graphics_id);
1157-
error::check(|| light_create_directional(graphics_entity, color.into(), illuminance))
1158-
.map(|e| e.to_bits())
1159-
.unwrap_or(0)
1193+
error::check(|| {
1194+
let mode = graphics_get_color_mode(graphics_entity)?;
1195+
light_create_directional(graphics_entity, color.resolve(&mode), illuminance)
1196+
})
1197+
.map(|e| e.to_bits())
1198+
.unwrap_or(0)
11601199
}
11611200

11621201
#[unsafe(no_mangle)]
@@ -1169,9 +1208,18 @@ pub extern "C" fn processing_light_create_point(
11691208
) -> u64 {
11701209
error::clear_error();
11711210
let graphics_entity = Entity::from_bits(graphics_id);
1172-
error::check(|| light_create_point(graphics_entity, color.into(), intensity, range, radius))
1173-
.map(|e| e.to_bits())
1174-
.unwrap_or(0)
1211+
error::check(|| {
1212+
let mode = graphics_get_color_mode(graphics_entity)?;
1213+
light_create_point(
1214+
graphics_entity,
1215+
color.resolve(&mode),
1216+
intensity,
1217+
range,
1218+
radius,
1219+
)
1220+
})
1221+
.map(|e| e.to_bits())
1222+
.unwrap_or(0)
11751223
}
11761224

11771225
#[unsafe(no_mangle)]
@@ -1187,9 +1235,10 @@ pub extern "C" fn processing_light_create_spot(
11871235
error::clear_error();
11881236
let graphics_entity = Entity::from_bits(graphics_id);
11891237
error::check(|| {
1238+
let mode = graphics_get_color_mode(graphics_entity)?;
11901239
light_create_spot(
11911240
graphics_entity,
1192-
color.into(),
1241+
color.resolve(&mode),
11931242
intensity,
11941243
range,
11951244
radius,

0 commit comments

Comments
 (0)