diff --git a/gfx/qcms/fuzz/fuzz_targets/fuzz_target_qcms.rs b/gfx/qcms/fuzz/fuzz_targets/fuzz_target_qcms.rs index 5526c5e1e9c0..dd38ec8c8ede 100644 --- a/gfx/qcms/fuzz/fuzz_targets/fuzz_target_qcms.rs +++ b/gfx/qcms/fuzz/fuzz_targets/fuzz_target_qcms.rs @@ -8,7 +8,9 @@ extern crate libc; * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ - use qcms::{iccread::{qcms_profile, qcms_profile_get_color_space}, transform::QCMS_DATA_RGBA_8, transform::QCMS_DATA_RGB_8, transform::QCMS_DATA_GRAYA_8, transform::QCMS_DATA_GRAY_8, iccread::icSigRgbData, iccread::qcms_profile_get_rendering_intent, transform::qcms_profile_precache_output_transform, transform::qcms_transform_create, transform::qcms_transform_data, transform::qcms_transform_release, transform::qcms_enable_iccv4, iccread::qcms_profile_from_memory, iccread::qcms_profile_release, iccread::qcms_profile_sRGB, iccread::qcms_profile_is_bogus, iccread::icSigGrayData}; + use qcms::iccread::{qcms_profile, icSigRgbData, qcms_profile_is_bogus, icSigGrayData}; + use qcms::c_bindings::{qcms_profile_get_color_space, qcms_profile_get_rendering_intent, qcms_profile_from_memory, qcms_profile_release, qcms_profile_sRGB}; + use qcms::transform::{QCMS_DATA_RGBA_8, QCMS_DATA_RGB_8, QCMS_DATA_GRAYA_8, QCMS_DATA_GRAY_8, qcms_profile_precache_output_transform, qcms_transform_create, qcms_transform_data, qcms_transform_release, qcms_enable_iccv4}; unsafe fn transform(src_profile: *mut qcms_profile, dst_profile: *mut qcms_profile, size: usize) { diff --git a/gfx/qcms/src/c_bindings.rs b/gfx/qcms/src/c_bindings.rs new file mode 100644 index 000000000000..de28cdef9207 --- /dev/null +++ b/gfx/qcms/src/c_bindings.rs @@ -0,0 +1,222 @@ +use std::{ptr::null_mut, slice}; + +use libc::{fclose, fopen, fread, free, malloc, FILE}; + +use crate::{iccread::*, qcms_intent}; + +#[no_mangle] +pub extern "C" fn qcms_profile_sRGB() -> *mut qcms_profile { + let profile = profile_sRGB(); + match profile { + Some(profile) => Box::into_raw(profile), + None => null_mut(), + } +} + +//XXX: it would be nice if we had a way of ensuring +// everything in a profile was initialized regardless of how it was created +//XXX: should this also be taking a black_point? +/* similar to CGColorSpaceCreateCalibratedRGB */ +#[no_mangle] +pub unsafe extern "C" fn qcms_profile_create_rgb_with_gamma_set( + mut white_point: qcms_CIE_xyY, + mut primaries: qcms_CIE_xyYTRIPLE, + mut redGamma: f32, + mut greenGamma: f32, + mut blueGamma: f32, +) -> *mut qcms_profile { + let profile = + profile_create_rgb_with_gamma_set(white_point, primaries, redGamma, greenGamma, blueGamma); + match profile { + Some(profile) => Box::into_raw(profile), + None => null_mut(), + } +} + +#[no_mangle] +pub unsafe extern "C" fn qcms_profile_create_gray_with_gamma(mut gamma: f32) -> *mut qcms_profile { + let profile = profile_create_gray_with_gamma(gamma); + match profile { + Some(profile) => Box::into_raw(profile), + None => null_mut(), + } +} + +#[no_mangle] +pub unsafe extern "C" fn qcms_profile_create_rgb_with_gamma( + mut white_point: qcms_CIE_xyY, + mut primaries: qcms_CIE_xyYTRIPLE, + mut gamma: f32, +) -> *mut qcms_profile { + return qcms_profile_create_rgb_with_gamma_set(white_point, primaries, gamma, gamma, gamma); +} + +#[no_mangle] +pub unsafe extern "C" fn qcms_profile_create_rgb_with_table( + mut white_point: qcms_CIE_xyY, + mut primaries: qcms_CIE_xyYTRIPLE, + mut table: *const u16, + mut num_entries: i32, +) -> *mut qcms_profile { + let table = slice::from_raw_parts(table, num_entries as usize); + let profile = profile_create_rgb_with_table(white_point, primaries, table); + match profile { + Some(profile) => Box::into_raw(profile), + None => null_mut(), + } +} + +/* qcms_profile_from_memory does not hold a reference to the memory passed in */ +#[no_mangle] +pub unsafe extern "C" fn qcms_profile_from_memory( + mut mem: *const libc::c_void, + mut size: usize, +) -> *mut qcms_profile { + let mem = slice::from_raw_parts(mem as *const libc::c_uchar, size); + let profile = profile_from_slice(mem); + match profile { + Some(profile) => Box::into_raw(profile), + None => null_mut(), + } +} + +#[no_mangle] +pub unsafe extern "C" fn qcms_profile_get_rendering_intent( + mut profile: *mut qcms_profile, +) -> qcms_intent { + return (*profile).rendering_intent; +} +#[no_mangle] +pub unsafe extern "C" fn qcms_profile_get_color_space( + mut profile: *mut qcms_profile, +) -> icColorSpaceSignature { + return (*profile).color_space; +} + +#[no_mangle] +pub unsafe extern "C" fn qcms_profile_release(mut profile: *mut qcms_profile) { + drop(Box::from_raw(profile)); +} +unsafe extern "C" fn qcms_data_from_file( + mut file: *mut FILE, + mut mem: *mut *mut libc::c_void, + mut size: *mut usize, +) { + let mut length: u32; + let mut remaining_length: u32; + let mut read_length: usize; + let mut length_be: be32 = 0; + let mut data: *mut libc::c_void; + *mem = 0 as *mut libc::c_void; + *size = 0; + if fread( + &mut length_be as *mut be32 as *mut libc::c_void, + 1, + ::std::mem::size_of::(), + file, + ) != ::std::mem::size_of::() + { + return; + } + length = u32::from_be(length_be); + if length > MAX_PROFILE_SIZE as libc::c_uint + || (length as libc::c_ulong) < ::std::mem::size_of::() as libc::c_ulong + { + return; + } + /* allocate room for the entire profile */ + data = malloc(length as usize); + if data.is_null() { + return; + } + /* copy in length to the front so that the buffer will contain the entire profile */ + *(data as *mut be32) = length_be; + remaining_length = + (length as libc::c_ulong - ::std::mem::size_of::() as libc::c_ulong) as u32; + /* read the rest profile */ + read_length = fread( + (data as *mut libc::c_uchar).offset(::std::mem::size_of::() as isize) + as *mut libc::c_void, + 1, + remaining_length as usize, + file, + ) as usize; + if read_length != remaining_length as usize { + free(data); + return; + } + /* successfully get the profile.*/ + *mem = data; + *size = length as usize; +} + +#[no_mangle] +pub unsafe extern "C" fn qcms_profile_from_file(mut file: *mut FILE) -> *mut qcms_profile { + let mut length: usize = 0; + let mut profile: *mut qcms_profile; + let mut data: *mut libc::c_void = 0 as *mut libc::c_void; + qcms_data_from_file(file, &mut data, &mut length); + if data.is_null() || length == 0 { + return 0 as *mut qcms_profile; + } + profile = qcms_profile_from_memory(data, length); + free(data); + return profile; +} +#[no_mangle] +pub unsafe extern "C" fn qcms_profile_from_path( + mut path: *const libc::c_char, +) -> *mut qcms_profile { + let mut profile: *mut qcms_profile = 0 as *mut qcms_profile; + let mut file = fopen(path, b"rb\x00" as *const u8 as *const libc::c_char); + if !file.is_null() { + profile = qcms_profile_from_file(file); + fclose(file); + } + return profile; +} +#[no_mangle] +pub unsafe extern "C" fn qcms_data_from_path( + mut path: *const libc::c_char, + mut mem: *mut *mut libc::c_void, + mut size: *mut usize, +) { + *mem = 0 as *mut libc::c_void; + *size = 0; + let file = fopen(path, b"rb\x00" as *const u8 as *const libc::c_char); + if !file.is_null() { + qcms_data_from_file(file, mem, size); + fclose(file); + }; +} + +#[cfg(windows)] +extern "C" { + pub fn _wfopen(filename: *const libc::wchar_t, mode: *const libc::wchar_t) -> *mut FILE; +} + +#[cfg(windows)] +#[no_mangle] +pub unsafe extern "C" fn qcms_profile_from_unicode_path(mut path: *const libc::wchar_t) { + let mut file = _wfopen(path, ['r' as u16, 'b' as u16, '\0' as u16].as_ptr()); + if !file.is_null() { + qcms_profile_from_file(file); + fclose(file); + }; +} + +#[cfg(windows)] +#[no_mangle] +pub unsafe extern "C" fn qcms_data_from_unicode_path( + mut path: *const libc::wchar_t, + mut mem: *mut *mut libc::c_void, + mut size: *mut usize, +) { + *mem = 0 as *mut libc::c_void; + *size = 0; + let mut file = _wfopen(path, ['r' as u16, 'b' as u16, '\0' as u16].as_ptr()); + if !file.is_null() { + qcms_data_from_file(file, mem, size); + fclose(file); + }; +} diff --git a/gfx/qcms/src/gtest.rs b/gfx/qcms/src/gtest.rs index 954da295e451..6890e7db8f74 100644 --- a/gfx/qcms/src/gtest.rs +++ b/gfx/qcms/src/gtest.rs @@ -1,8 +1,8 @@ #[cfg(test)] mod test { use crate::{ - iccread::*, transform::*, transform_util::lut_inverse_interp16, QCMS_INTENT_DEFAULT, - QCMS_INTENT_PERCEPTUAL, + c_bindings::*, iccread::*, transform::*, transform_util::lut_inverse_interp16, + QCMS_INTENT_DEFAULT, QCMS_INTENT_PERCEPTUAL, }; use libc::c_void; use std::ptr::null_mut; @@ -160,7 +160,7 @@ mod test { qcms_enable_avx() } }; - let sRGB_profile = crate::iccread::qcms_profile_sRGB(); + let sRGB_profile = crate::c_bindings::qcms_profile_sRGB(); let mut Rec709Primaries = qcms_CIE_xyYTRIPLE { red: qcms_CIE_xyY { @@ -212,7 +212,7 @@ mod test { #[test] fn gray_alpha() { - let sRGB_profile = crate::iccread::qcms_profile_sRGB(); + let sRGB_profile = qcms_profile_sRGB(); let other = unsafe { qcms_profile_create_gray_with_gamma(2.2) }; unsafe { qcms_profile_precache_output_transform(&mut *other) }; diff --git a/gfx/qcms/src/iccread.rs b/gfx/qcms/src/iccread.rs index 4cca53b7757f..1279d5e94221 100644 --- a/gfx/qcms/src/iccread.rs +++ b/gfx/qcms/src/iccread.rs @@ -22,14 +22,12 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. use std::{ - ptr::null_mut, - slice, sync::atomic::{AtomicBool, Ordering}, sync::Arc, }; use ::libc; -use libc::{fclose, fopen, fread, free, malloc, memset, FILE}; +use libc::{free, malloc, memset}; use crate::{ double_to_s15Fixed16Number, @@ -282,7 +280,7 @@ unsafe extern "C" fn write_u16(mut mem: *mut libc::c_void, mut offset: usize, mu } /* An arbitrary 4MB limit on profile size */ -const MAX_PROFILE_SIZE: usize = 1024 * 1024 * 4; +pub(crate) const MAX_PROFILE_SIZE: usize = 1024 * 1024 * 4; const MAX_TAG_COUNT: u32 = 1024; fn check_CMM_type_signature(mut src: &mut mem_source) { @@ -1076,69 +1074,7 @@ fn curve_from_gamma(mut gamma: f32) -> Box { // everything in a profile was initialized regardless of how it was created //XXX: should this also be taking a black_point? /* similar to CGColorSpaceCreateCalibratedRGB */ -#[no_mangle] -pub unsafe extern "C" fn qcms_profile_create_rgb_with_gamma_set( - mut white_point: qcms_CIE_xyY, - mut primaries: qcms_CIE_xyYTRIPLE, - mut redGamma: f32, - mut greenGamma: f32, - mut blueGamma: f32, -) -> *mut qcms_profile { - let mut profile = qcms_profile_create(); - - //XXX: should store the whitepoint - if !set_rgb_colorants(&mut profile, white_point, primaries) { - return null_mut(); - } - profile.redTRC = Some(curve_from_gamma(redGamma)); - profile.blueTRC = Some(curve_from_gamma(blueGamma)); - profile.greenTRC = Some(curve_from_gamma(greenGamma)); - profile.class_type = DISPLAY_DEVICE_PROFILE; - profile.rendering_intent = QCMS_INTENT_PERCEPTUAL; - profile.color_space = RGB_SIGNATURE; - profile.pcs = XYZ_TYPE; - return Box::into_raw(profile); -} - -#[no_mangle] -pub unsafe extern "C" fn qcms_profile_create_gray_with_gamma(mut gamma: f32) -> *mut qcms_profile { - let mut profile = qcms_profile_create(); - - profile.grayTRC = Some(curve_from_gamma(gamma)); - if profile.grayTRC.is_none() { - return null_mut(); - } - profile.class_type = DISPLAY_DEVICE_PROFILE; - profile.rendering_intent = QCMS_INTENT_PERCEPTUAL; - profile.color_space = GRAY_SIGNATURE; - profile.pcs = XYZ_TYPE; - return Box::into_raw(profile); -} - -#[no_mangle] -pub unsafe extern "C" fn qcms_profile_create_rgb_with_gamma( - mut white_point: qcms_CIE_xyY, - mut primaries: qcms_CIE_xyYTRIPLE, - mut gamma: f32, -) -> *mut qcms_profile { - return qcms_profile_create_rgb_with_gamma_set(white_point, primaries, gamma, gamma, gamma); -} -#[no_mangle] -pub unsafe extern "C" fn qcms_profile_create_rgb_with_table( - mut white_point: qcms_CIE_xyY, - mut primaries: qcms_CIE_xyYTRIPLE, - mut table: *const u16, - mut num_entries: i32, -) -> *mut qcms_profile { - let table = slice::from_raw_parts(table, num_entries as usize); - let profile = profile_create_rgb_with_table(white_point, primaries, table); - match profile { - Some(profile) => Box::into_raw(profile), - None => null_mut(), - } -} - -fn profile_create_rgb_with_table( +pub fn profile_create_rgb_with_table( mut white_point: qcms_CIE_xyY, mut primaries: qcms_CIE_xyYTRIPLE, table: &[u16], @@ -1243,26 +1179,39 @@ pub fn profile_sRGB() -> Option> { profile_create_rgb_with_table(D65, Rec709Primaries, &table) } -#[no_mangle] -pub extern "C" fn qcms_profile_sRGB() -> *mut qcms_profile { - let profile = profile_sRGB(); - match profile { - Some(profile) => Box::into_raw(profile), - None => null_mut(), - } + +pub fn profile_create_gray_with_gamma(gamma: f32) -> Option> { + let mut profile = qcms_profile_create(); + + profile.grayTRC = Some(curve_from_gamma(gamma)); + profile.class_type = DISPLAY_DEVICE_PROFILE; + profile.rendering_intent = QCMS_INTENT_PERCEPTUAL; + profile.color_space = GRAY_SIGNATURE; + profile.pcs = XYZ_TYPE; + Some(profile) } -/* qcms_profile_from_memory does not hold a reference to the memory passed in */ -#[no_mangle] -pub unsafe extern "C" fn qcms_profile_from_memory( - mut mem: *const libc::c_void, - mut size: usize, -) -> *mut qcms_profile { - let mem = slice::from_raw_parts(mem as *const libc::c_uchar, size); - let profile = profile_from_slice(mem); - match profile { - Some(profile) => Box::into_raw(profile), - None => null_mut(), + +pub fn profile_create_rgb_with_gamma_set( + mut white_point: qcms_CIE_xyY, + mut primaries: qcms_CIE_xyYTRIPLE, + mut redGamma: f32, + mut greenGamma: f32, + mut blueGamma: f32, +) -> Option> { + let mut profile = qcms_profile_create(); + + //XXX: should store the whitepoint + if !set_rgb_colorants(&mut profile, white_point, primaries) { + return None; } + profile.redTRC = Some(curve_from_gamma(redGamma)); + profile.blueTRC = Some(curve_from_gamma(blueGamma)); + profile.greenTRC = Some(curve_from_gamma(greenGamma)); + profile.class_type = DISPLAY_DEVICE_PROFILE; + profile.rendering_intent = QCMS_INTENT_PERCEPTUAL; + profile.color_space = RGB_SIGNATURE; + profile.pcs = XYZ_TYPE; + Some(profile) } pub fn profile_from_slice(mem: &[u8]) -> Option> { @@ -1375,145 +1324,6 @@ pub fn profile_from_slice(mem: &[u8]) -> Option> { } Some(profile) } -#[no_mangle] -pub unsafe extern "C" fn qcms_profile_get_rendering_intent( - mut profile: *mut qcms_profile, -) -> qcms_intent { - return (*profile).rendering_intent; -} -#[no_mangle] -pub unsafe extern "C" fn qcms_profile_get_color_space( - mut profile: *mut qcms_profile, -) -> icColorSpaceSignature { - return (*profile).color_space; -} - -#[no_mangle] -pub unsafe extern "C" fn qcms_profile_release(mut profile: *mut qcms_profile) { - drop(Box::from_raw(profile)); -} -unsafe extern "C" fn qcms_data_from_file( - mut file: *mut FILE, - mut mem: *mut *mut libc::c_void, - mut size: *mut usize, -) { - let mut length: u32; - let mut remaining_length: u32; - let mut read_length: usize; - let mut length_be: be32 = 0; - let mut data: *mut libc::c_void; - *mem = 0 as *mut libc::c_void; - *size = 0; - if fread( - &mut length_be as *mut be32 as *mut libc::c_void, - 1, - ::std::mem::size_of::(), - file, - ) != ::std::mem::size_of::() - { - return; - } - length = be32_to_cpu(length_be); - if length > MAX_PROFILE_SIZE as libc::c_uint - || (length as libc::c_ulong) < ::std::mem::size_of::() as libc::c_ulong - { - return; - } - /* allocate room for the entire profile */ - data = malloc(length as usize); - if data.is_null() { - return; - } - /* copy in length to the front so that the buffer will contain the entire profile */ - *(data as *mut be32) = length_be; - remaining_length = - (length as libc::c_ulong - ::std::mem::size_of::() as libc::c_ulong) as u32; - /* read the rest profile */ - read_length = fread( - (data as *mut libc::c_uchar).offset(::std::mem::size_of::() as isize) - as *mut libc::c_void, - 1, - remaining_length as usize, - file, - ) as usize; - if read_length != remaining_length as usize { - free(data); - return; - } - /* successfully get the profile.*/ - *mem = data; - *size = length as usize; -} -#[no_mangle] -pub unsafe extern "C" fn qcms_profile_from_file(mut file: *mut FILE) -> *mut qcms_profile { - let mut length: usize = 0; - let mut profile: *mut qcms_profile; - let mut data: *mut libc::c_void = 0 as *mut libc::c_void; - qcms_data_from_file(file, &mut data, &mut length); - if data.is_null() || length == 0 { - return 0 as *mut qcms_profile; - } - profile = qcms_profile_from_memory(data, length); - free(data); - return profile; -} -#[no_mangle] -pub unsafe extern "C" fn qcms_profile_from_path( - mut path: *const libc::c_char, -) -> *mut qcms_profile { - let mut profile: *mut qcms_profile = 0 as *mut qcms_profile; - let mut file = fopen(path, b"rb\x00" as *const u8 as *const libc::c_char); - if !file.is_null() { - profile = qcms_profile_from_file(file); - fclose(file); - } - return profile; -} -#[no_mangle] -pub unsafe extern "C" fn qcms_data_from_path( - mut path: *const libc::c_char, - mut mem: *mut *mut libc::c_void, - mut size: *mut usize, -) { - *mem = 0 as *mut libc::c_void; - *size = 0; - let file = fopen(path, b"rb\x00" as *const u8 as *const libc::c_char); - if !file.is_null() { - qcms_data_from_file(file, mem, size); - fclose(file); - }; -} - -#[cfg(windows)] -extern "C" { - pub fn _wfopen(filename: *const libc::wchar_t, mode: *const libc::wchar_t) -> *mut FILE; -} - -#[cfg(windows)] -#[no_mangle] -pub unsafe extern "C" fn qcms_profile_from_unicode_path(mut path: *const libc::wchar_t) { - let mut file = _wfopen(path, ['r' as u16, 'b' as u16, '\0' as u16].as_ptr()); - if !file.is_null() { - qcms_profile_from_file(file); - fclose(file); - }; -} - -#[cfg(windows)] -#[no_mangle] -pub unsafe extern "C" fn qcms_data_from_unicode_path( - mut path: *const libc::wchar_t, - mut mem: *mut *mut libc::c_void, - mut size: *mut usize, -) { - *mem = 0 as *mut libc::c_void; - *size = 0; - let mut file = _wfopen(path, ['r' as u16, 'b' as u16, '\0' as u16].as_ptr()); - if !file.is_null() { - qcms_data_from_file(file, mem, size); - fclose(file); - }; -} #[no_mangle] pub unsafe extern "C" fn qcms_data_create_rgb_with_gamma( diff --git a/gfx/qcms/src/lib.rs b/gfx/qcms/src/lib.rs index ac57599675bd..13b8a4a60540 100644 --- a/gfx/qcms/src/lib.rs +++ b/gfx/qcms/src/lib.rs @@ -40,6 +40,7 @@ fn double_to_s15Fixed16Number(mut v: f64) -> s15Fixed16Number { return (v * 65536f64) as i32; } +pub mod c_bindings; pub mod chain; pub mod gtest; pub mod iccread;