Bug 1681726 - Move c bindings to a separate file. r=aosmond

This will isolate the unsafe and make building without them easier.

Differential Revision: https://phabricator.services.mozilla.com/D99350
This commit is contained in:
Jeff Muizelaar 2020-12-10 14:34:39 +00:00
Родитель bf42446e07
Коммит 942dba0566
5 изменённых файлов: 264 добавлений и 229 удалений

Просмотреть файл

@ -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)
{

222
gfx/qcms/src/c_bindings.rs Normal file
Просмотреть файл

@ -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::<be32>(),
file,
) != ::std::mem::size_of::<be32>()
{
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::<be32>() 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::<be32>() as libc::c_ulong) as u32;
/* read the rest profile */
read_length = fread(
(data as *mut libc::c_uchar).offset(::std::mem::size_of::<be32>() 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);
};
}

Просмотреть файл

@ -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) };

Просмотреть файл

@ -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<curveType> {
// 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<Box<qcms_profile>> {
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<Box<qcms_profile>> {
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<Box<qcms_profile>> {
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<Box<qcms_profile>> {
@ -1375,145 +1324,6 @@ pub fn profile_from_slice(mem: &[u8]) -> Option<Box<qcms_profile>> {
}
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::<be32>(),
file,
) != ::std::mem::size_of::<be32>()
{
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::<be32>() 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::<be32>() as libc::c_ulong) as u32;
/* read the rest profile */
read_length = fread(
(data as *mut libc::c_uchar).offset(::std::mem::size_of::<be32>() 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(

Просмотреть файл

@ -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;