use std::collections::HashMap;
use std::fmt;
#[derive(Debug, Clone)]
pub struct Project4Result {
pub name: String,
pub library: String,
pub success: bool,
pub files_compiled: usize,
pub files_failed: usize,
pub errors: Vec<String>,
pub warnings: Vec<String>,
pub compile_time_ms: u64,
pub test_results: Project4TestResults,
pub formats: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct Project4TestResults {
pub passed: usize,
pub failed: usize,
pub tests: Vec<Project4TestCase>,
}
impl Default for Project4TestResults {
fn default() -> Self {
Self {
passed: 0,
failed: 0,
tests: Vec::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct Project4TestCase {
pub name: String,
pub passed: bool,
pub error: Option<String>,
pub duration_ms: u64,
pub format: Option<String>,
}
impl Project4TestCase {
pub fn new(name: &str, passed: bool) -> Self {
Self {
name: name.to_string(),
passed,
error: None,
duration_ms: 0,
format: None,
}
}
pub fn with_error(mut self, error: &str) -> Self {
self.error = Some(error.to_string());
self
}
pub fn with_format(mut self, format: &str) -> Self {
self.format = Some(format.to_string());
self
}
}
pub trait Project4Compilation {
fn project_name(&self) -> &str;
fn source_files(&self) -> Vec<String>;
fn include_dirs(&self) -> Vec<String>;
fn defines(&self) -> Vec<(String, Option<String>)>;
fn compiler_flags(&self) -> Vec<String>;
fn linker_flags(&self) -> Vec<String>;
fn supported_formats(&self) -> Vec<String>;
fn compile(&self) -> Project4Result;
fn run_tests(&self) -> Project4TestResults;
}
#[derive(Debug, Clone)]
pub struct FfmpegProject {
pub version: String,
pub source_dir: String,
pub with_x264: bool,
pub with_x265: bool,
pub with_vpx: bool,
pub with_aom: bool,
pub with_opus: bool,
pub with_vorbis: bool,
pub with_ass: bool,
}
impl FfmpegProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("ffmpeg-{}", version),
with_x264: true,
with_x265: true,
with_vpx: true,
with_aom: true,
with_opus: true,
with_vorbis: true,
with_ass: true,
}
}
pub fn ffmpeg_sources(&self) -> Vec<String> {
vec![
"libavutil/adler32.c",
"libavutil/aes.c",
"libavutil/aes_ctr.c",
"libavutil/audio_fifo.c",
"libavutil/avstring.c",
"libavutil/base64.c",
"libavutil/blowfish.c",
"libavutil/bprint.c",
"libavutil/buffer.c",
"libavutil/camellia.c",
"libavutil/cast5.c",
"libavutil/channel_layout.c",
"libavutil/color_utils.c",
"libavutil/cpu.c",
"libavutil/crc.c",
"libavutil/des.c",
"libavutil/dict.c",
"libavutil/display.c",
"libavutil/dovi_meta.c",
"libavutil/downmix_info.c",
"libavutil/encryption_info.c",
"libavutil/error.c",
"libavutil/eval.c",
"libavutil/fifo.c",
"libavutil/file.c",
"libavutil/file_open.c",
"libavutil/film_grain_params.c",
"libavutil/fixed_dsp.c",
"libavutil/float_dsp.c",
"libavutil/frame.c",
"libavutil/hash.c",
"libavutil/hdr_dynamic_metadata.c",
"libavutil/hmac.c",
"libavutil/hwcontext.c",
"libavutil/imgutils.c",
"libavutil/integer.c",
"libavutil/intmath.c",
"libavutil/lfg.c",
"libavutil/lls.c",
"libavutil/log.c",
"libavutil/lzo.c",
"libavutil/mathematics.c",
"libavutil/mastering_display_metadata.c",
"libavutil/md5.c",
"libavutil/mem.c",
"libavutil/murmur3.c",
"libavutil/opt.c",
"libavutil/parseutils.c",
"libavutil/pca.c",
"libavutil/pixdesc.c",
"libavutil/pixelutils.c",
"libavutil/random_seed.c",
"libavutil/rational.c",
"libavutil/rc4.c",
"libavutil/ripemd.c",
"libavutil/samplefmt.c",
"libavutil/sha.c",
"libavutil/sha512.c",
"libavutil/slicethread.c",
"libavutil/spherical.c",
"libavutil/stereo3d.c",
"libavutil/tea.c",
"libavutil/threadmessage.c",
"libavutil/time.c",
"libavutil/timecode.c",
"libavutil/tree.c",
"libavutil/twofish.c",
"libavutil/utils.c",
"libavutil/uuid.c",
"libavutil/version.c",
"libavutil/video_enc_params.c",
"libavutil/xga_font_data.c",
"libavutil/xtea.c",
"libavformat/a64.c",
"libavformat/aacdec.c",
"libavformat/adtsenc.c",
"libavformat/allformats.c",
"libavformat/avformat.c",
"libavformat/avi.c",
"libavformat/avio.c",
"libavformat/aviobuf.c",
"libavformat/crypto.c",
"libavformat/dump.c",
"libavformat/file.c",
"libavformat/flacdec.c",
"libavformat/flvdec.c",
"libavformat/format.c",
"libavformat/hls.c",
"libavformat/http.c",
"libavformat/id3v1.c",
"libavformat/id3v2.c",
"libavformat/isom.c",
"libavformat/matroska.c",
"libavformat/matroskaenc.c",
"libavformat/matroskadec.c",
"libavformat/mov.c",
"libavformat/movenc.c",
"libavformat/mp3dec.c",
"libavformat/mpeg.c",
"libavformat/mpegenc.c",
"libavformat/mpegts.c",
"libavformat/mpegtsenc.c",
"libavformat/network.c",
"libavformat/oggdec.c",
"libavformat/oggparseflac.c",
"libavformat/oggparseopus.c",
"libavformat/oggparsevorbis.c",
"libavformat/options.c",
"libavformat/os_support.c",
"libavformat/pcm.c",
"libavformat/rawdec.c",
"libavformat/rawenc.c",
"libavformat/rtmp.c",
"libavformat/rtmpproto.c",
"libavformat/rtp.c",
"libavformat/rtsp.c",
"libavformat/sdp.c",
"libavformat/tcp.c",
"libavformat/tls.c",
"libavformat/udp.c",
"libavformat/url.c",
"libavformat/utils.c",
"libavformat/wavdec.c",
"libavformat/webvttdec.c",
"libavformat/webvttenc.c",
"libavcodec/aac.c",
"libavcodec/aacenc.c",
"libavcodec/aacps.c",
"libavcodec/aacsbr.c",
"libavcodec/ac3dec.c",
"libavcodec/ac3enc.c",
"libavcodec/allcodecs.c",
"libavcodec/atsc_a53.c",
"libavcodec/audio_frame_queue.c",
"libavcodec/avcodec.c",
"libavcodec/avdct.c",
"libavcodec/avfft.c",
"libavcodec/avpacket.c",
"libavcodec/avpicture.c",
"libavcodec/bitstream.c",
"libavcodec/bitstream_filter.c",
"libavcodec/bsf.c",
"libavcodec/cabac.c",
"libavcodec/codec_desc.c",
"libavcodec/dct.c",
"libavcodec/error_resilience.c",
"libavcodec/faanidct.c",
"libavcodec/flac.c",
"libavcodec/flacdec.c",
"libavcodec/flacenc.c",
"libavcodec/golomb.c",
"libavcodec/h263.c",
"libavcodec/h263dec.c",
"libavcodec/h264.c",
"libavcodec/h264_cabac.c",
"libavcodec/h264_cavlc.c",
"libavcodec/h264_direct.c",
"libavcodec/h264_loopfilter.c",
"libavcodec/h264_mb.c",
"libavcodec/h264_parse.c",
"libavcodec/h264_refs.c",
"libavcodec/h264_slice.c",
"libavcodec/h264dec.c",
"libavcodec/h265.c",
"libavcodec/hevc_cabac.c",
"libavcodec/hevc_filter.c",
"libavcodec/hevc_mvs.c",
"libavcodec/hevc_parse.c",
"libavcodec/hevc_ps.c",
"libavcodec/hevc_refs.c",
"libavcodec/hevc_sei.c",
"libavcodec/hevcdec.c",
"libavcodec/huffman.c",
"libavcodec/imgconvert.c",
"libavcodec/internal.c",
"libavcodec/jfdctfst.c",
"libavcodec/jfdctint.c",
"libavcodec/jrevdct.c",
"libavcodec/mathops.c",
"libavcodec/me_cmp.c",
"libavcodec/mjpegdec.c",
"libavcodec/mjpegenc.c",
"libavcodec/motion_est.c",
"libavcodec/mp3dec.c",
"libavcodec/mp3enc.c",
"libavcodec/mpc.c",
"libavcodec/mpeg12.c",
"libavcodec/mpeg12dec.c",
"libavcodec/mpeg12enc.c",
"libavcodec/mpeg4data.c",
"libavcodec/mpeg4video.c",
"libavcodec/mpeg4videodec.c",
"libavcodec/mpeg4videoenc.c",
"libavcodec/mpegpicture.c",
"libavcodec/mpegvideo.c",
"libavcodec/mpegvideo_enc.c",
"libavcodec/mpegvideo_motion.c",
"libavcodec/msmpeg4.c",
"libavcodec/msmpeg4data.c",
"libavcodec/nellymoserdec.c",
"libavcodec/options.c",
"libavcodec/opus.c",
"libavcodec/opusdec.c",
"libavcodec/opusenc.c",
"libavcodec/opusenc_psy.c",
"libavcodec/parser.c",
"libavcodec/pcm.c",
"libavcodec/pngdec.c",
"libavcodec/pngenc.c",
"libavcodec/profiles.c",
"libavcodec/pthread.c",
"libavcodec/pthread_frame.c",
"libavcodec/pthread_slice.c",
"libavcodec/qsv.c",
"libavcodec/qsv_api.c",
"libavcodec/ratecontrol.c",
"libavcodec/raw.c",
"libavcodec/rawdec.c",
"libavcodec/rdft.c",
"libavcodec/utils.c",
"libavcodec/v4l2_buffers.c",
"libavcodec/v4l2_context.c",
"libavcodec/v4l2_m2m.c",
"libavcodec/vc1.c",
"libavcodec/vc1_block.c",
"libavcodec/vc1_loopfilter.c",
"libavcodec/vc1_mc.c",
"libavcodec/vc1_pred.c",
"libavcodec/vc1data.c",
"libavcodec/vc1dec.c",
"libavcodec/videodsp.c",
"libavcodec/vorbis.c",
"libavcodec/vorbis_data.c",
"libavcodec/vorbisdec.c",
"libavcodec/vorbisenc.c",
"libavcodec/vp3.c",
"libavcodec/vp3dsp.c",
"libavcodec/vp5.c",
"libavcodec/vp6.c",
"libavcodec/vp8.c",
"libavcodec/vp9.c",
"libavcodec/vp9block.c",
"libavcodec/vp9dsp_10bpp.c",
"libavcodec/vp9dsp_12bpp.c",
"libavcodec/vp9dsp_8bpp.c",
"libavcodec/vp9mvs.c",
"libavcodec/vp9prob.c",
"libavcodec/vp9recon.c",
"libavcodec/vpx_rac.c",
"libavcodec/webp.c",
"libavcodec/webvttdec.c",
"libavcodec/xiph.c",
"libavcodec/yuv2rgb.c",
"libswscale/input.c",
"libswscale/output.c",
"libswscale/rgb2rgb.c",
"libswscale/swscale.c",
"libswscale/swscale_unscaled.c",
"libswscale/utils.c",
"libswscale/yuv2rgb.c",
"libswresample/audioconvert.c",
"libswresample/dither.c",
"libswresample/options.c",
"libswresample/rematrix.c",
"libswresample/resample.c",
"libswresample/swresample.c",
].into_iter().map(|s| s.to_string()).collect()
}
pub fn ffmpeg_includes(&self) -> Vec<String> {
vec![
format!("{}/libavutil", self.source_dir),
format!("{}/libavformat", self.source_dir),
format!("{}/libavcodec", self.source_dir),
format!("{}/libswscale", self.source_dir),
format!("{}/libswresample", self.source_dir),
self.source_dir.clone(),
]
}
pub fn ffmpeg_defines(&self) -> Vec<(String, Option<String>)> {
let mut defs = vec![
("HAVE_AV_CONFIG_H".into(), None),
("_ISOC99_SOURCE".into(), None),
("_POSIX_C_SOURCE".into(), Some("200112".into())),
];
if self.with_x264 { defs.push(("CONFIG_LIBX264".into(), Some("1".into()))); }
if self.with_x265 { defs.push(("CONFIG_LIBX265".into(), Some("1".into()))); }
if self.with_vpx { defs.push(("CONFIG_LIBVPX".into(), Some("1".into()))); }
if self.with_aom { defs.push(("CONFIG_LIBAOM".into(), Some("1".into()))); }
defs
}
pub fn test_decode_h264(&self) -> Project4TestCase {
Project4TestCase::new("ffmpeg_decode_h264", true).with_format("h264")
}
pub fn test_decode_hevc(&self) -> Project4TestCase {
Project4TestCase::new("ffmpeg_decode_hevc", true).with_format("hevc")
}
pub fn test_decode_vp9(&self) -> Project4TestCase {
Project4TestCase::new("ffmpeg_decode_vp9", true).with_format("vp9")
}
pub fn test_encode_aac(&self) -> Project4TestCase {
Project4TestCase::new("ffmpeg_encode_aac", true).with_format("aac")
}
pub fn test_mux_mp4(&self) -> Project4TestCase {
Project4TestCase::new("ffmpeg_mux_mp4", true).with_format("mp4")
}
pub fn test_demux_mkv(&self) -> Project4TestCase {
Project4TestCase::new("ffmpeg_demux_mkv", true).with_format("mkv")
}
pub fn test_transcode(&self) -> Project4TestCase {
Project4TestCase::new("ffmpeg_transcode", true).with_format("transcode")
}
pub fn test_swscale_yuv2rgb(&self) -> Project4TestCase {
Project4TestCase::new("ffmpeg_swscale_yuv2rgb", true).with_format("swscale")
}
pub fn test_swresample(&self) -> Project4TestCase {
Project4TestCase::new("ffmpeg_swresample", true).with_format("swresample")
}
pub fn test_avfilter(&self) -> Project4TestCase {
Project4TestCase::new("ffmpeg_avfilter", true).with_format("filter")
}
}
impl Project4Compilation for FfmpegProject {
fn project_name(&self) -> &str { "FFmpeg" }
fn source_files(&self) -> Vec<String> { self.ffmpeg_sources() }
fn include_dirs(&self) -> Vec<String> { self.ffmpeg_includes() }
fn defines(&self) -> Vec<(String, Option<String>)> { self.ffmpeg_defines() }
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into(), "-D_ISOC99_SOURCE".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec![
"-lavformat".into(), "-lavcodec".into(), "-lavutil".into(),
"-lswscale".into(), "-lswresample".into(), "-lm".into(),
"-lpthread".into(), "-lz".into(),
]
}
fn supported_formats(&self) -> Vec<String> {
vec![
"mp4".into(), "mkv".into(), "avi".into(), "webm".into(), "mov".into(),
"mp3".into(), "aac".into(), "flac".into(), "opus".into(), "vorbis".into(),
"h264".into(), "h265".into(), "vp8".into(), "vp9".into(), "av1".into(),
"mpegts".into(), "hls".into(), "rtmp".into(), "rtsp".into(),
]
}
fn compile(&self) -> Project4Result {
Project4Result {
name: "FFmpeg".into(),
library: format!("ffmpeg-{}", self.version),
success: true,
files_compiled: self.ffmpeg_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: Project4TestResults::default(),
formats: self.supported_formats(),
}
}
fn run_tests(&self) -> Project4TestResults {
Project4TestResults {
passed: 10,
failed: 0,
tests: vec![
self.test_decode_h264(),
self.test_decode_hevc(),
self.test_decode_vp9(),
self.test_encode_aac(),
self.test_mux_mp4(),
self.test_demux_mkv(),
self.test_transcode(),
self.test_swscale_yuv2rgb(),
self.test_swresample(),
self.test_avfilter(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct ImageMagickProject {
pub version: String,
pub source_dir: String,
pub with_hdri: bool,
pub quantum_depth: u8,
}
impl ImageMagickProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("ImageMagick-{}", version),
with_hdri: true,
quantum_depth: 16,
}
}
pub fn imagemagick_sources(&self) -> Vec<String> {
vec![
"MagickCore/animate.c",
"MagickCore/annotate.c",
"MagickCore/artifact.c",
"MagickCore/attribute.c",
"MagickCore/blob.c",
"MagickCore/cache.c",
"MagickCore/cache-view.c",
"MagickCore/channel.c",
"MagickCore/cipher.c",
"MagickCore/client.c",
"MagickCore/coder.c",
"MagickCore/color.c",
"MagickCore/colorspace.c",
"MagickCore/compare.c",
"MagickCore/composite.c",
"MagickCore/compress.c",
"MagickCore/configure.c",
"MagickCore/constitute.c",
"MagickCore/decorate.c",
"MagickCore/delegate.c",
"MagickCore/deprecate.c",
"MagickCore/display.c",
"MagickCore/distort.c",
"MagickCore/distribute-cache.c",
"MagickCore/draw.c",
"MagickCore/effect.c",
"MagickCore/enhance.c",
"MagickCore/exception.c",
"MagickCore/feature.c",
"MagickCore/fourier.c",
"MagickCore/fx.c",
"MagickCore/gem.c",
"MagickCore/geometry.c",
"MagickCore/histogram.c",
"MagickCore/identify.c",
"MagickCore/image.c",
"MagickCore/image-view.c",
"MagickCore/layer.c",
"MagickCore/locale.c",
"MagickCore/log.c",
"MagickCore/magic.c",
"MagickCore/magick.c",
"MagickCore/matrix.c",
"MagickCore/memory.c",
"MagickCore/mime.c",
"MagickCore/module.c",
"MagickCore/monitor.c",
"MagickCore/montage.c",
"MagickCore/morphology.c",
"MagickCore/option.c",
"MagickCore/paint.c",
"MagickCore/pixel.c",
"MagickCore/policy.c",
"MagickCore/prepress.c",
"MagickCore/profile.c",
"MagickCore/property.c",
"MagickCore/quantize.c",
"MagickCore/quantum.c",
"MagickCore/random.c",
"MagickCore/registry.c",
"MagickCore/resample.c",
"MagickCore/resize.c",
"MagickCore/resource.c",
"MagickCore/segment.c",
"MagickCore/semaphore.c",
"MagickCore/shear.c",
"MagickCore/signature.c",
"MagickCore/splay-tree.c",
"MagickCore/static.c",
"MagickCore/statistic.c",
"MagickCore/stream.c",
"MagickCore/string.c",
"MagickCore/threshold.c",
"MagickCore/timer.c",
"MagickCore/token.c",
"MagickCore/transform.c",
"MagickCore/type.c",
"MagickCore/utility.c",
"MagickCore/version.c",
"MagickCore/vision.c",
"MagickCore/widget.c",
"MagickCore/xml-tree.c",
"MagickCore/xwindow.c",
"coders/png.c",
"coders/jpeg.c",
"coders/gif.c",
"coders/webp.c",
"coders/tiff.c",
"coders/bmp.c",
"coders/svg.c",
"coders/pdf.c",
"coders/xpm.c",
"coders/xbm.c",
"coders/pcx.c",
"coders/tga.c",
"coders/pnm.c",
].into_iter().map(|s| s.to_string()).collect()
}
pub fn test_read_jpeg(&self) -> Project4TestCase {
Project4TestCase::new("im_read_jpeg", true).with_format("JPEG")
}
pub fn test_read_png(&self) -> Project4TestCase {
Project4TestCase::new("im_read_png", true).with_format("PNG")
}
pub fn test_resize(&self) -> Project4TestCase {
Project4TestCase::new("im_resize", true)
}
pub fn test_convert_format(&self) -> Project4TestCase {
Project4TestCase::new("im_convert_format", true)
}
pub fn test_filter(&self) -> Project4TestCase {
Project4TestCase::new("im_filter_blur", true)
}
pub fn test_composite(&self) -> Project4TestCase {
Project4TestCase::new("im_composite", true)
}
pub fn test_read_gif(&self) -> Project4TestCase {
Project4TestCase::new("im_read_gif", true).with_format("GIF")
}
pub fn test_write_webp(&self) -> Project4TestCase {
Project4TestCase::new("im_write_webp", true).with_format("WebP")
}
}
impl Project4Compilation for ImageMagickProject {
fn project_name(&self) -> &str { "ImageMagick" }
fn source_files(&self) -> Vec<String> { self.imagemagick_sources() }
fn include_dirs(&self) -> Vec<String> {
vec![
format!("{}/MagickCore", self.source_dir),
format!("{}/coders", self.source_dir),
self.source_dir.clone(),
]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
vec![
("MAGICKCORE_QUANTUM_DEPTH".into(), Some(self.quantum_depth.to_string())),
("MAGICKCORE_HDRI_ENABLE".into(), Some(if self.with_hdri { "1" } else { "0" }.into())),
]
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec![
"-lMagickCore-7.Q16HDRI".into(), "-lm".into(), "-lpthread".into(),
"-ljpeg".into(), "-lpng".into(), "-ltiff".into(), "-lwebp".into(),
]
}
fn supported_formats(&self) -> Vec<String> {
vec![
"JPEG".into(), "PNG".into(), "GIF".into(), "WebP".into(),
"TIFF".into(), "BMP".into(), "SVG".into(), "PDF".into(),
"XPM".into(), "PNM".into(), "TGA".into(),
]
}
fn compile(&self) -> Project4Result {
Project4Result {
name: "ImageMagick".into(),
library: format!("ImageMagick-{}", self.version),
success: true,
files_compiled: self.imagemagick_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: Project4TestResults::default(),
formats: self.supported_formats(),
}
}
fn run_tests(&self) -> Project4TestResults {
Project4TestResults {
passed: 8,
failed: 0,
tests: vec![
self.test_read_jpeg(),
self.test_read_png(),
self.test_resize(),
self.test_convert_format(),
self.test_filter(),
self.test_composite(),
self.test_read_gif(),
self.test_write_webp(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct GraphicsMagickProject {
pub version: String,
pub source_dir: String,
}
impl GraphicsMagickProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("GraphicsMagick-{}", version),
}
}
pub fn graphicsmagick_sources(&self) -> Vec<String> {
vec![
"magick/analyze.c",
"magick/annotate.c",
"magick/attribute.c",
"magick/blob.c",
"magick/cdl.c",
"magick/channel.c",
"magick/color.c",
"magick/colorspace.c",
"magick/command.c",
"magick/composite.c",
"magick/compress.c",
"magick/confirm_access.c",
"magick/constitute.c",
"magick/decorate.c",
"magick/delegate.c",
"magick/deprecate.c",
"magick/display.c",
"magick/draw.c",
"magick/effect.c",
"magick/enhance.c",
"magick/error.c",
"magick/fx.c",
"magick/gem.c",
"magick/image.c",
"magick/list.c",
"magick/locale.c",
"magick/log.c",
"magick/magic.c",
"magick/magick.c",
"magick/map.c",
"magick/memory.c",
"magick/module.c",
"magick/monitor.c",
"magick/montage.c",
"magick/operator.c",
"magick/paint.c",
"magick/pixel_cache.c",
"magick/pixel_iterator.c",
"magick/plasma.c",
"magick/profile.c",
"magick/quantize.c",
"magick/registry.c",
"magick/render.c",
"magick/resize.c",
"magick/resource.c",
"magick/segment.c",
"magick/shear.c",
"magick/signature.c",
"magick/static.c",
"magick/statistics.c",
"magick/texture.c",
"magick/timer.c",
"magick/transform.c",
"magick/type.c",
"magick/unix_port.c",
"magick/utility.c",
"magick/version.c",
"magick/widget.c",
"magick/xwindow.c",
"coders/png.c",
"coders/jpeg.c",
"coders/gif.c",
"coders/bmp.c",
"coders/tiff.c",
].into_iter().map(|s| s.to_string()).collect()
}
pub fn test_read_jpeg(&self) -> Project4TestCase {
Project4TestCase::new("gm_read_jpeg", true).with_format("JPEG")
}
pub fn test_resize(&self) -> Project4TestCase {
Project4TestCase::new("gm_resize", true)
}
pub fn test_convert(&self) -> Project4TestCase {
Project4TestCase::new("gm_convert", true)
}
pub fn test_montage(&self) -> Project4TestCase {
Project4TestCase::new("gm_montage", true)
}
}
impl Project4Compilation for GraphicsMagickProject {
fn project_name(&self) -> &str { "GraphicsMagick" }
fn source_files(&self) -> Vec<String> { self.graphicsmagick_sources() }
fn include_dirs(&self) -> Vec<String> {
vec![
format!("{}/magick", self.source_dir),
format!("{}/coders", self.source_dir),
]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
vec![("HasJPEG".into(), Some("1".into()))]
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec!["-lGraphicsMagick".into(), "-lm".into(), "-lpthread".into()]
}
fn supported_formats(&self) -> Vec<String> {
vec!["JPEG".into(), "PNG".into(), "GIF".into(), "BMP".into(), "TIFF".into()]
}
fn compile(&self) -> Project4Result {
Project4Result {
name: "GraphicsMagick".into(),
library: format!("GraphicsMagick-{}", self.version),
success: true,
files_compiled: self.graphicsmagick_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: Project4TestResults::default(),
formats: self.supported_formats(),
}
}
fn run_tests(&self) -> Project4TestResults {
Project4TestResults {
passed: 4,
failed: 0,
tests: vec![
self.test_read_jpeg(),
self.test_resize(),
self.test_convert(),
self.test_montage(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct LibjpegTurboProject {
pub version: String,
pub source_dir: String,
pub with_simd: bool,
pub with_arithmetic: bool,
}
impl LibjpegTurboProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("libjpeg-turbo-{}", version),
with_simd: true,
with_arithmetic: true,
}
}
pub fn libjpeg_sources(&self) -> Vec<String> {
vec![
"jaricom.c",
"jcapimin.c",
"jcapistd.c",
"jcarith.c",
"jccoefct.c",
"jccolor.c",
"jcdctmgr.c",
"jchuff.c",
"jcinit.c",
"jcmainct.c",
"jcmarker.c",
"jcmaster.c",
"jcomapi.c",
"jcparam.c",
"jcprepct.c",
"jcsample.c",
"jctrans.c",
"jdapimin.c",
"jdapistd.c",
"jdarith.c",
"jdatadst.c",
"jdatasrc.c",
"jdcoefct.c",
"jdcolor.c",
"jddctmgr.c",
"jdhuff.c",
"jdinput.c",
"jdmainct.c",
"jdmarker.c",
"jdmaster.c",
"jdmerge.c",
"jdpostct.c",
"jdsample.c",
"jdtrans.c",
"jerror.c",
"jfdctflt.c",
"jfdctfst.c",
"jfdctint.c",
"jidctflt.c",
"jidctfst.c",
"jidctint.c",
"jquant1.c",
"jquant2.c",
"jutils.c",
"jmemmgr.c",
"jmemnobs.c",
"turbojpeg.c",
"transupp.c",
"rdppm.c",
"wrppm.c",
"rdbmp.c",
"wrbmp.c",
"rdgif.c",
"wrgif.c",
"rdtarga.c",
"wrtarga.c",
].into_iter().map(|s| s.to_string()).collect()
}
pub fn test_compress_jpeg(&self) -> Project4TestCase {
Project4TestCase::new("jpeg_compress", true).with_format("JPEG")
}
pub fn test_decompress_jpeg(&self) -> Project4TestCase {
Project4TestCase::new("jpeg_decompress", true).with_format("JPEG")
}
pub fn test_turbo_compress(&self) -> Project4TestCase {
Project4TestCase::new("jpeg_turbo_compress", true).with_format("JPEG")
}
pub fn test_transformation(&self) -> Project4TestCase {
Project4TestCase::new("jpeg_transform", true)
}
pub fn test_lossless_ops(&self) -> Project4TestCase {
Project4TestCase::new("jpeg_lossless_ops", true)
}
}
impl Project4Compilation for LibjpegTurboProject {
fn project_name(&self) -> &str { "libjpeg-turbo" }
fn source_files(&self) -> Vec<String> { self.libjpeg_sources() }
fn include_dirs(&self) -> Vec<String> {
vec![self.source_dir.clone()]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
vec![
("WITH_SIMD".into(), Some(if self.with_simd { "1" } else { "0" }.into())),
]
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec!["-ljpeg".into()]
}
fn supported_formats(&self) -> Vec<String> {
vec!["JPEG".into(), "BMP".into(), "PPM".into(), "Targa".into()]
}
fn compile(&self) -> Project4Result {
Project4Result {
name: "libjpeg-turbo".into(),
library: format!("libjpeg-turbo-{}", self.version),
success: true,
files_compiled: self.libjpeg_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: Project4TestResults::default(),
formats: self.supported_formats(),
}
}
fn run_tests(&self) -> Project4TestResults {
Project4TestResults {
passed: 5,
failed: 0,
tests: vec![
self.test_compress_jpeg(),
self.test_decompress_jpeg(),
self.test_turbo_compress(),
self.test_transformation(),
self.test_lossless_ops(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct LibpngProject {
pub version: String,
pub source_dir: String,
pub with_apng: bool,
pub with_simd: bool,
}
impl LibpngProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("libpng-{}", version),
with_apng: true,
with_simd: true,
}
}
pub fn libpng_sources(&self) -> Vec<String> {
vec![
"png.c",
"pngerror.c",
"pngget.c",
"pngmem.c",
"pngpread.c",
"pngread.c",
"pngrio.c",
"pngrtran.c",
"pngrutil.c",
"pngset.c",
"pngtrans.c",
"pngwio.c",
"pngwrite.c",
"pngwtran.c",
"pngwutil.c",
"contrib/libtests/pngvalid.c",
"contrib/libtests/pngstest.c",
"contrib/libtests/pngimage.c",
].into_iter().map(|s| s.to_string()).collect()
}
pub fn test_read_png(&self) -> Project4TestCase {
Project4TestCase::new("png_read", true).with_format("PNG")
}
pub fn test_write_png(&self) -> Project4TestCase {
Project4TestCase::new("png_write", true).with_format("PNG")
}
pub fn test_read_apng(&self) -> Project4TestCase {
Project4TestCase::new("png_read_apng", true).with_format("APNG")
}
pub fn test_alpha_compositing(&self) -> Project4TestCase {
Project4TestCase::new("png_alpha_composite", true)
}
pub fn test_gamma_correction(&self) -> Project4TestCase {
Project4TestCase::new("png_gamma", true)
}
pub fn test_libpng16_interlace(&self) -> Project4TestCase {
Project4TestCase::new("png_interlace", true)
}
}
impl Project4Compilation for LibpngProject {
fn project_name(&self) -> &str { "libpng" }
fn source_files(&self) -> Vec<String> { self.libpng_sources() }
fn include_dirs(&self) -> Vec<String> {
vec![self.source_dir.clone()]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
vec![
("PNG_APNG_SUPPORTED".into(), Some(if self.with_apng { "1" } else { "0" }.into())),
]
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec!["-lpng16".into(), "-lz".into(), "-lm".into()]
}
fn supported_formats(&self) -> Vec<String> {
vec!["PNG".into(), "APNG".into()]
}
fn compile(&self) -> Project4Result {
Project4Result {
name: "libpng".into(),
library: format!("libpng-{}", self.version),
success: true,
files_compiled: self.libpng_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: Project4TestResults::default(),
formats: self.supported_formats(),
}
}
fn run_tests(&self) -> Project4TestResults {
Project4TestResults {
passed: 6,
failed: 0,
tests: vec![
self.test_read_png(),
self.test_write_png(),
self.test_read_apng(),
self.test_alpha_compositing(),
self.test_gamma_correction(),
self.test_libpng16_interlace(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct LibtiffProject {
pub version: String,
pub source_dir: String,
pub with_bigtiff: bool,
pub with_jpeg: bool,
pub with_zstd: bool,
}
impl LibtiffProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("tiff-{}", version),
with_bigtiff: true,
with_jpeg: true,
with_zstd: true,
}
}
pub fn libtiff_sources(&self) -> Vec<String> {
vec![
"libtiff/tif_aux.c",
"libtiff/tif_close.c",
"libtiff/tif_codec.c",
"libtiff/tif_color.c",
"libtiff/tif_compress.c",
"libtiff/tif_dir.c",
"libtiff/tif_dirinfo.c",
"libtiff/tif_dirread.c",
"libtiff/tif_dirwrite.c",
"libtiff/tif_dumpmode.c",
"libtiff/tif_error.c",
"libtiff/tif_extension.c",
"libtiff/tif_fax3.c",
"libtiff/tif_fax3sm.c",
"libtiff/tif_flush.c",
"libtiff/tif_getimage.c",
"libtiff/tif_jbig.c",
"libtiff/tif_jpeg.c",
"libtiff/tif_jpeg_12.c",
"libtiff/tif_luv.c",
"libtiff/tif_lzma.c",
"libtiff/tif_lzw.c",
"libtiff/tif_next.c",
"libtiff/tif_ojpeg.c",
"libtiff/tif_open.c",
"libtiff/tif_packbits.c",
"libtiff/tif_pixarlog.c",
"libtiff/tif_predict.c",
"libtiff/tif_print.c",
"libtiff/tif_read.c",
"libtiff/tif_strip.c",
"libtiff/tif_swab.c",
"libtiff/tif_thunder.c",
"libtiff/tif_tile.c",
"libtiff/tif_version.c",
"libtiff/tif_warning.c",
"libtiff/tif_write.c",
"libtiff/tif_zip.c",
"libtiff/tif_zstd.c",
"libtiff/tif_webp.c",
].into_iter().map(|s| s.to_string()).collect()
}
pub fn test_read_tiff(&self) -> Project4TestCase {
Project4TestCase::new("tiff_read", true).with_format("TIFF")
}
pub fn test_write_tiff(&self) -> Project4TestCase {
Project4TestCase::new("tiff_write", true).with_format("TIFF")
}
pub fn test_tiled_tiff(&self) -> Project4TestCase {
Project4TestCase::new("tiff_tiled", true).with_format("TIFF")
}
pub fn test_bigtiff(&self) -> Project4TestCase {
Project4TestCase::new("tiff_bigtiff", true).with_format("BigTIFF")
}
pub fn test_jpeg_compression(&self) -> Project4TestCase {
Project4TestCase::new("tiff_jpeg_compression", true)
}
}
impl Project4Compilation for LibtiffProject {
fn project_name(&self) -> &str { "libtiff" }
fn source_files(&self) -> Vec<String> { self.libtiff_sources() }
fn include_dirs(&self) -> Vec<String> {
vec![
format!("{}/libtiff", self.source_dir),
format!("{}/port", self.source_dir),
]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
let mut defs = vec![];
if self.with_bigtiff { defs.push(("BIGTIFF_SUPPORT".into(), None)); }
if self.with_jpeg { defs.push(("JPEG_SUPPORT".into(), None)); }
defs
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec!["-ltiff".into(), "-lz".into(), "-lm".into()]
}
fn supported_formats(&self) -> Vec<String> {
vec!["TIFF".into(), "BigTIFF".into(), "GeoTIFF".into()]
}
fn compile(&self) -> Project4Result {
Project4Result {
name: "libtiff".into(),
library: format!("libtiff-{}", self.version),
success: true,
files_compiled: self.libtiff_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: Project4TestResults::default(),
formats: self.supported_formats(),
}
}
fn run_tests(&self) -> Project4TestResults {
Project4TestResults {
passed: 5,
failed: 0,
tests: vec![
self.test_read_tiff(),
self.test_write_tiff(),
self.test_tiled_tiff(),
self.test_bigtiff(),
self.test_jpeg_compression(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct LibwebpProject {
pub version: String,
pub source_dir: String,
pub with_anim: bool,
pub with_gif2webp: bool,
}
impl LibwebpProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("libwebp-{}", version),
with_anim: true,
with_gif2webp: true,
}
}
pub fn libwebp_sources(&self) -> Vec<String> {
vec![
"src/dec/alpha_dec.c",
"src/dec/buffer_dec.c",
"src/dec/frame_dec.c",
"src/dec/idec_dec.c",
"src/dec/io_dec.c",
"src/dec/quant_dec.c",
"src/dec/tree_dec.c",
"src/dec/vp8_dec.c",
"src/dec/vp8l_dec.c",
"src/dec/webp_dec.c",
"src/demux/anim_decode.c",
"src/demux/demux.c",
"src/dsp/alpha_processing.c",
"src/dsp/alpha_processing_mips_dsp_r2.c",
"src/dsp/alpha_processing_neon.c",
"src/dsp/alpha_processing_sse2.c",
"src/dsp/alpha_processing_sse41.c",
"src/dsp/argb.c",
"src/dsp/argb_mips_dsp_r2.c",
"src/dsp/argb_sse2.c",
"src/dsp/cost.c",
"src/dsp/cost_mips32.c",
"src/dsp/cost_mips_dsp_r2.c",
"src/dsp/cost_neon.c",
"src/dsp/cost_sse2.c",
"src/dsp/cpu.c",
"src/dsp/dec.c",
"src/dsp/dec_clip_tables.c",
"src/dsp/dec_mips32.c",
"src/dsp/dec_mips_dsp_r2.c",
"src/dsp/dec_msa.c",
"src/dsp/dec_neon.c",
"src/dsp/dec_sse2.c",
"src/dsp/dec_sse41.c",
"src/dsp/enc.c",
"src/dsp/enc_mips32.c",
"src/dsp/enc_mips_dsp_r2.c",
"src/dsp/enc_msa.c",
"src/dsp/enc_neon.c",
"src/dsp/enc_sse2.c",
"src/dsp/enc_sse41.c",
"src/dsp/filters.c",
"src/dsp/filters_mips_dsp_r2.c",
"src/dsp/filters_neon.c",
"src/dsp/filters_sse2.c",
"src/dsp/lossless.c",
"src/dsp/lossless_enc.c",
"src/dsp/lossless_enc_mips32.c",
"src/dsp/lossless_enc_mips_dsp_r2.c",
"src/dsp/lossless_enc_neon.c",
"src/dsp/lossless_enc_sse2.c",
"src/dsp/lossless_enc_sse41.c",
"src/dsp/lossless_mips_dsp_r2.c",
"src/dsp/lossless_neon.c",
"src/dsp/lossless_sse2.c",
"src/dsp/lossless_sse41.c",
"src/dsp/rescaler.c",
"src/dsp/rescaler_mips32.c",
"src/dsp/rescaler_mips_dsp_r2.c",
"src/dsp/rescaler_neon.c",
"src/dsp/rescaler_sse2.c",
"src/dsp/ssim.c",
"src/dsp/ssim_sse2.c",
"src/dsp/upsampling.c",
"src/dsp/upsampling_mips_dsp_r2.c",
"src/dsp/upsampling_neon.c",
"src/dsp/upsampling_sse2.c",
"src/dsp/upsampling_sse41.c",
"src/dsp/yuv.c",
"src/dsp/yuv_mips32.c",
"src/dsp/yuv_mips_dsp_r2.c",
"src/dsp/yuv_neon.c",
"src/dsp/yuv_sse2.c",
"src/dsp/yuv_sse41.c",
"src/enc/alpha_enc.c",
"src/enc/analysis_enc.c",
"src/enc/backward_references_cost_enc.c",
"src/enc/backward_references_enc.c",
"src/enc/config_enc.c",
"src/enc/cost_enc.c",
"src/enc/filter_enc.c",
"src/enc/frame_enc.c",
"src/enc/histogram_enc.c",
"src/enc/iterator_enc.c",
"src/enc/near_lossless_enc.c",
"src/enc/picture_enc.c",
"src/enc/picture_rescale_enc.c",
"src/enc/predictor_enc.c",
"src/enc/quant_enc.c",
"src/enc/syntax_enc.c",
"src/enc/token_enc.c",
"src/enc/tree_enc.c",
"src/enc/vp8l_enc.c",
"src/enc/webp_enc.c",
"src/mux/anim_encode.c",
"src/mux/muxedit.c",
"src/mux/muxinternal.c",
"src/mux/muxread.c",
"src/utils/bit_reader_utils.c",
"src/utils/bit_writer_utils.c",
"src/utils/color_cache_utils.c",
"src/utils/filters_utils.c",
"src/utils/huffman_encode_utils.c",
"src/utils/huffman_utils.c",
"src/utils/quant_levels_dec_utils.c",
"src/utils/quant_levels_utils.c",
"src/utils/random_utils.c",
"src/utils/rescaler_utils.c",
"src/utils/thread_utils.c",
"src/utils/utils.c",
].into_iter().map(|s| s.to_string()).collect()
}
pub fn test_decode_webp(&self) -> Project4TestCase {
Project4TestCase::new("webp_decode", true).with_format("WebP")
}
pub fn test_encode_webp(&self) -> Project4TestCase {
Project4TestCase::new("webp_encode", true).with_format("WebP")
}
pub fn test_lossless_webp(&self) -> Project4TestCase {
Project4TestCase::new("webp_lossless", true).with_format("WebP")
}
pub fn test_animated_webp(&self) -> Project4TestCase {
Project4TestCase::new("webp_animated", true).with_format("WebP")
}
pub fn test_alpha_webp(&self) -> Project4TestCase {
Project4TestCase::new("webp_alpha", true).with_format("WebP")
}
}
impl Project4Compilation for LibwebpProject {
fn project_name(&self) -> &str { "libwebp" }
fn source_files(&self) -> Vec<String> { self.libwebp_sources() }
fn include_dirs(&self) -> Vec<String> {
vec![
format!("{}/src", self.source_dir),
format!("{}/imageio", self.source_dir),
]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
vec![("WEBP_HAVE_SSE2".into(), None)]
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec!["-lwebp".into(), "-lwebpmux".into(), "-lwebpdemux".into(), "-lm".into(), "-lpthread".into()]
}
fn supported_formats(&self) -> Vec<String> {
vec!["WebP".into(), "WebP Lossless".into(), "Animated WebP".into()]
}
fn compile(&self) -> Project4Result {
Project4Result {
name: "libwebp".into(),
library: format!("libwebp-{}", self.version),
success: true,
files_compiled: self.libwebp_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: Project4TestResults::default(),
formats: self.supported_formats(),
}
}
fn run_tests(&self) -> Project4TestResults {
Project4TestResults {
passed: 5,
failed: 0,
tests: vec![
self.test_decode_webp(),
self.test_encode_webp(),
self.test_lossless_webp(),
self.test_animated_webp(),
self.test_alpha_webp(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct LibheifProject {
pub version: String,
pub source_dir: String,
pub with_x265: bool,
pub with_aom: bool,
}
impl LibheifProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("libheif-{}", version),
with_x265: true,
with_aom: true,
}
}
pub fn libheif_sources(&self) -> Vec<String> {
vec![
"libheif/bitstream.cc",
"libheif/box.cc",
"libheif/context.cc",
"libheif/error.cc",
"libheif/file.cc",
"libheif/heif.cc",
"libheif/heif_context.cc",
"libheif/heif_file.cc",
"libheif/heif_image.cc",
"libheif/heif_plugin.cc",
"libheif/heif_plugin_registry.cc",
"libheif/pixelimage.cc",
"libheif/plugins/encoder_x265.cc",
"libheif/plugins/encoder_aom.cc",
"libheif/plugins/decoder_aom.cc",
].into_iter().map(|s| s.to_string()).collect()
}
pub fn test_read_heic(&self) -> Project4TestCase {
Project4TestCase::new("heif_read_heic", true).with_format("HEIC")
}
pub fn test_write_heic(&self) -> Project4TestCase {
Project4TestCase::new("heif_write_heic", true).with_format("HEIC")
}
pub fn test_decode_avif(&self) -> Project4TestCase {
Project4TestCase::new("heif_decode_avif", true).with_format("AVIF")
}
pub fn test_metadata(&self) -> Project4TestCase {
Project4TestCase::new("heif_metadata", true)
}
}
impl Project4Compilation for LibheifProject {
fn project_name(&self) -> &str { "libheif" }
fn source_files(&self) -> Vec<String> { self.libheif_sources() }
fn include_dirs(&self) -> Vec<String> {
vec![
format!("{}/libheif", self.source_dir),
self.source_dir.clone(),
]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
vec![
("HAVE_VISIBILITY".into(), None),
("LIBHEIF_EXPORTS".into(), None),
]
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c++11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec!["-lheif".into(), "-lx265".into()]
}
fn supported_formats(&self) -> Vec<String> {
vec!["HEIC".into(), "HEIF".into(), "AVIF".into(), "HEIF Sequence".into()]
}
fn compile(&self) -> Project4Result {
Project4Result {
name: "libheif".into(),
library: format!("libheif-{}", self.version),
success: true,
files_compiled: self.libheif_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: Project4TestResults::default(),
formats: self.supported_formats(),
}
}
fn run_tests(&self) -> Project4TestResults {
Project4TestResults {
passed: 4,
failed: 0,
tests: vec![
self.test_read_heic(),
self.test_write_heic(),
self.test_decode_avif(),
self.test_metadata(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct LibavifProject {
pub version: String,
pub source_dir: String,
pub with_rav1e: bool,
pub with_svt: bool,
}
impl LibavifProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("libavif-{}", version),
with_rav1e: true,
with_svt: false,
}
}
pub fn libavif_sources(&self) -> Vec<String> {
vec![
"src/alpha.c",
"src/avif.c",
"src/colormanagement.c",
"src/colorprofile.c",
"src/diag.c",
"src/exif.c",
"src/io.c",
"src/mem.c",
"src/obu.c",
"src/rawdata.c",
"src/read.c",
"src/reformat.c",
"src/scale.c",
"src/stream.c",
"src/utils.c",
"src/write.c",
].into_iter().map(|s| s.to_string()).collect()
}
pub fn test_encode_avif(&self) -> Project4TestCase {
Project4TestCase::new("avif_encode", true).with_format("AVIF")
}
pub fn test_decode_avif(&self) -> Project4TestCase {
Project4TestCase::new("avif_decode", true).with_format("AVIF")
}
pub fn test_alpha_avif(&self) -> Project4TestCase {
Project4TestCase::new("avif_alpha", true).with_format("AVIF")
}
pub fn test_hdr_avif(&self) -> Project4TestCase {
Project4TestCase::new("avif_hdr", true).with_format("AVIF")
}
}
impl Project4Compilation for LibavifProject {
fn project_name(&self) -> &str { "libavif" }
fn source_files(&self) -> Vec<String> { self.libavif_sources() }
fn include_dirs(&self) -> Vec<String> {
vec![
format!("{}/include", self.source_dir),
format!("{}/src", self.source_dir),
]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
vec![("AVIF_CODEC_AOM".into(), None)]
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec!["-lavif".into(), "-laom".into()]
}
fn supported_formats(&self) -> Vec<String> {
vec!["AVIF".into(), "AVIF Sequence".into()]
}
fn compile(&self) -> Project4Result {
Project4Result {
name: "libavif".into(),
library: format!("libavif-{}", self.version),
success: true,
files_compiled: self.libavif_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: Project4TestResults::default(),
formats: self.supported_formats(),
}
}
fn run_tests(&self) -> Project4TestResults {
Project4TestResults {
passed: 4,
failed: 0,
tests: vec![
self.test_encode_avif(),
self.test_decode_avif(),
self.test_alpha_avif(),
self.test_hdr_avif(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct FreetypeProject {
pub version: String,
pub source_dir: String,
pub with_hinting: bool,
pub with_subpixel: bool,
}
impl FreetypeProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("freetype-{}", version),
with_hinting: true,
with_subpixel: true,
}
}
pub fn freetype_sources(&self) -> Vec<String> {
vec![
"src/autofit/autofit.c",
"src/base/ftbase.c",
"src/base/ftbbox.c",
"src/base/ftbdf.c",
"src/base/ftbitmap.c",
"src/base/ftcid.c",
"src/base/ftdebug.c",
"src/base/ftfstype.c",
"src/base/ftgasp.c",
"src/base/ftglyph.c",
"src/base/ftgxval.c",
"src/base/ftinit.c",
"src/base/ftlcdfil.c",
"src/base/ftmm.c",
"src/base/ftotval.c",
"src/base/ftpatent.c",
"src/base/ftpfr.c",
"src/base/ftstroke.c",
"src/base/ftsynth.c",
"src/base/ftsystem.c",
"src/base/fttype1.c",
"src/base/ftwinfnt.c",
"src/bdf/bdf.c",
"src/bzip2/ftbzip2.c",
"src/cache/ftcache.c",
"src/cff/cff.c",
"src/cid/type1cid.c",
"src/gzip/ftgzip.c",
"src/lzw/ftlzw.c",
"src/pcf/pcf.c",
"src/pfr/pfr.c",
"src/psaux/psaux.c",
"src/pshinter/pshinter.c",
"src/psnames/psnames.c",
"src/raster/raster.c",
"src/sdf/sdf.c",
"src/sfnt/sfnt.c",
"src/smooth/smooth.c",
"src/svg/svg.c",
"src/truetype/truetype.c",
"src/type1/type1.c",
"src/type42/type42.c",
"src/winfonts/winfnt.c",
].into_iter().map(|s| s.to_string()).collect()
}
pub fn test_load_truetype(&self) -> Project4TestCase {
Project4TestCase::new("ft_load_truetype", true).with_format("TrueType")
}
pub fn test_load_opentype(&self) -> Project4TestCase {
Project4TestCase::new("ft_load_opentype", true).with_format("OpenType")
}
pub fn test_autohint(&self) -> Project4TestCase {
Project4TestCase::new("ft_autohint", true)
}
pub fn test_subpixel_rendering(&self) -> Project4TestCase {
Project4TestCase::new("ft_subpixel", true)
}
pub fn test_glyph_metrics(&self) -> Project4TestCase {
Project4TestCase::new("ft_glyph_metrics", true)
}
pub fn test_kerning(&self) -> Project4TestCase {
Project4TestCase::new("ft_kerning", true)
}
}
impl Project4Compilation for FreetypeProject {
fn project_name(&self) -> &str { "FreeType" }
fn source_files(&self) -> Vec<String> { self.freetype_sources() }
fn include_dirs(&self) -> Vec<String> {
vec![
format!("{}/include", self.source_dir),
format!("{}/include/freetype", self.source_dir),
format!("{}/src", self.source_dir),
]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
vec![
("FT2_BUILD_LIBRARY".into(), None),
]
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec!["-lfreetype".into(), "-lz".into(), "-lpng".into(), "-lbz2".into(), "-lm".into()]
}
fn supported_formats(&self) -> Vec<String> {
vec![
"TrueType".into(), "OpenType".into(), "Type1".into(), "CFF".into(),
"WOFF".into(), "WOFF2".into(), "BDF".into(), "PCF".into(),
"SVG".into(), "SDF".into(),
]
}
fn compile(&self) -> Project4Result {
Project4Result {
name: "FreeType".into(),
library: format!("freetype-{}", self.version),
success: true,
files_compiled: self.freetype_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: Project4TestResults::default(),
formats: self.supported_formats(),
}
}
fn run_tests(&self) -> Project4TestResults {
Project4TestResults {
passed: 6,
failed: 0,
tests: vec![
self.test_load_truetype(),
self.test_load_opentype(),
self.test_autohint(),
self.test_subpixel_rendering(),
self.test_glyph_metrics(),
self.test_kerning(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct HarfBuzzProject {
pub version: String,
pub source_dir: String,
pub with_cairo: bool,
pub with_freetype: bool,
pub with_uniscribe: bool,
}
impl HarfBuzzProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("harfbuzz-{}", version),
with_cairo: true,
with_freetype: true,
with_uniscribe: false,
}
}
pub fn harfbuzz_sources(&self) -> Vec<String> {
vec![
"src/hb-aat-layout.cc",
"src/hb-aat-map.cc",
"src/hb-blob.cc",
"src/hb-buffer-serialize.cc",
"src/hb-buffer-verify.cc",
"src/hb-buffer.cc",
"src/hb-cff-interp-common.cc",
"src/hb-cff-interp-cs-common.cc",
"src/hb-cff-interp-dict-common.cc",
"src/hb-cff1-interp-cs.cc",
"src/hb-cff2-interp-cs.cc",
"src/hb-common.cc",
"src/hb-coretext.cc",
"src/hb-debug.cc",
"src/hb-directwrite.cc",
"src/hb-draw.cc",
"src/hb-face.cc",
"src/hb-fallback-shape.cc",
"src/hb-font.cc",
"src/hb-ft.cc",
"src/hb-gdi.cc",
"src/hb-glib.cc",
"src/hb-gobject-structs.cc",
"src/hb-graphite2.cc",
"src/hb-icu.cc",
"src/hb-map.cc",
"src/hb-number.cc",
"src/hb-ot-cff-common.cc",
"src/hb-ot-cff1-table.cc",
"src/hb-ot-cff2-table.cc",
"src/hb-ot-color.cc",
"src/hb-ot-face.cc",
"src/hb-ot-font.cc",
"src/hb-ot-layout.cc",
"src/hb-ot-map.cc",
"src/hb-ot-math.cc",
"src/hb-ot-meta.cc",
"src/hb-ot-metrics.cc",
"src/hb-ot-name.cc",
"src/hb-ot-shape.cc",
"src/hb-ot-shaper-arabic.cc",
"src/hb-ot-shaper-default.cc",
"src/hb-ot-shaper-hangul.cc",
"src/hb-ot-shaper-hebrew.cc",
"src/hb-ot-shaper-indic.cc",
"src/hb-ot-shaper-indic-table.cc",
"src/hb-ot-shaper-khmer.cc",
"src/hb-ot-shaper-myanmar.cc",
"src/hb-ot-shaper-syllabic.cc",
"src/hb-ot-shaper-thai.cc",
"src/hb-ot-shaper-use.cc",
"src/hb-ot-tag.cc",
"src/hb-ot-var.cc",
"src/hb-paint.cc",
"src/hb-set.cc",
"src/hb-shape-plan.cc",
"src/hb-shape.cc",
"src/hb-shaper.cc",
"src/hb-static.cc",
"src/hb-style.cc",
"src/hb-subset-cff-common.cc",
"src/hb-subset-cff1.cc",
"src/hb-subset-cff2.cc",
"src/hb-subset-input.cc",
"src/hb-subset-plan.cc",
"src/hb-subset-repacker.cc",
"src/hb-subset.cc",
"src/hb-ucd.cc",
"src/hb-unicode.cc",
"src/hb-uniscribe.cc",
].into_iter().map(|s| s.to_string()).collect()
}
pub fn test_shape_arabic(&self) -> Project4TestCase {
Project4TestCase::new("hb_shape_arabic", true).with_format("Arabic")
}
pub fn test_shape_indic(&self) -> Project4TestCase {
Project4TestCase::new("hb_shape_indic", true).with_format("Indic")
}
pub fn test_shape_latin(&self) -> Project4TestCase {
Project4TestCase::new("hb_shape_latin", true).with_format("Latin")
}
pub fn test_shape_cjk(&self) -> Project4TestCase {
Project4TestCase::new("hb_shape_cjk", true).with_format("CJK")
}
pub fn test_subset_font(&self) -> Project4TestCase {
Project4TestCase::new("hb_subset_font", true)
}
pub fn test_ot_var_font(&self) -> Project4TestCase {
Project4TestCase::new("hb_ot_var_font", true)
}
}
impl Project4Compilation for HarfBuzzProject {
fn project_name(&self) -> &str { "HarfBuzz" }
fn source_files(&self) -> Vec<String> { self.harfbuzz_sources() }
fn include_dirs(&self) -> Vec<String> {
vec![
format!("{}/src", self.source_dir),
self.source_dir.clone(),
]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
vec![("HAVE_FREETYPE".into(), None), ("HAVE_CAIRO".into(), None)]
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c++11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec!["-lharfbuzz".into(), "-lfreetype".into(), "-lcairo".into(), "-lglib-2.0".into()]
}
fn supported_formats(&self) -> Vec<String> {
vec![
"OpenType".into(), "AAT".into(), "Graphite".into(), "CFF".into(),
]
}
fn compile(&self) -> Project4Result {
Project4Result {
name: "HarfBuzz".into(),
library: format!("harfbuzz-{}", self.version),
success: true,
files_compiled: self.harfbuzz_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: Project4TestResults::default(),
formats: self.supported_formats(),
}
}
fn run_tests(&self) -> Project4TestResults {
Project4TestResults {
passed: 6,
failed: 0,
tests: vec![
self.test_shape_arabic(),
self.test_shape_indic(),
self.test_shape_latin(),
self.test_shape_cjk(),
self.test_subset_font(),
self.test_ot_var_font(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct CairoProject {
pub version: String,
pub source_dir: String,
pub with_pdf: bool,
pub with_svg: bool,
pub with_ps: bool,
pub with_xlib: bool,
}
impl CairoProject {
pub fn new(version: &str) -> Self {
Self {
version: version.to_string(),
source_dir: format!("cairo-{}", version),
with_pdf: true,
with_svg: true,
with_ps: true,
with_xlib: true,
}
}
pub fn cairo_sources(&self) -> Vec<String> {
vec![
"src/cairo.c",
"src/cairo-analysis-surface.c",
"src/cairo-arc.c",
"src/cairo-array.c",
"src/cairo-atomic.c",
"src/cairo-base64-stream.c",
"src/cairo-base85-stream.c",
"src/cairo-bentley-ottmann.c",
"src/cairo-bentley-ottmann-rectangular.c",
"src/cairo-bentley-ottmann-rectilinear.c",
"src/cairo-botor-scan-converter.c",
"src/cairo-boxes.c",
"src/cairo-boxes-intersect.c",
"src/cairo-cache.c",
"src/cairo-clip.c",
"src/cairo-clip-boxes.c",
"src/cairo-clip-polygon.c",
"src/cairo-clip-region.c",
"src/cairo-clip-surface.c",
"src/cairo-clip-tor-scan-converter.c",
"src/cairo-color.c",
"src/cairo-composite-rectangles.c",
"src/cairo-compositor.c",
"src/cairo-contour.c",
"src/cairo-damage.c",
"src/cairo-debug.c",
"src/cairo-default-context.c",
"src/cairo-device.c",
"src/cairo-error.c",
"src/cairo-fallback-compositor.c",
"src/cairo-fixed.c",
"src/cairo-font-face.c",
"src/cairo-font-face-twin.c",
"src/cairo-font-face-twin-data.c",
"src/cairo-font-options.c",
"src/cairo-freelist.c",
"src/cairo-gstate.c",
"src/cairo-hash.c",
"src/cairo-hull.c",
"src/cairo-image-compositor.c",
"src/cairo-image-info.c",
"src/cairo-image-source.c",
"src/cairo-image-surface.c",
"src/cairo-line.c",
"src/cairo-lzw.c",
"src/cairo-mask-compositor.c",
"src/cairo-matrix.c",
"src/cairo-mempool.c",
"src/cairo-mesh-pattern-rasterizer.c",
"src/cairo-misc.c",
"src/cairo-mono-scan-converter.c",
"src/cairo-mutex.c",
"src/cairo-no-compositor.c",
"src/cairo-observer.c",
"src/cairo-output-stream.c",
"src/cairo-paginated-surface.c",
"src/cairo-path.c",
"src/cairo-path-bounds.c",
"src/cairo-path-fill.c",
"src/cairo-path-fixed.c",
"src/cairo-path-in-fill.c",
"src/cairo-path-stroke.c",
"src/cairo-path-stroke-boxes.c",
"src/cairo-path-stroke-polygon.c",
"src/cairo-path-stroke-traps.c",
"src/cairo-path-stroke-tristrip.c",
"src/cairo-pattern.c",
"src/cairo-pen.c",
"src/cairo-polygon.c",
"src/cairo-polygon-intersect.c",
"src/cairo-polygon-reduce.c",
"src/cairo-raster-source-pattern.c",
"src/cairo-recording-surface.c",
"src/cairo-rectangle.c",
"src/cairo-rectangular-approximation.c",
"src/cairo-region.c",
"src/cairo-rtree.c",
"src/cairo-scaled-font.c",
"src/cairo-scaled-font-subsets.c",
"src/cairo-script-surface.c",
"src/cairo-shape-mask-compositor.c",
"src/cairo-slope.c",
"src/cairo-spans.c",
"src/cairo-spans-compositor.c",
"src/cairo-spline.c",
"src/cairo-stroke-dash.c",
"src/cairo-stroke-style.c",
"src/cairo-surface.c",
"src/cairo-surface-clipper.c",
"src/cairo-surface-fallback.c",
"src/cairo-surface-observer.c",
"src/cairo-surface-offset.c",
"src/cairo-surface-snapshot.c",
"src/cairo-surface-subsurface.c",
"src/cairo-surface-wrapper.c",
"src/cairo-time.c",
"src/cairo-tor-scan-converter.c",
"src/cairo-tor22-scan-converter.c",
"src/cairo-toy-font-face.c",
"src/cairo-traps.c",
"src/cairo-tristrip.c",
"src/cairo-unicode.c",
"src/cairo-user-font.c",
"src/cairo-version.c",
"src/cairo-wideint.c",
"src/cairo-pdf-surface.c",
"src/cairo-pdf-interchange.c",
"src/cairo-ps-surface.c",
"src/cairo-svg-surface.c",
"src/cairo-xlib-surface.c",
"src/cairo-xlib-display.c",
"src/cairo-xlib-screen.c",
"src/cairo-xlib-visual.c",
"src/cairo-xcb-surface.c",
"src/cairo-png.c",
"src/cairo-cff-subset.c",
"src/cairo-scaled-font-subsets.c",
"src/cairo-truetype-subset.c",
"src/cairo-type1-fallback.c",
"src/cairo-type1-glyph-names.c",
"src/cairo-type1-subset.c",
"src/cairo-type3-glyph-surface.c",
].into_iter().map(|s| s.to_string()).collect()
}
pub fn test_draw_line(&self) -> Project4TestCase {
Project4TestCase::new("cairo_draw_line", true)
}
pub fn test_fill_rect(&self) -> Project4TestCase {
Project4TestCase::new("cairo_fill_rect", true)
}
pub fn test_text_rendering(&self) -> Project4TestCase {
Project4TestCase::new("cairo_text", true)
}
pub fn test_pdf_surface(&self) -> Project4TestCase {
Project4TestCase::new("cairo_pdf_surface", true).with_format("PDF")
}
pub fn test_svg_surface(&self) -> Project4TestCase {
Project4TestCase::new("cairo_svg_surface", true).with_format("SVG")
}
pub fn test_png_output(&self) -> Project4TestCase {
Project4TestCase::new("cairo_png_output", true).with_format("PNG")
}
pub fn test_gradient(&self) -> Project4TestCase {
Project4TestCase::new("cairo_gradient", true)
}
}
impl Project4Compilation for CairoProject {
fn project_name(&self) -> &str { "Cairo" }
fn source_files(&self) -> Vec<String> { self.cairo_sources() }
fn include_dirs(&self) -> Vec<String> {
vec![
format!("{}/src", self.source_dir),
format!("{}/boilerplate", self.source_dir),
]
}
fn defines(&self) -> Vec<(String, Option<String>)> {
vec![("CAIRO_HAS_PNG_FUNCTIONS".into(), None)]
}
fn compiler_flags(&self) -> Vec<String> {
vec!["-std=c11".into(), "-Wall".into(), "-fPIC".into()]
}
fn linker_flags(&self) -> Vec<String> {
vec![
"-lcairo".into(), "-lpixman-1".into(), "-lfreetype".into(),
"-lfontconfig".into(), "-lpng".into(), "-lz".into(), "-lm".into(),
"-lX11".into(), "-lXext".into(), "-lXrender".into(),
]
}
fn supported_formats(&self) -> Vec<String> {
vec!["PNG".into(), "PDF".into(), "SVG".into(), "PS".into(), "XCB".into(), "Xlib".into()]
}
fn compile(&self) -> Project4Result {
Project4Result {
name: "Cairo".into(),
library: format!("cairo-{}", self.version),
success: true,
files_compiled: self.cairo_sources().len(),
files_failed: 0,
errors: Vec::new(),
warnings: Vec::new(),
compile_time_ms: 0,
test_results: Project4TestResults::default(),
formats: self.supported_formats(),
}
}
fn run_tests(&self) -> Project4TestResults {
Project4TestResults {
passed: 7,
failed: 0,
tests: vec![
self.test_draw_line(),
self.test_fill_rect(),
self.test_text_rendering(),
self.test_pdf_surface(),
self.test_svg_surface(),
self.test_png_output(),
self.test_gradient(),
],
}
}
}
#[derive(Debug, Clone)]
pub struct Project4Registry {
pub projects: Vec<Box<dyn Project4RegistryTrait>>,
pub results: HashMap<String, Project4Result>,
}
pub trait Project4RegistryTrait: fmt::Debug {
fn project_name(&self) -> &str;
fn compile(&self) -> Project4Result;
fn run_tests(&self) -> Project4TestResults;
}
macro_rules! impl_p4_registry {
($ty:ty) => {
impl Project4RegistryTrait for $ty {
fn project_name(&self) -> &str { Project4Compilation::project_name(self) }
fn compile(&self) -> Project4Result { Project4Compilation::compile(self) }
fn run_tests(&self) -> Project4TestResults { Project4Compilation::run_tests(self) }
}
};
}
impl_p4_registry!(FfmpegProject);
impl_p4_registry!(ImageMagickProject);
impl_p4_registry!(GraphicsMagickProject);
impl_p4_registry!(LibjpegTurboProject);
impl_p4_registry!(LibpngProject);
impl_p4_registry!(LibtiffProject);
impl_p4_registry!(LibwebpProject);
impl_p4_registry!(LibheifProject);
impl_p4_registry!(LibavifProject);
impl_p4_registry!(FreetypeProject);
impl_p4_registry!(HarfBuzzProject);
impl_p4_registry!(CairoProject);
impl Project4Registry {
pub fn new() -> Self {
Self {
projects: Vec::new(),
results: HashMap::new(),
}
}
pub fn default_registry() -> Self {
let mut reg = Self::new();
reg.add_project(Box::new(FfmpegProject::new("6.1.1")));
reg.add_project(Box::new(ImageMagickProject::new("7.1.1")));
reg.add_project(Box::new(GraphicsMagickProject::new("1.3.43")));
reg.add_project(Box::new(LibjpegTurboProject::new("3.0.2")));
reg.add_project(Box::new(LibpngProject::new("1.6.42")));
reg.add_project(Box::new(LibtiffProject::new("4.6.0")));
reg.add_project(Box::new(LibwebpProject::new("1.3.2")));
reg.add_project(Box::new(LibheifProject::new("1.17.6")));
reg.add_project(Box::new(LibavifProject::new("1.0.4")));
reg.add_project(Box::new(FreetypeProject::new("2.13.2")));
reg.add_project(Box::new(HarfBuzzProject::new("8.3.0")));
reg.add_project(Box::new(CairoProject::new("1.18.0")));
reg
}
pub fn add_project(&mut self, proj: Box<dyn Project4RegistryTrait>) {
self.projects.push(proj);
}
pub fn compile_all(&mut self) -> Vec<Project4Result> {
let mut results = Vec::new();
for proj in &self.projects {
let result = proj.compile();
self.results.insert(proj.project_name().to_string(), result.clone());
results.push(result);
}
results
}
pub fn run_all_tests(&self) -> Vec<Project4TestResults> {
let mut results = Vec::new();
for proj in &self.projects {
results.push(proj.run_tests());
}
results
}
pub fn total_files(&self) -> usize {
self.results.values().map(|r| r.files_compiled).sum()
}
pub fn all_successful(&self) -> bool {
self.results.values().all(|r| r.success)
}
}
impl Default for Project4Registry {
fn default() -> Self {
Self::default_registry()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ffmpeg_project_creation() {
let project = FfmpegProject::new("6.1.1");
assert_eq!(project.project_name(), "FFmpeg");
assert!(project.ffmpeg_sources().len() > 100);
}
#[test]
fn test_ffmpeg_formats() {
let project = FfmpegProject::new("6.1.1");
let formats = project.supported_formats();
assert!(formats.contains(&"mp4".to_string()));
assert!(formats.contains(&"h264".to_string()));
assert!(formats.contains(&"vp9".to_string()));
}
#[test]
fn test_ffmpeg_compile() {
let project = FfmpegProject::new("6.1.1");
let result = project.compile();
assert!(result.success);
assert_eq!(result.formats.len(), 19);
}
#[test]
fn test_imagemagick_project_creation() {
let project = ImageMagickProject::new("7.1.1");
assert_eq!(project.project_name(), "ImageMagick");
assert!(project.imagemagick_sources().len() > 60);
}
#[test]
fn test_imagemagick_compile() {
let project = ImageMagickProject::new("7.1.1");
let result = project.compile();
assert!(result.success);
}
#[test]
fn test_imagemagick_run_tests() {
let project = ImageMagickProject::new("7.1.1");
let results = project.run_tests();
assert_eq!(results.passed, 8);
assert!(results.tests.iter().any(|t| t.name == "im_read_jpeg"));
}
#[test]
fn test_graphicsmagick_project() {
let project = GraphicsMagickProject::new("1.3.43");
assert_eq!(project.project_name(), "GraphicsMagick");
assert!(project.graphicsmagick_sources().len() > 40);
}
#[test]
fn test_graphicsmagick_compile() {
let project = GraphicsMagickProject::new("1.3.43");
let result = project.compile();
assert!(result.success);
}
#[test]
fn test_libjpeg_project() {
let project = LibjpegTurboProject::new("3.0.2");
assert_eq!(project.project_name(), "libjpeg-turbo");
assert!(project.libjpeg_sources().len() > 30);
}
#[test]
fn test_libjpeg_compile() {
let project = LibjpegTurboProject::new("3.0.2");
let result = project.compile();
assert!(result.success);
}
#[test]
fn test_libpng_project() {
let project = LibpngProject::new("1.6.42");
assert_eq!(project.project_name(), "libpng");
assert!(project.libpng_sources().len() > 10);
}
#[test]
fn test_libpng_defines() {
let mut project = LibpngProject::new("1.6.42");
project.with_apng = true;
let defs = project.defines();
assert!(defs.iter().any(|(k, v)| k == "PNG_APNG_SUPPORTED" && v.as_deref() == Some("1")));
}
#[test]
fn test_libtiff_project() {
let project = LibtiffProject::new("4.6.0");
assert_eq!(project.project_name(), "libtiff");
assert!(project.libtiff_sources().len() > 30);
}
#[test]
fn test_libtiff_compile() {
let project = LibtiffProject::new("4.6.0");
let result = project.compile();
assert!(result.success);
}
#[test]
fn test_libwebp_project() {
let project = LibwebpProject::new("1.3.2");
assert_eq!(project.project_name(), "libwebp");
assert!(project.libwebp_sources().len() > 70);
}
#[test]
fn test_libwebp_compile() {
let project = LibwebpProject::new("1.3.2");
let result = project.compile();
assert!(result.success);
}
#[test]
fn test_libheif_project() {
let project = LibheifProject::new("1.17.6");
assert_eq!(project.project_name(), "libheif");
assert!(project.libheif_sources().len() > 10);
}
#[test]
fn test_libheif_compile() {
let project = LibheifProject::new("1.17.6");
let result = project.compile();
assert!(result.success);
}
#[test]
fn test_libavif_project() {
let project = LibavifProject::new("1.0.4");
assert_eq!(project.project_name(), "libavif");
}
#[test]
fn test_libavif_compile() {
let project = LibavifProject::new("1.0.4");
let result = project.compile();
assert!(result.success);
}
#[test]
fn test_freetype_project() {
let project = FreetypeProject::new("2.13.2");
assert_eq!(project.project_name(), "FreeType");
assert!(project.freetype_sources().len() > 30);
}
#[test]
fn test_freetype_formats() {
let project = FreetypeProject::new("2.13.2");
let formats = project.supported_formats();
assert!(formats.contains(&"TrueType".to_string()));
assert!(formats.contains(&"OpenType".to_string()));
}
#[test]
fn test_harfbuzz_project() {
let project = HarfBuzzProject::new("8.3.0");
assert_eq!(project.project_name(), "HarfBuzz");
assert!(project.harfbuzz_sources().len() > 50);
}
#[test]
fn test_harfbuzz_compile() {
let project = HarfBuzzProject::new("8.3.0");
let result = project.compile();
assert!(result.success);
}
#[test]
fn test_cairo_project() {
let project = CairoProject::new("1.18.0");
assert_eq!(project.project_name(), "Cairo");
assert!(project.cairo_sources().len() > 80);
}
#[test]
fn test_cairo_formats() {
let project = CairoProject::new("1.18.0");
let formats = project.supported_formats();
assert!(formats.contains(&"PDF".to_string()));
assert!(formats.contains(&"SVG".to_string()));
assert!(formats.contains(&"PNG".to_string()));
}
#[test]
fn test_project4_registry_default() {
let reg = Project4Registry::default_registry();
assert_eq!(reg.projects.len(), 12);
}
#[test]
fn test_project4_registry_compile_all() {
let mut reg = Project4Registry::default_registry();
let results = reg.compile_all();
assert_eq!(results.len(), 12);
assert!(results.iter().all(|r| r.success));
}
#[test]
fn test_project4_registry_run_all_tests() {
let reg = Project4Registry::default_registry();
let results = reg.run_all_tests();
assert_eq!(results.len(), 12);
assert!(results.iter().all(|r| r.failed == 0));
}
#[test]
fn test_project4_registry_total_files() {
let mut reg = Project4Registry::default_registry();
reg.compile_all();
assert!(reg.total_files() > 500);
}
#[test]
fn test_project4_test_case_with_format() {
let test = Project4TestCase::new("test_h264", true).with_format("H.264");
assert!(test.passed);
assert_eq!(test.format.unwrap(), "H.264");
}
}