diff --git a/src/context.rs b/src/context.rs index 43ee619..3f05001 100644 --- a/src/context.rs +++ b/src/context.rs @@ -10,12 +10,12 @@ use base::CGFloat; use color_space::{CGColorSpace, CGColorSpaceRef}; use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType}; -use image::{CGImage,CGImageRef}; use libc::{c_void, size_t}; use std::mem; use std::ptr; use std::slice; use geometry::CGRect; +use image::{CGImage, CGImageRef}; #[repr(C)] pub enum CGTextDrawingMode { @@ -88,7 +88,8 @@ impl TCFType for CGContext { } impl CGContext { - pub fn create_bitmap_context(width: size_t, + pub fn create_bitmap_context(data: Option<*mut c_void>, + width: size_t, height: size_t, bits_per_component: size_t, bytes_per_row: size_t, @@ -96,7 +97,7 @@ impl CGContext { bitmap_info: u32) -> CGContext { unsafe { - let result = CGBitmapContextCreate(ptr::null_mut(), + let result = CGBitmapContextCreate(data.unwrap_or(ptr::null_mut()), width, height, bits_per_component, @@ -199,11 +200,20 @@ impl CGContext { } } - pub fn draw_image(&self, rect: CGRect, image: CGImage) { + pub fn draw_image(&self, rect: CGRect, image: &CGImage) { unsafe { CGContextDrawImage(self.as_concrete_TypeRef(), rect, image.as_concrete_TypeRef()); } } + + pub fn create_image(&self) -> Option { + let image = unsafe { CGBitmapContextCreateImage(self.as_concrete_TypeRef()) }; + if image != ptr::null() { + Some(unsafe { CGImage::wrap_under_create_rule(image) }) + } else { + None + } + } } #[link(name = "ApplicationServices", kind = "framework")] @@ -220,6 +230,7 @@ extern { fn CGBitmapContextGetWidth(context: CGContextRef) -> size_t; fn CGBitmapContextGetHeight(context: CGContextRef) -> size_t; fn CGBitmapContextGetBytesPerRow(context: CGContextRef) -> size_t; + fn CGBitmapContextCreateImage(context: CGContextRef) -> CGImageRef; fn CGContextGetTypeID() -> CFTypeID; fn CGContextSetAllowsFontSmoothing(c: CGContextRef, allowsFontSmoothing: bool); fn CGContextSetShouldSmoothFonts(c: CGContextRef, shouldSmoothFonts: bool); @@ -241,6 +252,6 @@ extern { alpha: CGFloat); fn CGContextFillRect(context: CGContextRef, rect: CGRect); - fn CGContextDrawImage(context: CGContextRef, rect: CGRect, image: CGImageRef); + fn CGContextDrawImage(c: CGContextRef, rect: CGRect, image: CGImageRef); } diff --git a/src/data_provider.rs b/src/data_provider.rs index 10d9cb1..aaa5f75 100644 --- a/src/data_provider.rs +++ b/src/data_provider.rs @@ -8,6 +8,7 @@ // except according to those terms. use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType}; +use core_foundation::data::{CFData, CFDataRef}; use libc::{c_void, size_t, off_t}; use std::mem; @@ -86,11 +87,16 @@ impl CGDataProvider { TCFType::wrap_under_create_rule(result) } } + + /// Creates a copy of the data from the underlying `CFDataProviderRef`. + pub fn copy_data(&self) -> CFData { + unsafe { CFData::wrap_under_create_rule(CGDataProviderCopyData(self.obj)) } + } } #[link(name = "ApplicationServices", kind = "framework")] extern { - //fn CGDataProviderCopyData + fn CGDataProviderCopyData(provider: CGDataProviderRef) -> CFDataRef; //fn CGDataProviderCreateDirect //fn CGDataProviderCreateSequential //fn CGDataProviderCreateWithCFData diff --git a/src/display.rs b/src/display.rs index 491e277..5328737 100644 --- a/src/display.rs +++ b/src/display.rs @@ -15,6 +15,8 @@ use libc; pub use base::{CGError, boolean_t}; pub use geometry::{CGRect, CGPoint, CGSize}; +use image::CGImageRef; + pub type CGDirectDisplayID = libc::uint32_t; pub type CGWindowID = libc::uint32_t; @@ -30,6 +32,14 @@ pub const kCGWindowListOptionOnScreenBelowWindow: CGWindowListOption = 1 << 2; pub const kCGWindowListOptionIncludingWindow: CGWindowListOption = 1 << 3; pub const kCGWindowListExcludeDesktopElements: CGWindowListOption = 1 << 4; +pub type CGWindowImageOption = libc::uint32_t; + +pub const kCGWindowImageDefault: CGWindowImageOption = 0; +pub const kCGWindowImageBoundsIgnoreFraming: CGWindowImageOption = 1 << 0; +pub const kCGWindowImageShouldBeOpaque: CGWindowImageOption = 1 << 1; +pub const kCGWindowImageOnlyShadows: CGWindowImageOption = 1 << 2; +pub const kCGWindowImageBestResolution: CGWindowImageOption = 1 << 3; +pub const kCGWindowImageNominalResolution: CGWindowImageOption = 1 << 4; pub use core_foundation::dictionary::{ CFDictionary, CFDictionaryRef, CFDictionaryGetValueIfPresent }; pub use core_foundation::array::{ CFArray, CFArrayRef }; @@ -38,6 +48,9 @@ pub use core_foundation::base::{ CFIndex, CFRelease, CFTypeRef }; #[link(name = "ApplicationServices", kind = "framework")] extern { + pub static CGRectNull: CGRect; + pub static CGRectInfinite: CGRect; + pub fn CGMainDisplayID() -> CGDirectDisplayID; pub fn CGDisplayIsActive(display: CGDirectDisplayID) -> boolean_t; pub fn CGDisplayIsAlwaysInMirrorSet(display: CGDirectDisplayID) -> boolean_t; @@ -73,5 +86,9 @@ extern { // Window Services Reference pub fn CGWindowListCopyWindowInfo(option: CGWindowListOption, relativeToWindow: CGWindowID ) -> CFArrayRef; + pub fn CGWindowListCreateImage(screenBounds: CGRect, + listOptions: CGWindowListOption, + windowId: CGWindowID, + imageOptions: CGWindowImageOption) -> CGImageRef; } diff --git a/src/geometry.rs b/src/geometry.rs index e4145da..9497fbb 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -8,6 +8,8 @@ // except according to those terms. use base::CGFloat; +use core_foundation::base::TCFType; +use core_foundation::dictionary::CFDictionary; pub const CG_ZERO_POINT: CGPoint = CGPoint { x: 0.0, @@ -70,15 +72,31 @@ impl CGRect { ffi::CGRectInset(*self, size.width, size.height) } } + + #[inline] + pub fn from_dict_representation(dict: &CFDictionary) -> Option { + let mut rect = CGRect::new(&CGPoint::new(0., 0.), &CGSize::new(0., 0.)); + let result = unsafe { + ffi::CGRectMakeWithDictionaryRepresentation(dict.as_concrete_TypeRef(), &mut rect) + }; + if result == 0 { + None + } else { + Some(rect) + } + } } mod ffi { - use base::CGFloat; + use base::{CGFloat, boolean_t}; use geometry::CGRect; + use core_foundation::dictionary::CFDictionaryRef; #[link(name = "ApplicationServices", kind = "framework")] extern { pub fn CGRectInset(rect: CGRect, dx: CGFloat, dy: CGFloat) -> CGRect; + pub fn CGRectMakeWithDictionaryRepresentation(dict: CFDictionaryRef, + rect: *mut CGRect) -> boolean_t; } } diff --git a/src/image.rs b/src/image.rs index 0e1e988..aea7742 100644 --- a/src/image.rs +++ b/src/image.rs @@ -1,6 +1,9 @@ -use core_foundation::base::{CFRelease, CFRetain, CFTypeID, CFTypeRef, TCFType}; +use core_foundation::base::{CFRetain, CFTypeID, CFTypeRef, TCFType}; +use core_foundation::data::CFData; use color_space::{CGColorSpace, CGColorSpaceRef}; -use libc::{size_t}; +use data_provider::{CGDataProvider, CGDataProviderRef}; +use libc::size_t; +use std::ops::Deref; use std::mem; #[repr(C)] @@ -36,7 +39,7 @@ pub struct CGImage { impl Drop for CGImage { fn drop(&mut self) { unsafe { - CFRelease(self.as_CFTypeRef()) + CGImageRelease(self.as_concrete_TypeRef()) } } } @@ -49,6 +52,8 @@ impl Clone for CGImage { } } +// TODO: Replace all this stuff by simply using: +// impl_TCFType!(CGImage, CGImageRef, CGImageGetTypeID); impl TCFType for CGImage { #[inline] fn as_concrete_TypeRef(&self) -> CGImageRef { @@ -119,6 +124,24 @@ impl CGImage { TCFType::wrap_under_get_rule(CGImageGetColorSpace(self.as_concrete_TypeRef())) } } + + /// Returns the raw image bytes wrapped in `CFData`. Note, the returned `CFData` owns the + /// underlying buffer. + pub fn data(&self) -> CFData { + let data_provider = unsafe { + CGDataProvider::wrap_under_get_rule(CGImageGetDataProvider(self.as_concrete_TypeRef())) + }; + data_provider.copy_data() + } +} + +impl Deref for CGImage { + type Target = CGImageRef; + + #[inline] + fn deref(&self) -> &CGImageRef { + &self.obj + } } #[link(name = "ApplicationServices", kind = "framework")] @@ -130,4 +153,9 @@ extern { fn CGImageGetBitsPerPixel(image: CGImageRef) -> size_t; fn CGImageGetBytesPerRow(image: CGImageRef) -> size_t; fn CGImageGetColorSpace(image: CGImageRef) -> CGColorSpaceRef; + fn CGImageGetDataProvider(image: CGImageRef) -> CGDataProviderRef; + fn CGImageRelease(image: CGImageRef); + + //fn CGImageGetAlphaInfo(image: CGImageRef) -> CGImageAlphaInfo; + //fn CGImageCreateCopyWithColorSpace(image: CGImageRef, space: CGColorSpaceRef) -> CGImageRef } diff --git a/src/lib.rs b/src/lib.rs index c0078a1..daed628 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ // except according to those terms. extern crate libc; +#[macro_use] extern crate core_foundation; #[macro_use] @@ -19,8 +20,8 @@ pub mod context; pub mod data_provider; pub mod display; pub mod event; -pub mod event_source; +pub mod event_source; pub mod font; pub mod geometry; -pub mod image; pub mod private; +pub mod image;