diff options
Diffstat (limited to 'third_party/rust/core-graphics')
23 files changed, 3841 insertions, 0 deletions
diff --git a/third_party/rust/core-graphics/.cargo-checksum.json b/third_party/rust/core-graphics/.cargo-checksum.json new file mode 100644 index 0000000000..9dafee4db2 --- /dev/null +++ b/third_party/rust/core-graphics/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"453b079ac8a6df8842e7e8a37222318c500f68e1605db7adbdf87337830df593","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"6745c3c38183d2eda9b1fa265fb0a95018db5c110cbabc00b32327d951bbe2ea","src/base.rs":"838683ff67253f4aff1d4b4177531210ca73d4e61f05c5d96a8f196b2a88c787","src/color.rs":"4c8ec4ab828cbc1b2a1538a34a51f5b380927f2f1daf187dff6f732f57a43656","src/color_space.rs":"b3d7ee8a21703c789160867cb8eb2188bd1daa193e3d030f21adb6f1a6f872de","src/context.rs":"8bda7f9ecb5be768b09a29cc3b0a4f329f55d2a2ab74030d121610283862d833","src/data_provider.rs":"b25201fdea43ea1a019c68aa5e997725d04d0824a238354ddc9f2dd8a6835cc4","src/display.rs":"9db5e5440fd302849b13b48393cab4db95447df8d5057c4534a9d8be948ca480","src/event.rs":"17c601ca0b8a0d806fc576cc6cee63a784deaf4246793cf6ce3abcb562de15c5","src/event_source.rs":"d55a4f5b5e62789325028febc51bbf54c74b15ab1a4e70c6ad749a2f9753e081","src/font.rs":"2a7ac5024f17550dd2b6eb97f6971559f930c163eac3a6625d6d55703fd5e96e","src/geometry.rs":"8e12dc89835406bfa514de8fb58f5fd435724d1ddb97dc3a70392efbcf1c42ed","src/gradient.rs":"8ee8661706f36914d08e903840c4f07414b38ba40ea4a482d34b900ac6ac7cf9","src/image.rs":"a5a5df8c0f310455f038eeb16688015f481688cb417f8e8f424a4c1d2a1cdd57","src/lib.rs":"78264571227db6fc9194cb90d64beaff1738a501f88b5da55eb17ae42592d26f","src/path.rs":"c429afeaed999b02ac00f89a867b5fc64f1e223039079a4e0529306b734ff117","src/private.rs":"da3fd61338bab2d8e26aa5433b2e18ecd2a0a408c62e1ac2b33a0f87f2dad88a","src/sys.rs":"3077395beb77193530b713aa681cb61f7b86fa79e4e4060133b6d61cf9f47e09","src/window.rs":"2f6c3dc958ae2c0c9e2fc5033300b96e60ed0abee9823ea1f03797d64df0911a"},"package":"2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb"}
\ No newline at end of file diff --git a/third_party/rust/core-graphics/COPYRIGHT b/third_party/rust/core-graphics/COPYRIGHT new file mode 100644 index 0000000000..8b7291ad28 --- /dev/null +++ b/third_party/rust/core-graphics/COPYRIGHT @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +<LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +option. All files in the project carrying such notice may not be +copied, modified, or distributed except according to those terms. diff --git a/third_party/rust/core-graphics/Cargo.toml b/third_party/rust/core-graphics/Cargo.toml new file mode 100644 index 0000000000..b3871d54f4 --- /dev/null +++ b/third_party/rust/core-graphics/Cargo.toml @@ -0,0 +1,41 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies +# +# If you believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "core-graphics" +version = "0.22.3" +authors = ["The Servo Project Developers"] +description = "Bindings to Core Graphics for macOS" +homepage = "https://github.com/servo/core-graphics-rs" +license = "MIT / Apache-2.0" +repository = "https://github.com/servo/core-foundation-rs" +[package.metadata.docs.rs] +default-target = "x86_64-apple-darwin" +[dependencies.bitflags] +version = "1.0" + +[dependencies.core-foundation] +version = "0.9" + +[dependencies.core-graphics-types] +version = "0.1" + +[dependencies.foreign-types] +version = "0.3.0" + +[dependencies.libc] +version = "0.2" + +[features] +default = [] +elcapitan = [] +highsierra = [] diff --git a/third_party/rust/core-graphics/LICENSE-APACHE b/third_party/rust/core-graphics/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/third_party/rust/core-graphics/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/third_party/rust/core-graphics/LICENSE-MIT b/third_party/rust/core-graphics/LICENSE-MIT new file mode 100644 index 0000000000..807526f57f --- /dev/null +++ b/third_party/rust/core-graphics/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2012-2013 Mozilla Foundation + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/third_party/rust/core-graphics/README.md b/third_party/rust/core-graphics/README.md new file mode 100644 index 0000000000..22175688cd --- /dev/null +++ b/third_party/rust/core-graphics/README.md @@ -0,0 +1,3 @@ +# core-graphics-rs + +[![Build Status](https://travis-ci.com/servo/core-graphics-rs.svg?branch=master)](https://travis-ci.com/servo/core-graphics-rs) diff --git a/third_party/rust/core-graphics/src/base.rs b/third_party/rust/core-graphics/src/base.rs new file mode 100644 index 0000000000..25baf89153 --- /dev/null +++ b/third_party/rust/core-graphics/src/base.rs @@ -0,0 +1,45 @@ +// Copyright 2013 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// this file defines CGFloat, as well as stubbed data types. + +#![allow(non_camel_case_types)] +#![allow(non_upper_case_globals)] + +pub use core_graphics_types::base::*; + +pub const kCGImageAlphaNone: u32 = 0; +pub const kCGImageAlphaPremultipliedLast: u32 = 1; +pub const kCGImageAlphaPremultipliedFirst: u32 = 2; +pub const kCGImageAlphaLast: u32 = 3; +pub const kCGImageAlphaFirst: u32 = 4; +pub const kCGImageAlphaNoneSkipLast: u32 = 5; +pub const kCGImageAlphaNoneSkipFirst: u32 = 6; + +pub const kCGBitmapByteOrderDefault: u32 = 0 << 12; +pub const kCGBitmapByteOrder16Little: u32 = 1 << 12; +pub const kCGBitmapByteOrder32Little: u32 = 2 << 12; +pub const kCGBitmapByteOrder16Big: u32 = 3 << 12; +pub const kCGBitmapByteOrder32Big: u32 = 4 << 12; + +pub const kCGRenderingIntentDefault: u32 = 0; +pub const kCGRenderingIntentAbsoluteColorimetric: u32 = 1; +pub const kCGRenderingIntentRelativeColorimetric: u32 = 2; +pub const kCGRenderingIntentPerceptual: u32 = 3; +pub const kCGRenderingIntentSaturation: u32 = 4; + +#[cfg(target_endian = "big")] +pub const kCGBitmapByteOrder16Host: u32 = kCGBitmapByteOrder16Big; +#[cfg(target_endian = "big")] +pub const kCGBitmapByteOrder32Host: u32 = kCGBitmapByteOrder32Big; + +#[cfg(target_endian = "little")] +pub const kCGBitmapByteOrder16Host: u32 = kCGBitmapByteOrder16Little; +#[cfg(target_endian = "little")] +pub const kCGBitmapByteOrder32Host: u32 = kCGBitmapByteOrder32Little; diff --git a/third_party/rust/core-graphics/src/color.rs b/third_party/rust/core-graphics/src/color.rs new file mode 100644 index 0000000000..79ef9a0072 --- /dev/null +++ b/third_party/rust/core-graphics/src/color.rs @@ -0,0 +1,35 @@ +// Copyright 2013 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core_foundation::base::{CFTypeID}; +use base::CGFloat; +use core_foundation::base::TCFType; +use super::sys::{CGColorRef}; + +pub use super::sys::CGColorRef as SysCGColorRef; + +declare_TCFType!{ + CGColor, CGColorRef +} +impl_TCFType!(CGColor, CGColorRef, CGColorGetTypeID); + +impl CGColor { + pub fn rgb(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) -> Self { + unsafe { + let ptr = CGColorCreateGenericRGB(red, green, blue, alpha); + CGColor::wrap_under_create_rule(ptr) + } + } +} + +#[link(name = "CoreGraphics", kind = "framework")] +extern { + fn CGColorCreateGenericRGB(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) -> ::sys::CGColorRef; + fn CGColorGetTypeID() -> CFTypeID; +} diff --git a/third_party/rust/core-graphics/src/color_space.rs b/third_party/rust/core-graphics/src/color_space.rs new file mode 100644 index 0000000000..9eef09c30b --- /dev/null +++ b/third_party/rust/core-graphics/src/color_space.rs @@ -0,0 +1,69 @@ +// Copyright 2015 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core_foundation::base::{CFRelease, CFRetain, CFTypeID}; +use core_foundation::string::CFStringRef; +use foreign_types::ForeignType; + +foreign_type! { + #[doc(hidden)] + type CType = ::sys::CGColorSpace; + fn drop = |p| CFRelease(p as *mut _); + fn clone = |p| CFRetain(p as *const _) as *mut _; + pub struct CGColorSpace; + pub struct CGColorSpaceRef; +} + +impl CGColorSpace { + pub fn type_id() -> CFTypeID { + unsafe { + CGColorSpaceGetTypeID() + } + } + + pub fn create_with_name(name: CFStringRef) -> Option<CGColorSpace> { + unsafe { + let p = CGColorSpaceCreateWithName(name); + if !p.is_null() {Some(CGColorSpace::from_ptr(p))} else {None} + } + } + + #[inline] + pub fn create_device_rgb() -> CGColorSpace { + unsafe { + let result = CGColorSpaceCreateDeviceRGB(); + CGColorSpace::from_ptr(result) + } + } + + #[inline] + pub fn create_device_gray() -> CGColorSpace { + unsafe { + let result = CGColorSpaceCreateDeviceGray(); + CGColorSpace::from_ptr(result) + } + } +} + +#[link(name = "CoreGraphics", kind = "framework")] +extern { + pub static kCGColorSpaceSRGB: CFStringRef; + pub static kCGColorSpaceAdobeRGB1998: CFStringRef; + pub static kCGColorSpaceGenericGray: CFStringRef; + pub static kCGColorSpaceGenericRGB: CFStringRef; + pub static kCGColorSpaceGenericCMYK: CFStringRef; + pub static kCGColorSpaceGenericRGBLinear: CFStringRef; + pub static kCGColorSpaceGenericGrayGamma2_2: CFStringRef; + + fn CGColorSpaceCreateDeviceRGB() -> ::sys::CGColorSpaceRef; + fn CGColorSpaceCreateDeviceGray() -> ::sys::CGColorSpaceRef; + fn CGColorSpaceCreateWithName(name: CFStringRef) -> ::sys::CGColorSpaceRef; + fn CGColorSpaceGetTypeID() -> CFTypeID; +} + diff --git a/third_party/rust/core-graphics/src/context.rs b/third_party/rust/core-graphics/src/context.rs new file mode 100644 index 0000000000..4efc0f70a3 --- /dev/null +++ b/third_party/rust/core-graphics/src/context.rs @@ -0,0 +1,775 @@ +// Copyright 2015 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use base::CGFloat; +use color_space::CGColorSpace; +use core_foundation::base::{CFTypeID, TCFType}; +use font::{CGFont, CGGlyph}; +use geometry::{CGPoint, CGSize}; +use gradient::{CGGradient, CGGradientDrawingOptions}; +use color::CGColor; +use path::CGPathRef; +use libc::{c_int, size_t}; +use std::os::raw::c_void; + +use std::cmp; +use std::ptr; +use std::slice; +use geometry::{CGAffineTransform, CGRect}; +use image::CGImage; +use foreign_types::{ForeignType, ForeignTypeRef}; + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub enum CGBlendMode { + Normal = 0, + Multiply, + Screen, + Overlay, + Darken, + Lighten, + ColorDodge, + ColorBurn, + SoftLight, + HardLight, + Difference, + Exclusion, + Hue, + Saturation, + Color, + Luminosity, + // 10.5 and up: + Clear, + Copy, + SourceIn, + SourceOut, + SourceAtop, + DestinationOver, + DestinationIn, + DestinationOut, + DestinationAtop, + Xor, + PlusDarker, + PlusLighter, +} + +#[repr(C)] +pub enum CGTextDrawingMode { + CGTextFill, + CGTextStroke, + CGTextFillStroke, + CGTextInvisible, + CGTextFillClip, + CGTextStrokeClip, + CGTextFillStrokeClip, + CGTextClip +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub enum CGLineCap { + CGLineCapButt, + CGLineCapRound, + CGLineCapSquare, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub enum CGLineJoin { + CGLineJoinMiter, + CGLineJoinRound, + CGLineJoinBevel, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub enum CGPathDrawingMode { + CGPathFill, + CGPathEOFill, + CGPathStroke, + CGPathFillStroke, + CGPathEOFillStroke, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub enum CGInterpolationQuality { + CGInterpolationQualityDefault, + CGInterpolationQualityNone, + CGInterpolationQualityLow, + CGInterpolationQualityMedium, + CGInterpolationQualityHigh, +} + +foreign_type! { + #[doc(hidden)] + type CType = ::sys::CGContext; + fn drop = |cs| CGContextRelease(cs); + fn clone = |p| CGContextRetain(p); + pub struct CGContext; + pub struct CGContextRef; +} + +impl CGContext { + pub fn type_id() -> CFTypeID { + unsafe { + CGContextGetTypeID() + } + } + + /// Creates a `CGContext` instance from an existing [`CGContextRef`] pointer. + /// + /// This funtion will internally call [`CGRetain`] and hence there is no need to call it explicitly. + /// + /// This function is particularly useful for cases when the context is not instantiated/managed + /// by the caller, but it's retrieve via other means (e.g., by calling the method [`NSGraphicsContext::CGContext`] + /// in a cocoa application). + /// + /// [`CGContextRef`]: https://developer.apple.com/documentation/coregraphics/cgcontextref + /// [`CGRetain`]: https://developer.apple.com/documentation/coregraphics/1586506-cgcontextretain + /// [`NSGraphicsContext::CGContext`]: https://developer.apple.com/documentation/appkit/nsgraphicscontext/1535352-currentcontext + pub unsafe fn from_existing_context_ptr(ctx: *mut ::sys::CGContext) -> CGContext { + CGContextRetain(ctx); + Self::from_ptr(ctx) + } + + 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, + space: &CGColorSpace, + bitmap_info: u32) + -> CGContext { + unsafe { + let result = CGBitmapContextCreate(data.unwrap_or(ptr::null_mut()), + width, + height, + bits_per_component, + bytes_per_row, + space.as_ptr(), + bitmap_info); + assert!(!result.is_null()); + Self::from_ptr(result) + } + } + + pub fn data(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut( + CGBitmapContextGetData(self.as_ptr()) as *mut u8, + (self.height() * self.bytes_per_row()) as usize) + } + } +} + +impl CGContextRef { + pub fn flush(&self) { + unsafe { + CGContextFlush(self.as_ptr()) + } + } + + pub fn width(&self) -> size_t { + unsafe { + CGBitmapContextGetWidth(self.as_ptr()) + } + } + + pub fn height(&self) -> size_t { + unsafe { + CGBitmapContextGetHeight(self.as_ptr()) + } + } + + pub fn bytes_per_row(&self) -> size_t { + unsafe { + CGBitmapContextGetBytesPerRow(self.as_ptr()) + } + } + + pub fn clip_bounding_box(&self) -> CGRect { + unsafe { + CGContextGetClipBoundingBox(self.as_ptr()) + } + } + + pub fn set_fill_color(&self, color: &CGColor) { + unsafe { + CGContextSetFillColorWithColor(self.as_ptr(), color.as_concrete_TypeRef()); + } + } + + pub fn set_rgb_fill_color(&self, red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) { + unsafe { + CGContextSetRGBFillColor(self.as_ptr(), red, green, blue, alpha) + } + } + + pub fn set_rgb_stroke_color(&self, red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) { + unsafe { + CGContextSetRGBStrokeColor(self.as_ptr(), red, green, blue, alpha) + } + } + + pub fn set_gray_fill_color(&self, gray: CGFloat, alpha: CGFloat) { + unsafe { + CGContextSetGrayFillColor(self.as_ptr(), gray, alpha) + } + } + + pub fn set_blend_mode(&self, blend_mode: CGBlendMode) { + unsafe { + CGContextSetBlendMode(self.as_ptr(), blend_mode) + } + } + + pub fn set_allows_font_smoothing(&self, allows_font_smoothing: bool) { + unsafe { + CGContextSetAllowsFontSmoothing(self.as_ptr(), allows_font_smoothing) + } + } + + pub fn set_font_smoothing_style(&self, style: i32) { + unsafe { + CGContextSetFontSmoothingStyle(self.as_ptr(), style as _); + } + } + + pub fn set_should_smooth_fonts(&self, should_smooth_fonts: bool) { + unsafe { + CGContextSetShouldSmoothFonts(self.as_ptr(), should_smooth_fonts) + } + } + + pub fn set_allows_antialiasing(&self, allows_antialiasing: bool) { + unsafe { + CGContextSetAllowsAntialiasing(self.as_ptr(), allows_antialiasing) + } + } + + pub fn set_should_antialias(&self, should_antialias: bool) { + unsafe { + CGContextSetShouldAntialias(self.as_ptr(), should_antialias) + } + } + + pub fn set_allows_font_subpixel_quantization(&self, allows_font_subpixel_quantization: bool) { + unsafe { + CGContextSetAllowsFontSubpixelQuantization(self.as_ptr(), allows_font_subpixel_quantization) + } + } + + pub fn set_should_subpixel_quantize_fonts(&self, should_subpixel_quantize_fonts: bool) { + unsafe { + CGContextSetShouldSubpixelQuantizeFonts(self.as_ptr(), should_subpixel_quantize_fonts) + } + } + + pub fn set_allows_font_subpixel_positioning(&self, allows_font_subpixel_positioning: bool) { + unsafe { + CGContextSetAllowsFontSubpixelPositioning(self.as_ptr(), allows_font_subpixel_positioning) + } + } + + pub fn set_should_subpixel_position_fonts(&self, should_subpixel_position_fonts: bool) { + unsafe { + CGContextSetShouldSubpixelPositionFonts(self.as_ptr(), should_subpixel_position_fonts) + } + } + + pub fn set_text_drawing_mode(&self, mode: CGTextDrawingMode) { + unsafe { + CGContextSetTextDrawingMode(self.as_ptr(), mode) + } + } + + pub fn set_line_cap(&self, cap: CGLineCap) { + unsafe { + CGContextSetLineCap(self.as_ptr(), cap) + } + } + + pub fn set_line_dash(&self, phase: CGFloat, lengths: &[CGFloat]) { + unsafe { + CGContextSetLineDash(self.as_ptr(), phase, lengths.as_ptr(), lengths.len()) + } + } + + pub fn set_line_join(&self, join: CGLineJoin) { + unsafe { + CGContextSetLineJoin(self.as_ptr(), join) + } + } + + pub fn set_line_width(&self, width: CGFloat) { + unsafe { + CGContextSetLineWidth(self.as_ptr(), width) + } + } + + pub fn set_miter_limit(&self, limit: CGFloat) { + unsafe { + CGContextSetMiterLimit(self.as_ptr(), limit) + } + } + + pub fn add_path(&self, path: &CGPathRef) { + unsafe { + CGContextAddPath(self.as_ptr(), path.as_ptr()); + } + } + + pub fn add_curve_to_point(&self, + cp1x: CGFloat, + cp1y: CGFloat, + cp2x: CGFloat, + cp2y: CGFloat, + x: CGFloat, + y: CGFloat) { + unsafe { + CGContextAddCurveToPoint(self.as_ptr(), + cp1x, cp1y, + cp2x, cp2y, + x, y); + } + } + + pub fn add_quad_curve_to_point(&self, + cpx: CGFloat, + cpy: CGFloat, + x: CGFloat, + y: CGFloat) { + unsafe { + CGContextAddQuadCurveToPoint(self.as_ptr(), + cpx, cpy, + x, y); + } + } + + pub fn add_line_to_point(&self, x: CGFloat, y: CGFloat) { + unsafe { + CGContextAddLineToPoint(self.as_ptr(), x, y); + } + } + + pub fn begin_path(&self) { + unsafe { + CGContextBeginPath(self.as_ptr()); + } + } + + pub fn close_path(&self) { + unsafe { + CGContextClosePath(self.as_ptr()); + } + } + + pub fn move_to_point(&self, x: CGFloat, y: CGFloat) { + unsafe { + CGContextMoveToPoint(self.as_ptr(), x, y); + } + } + + pub fn clip(&self) { + unsafe { + CGContextClip(self.as_ptr()); + } + } + + pub fn eo_clip(&self) { + unsafe { + CGContextEOClip(self.as_ptr()); + } + } + + pub fn draw_path(&self, mode: CGPathDrawingMode) { + unsafe { + CGContextDrawPath(self.as_ptr(), mode); + } + } + + pub fn fill_path(&self) { + unsafe { + CGContextFillPath(self.as_ptr()); + } + } + + pub fn eo_fill_path(&self) { + unsafe { + CGContextEOFillPath(self.as_ptr()); + } + } + + pub fn stroke_path(&self) { + unsafe { + CGContextStrokePath(self.as_ptr()); + } + } + + pub fn fill_rect(&self, rect: CGRect) { + unsafe { + CGContextFillRect(self.as_ptr(), rect) + } + } + + pub fn fill_rects(&self, rects: &[CGRect]) { + unsafe { + CGContextFillRects(self.as_ptr(), rects.as_ptr(), rects.len()) + } + } + + pub fn clear_rect(&self, rect: CGRect) { + unsafe { + CGContextClearRect(self.as_ptr(), rect) + } + } + + pub fn stroke_rect(&self, rect: CGRect) { + unsafe { + CGContextStrokeRect(self.as_ptr(), rect) + } + } + + pub fn stroke_rect_with_width(&self, rect: CGRect, width: CGFloat) { + unsafe { + CGContextStrokeRectWithWidth(self.as_ptr(), rect, width) + } + } + + pub fn clip_to_rect(&self, rect: CGRect) { + unsafe { + CGContextClipToRect(self.as_ptr(), rect) + } + } + + pub fn clip_to_rects(&self, rects: &[CGRect]) { + unsafe { + CGContextClipToRects(self.as_ptr(), rects.as_ptr(), rects.len()) + } + } + + pub fn clip_to_mask(&self, rect: CGRect, image: &CGImage) { + unsafe { + CGContextClipToMask(self.as_ptr(), rect, image.as_ptr()) + } + } + + pub fn replace_path_with_stroked_path(&self) { + unsafe { + CGContextReplacePathWithStrokedPath(self.as_ptr()) + } + } + + pub fn fill_ellipse_in_rect(&self, rect: CGRect) { + unsafe { + CGContextFillEllipseInRect(self.as_ptr(), rect) + } + } + + pub fn stroke_ellipse_in_rect(&self, rect: CGRect) { + unsafe { + CGContextStrokeEllipseInRect(self.as_ptr(), rect) + } + } + + pub fn stroke_line_segments(&self, points: &[CGPoint]) { + unsafe { + CGContextStrokeLineSegments(self.as_ptr(), points.as_ptr(), points.len()) + } + } + + pub fn set_interpolation_quality(&self, quality: CGInterpolationQuality) { + unsafe { + CGContextSetInterpolationQuality(self.as_ptr(), quality); + } + } + + pub fn get_interpolation_quality(&self) -> CGInterpolationQuality { + unsafe { + CGContextGetInterpolationQuality(self.as_ptr()) + + } + } + + pub fn draw_image(&self, rect: CGRect, image: &CGImage) { + unsafe { + CGContextDrawImage(self.as_ptr(), rect, image.as_ptr()); + } + } + + pub fn create_image(&self) -> Option<CGImage> { + let image = unsafe { CGBitmapContextCreateImage(self.as_ptr()) }; + if !image.is_null() { + Some(unsafe { CGImage::from_ptr(image) }) + } else { + None + } + } + + pub fn set_font(&self, font: &CGFont) { + unsafe { + CGContextSetFont(self.as_ptr(), font.as_ptr()) + } + } + + pub fn set_font_size(&self, size: CGFloat) { + unsafe { + CGContextSetFontSize(self.as_ptr(), size) + } + } + + pub fn set_text_matrix(&self, t: &CGAffineTransform) { + unsafe { + CGContextSetTextMatrix(self.as_ptr(), *t) + } + } + + pub fn set_text_position(&self, x: CGFloat, y: CGFloat) { + unsafe { + CGContextSetTextPosition(self.as_ptr(), x, y) + } + } + + pub fn show_glyphs_at_positions(&self, glyphs: &[CGGlyph], positions: &[CGPoint]) { + unsafe { + let count = cmp::min(glyphs.len(), positions.len()); + CGContextShowGlyphsAtPositions(self.as_ptr(), + glyphs.as_ptr(), + positions.as_ptr(), + count) + } + } + + pub fn save(&self) { + unsafe { + CGContextSaveGState(self.as_ptr()); + } + } + + pub fn restore(&self) { + unsafe { + CGContextRestoreGState(self.as_ptr()); + } + } + + pub fn translate(&self, tx: CGFloat, ty: CGFloat) { + unsafe { + CGContextTranslateCTM(self.as_ptr(), tx, ty); + } + } + + pub fn scale(&self, sx: CGFloat, sy: CGFloat) { + unsafe { + CGContextScaleCTM(self.as_ptr(), sx, sy); + } + } + + pub fn rotate(&self, angle: CGFloat) { + unsafe { + CGContextRotateCTM(self.as_ptr(), angle); + } + } + + pub fn get_ctm(&self) -> CGAffineTransform { + unsafe { + CGContextGetCTM(self.as_ptr()) + } + } + + pub fn concat_ctm(&self, transform: CGAffineTransform) { + unsafe { + CGContextConcatCTM(self.as_ptr(), transform) + } + } + + pub fn draw_linear_gradient(&self, gradient: &CGGradient, start_point: CGPoint, end_point: CGPoint, options: CGGradientDrawingOptions) { + unsafe { + CGContextDrawLinearGradient(self.as_ptr(), gradient.as_ptr(), start_point, end_point, options); + } + } + + pub fn draw_radial_gradient(&self, gradient: &CGGradient, start_center: CGPoint, start_radius: CGFloat, end_center: CGPoint, end_radius: CGFloat, options: CGGradientDrawingOptions) { + unsafe { + CGContextDrawRadialGradient(self.as_ptr(), gradient.as_ptr(), start_center, start_radius, end_center, end_radius, options); + } + } + + pub fn set_shadow(&self, offset: CGSize, blur: CGFloat) { + unsafe { + CGContextSetShadow(self.as_ptr(), offset, blur); + } + } + + pub fn set_shadow_with_color(&self, offset: CGSize, blur: CGFloat, color: &CGColor) { + unsafe { + CGContextSetShadowWithColor(self.as_ptr(), offset, blur, color.as_concrete_TypeRef()); + } + } +} + +#[test] +fn create_bitmap_context_test() { + use geometry::*; + + let cs = CGColorSpace::create_device_rgb(); + let ctx = CGContext::create_bitmap_context(None, + 16, 8, + 8, 0, + &cs, + ::base::kCGImageAlphaPremultipliedLast); + ctx.set_rgb_fill_color(1.,0.,1.,1.); + ctx.set_miter_limit(4.); + ctx.fill_rect(CGRect::new(&CGPoint::new(0.,0.), &CGSize::new(8.,8.))); + let img = ctx.create_image().unwrap(); + assert_eq!(16, img.width()); + assert_eq!(8, img.height()); + assert_eq!(8, img.bits_per_component()); + assert_eq!(32, img.bits_per_pixel()); + let data = img.data(); + assert_eq!(255, data.bytes()[0]); + assert_eq!(0, data.bytes()[1]); + assert_eq!(255, data.bytes()[2]); + assert_eq!(255, data.bytes()[3]); +} + +#[link(name = "CoreGraphics", kind = "framework")] +extern { + fn CGContextRetain(c: ::sys::CGContextRef) -> ::sys::CGContextRef; + fn CGContextRelease(c: ::sys::CGContextRef); + + fn CGBitmapContextCreate(data: *mut c_void, + width: size_t, + height: size_t, + bitsPerComponent: size_t, + bytesPerRow: size_t, + space: ::sys::CGColorSpaceRef, + bitmapInfo: u32) + -> ::sys::CGContextRef; + fn CGBitmapContextGetData(context: ::sys::CGContextRef) -> *mut c_void; + fn CGBitmapContextGetWidth(context: ::sys::CGContextRef) -> size_t; + fn CGBitmapContextGetHeight(context: ::sys::CGContextRef) -> size_t; + fn CGBitmapContextGetBytesPerRow(context: ::sys::CGContextRef) -> size_t; + fn CGBitmapContextCreateImage(context: ::sys::CGContextRef) -> ::sys::CGImageRef; + fn CGContextGetTypeID() -> CFTypeID; + fn CGContextGetClipBoundingBox(c: ::sys::CGContextRef) -> CGRect; + fn CGContextFlush(c: ::sys::CGContextRef); + fn CGContextSetBlendMode(c: ::sys::CGContextRef, blendMode: CGBlendMode); + fn CGContextSetAllowsFontSmoothing(c: ::sys::CGContextRef, allowsFontSmoothing: bool); + fn CGContextSetShouldSmoothFonts(c: ::sys::CGContextRef, shouldSmoothFonts: bool); + fn CGContextSetFontSmoothingStyle(c: ::sys::CGContextRef, style: c_int); + fn CGContextSetAllowsAntialiasing(c: ::sys::CGContextRef, allowsAntialiasing: bool); + fn CGContextSetShouldAntialias(c: ::sys::CGContextRef, shouldAntialias: bool); + fn CGContextSetAllowsFontSubpixelQuantization(c: ::sys::CGContextRef, + allowsFontSubpixelQuantization: bool); + fn CGContextSetShouldSubpixelQuantizeFonts(c: ::sys::CGContextRef, + shouldSubpixelQuantizeFonts: bool); + fn CGContextSetAllowsFontSubpixelPositioning(c: ::sys::CGContextRef, + allowsFontSubpixelPositioning: bool); + fn CGContextSetShouldSubpixelPositionFonts(c: ::sys::CGContextRef, + shouldSubpixelPositionFonts: bool); + fn CGContextSetTextDrawingMode(c: ::sys::CGContextRef, mode: CGTextDrawingMode); + fn CGContextSetFillColorWithColor(c: ::sys::CGContextRef, color: ::sys::CGColorRef); + fn CGContextSetLineCap(c: ::sys::CGContextRef, cap: CGLineCap); + fn CGContextSetLineDash(c: ::sys::CGContextRef, phase: CGFloat, lengths: *const CGFloat, count: size_t); + fn CGContextSetLineJoin(c: ::sys::CGContextRef, join: CGLineJoin); + fn CGContextSetLineWidth(c: ::sys::CGContextRef, width: CGFloat); + fn CGContextSetMiterLimit(c: ::sys::CGContextRef, limit: CGFloat); + + fn CGContextAddPath(c: ::sys::CGContextRef, path: ::sys::CGPathRef); + fn CGContextAddCurveToPoint(c: ::sys::CGContextRef, + cp1x: CGFloat, + cp1y: CGFloat, + cp2x: CGFloat, + cp2y: CGFloat, + x: CGFloat, + y: CGFloat); + fn CGContextAddQuadCurveToPoint(c: ::sys::CGContextRef, + cpx: CGFloat, + cpy: CGFloat, + x: CGFloat, + y: CGFloat); + fn CGContextAddLineToPoint(c: ::sys::CGContextRef, + x: CGFloat, + y: CGFloat); + fn CGContextBeginPath(c: ::sys::CGContextRef); + fn CGContextClosePath(c: ::sys::CGContextRef); + fn CGContextMoveToPoint(c: ::sys::CGContextRef, + x: CGFloat, + y: CGFloat); + fn CGContextDrawPath(c: ::sys::CGContextRef, mode: CGPathDrawingMode); + fn CGContextFillPath(c: ::sys::CGContextRef); + fn CGContextEOFillPath(c: ::sys::CGContextRef); + fn CGContextClip(c: ::sys::CGContextRef); + fn CGContextEOClip(c: ::sys::CGContextRef); + fn CGContextStrokePath(c: ::sys::CGContextRef); + fn CGContextSetRGBFillColor(context: ::sys::CGContextRef, + red: CGFloat, + green: CGFloat, + blue: CGFloat, + alpha: CGFloat); + fn CGContextSetRGBStrokeColor(context: ::sys::CGContextRef, + red: CGFloat, + green: CGFloat, + blue: CGFloat, + alpha: CGFloat); + fn CGContextSetGrayFillColor(context: ::sys::CGContextRef, gray: CGFloat, alpha: CGFloat); + fn CGContextClearRect(context: ::sys::CGContextRef, + rect: CGRect); + fn CGContextFillRect(context: ::sys::CGContextRef, + rect: CGRect); + fn CGContextFillRects(context: ::sys::CGContextRef, + rects: *const CGRect, + count: size_t); + fn CGContextStrokeRect(context: ::sys::CGContextRef, + rect: CGRect); + fn CGContextStrokeRectWithWidth(context: ::sys::CGContextRef, + rect: CGRect, + width: CGFloat); + fn CGContextClipToRect(context: ::sys::CGContextRef, + rect: CGRect); + fn CGContextClipToRects(context: ::sys::CGContextRef, + rects: *const CGRect, + count: size_t); + fn CGContextClipToMask(ctx: ::sys::CGContextRef, rect: CGRect, mask: ::sys::CGImageRef); + fn CGContextReplacePathWithStrokedPath(context: ::sys::CGContextRef); + fn CGContextFillEllipseInRect(context: ::sys::CGContextRef, + rect: CGRect); + fn CGContextStrokeEllipseInRect(context: ::sys::CGContextRef, + rect: CGRect); + fn CGContextStrokeLineSegments(context: ::sys::CGContextRef, + points: *const CGPoint, + count: size_t); + fn CGContextDrawImage(c: ::sys::CGContextRef, rect: CGRect, image: ::sys::CGImageRef); + fn CGContextSetInterpolationQuality(c: ::sys::CGContextRef, quality: CGInterpolationQuality); + fn CGContextGetInterpolationQuality(c: ::sys::CGContextRef) -> CGInterpolationQuality; + fn CGContextSetFont(c: ::sys::CGContextRef, font: ::sys::CGFontRef); + fn CGContextSetFontSize(c: ::sys::CGContextRef, size: CGFloat); + fn CGContextSetTextMatrix(c: ::sys::CGContextRef, t: CGAffineTransform); + fn CGContextSetTextPosition(c: ::sys::CGContextRef, x: CGFloat, y: CGFloat); + fn CGContextShowGlyphsAtPositions(c: ::sys::CGContextRef, + glyphs: *const CGGlyph, + positions: *const CGPoint, + count: size_t); + + fn CGContextSaveGState(c: ::sys::CGContextRef); + fn CGContextRestoreGState(c: ::sys::CGContextRef); + fn CGContextTranslateCTM(c: ::sys::CGContextRef, tx: CGFloat, ty: CGFloat); + fn CGContextScaleCTM(c: ::sys::CGContextRef, sx: CGFloat, sy: CGFloat); + fn CGContextRotateCTM(c: ::sys::CGContextRef, angle: CGFloat); + fn CGContextGetCTM(c: ::sys::CGContextRef) -> CGAffineTransform; + fn CGContextConcatCTM(c: ::sys::CGContextRef, transform: CGAffineTransform); + + fn CGContextDrawLinearGradient(c: ::sys::CGContextRef, gradient: ::sys::CGGradientRef, startPoint: CGPoint, endPoint: CGPoint, options: CGGradientDrawingOptions); + fn CGContextDrawRadialGradient(c: ::sys::CGContextRef, gradient: ::sys::CGGradientRef, startCenter: CGPoint, startRadius: CGFloat, endCenter:CGPoint, endRadius:CGFloat, options: CGGradientDrawingOptions); + + fn CGContextSetShadow(c: ::sys::CGContextRef, offset: CGSize, blur: CGFloat); + fn CGContextSetShadowWithColor(c: ::sys::CGContextRef, offset: CGSize, blur: CGFloat, color: ::sys::CGColorRef); +} + diff --git a/third_party/rust/core-graphics/src/data_provider.rs b/third_party/rust/core-graphics/src/data_provider.rs new file mode 100644 index 0000000000..e8bb0a0241 --- /dev/null +++ b/third_party/rust/core-graphics/src/data_provider.rs @@ -0,0 +1,162 @@ +// Copyright 2013 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core_foundation::base::{CFRelease, CFRetain, CFTypeID, TCFType}; +use core_foundation::data::{CFData, CFDataRef}; + +use libc::{size_t, off_t}; +use std::mem; +use std::ptr; +use std::sync::Arc; +use std::os::raw::c_void; + +use foreign_types::{ForeignType, ForeignTypeRef}; + +pub type CGDataProviderGetBytesCallback = Option<unsafe extern fn (*mut c_void, *mut c_void, size_t) -> size_t>; +pub type CGDataProviderReleaseInfoCallback = Option<unsafe extern fn (*mut c_void)>; +pub type CGDataProviderRewindCallback = Option<unsafe extern fn (*mut c_void)>; +pub type CGDataProviderSkipBytesCallback = Option<unsafe extern fn (*mut c_void, size_t)>; +pub type CGDataProviderSkipForwardCallback = Option<unsafe extern fn (*mut c_void, off_t) -> off_t>; + +pub type CGDataProviderGetBytePointerCallback = Option<unsafe extern fn (*mut c_void) -> *mut c_void>; +pub type CGDataProviderGetBytesAtOffsetCallback = Option<unsafe extern fn (*mut c_void, *mut c_void, size_t, size_t)>; +pub type CGDataProviderReleaseBytePointerCallback = Option<unsafe extern fn (*mut c_void, *const c_void)>; +pub type CGDataProviderReleaseDataCallback = Option<unsafe extern fn (*mut c_void, *const c_void, size_t)>; +pub type CGDataProviderGetBytesAtPositionCallback = Option<unsafe extern fn (*mut c_void, *mut c_void, off_t, size_t)>; + +foreign_type! { + #[doc(hidden)] + type CType = ::sys::CGDataProvider; + fn drop = |cs| CFRelease(cs as *mut _); + fn clone = |p| CFRetain(p as *const _) as *mut _; + pub struct CGDataProvider; + pub struct CGDataProviderRef; +} + +impl CGDataProvider { + pub fn type_id() -> CFTypeID { + unsafe { + CGDataProviderGetTypeID() + } + } + + /// Creates a data provider from the given reference-counted buffer. + /// + /// The `CGDataProvider` object takes ownership of the reference. Once the data provider + /// is destroyed, the reference count of the buffer is automatically decremented. + pub fn from_buffer<T: AsRef<[u8]> + Sync + Send>(buffer: Arc<T>) -> Self { + unsafe { + let ptr = (*buffer).as_ref().as_ptr() as *const c_void; + let len = (*buffer).as_ref().len() as size_t; + let info = Arc::into_raw(buffer) as *mut c_void; + let result = CGDataProviderCreateWithData(info, ptr, len, Some(release::<T>)); + return CGDataProvider::from_ptr(result); + } + + unsafe extern "C" fn release<T>(info: *mut c_void, _: *const c_void, _: size_t) { + drop(Arc::from_raw(info as *mut T)) + } + } + + /// Creates a data prvider from a given slice. The data provider does not own the slice in this + /// case, so it's up to the user to ensure the memory safety here. + pub unsafe fn from_slice(buffer: &[u8]) -> Self { + let ptr = buffer.as_ptr() as *const c_void; + let len = buffer.len() as size_t; + let result = CGDataProviderCreateWithData(ptr::null_mut(), ptr, len, None); + CGDataProvider::from_ptr(result) + } + + /// Creates a data provider from the given raw pointer, length, and destructor function. + /// + /// This is double-boxed because the Core Text API requires that the userdata be a single + /// pointer. + pub unsafe fn from_custom_data(custom_data: Box<Box<dyn CustomData>>) -> Self { + let (ptr, len) = (custom_data.ptr() as *const c_void, custom_data.len()); + let userdata = mem::transmute::<Box<Box<dyn CustomData>>, &mut c_void>(custom_data); + let data_provider = CGDataProviderCreateWithData(userdata, ptr, len, Some(release)); + return CGDataProvider::from_ptr(data_provider); + + unsafe extern "C" fn release(info: *mut c_void, _: *const c_void, _: size_t) { + drop(mem::transmute::<*mut c_void, Box<Box<dyn CustomData>>>(info)) + } + } +} + +impl CGDataProviderRef { + /// Creates a copy of the data from the underlying `CFDataProviderRef`. + pub fn copy_data(&self) -> CFData { + unsafe { CFData::wrap_under_create_rule(CGDataProviderCopyData(self.as_ptr())) } + } +} + +/// Encapsulates custom data that can be wrapped. +pub trait CustomData { + /// Returns a pointer to the start of the custom data. This pointer *must not change* during + /// the lifespan of this CustomData. + unsafe fn ptr(&self) -> *const u8; + /// Returns the length of this custom data. This value must not change during the lifespan of + /// this CustomData. + unsafe fn len(&self) -> usize; +} + +#[test] +fn test_data_provider() { + let l = vec![5]; + CGDataProvider::from_buffer(Arc::new(l)); + + let l = vec![5]; + CGDataProvider::from_buffer(Arc::new(l.into_boxed_slice())); + + // Make sure the buffer is actually dropped + use std::sync::atomic::{AtomicBool, Ordering::SeqCst}; + struct VecWrapper { + inner: Vec<u8>, + dropped: Arc<AtomicBool>, + } + + impl Drop for VecWrapper { + fn drop(&mut self) { + self.dropped.store(true, SeqCst) + } + } + + impl std::convert::AsRef<[u8]> for VecWrapper { + fn as_ref(&self) -> &[u8] { + &self.inner + } + } + + let dropped = Arc::new(AtomicBool::default()); + let l = Arc::new(VecWrapper {inner: vec![5], dropped: dropped.clone() }); + let m = l.clone(); + let dp = CGDataProvider::from_buffer(l); + drop(m); + assert!(!dropped.load(SeqCst)); + drop(dp); + assert!(dropped.load(SeqCst)) +} + +#[link(name = "CoreGraphics", kind = "framework")] +extern { + fn CGDataProviderCopyData(provider: ::sys::CGDataProviderRef) -> CFDataRef; + //fn CGDataProviderCreateDirect + //fn CGDataProviderCreateSequential + //fn CGDataProviderCreateWithCFData + fn CGDataProviderCreateWithData(info: *mut c_void, + data: *const c_void, + size: size_t, + releaseData: CGDataProviderReleaseDataCallback + ) -> ::sys::CGDataProviderRef; + //fn CGDataProviderCreateWithFilename(filename: *c_char) -> CGDataProviderRef; + //fn CGDataProviderCreateWithURL + fn CGDataProviderGetTypeID() -> CFTypeID; + //fn CGDataProviderRelease(provider: CGDataProviderRef); + //fn CGDataProviderRetain(provider: CGDataProviderRef) -> CGDataProviderRef; +} diff --git a/third_party/rust/core-graphics/src/display.rs b/third_party/rust/core-graphics/src/display.rs new file mode 100644 index 0000000000..394520bae4 --- /dev/null +++ b/third_party/rust/core-graphics/src/display.rs @@ -0,0 +1,723 @@ +// Copyright 2013 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(non_upper_case_globals)] + +use libc; +use std::ptr; +use std::ops::Deref; + +pub use base::{CGError, boolean_t}; +pub use geometry::{CGRect, CGPoint, CGSize}; + +use core_foundation::string::{CFString, CFStringRef}; +use core_foundation::base::{CFRetain, TCFType}; +use image::CGImage; +use foreign_types::ForeignType; + +pub type CGDirectDisplayID = u32; +pub type CGWindowID = u32; + +pub const kCGNullWindowID: CGWindowID = 0 as CGWindowID; +pub const kCGNullDirectDisplayID: CGDirectDisplayID = 0 as CGDirectDisplayID; + +pub type CGWindowListOption = u32; + +pub const kCGWindowListOptionAll: CGWindowListOption = 0; +pub const kCGWindowListOptionOnScreenOnly: CGWindowListOption = 1 << 0; +pub const kCGWindowListOptionOnScreenAboveWindow: CGWindowListOption = 1 << 1; +pub const kCGWindowListOptionOnScreenBelowWindow: CGWindowListOption = 1 << 2; +pub const kCGWindowListOptionIncludingWindow: CGWindowListOption = 1 << 3; +pub const kCGWindowListExcludeDesktopElements: CGWindowListOption = 1 << 4; + +pub type CGWindowImageOption = u32; + +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 const kDisplayModeValidFlag: u32 = 0x00000001; +pub const kDisplayModeSafeFlag: u32 = 0x00000002; +pub const kDisplayModeDefaultFlag: u32 = 0x00000004; +pub const kDisplayModeAlwaysShowFlag: u32 = 0x00000008; +pub const kDisplayModeNeverShowFlag: u32 = 0x00000080; +pub const kDisplayModeNotResizeFlag: u32 = 0x00000010; +pub const kDisplayModeRequiresPanFlag: u32 = 0x00000020; +pub const kDisplayModeInterlacedFlag: u32 = 0x00000040; +pub const kDisplayModeSimulscanFlag: u32 = 0x00000100; +pub const kDisplayModeBuiltInFlag: u32 = 0x00000400; +pub const kDisplayModeNotPresetFlag: u32 = 0x00000200; +pub const kDisplayModeStretchedFlag: u32 = 0x00000800; +pub const kDisplayModeNotGraphicsQualityFlag: u32 = 0x00001000; +pub const kDisplayModeValidateAgainstDisplay: u32 = 0x00002000; +pub const kDisplayModeTelevisionFlag: u32 = 0x00100000; +pub const kDisplayModeValidForMirroringFlag: u32 = 0x00200000; +pub const kDisplayModeAcceleratorBackedFlag: u32 = 0x00400000; +pub const kDisplayModeValidForHiResFlag: u32 = 0x00800000; +pub const kDisplayModeValidForAirPlayFlag: u32 = 0x01000000; +pub const kDisplayModeNativeFlag: u32 = 0x02000000; + +pub const kDisplayModeSafetyFlags: u32 = 0x00000007; + +pub const IO1BitIndexedPixels: &str = "P"; +pub const IO2BitIndexedPixels: &str = "PP"; +pub const IO4BitIndexedPixels: &str = "PPPP"; +pub const IO8BitIndexedPixels: &str = "PPPPPPPP"; +pub const IO16BitDirectPixels: &str = "-RRRRRGGGGGBBBBB"; +pub const IO32BitDirectPixels: &str = "--------RRRRRRRRGGGGGGGGBBBBBBBB"; +pub const kIO30BitDirectPixels: &str = "--RRRRRRRRRRGGGGGGGGGGBBBBBBBBBB"; +pub const kIO64BitDirectPixels: &str = "-16R16G16B16"; +pub const kIO16BitFloatPixels: &str = "-16FR16FG16FB16"; +pub const kIO32BitFloatPixels: &str = "-32FR32FG32FB32"; +pub const IOYUV422Pixels: &str = "Y4U2V2"; +pub const IO8BitOverlayPixels: &str = "O8"; + + +pub use core_foundation::dictionary::{ CFDictionary, CFDictionaryRef, CFDictionaryGetValueIfPresent }; +pub use core_foundation::array::{ CFArray, CFArrayRef }; +pub use core_foundation::array::{ CFArrayGetCount, CFArrayGetValueAtIndex }; +pub use core_foundation::base::{ CFIndex, CFRelease, CFTypeRef }; + +pub type CGDisplayConfigRef = *mut libc::c_void; + +#[repr(u32)] +#[derive(Clone, Copy)] +pub enum CGConfigureOption { + ConfigureForAppOnly = 0, + ConfigureForSession = 1, + ConfigurePermanently = 2, +} + +#[derive(Copy, Clone, Debug)] +pub struct CGDisplay { + pub id: CGDirectDisplayID, +} + +foreign_type! { + #[doc(hidden)] + type CType = ::sys::CGDisplayMode; + fn drop = CGDisplayModeRelease; + fn clone = |p| CFRetain(p as *const _) as *mut _; + pub struct CGDisplayMode; + pub struct CGDisplayModeRef; +} + +impl CGDisplay { + #[inline] + pub fn new(id: CGDirectDisplayID) -> CGDisplay { + CGDisplay { id: id } + } + + /// Returns the the main display. + #[inline] + pub fn main() -> CGDisplay { + CGDisplay::new(unsafe { CGMainDisplayID() }) + } + + /// A value that will never correspond to actual hardware. + pub fn null_display() -> CGDisplay { + CGDisplay::new(kCGNullDirectDisplayID) + } + + /// Returns the bounds of a display in the global display coordinate space. + #[inline] + pub fn bounds(&self) -> CGRect { + unsafe { CGDisplayBounds(self.id) } + } + + /// Returns information about a display's current configuration. + #[inline] + pub fn display_mode(&self) -> Option<CGDisplayMode> { + unsafe { + let mode_ref = CGDisplayCopyDisplayMode(self.id); + if !mode_ref.is_null() { + Some(CGDisplayMode::from_ptr(mode_ref)) + } else { + None + } + } + } + + /// Begins a new set of display configuration changes. + pub fn begin_configuration(&self) -> Result<CGDisplayConfigRef, CGError> { + unsafe { + let mut config_ref: CGDisplayConfigRef = ptr::null_mut(); + let result = CGBeginDisplayConfiguration(&mut config_ref); + if result == 0 { + Ok(config_ref) + } else { + Err(result) + } + } + } + + /// Cancels a set of display configuration changes. + pub fn cancel_configuration(&self, config_ref: &CGDisplayConfigRef) -> Result<(), CGError> { + let result = unsafe { CGCancelDisplayConfiguration(*config_ref) }; + if result == 0 { + Ok(()) + } else { + Err(result) + } + } + + /// Completes a set of display configuration changes. + pub fn complete_configuration( + &self, + config_ref: &CGDisplayConfigRef, + option: CGConfigureOption, + ) -> Result<(), CGError> { + let result = unsafe { CGCompleteDisplayConfiguration(*config_ref, option) }; + if result == 0 { + Ok(()) + } else { + Err(result) + } + } + + /// Configures the display mode of a display. + pub fn configure_display_with_display_mode( + &self, + config_ref: &CGDisplayConfigRef, + display_mode: &CGDisplayMode, + ) -> Result<(), CGError> { + let result = unsafe { + CGConfigureDisplayWithDisplayMode( + *config_ref, + self.id, + display_mode.as_ptr(), + ptr::null(), + ) + }; + if result == 0 { + Ok(()) + } else { + Err(result) + } + } + + /// Configures the origin of a display in the global display coordinate space. + pub fn configure_display_origin( + &self, + config_ref: &CGDisplayConfigRef, + x: i32, + y: i32, + ) -> Result<(), CGError> { + let result = unsafe { CGConfigureDisplayOrigin(*config_ref, self.id, x, y) }; + + if result == 0 { + Ok(()) + } else { + Err(result) + } + } + + /// Changes the configuration of a mirroring set. + pub fn configure_display_mirror_of_display( + &self, + config_ref: &CGDisplayConfigRef, + master: &CGDisplay, + ) -> Result<(), CGError> { + let result = unsafe { CGConfigureDisplayMirrorOfDisplay(*config_ref, self.id, master.id) }; + + if result == 0 { + Ok(()) + } else { + Err(result) + } + } + + /// Returns an image containing the contents of the specified display. + #[inline] + pub fn image(&self) -> Option<CGImage> { + unsafe { + let image_ref = CGDisplayCreateImage(self.id); + if !image_ref.is_null() { + Some(CGImage::from_ptr(image_ref)) + } else { + None + } + } + } + + /// Returns a composite image based on a dynamically generated list of + /// windows. + #[inline] + pub fn screenshot( + bounds: CGRect, + list_option: CGWindowListOption, + window_id: CGWindowID, + image_option: CGWindowImageOption, + ) -> Option<CGImage> { + unsafe { + let image_ref = CGWindowListCreateImage(bounds, list_option, window_id, image_option); + if !image_ref.is_null() { + Some(CGImage::from_ptr(image_ref)) + } else { + None + } + } + } + + /// Returns a composite image of the specified windows. + #[inline] + pub fn screenshot_from_windows( + bounds: CGRect, + windows: CFArray, + image_option: CGWindowImageOption, + ) -> Option<CGImage> { + unsafe { + let image_ref = CGWindowListCreateImageFromArray( + bounds, + windows.as_concrete_TypeRef(), + image_option, + ); + if !image_ref.is_null() { + Some(CGImage::from_ptr(image_ref)) + } else { + None + } + } + } + + /// Generates and returns information about the selected windows in the + /// current user session. + pub fn window_list_info( + option: CGWindowListOption, + relative_to_window: Option<CGWindowID>, + ) -> Option<CFArray> { + let relative_to_window = relative_to_window.unwrap_or(kCGNullWindowID); + let array_ref = unsafe { CGWindowListCopyWindowInfo(option, relative_to_window) }; + if !array_ref.is_null() { + Some(unsafe { TCFType::wrap_under_create_rule(array_ref) }) + } else { + None + } + } + + /// Returns a Boolean value indicating whether a display is active. + #[inline] + pub fn is_active(&self) -> bool { + unsafe { CGDisplayIsActive(self.id) != 0 } + } + + /// Returns a boolean indicating whether a display is always in a + /// mirroring set. + #[inline] + pub fn is_always_in_mirror_set(&self) -> bool { + unsafe { CGDisplayIsAlwaysInMirrorSet(self.id) != 0 } + } + + /// Returns a boolean indicating whether a display is sleeping (and is + /// therefore not drawable.) + #[inline] + pub fn is_asleep(&self) -> bool { + unsafe { CGDisplayIsAsleep(self.id) != 0 } + } + + /// Returns a boolean indicating whether a display is built-in, such as + /// the internal display in portable systems. + #[inline] + pub fn is_builtin(&self) -> bool { + unsafe { CGDisplayIsBuiltin(self.id) != 0 } + } + + /// Returns a boolean indicating whether a display is in a hardware + /// mirroring set. + #[inline] + pub fn is_in_hw_mirror_set(&self) -> bool { + unsafe { CGDisplayIsInHWMirrorSet(self.id) != 0 } + } + + /// Returns a boolean indicating whether a display is in a mirroring set. + #[inline] + pub fn is_in_mirror_set(&self) -> bool { + unsafe { CGDisplayIsInMirrorSet(self.id) != 0 } + } + + /// Returns a boolean indicating whether a display is the main display. + #[inline] + pub fn is_main(&self) -> bool { + unsafe { CGDisplayIsMain(self.id) != 0 } + } + + /// Returns a boolean indicating whether a display is connected or online. + #[inline] + pub fn is_online(&self) -> bool { + unsafe { CGDisplayIsOnline(self.id) != 0 } + } + + /// Returns a boolean indicating whether Quartz is using OpenGL-based + /// window acceleration (Quartz Extreme) to render in a display. + #[inline] + pub fn uses_open_gl_acceleration(&self) -> bool { + unsafe { CGDisplayUsesOpenGLAcceleration(self.id) != 0 } + } + + /// Returns a boolean indicating whether a display is running in a stereo + /// graphics mode. + #[inline] + pub fn is_stereo(&self) -> bool { + unsafe { CGDisplayIsStereo(self.id) != 0 } + } + + /// For a secondary display in a mirroring set, returns the primary + /// display. + #[inline] + pub fn mirrors_display(&self) -> CGDirectDisplayID { + unsafe { CGDisplayMirrorsDisplay(self.id) } + } + + /// Returns the primary display in a hardware mirroring set. + #[inline] + pub fn primary_display(&self) -> CGDirectDisplayID { + unsafe { CGDisplayPrimaryDisplay(self.id) } + } + + /// Returns the rotation angle of a display in degrees. + #[inline] + pub fn rotation(&self) -> f64 { + unsafe { CGDisplayRotation(self.id) } + } + + /// Returns the width and height of a display in millimeters. + #[inline] + pub fn screen_size(&self) -> CGSize { + unsafe { CGDisplayScreenSize(self.id) } + } + + /// Returns the serial number of a display monitor. + #[inline] + pub fn serial_number(&self) -> u32 { + unsafe { CGDisplaySerialNumber(self.id) } + } + + /// Returns the logical unit number of a display. + #[inline] + pub fn unit_number(&self) -> u32 { + unsafe { CGDisplayUnitNumber(self.id) } + } + + /// Returns the vendor number of the specified display's monitor. + #[inline] + pub fn vendor_number(&self) -> u32 { + unsafe { CGDisplayVendorNumber(self.id) } + } + + /// Returns the model number of a display monitor. + #[inline] + pub fn model_number(&self) -> u32 { + unsafe { CGDisplayModelNumber(self.id) } + } + + /// Returns the display height in pixel units. + #[inline] + pub fn pixels_high(&self) -> u64 { + unsafe { CGDisplayPixelsHigh(self.id) as u64 } + } + + /// Returns the display width in pixel units. + #[inline] + pub fn pixels_wide(&self) -> u64 { + unsafe { CGDisplayPixelsWide(self.id) as u64 } + } + + /// Provides a list of displays that are active (or drawable). + #[inline] + pub fn active_displays() -> Result<Vec<CGDirectDisplayID>, CGError> { + let count = CGDisplay::active_display_count()?; + let mut buf: Vec<CGDirectDisplayID> = vec![0; count as usize]; + let result = + unsafe { CGGetActiveDisplayList(count as u32, buf.as_mut_ptr(), ptr::null_mut()) }; + if result == 0 { + Ok(buf) + } else { + Err(result) + } + } + + /// Provides count of displays that are active (or drawable). + #[inline] + pub fn active_display_count() -> Result<u32, CGError> { + let mut count: u32 = 0; + let result = unsafe { CGGetActiveDisplayList(0, ptr::null_mut(), &mut count) }; + if result == 0 { + Ok(count as u32) + } else { + Err(result) + } + } + + /// Hides the mouse cursor, and increments the hide cursor count. + #[inline] + pub fn hide_cursor(&self) -> Result<(), CGError> { + let result = unsafe { CGDisplayHideCursor(self.id) }; + if result == 0 { + Ok(()) + } else { + Err(result) + } + } + + /// Decrements the hide cursor count, and shows the mouse cursor if the + /// count is 0. + #[inline] + pub fn show_cursor(&self) -> Result<(), CGError> { + let result = unsafe { CGDisplayShowCursor(self.id) }; + if result == 0 { + Ok(()) + } else { + Err(result) + } + } + + /// Moves the mouse cursor to a specified point relative to the display + /// origin (the upper-left corner of the display). + #[inline] + pub fn move_cursor_to_point(&self, point: CGPoint) -> Result<(), CGError> { + let result = unsafe { CGDisplayMoveCursorToPoint(self.id, point) }; + if result == 0 { + Ok(()) + } else { + Err(result) + } + } + + /// Moves the mouse cursor without generating events. + #[inline] + pub fn warp_mouse_cursor_position(point: CGPoint) -> Result<(), CGError> { + let result = unsafe { CGWarpMouseCursorPosition(point) }; + if result == 0 { + Ok(()) + } else { + Err(result) + } + } + + /// Connects or disconnects the mouse and cursor while an application is + /// in the foreground. + #[inline] + pub fn associate_mouse_and_mouse_cursor_position(connected: bool) -> Result<(), CGError> { + let result = unsafe { CGAssociateMouseAndMouseCursorPosition(connected as boolean_t) }; + if result == 0 { + Ok(()) + } else { + Err(result) + } + } +} + +impl CGDisplayMode { + /// Returns all display modes for the specified display id. + pub fn all_display_modes( + display_id: CGDirectDisplayID, + options: CFDictionaryRef, + ) -> Option<Vec<CGDisplayMode>> { + let array_opt: Option<CFArray> = unsafe { + let array_ref = CGDisplayCopyAllDisplayModes(display_id, options); + if !array_ref.is_null() { + Some(CFArray::wrap_under_create_rule(array_ref)) + } else { + None + } + }; + match array_opt { + Some(modes) => { + let vec: Vec<CGDisplayMode> = modes + .into_iter() + .map(|value0| { + let x = *value0.deref() as *mut ::sys::CGDisplayMode; + unsafe { CGDisplayMode::from_ptr(x) } + }).collect(); + Some(vec) + } + None => None, + } + } + + /// Returns the height of the specified display mode. + #[inline] + pub fn height(&self) -> u64 { + unsafe { CGDisplayModeGetHeight(self.as_ptr()) as u64 } + } + + /// Returns the width of the specified display mode. + #[inline] + pub fn width(&self) -> u64 { + unsafe { CGDisplayModeGetWidth(self.as_ptr()) as u64 } + } + + /// Returns the pixel height of the specified display mode. + #[inline] + pub fn pixel_height(&self) -> u64 { + unsafe { CGDisplayModeGetPixelHeight(self.as_ptr()) as u64 } + } + + /// Returns the pixel width of the specified display mode. + #[inline] + pub fn pixel_width(&self) -> u64 { + unsafe { CGDisplayModeGetPixelWidth(self.as_ptr()) as u64 } + } + + #[inline] + pub fn refresh_rate(&self) -> f64 { + unsafe { CGDisplayModeGetRefreshRate(self.as_ptr()) } + } + + /// Returns the I/O Kit flags of the specified display mode. + #[inline] + pub fn io_flags(&self) -> u32 { + unsafe { CGDisplayModeGetIOFlags(self.as_ptr()) as u32 } + } + + /// Returns the pixel encoding of the specified display mode. + #[inline] + pub fn pixel_encoding(&self) -> CFString { + unsafe { CFString::wrap_under_create_rule(CGDisplayModeCopyPixelEncoding(self.as_ptr())) } + } + + /// Returns the number of bits per pixel of the specified display mode. + pub fn bit_depth(&self) -> usize { + let pixel_encoding = self.pixel_encoding().to_string(); + // my numerical representation for kIO16BitFloatPixels and kIO32bitFloatPixels + // are made up and possibly non-sensical + if pixel_encoding.eq_ignore_ascii_case(kIO32BitFloatPixels) { + 96 + } else if pixel_encoding.eq_ignore_ascii_case(kIO64BitDirectPixels) { + 64 + } else if pixel_encoding.eq_ignore_ascii_case(kIO16BitFloatPixels) { + 48 + } else if pixel_encoding.eq_ignore_ascii_case(IO32BitDirectPixels) { + 32 + } else if pixel_encoding.eq_ignore_ascii_case(kIO30BitDirectPixels) { + 30 + } else if pixel_encoding.eq_ignore_ascii_case(IO16BitDirectPixels) { + 16 + } else if pixel_encoding.eq_ignore_ascii_case(IO8BitIndexedPixels) { + 8 + }else{ + 0 + } + } + + pub fn mode_id(&self) -> i32 { + unsafe { CGDisplayModeGetIODisplayModeID(self.as_ptr()) } + } +} + +#[link(name = "CoreGraphics", kind = "framework")] +extern "C" { + pub static CGRectNull: CGRect; + pub static CGRectInfinite: CGRect; + + pub static kCGDisplayShowDuplicateLowResolutionModes: CFStringRef; + + pub fn CGDisplayModeRelease(mode: ::sys::CGDisplayModeRef); + + pub fn CGMainDisplayID() -> CGDirectDisplayID; + pub fn CGDisplayIsActive(display: CGDirectDisplayID) -> boolean_t; + pub fn CGDisplayIsAlwaysInMirrorSet(display: CGDirectDisplayID) -> boolean_t; + pub fn CGDisplayIsAsleep(display: CGDirectDisplayID) -> boolean_t; + pub fn CGDisplayIsBuiltin(display: CGDirectDisplayID) -> boolean_t; + pub fn CGDisplayIsInHWMirrorSet(display: CGDirectDisplayID) -> boolean_t; + pub fn CGDisplayIsInMirrorSet(display: CGDirectDisplayID) -> boolean_t; + pub fn CGDisplayIsMain(display: CGDirectDisplayID) -> boolean_t; + pub fn CGDisplayIsOnline(display: CGDirectDisplayID) -> boolean_t; + pub fn CGDisplayIsStereo(display: CGDirectDisplayID) -> boolean_t; + pub fn CGDisplayMirrorsDisplay(display: CGDirectDisplayID) -> CGDirectDisplayID; + pub fn CGDisplayPrimaryDisplay(display: CGDirectDisplayID) -> CGDirectDisplayID; + pub fn CGDisplayRotation(display: CGDirectDisplayID) -> libc::c_double; + pub fn CGDisplayScreenSize(display: CGDirectDisplayID) -> CGSize; + pub fn CGDisplaySerialNumber(display: CGDirectDisplayID) -> u32; + pub fn CGDisplayUnitNumber(display: CGDirectDisplayID) -> u32; + pub fn CGDisplayUsesOpenGLAcceleration(display: CGDirectDisplayID) -> boolean_t; + pub fn CGDisplayVendorNumber(display: CGDirectDisplayID) -> u32; + pub fn CGGetActiveDisplayList( + max_displays: u32, + active_displays: *mut CGDirectDisplayID, + display_count: *mut u32, + ) -> CGError; + pub fn CGGetDisplaysWithRect( + rect: CGRect, + max_displays: u32, + displays: *mut CGDirectDisplayID, + matching_display_count: *mut u32, + ) -> CGError; + pub fn CGDisplayModelNumber(display: CGDirectDisplayID) -> u32; + pub fn CGDisplayPixelsHigh(display: CGDirectDisplayID) -> libc::size_t; + pub fn CGDisplayPixelsWide(display: CGDirectDisplayID) -> libc::size_t; + pub fn CGDisplayBounds(display: CGDirectDisplayID) -> CGRect; + pub fn CGDisplayCreateImage(display: CGDirectDisplayID) -> ::sys::CGImageRef; + + pub fn CGBeginDisplayConfiguration(config: *mut CGDisplayConfigRef) -> CGError; + pub fn CGCancelDisplayConfiguration(config: CGDisplayConfigRef) -> CGError; + pub fn CGCompleteDisplayConfiguration( + config: CGDisplayConfigRef, + option: CGConfigureOption, + ) -> CGError; + pub fn CGConfigureDisplayWithDisplayMode( + config: CGDisplayConfigRef, + display: CGDirectDisplayID, + mode: ::sys::CGDisplayModeRef, + options: CFDictionaryRef, + ) -> CGError; + pub fn CGConfigureDisplayMirrorOfDisplay( + config: CGDisplayConfigRef, + display: CGDirectDisplayID, + master: CGDirectDisplayID, + ) -> CGError; + pub fn CGConfigureDisplayOrigin( + config: CGDisplayConfigRef, + display: CGDirectDisplayID, + x: i32, + y: i32, + ) -> CGError; + + pub fn CGDisplayCopyDisplayMode(display: CGDirectDisplayID) -> ::sys::CGDisplayModeRef; + pub fn CGDisplayModeGetHeight(mode: ::sys::CGDisplayModeRef) -> libc::size_t; + pub fn CGDisplayModeGetWidth(mode: ::sys::CGDisplayModeRef) -> libc::size_t; + pub fn CGDisplayModeGetPixelHeight(mode: ::sys::CGDisplayModeRef) -> libc::size_t; + pub fn CGDisplayModeGetPixelWidth(mode: ::sys::CGDisplayModeRef) -> libc::size_t; + pub fn CGDisplayModeGetRefreshRate(mode: ::sys::CGDisplayModeRef) -> libc::c_double; + pub fn CGDisplayModeGetIOFlags(mode: ::sys::CGDisplayModeRef) -> u32; + pub fn CGDisplayModeCopyPixelEncoding(mode: ::sys::CGDisplayModeRef) -> CFStringRef; + pub fn CGDisplayModeGetIODisplayModeID(mode: ::sys::CGDisplayModeRef) -> i32; + + pub fn CGDisplayCopyAllDisplayModes( + display: CGDirectDisplayID, + options: CFDictionaryRef, + ) -> CFArrayRef; + + // mouse stuff + pub fn CGDisplayHideCursor(display: CGDirectDisplayID) -> CGError; + pub fn CGDisplayShowCursor(display: CGDirectDisplayID) -> CGError; + pub fn CGDisplayMoveCursorToPoint(display: CGDirectDisplayID, point: CGPoint) -> CGError; + pub fn CGWarpMouseCursorPosition(point: CGPoint) -> CGError; + pub fn CGAssociateMouseAndMouseCursorPosition(connected: boolean_t) -> CGError; + + // Window Services Reference + pub fn CGWindowListCopyWindowInfo( + option: CGWindowListOption, + relativeToWindow: CGWindowID, + ) -> CFArrayRef; + pub fn CGWindowListCreateImage( + screenBounds: CGRect, + listOptions: CGWindowListOption, + windowId: CGWindowID, + imageOptions: CGWindowImageOption, + ) -> ::sys::CGImageRef; + pub fn CGWindowListCreateImageFromArray( + screenBounds: CGRect, + windowArray: CFArrayRef, + imageOptions: CGWindowImageOption, + ) -> ::sys::CGImageRef; +} diff --git a/third_party/rust/core-graphics/src/event.rs b/third_party/rust/core-graphics/src/event.rs new file mode 100644 index 0000000000..8cf9c6262e --- /dev/null +++ b/third_party/rust/core-graphics/src/event.rs @@ -0,0 +1,814 @@ +#![allow(non_upper_case_globals)] +use core_foundation::{ + base::{CFRelease, CFRetain, CFTypeID, TCFType}, + mach_port::{CFMachPort, CFMachPortRef}, +}; +use event_source::CGEventSource; +use foreign_types::ForeignType; +use geometry::CGPoint; +use libc::c_void; +use std::mem::ManuallyDrop; + +pub type CGEventField = u32; +pub type CGKeyCode = u16; +pub type CGScrollEventUnit = u32; + +bitflags! { + /// Flags for events + /// + /// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h) + #[repr(C)] + pub struct CGEventFlags: u64 { + const CGEventFlagNull = 0; + + // Device-independent modifier key bits. + const CGEventFlagAlphaShift = 0x00010000; + const CGEventFlagShift = 0x00020000; + const CGEventFlagControl = 0x00040000; + const CGEventFlagAlternate = 0x00080000; + const CGEventFlagCommand = 0x00100000; + + // Special key identifiers. + const CGEventFlagHelp = 0x00400000; + const CGEventFlagSecondaryFn = 0x00800000; + + // Identifies key events from numeric keypad area on extended keyboards. + const CGEventFlagNumericPad = 0x00200000; + + // Indicates if mouse/pen movement events are not being coalesced + const CGEventFlagNonCoalesced = 0x00000100; + } +} + +/// Key codes for keys that are independent of keyboard layout. +/// +/// [Ref](https://github.com/phracker/MacOSX-SDKs/blob/master/MacOSX10.13.sdk/System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/Events.h) +#[repr(C)] +pub struct KeyCode; +impl KeyCode { + pub const RETURN: CGKeyCode = 0x24; + pub const TAB: CGKeyCode = 0x30; + pub const SPACE: CGKeyCode = 0x31; + pub const DELETE: CGKeyCode = 0x33; + pub const ESCAPE: CGKeyCode = 0x35; + pub const COMMAND: CGKeyCode = 0x37; + pub const SHIFT: CGKeyCode = 0x38; + pub const CAPS_LOCK: CGKeyCode = 0x39; + pub const OPTION: CGKeyCode = 0x3A; + pub const CONTROL: CGKeyCode = 0x3B; + pub const RIGHT_COMMAND: CGKeyCode = 0x36; + pub const RIGHT_SHIFT: CGKeyCode = 0x3C; + pub const RIGHT_OPTION: CGKeyCode = 0x3D; + pub const RIGHT_CONTROL: CGKeyCode = 0x3E; + pub const FUNCTION: CGKeyCode = 0x3F; + pub const VOLUME_UP: CGKeyCode = 0x48; + pub const VOLUME_DOWN: CGKeyCode = 0x49; + pub const MUTE: CGKeyCode = 0x4A; + pub const F1: CGKeyCode = 0x7A; + pub const F2: CGKeyCode = 0x78; + pub const F3: CGKeyCode = 0x63; + pub const F4: CGKeyCode = 0x76; + pub const F5: CGKeyCode = 0x60; + pub const F6: CGKeyCode = 0x61; + pub const F7: CGKeyCode = 0x62; + pub const F8: CGKeyCode = 0x64; + pub const F9: CGKeyCode = 0x65; + pub const F10: CGKeyCode = 0x6D; + pub const F11: CGKeyCode = 0x67; + pub const F12: CGKeyCode = 0x6F; + pub const F13: CGKeyCode = 0x69; + pub const F14: CGKeyCode = 0x6B; + pub const F15: CGKeyCode = 0x71; + pub const F16: CGKeyCode = 0x6A; + pub const F17: CGKeyCode = 0x40; + pub const F18: CGKeyCode = 0x4F; + pub const F19: CGKeyCode = 0x50; + pub const F20: CGKeyCode = 0x5A; + pub const HELP: CGKeyCode = 0x72; + pub const HOME: CGKeyCode = 0x73; + pub const PAGE_UP: CGKeyCode = 0x74; + pub const FORWARD_DELETE: CGKeyCode = 0x75; + pub const END: CGKeyCode = 0x77; + pub const PAGE_DOWN: CGKeyCode = 0x79; + pub const LEFT_ARROW: CGKeyCode = 0x7B; + pub const RIGHT_ARROW: CGKeyCode = 0x7C; + pub const DOWN_ARROW: CGKeyCode = 0x7D; + pub const UP_ARROW: CGKeyCode = 0x7E; +} + +#[repr(C)] +pub struct ScrollEventUnit {} +impl ScrollEventUnit { + pub const PIXEL: CGScrollEventUnit = 0; + pub const LINE: CGScrollEventUnit = 1; +} + +/// Constants that specify the different types of input events. +/// +/// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h) +#[repr(u32)] +#[derive(Clone, Copy, Debug)] +pub enum CGEventType { + Null = 0, + + // Mouse events. + LeftMouseDown = 1, + LeftMouseUp = 2, + RightMouseDown = 3, + RightMouseUp = 4, + MouseMoved = 5, + LeftMouseDragged = 6, + RightMouseDragged = 7, + + // Keyboard events. + KeyDown = 10, + KeyUp = 11, + FlagsChanged = 12, + + // Specialized control devices. + ScrollWheel = 22, + TabletPointer = 23, + TabletProximity = 24, + OtherMouseDown = 25, + OtherMouseUp = 26, + OtherMouseDragged = 27, + + // Out of band event types. These are delivered to the event tap callback + // to notify it of unusual conditions that disable the event tap. + TapDisabledByTimeout = 0xFFFFFFFE, + TapDisabledByUserInput = 0xFFFFFFFF, +} + +/// Constants used as keys to access specialized fields in low-level events. +/// +/// [Ref](https://developer.apple.com/documentation/coregraphics/cgeventfield) +pub struct EventField; +impl EventField { + /// Key to access an integer field that contains the mouse button event + /// number. Matching mouse-down and mouse-up events will have the same + /// event number. + pub const MOUSE_EVENT_NUMBER: CGEventField = 0; + + /// Key to access an integer field that contains the mouse button click + /// state. A click state of 1 represents a single click. A click state of + /// 2 represents a double-click. A click state of 3 represents a + /// triple-click. + pub const MOUSE_EVENT_CLICK_STATE: CGEventField = 1; + + /// Key to access a double field that contains the mouse button pressure. + /// The pressure value may range from 0 to 1, with 0 representing the + /// mouse being up. This value is commonly set by tablet pens mimicking a + /// mouse. + pub const MOUSE_EVENT_PRESSURE: CGEventField = 2; + + /// Key to access an integer field that contains the mouse button number. + pub const MOUSE_EVENT_BUTTON_NUMBER: CGEventField = 3; + + /// Key to access an integer field that contains the horizontal mouse + /// delta since the last mouse movement event. + pub const MOUSE_EVENT_DELTA_X: CGEventField = 4; + + /// Key to access an integer field that contains the vertical mouse delta + /// since the last mouse movement event. + pub const MOUSE_EVENT_DELTA_Y: CGEventField = 5; + + /// Key to access an integer field. The value is non-zero if the event + /// should be ignored by the Inkwell subsystem. + pub const MOUSE_EVENT_INSTANT_MOUSER: CGEventField = 6; + + /// Key to access an integer field that encodes the mouse event subtype as + /// a `kCFNumberIntType'. + pub const MOUSE_EVENT_SUB_TYPE: CGEventField = 7; + + /// Key to access an integer field, non-zero when this is an autorepeat of + /// a key-down, and zero otherwise. + pub const KEYBOARD_EVENT_AUTOREPEAT: CGEventField = 8; + + /// Key to access an integer field that contains the virtual keycode of the + /// key-down or key-up event. + pub const KEYBOARD_EVENT_KEYCODE: CGEventField = 9; + + /// Key to access an integer field that contains the keyboard type + /// identifier. + pub const KEYBOARD_EVENT_KEYBOARD_TYPE: CGEventField = 10; + + /// Key to access an integer field that contains scrolling data. This field + /// typically contains the change in vertical position since the last + /// scrolling event from a Mighty Mouse scroller or a single-wheel mouse + /// scroller. + pub const SCROLL_WHEEL_EVENT_DELTA_AXIS_1: CGEventField = 11; + + /// Key to access an integer field that contains scrolling data. This field + /// typically contains the change in horizontal position since the last + /// scrolling event from a Mighty Mouse scroller. + pub const SCROLL_WHEEL_EVENT_DELTA_AXIS_2: CGEventField = 12; + + /// Key to access a field that contains scrolling data. The scrolling data + /// represents a line-based or pixel-based change in vertical position + /// since the last scrolling event from a Mighty Mouse scroller or a + /// single-wheel mouse scroller. The scrolling data uses a fixed-point + /// 16.16 signed integer format. If this key is passed to + /// `CGEventGetDoubleValueField', the fixed-point value is converted to a + /// double value. + pub const SCROLL_WHEEL_EVENT_FIXED_POINT_DELTA_AXIS_1: CGEventField = 93; + + /// Key to access a field that contains scrolling data. The scrolling data + /// represents a line-based or pixel-based change in horizontal position + /// since the last scrolling event from a Mighty Mouse scroller. The + /// scrolling data uses a fixed-point 16.16 signed integer format. If this + /// key is passed to `CGEventGetDoubleValueField', the fixed-point value is + /// converted to a double value. + pub const SCROLL_WHEEL_EVENT_FIXED_POINT_DELTA_AXIS_2: CGEventField = 94; + + /// Key to access an integer field that contains pixel-based scrolling + /// data. The scrolling data represents the change in vertical position + /// since the last scrolling event from a Mighty Mouse scroller or a + /// single-wheel mouse scroller. + pub const SCROLL_WHEEL_EVENT_POINT_DELTA_AXIS_1: CGEventField = 96; + + /// Key to access an integer field that contains pixel-based scrolling + /// data. The scrolling data represents the change in horizontal position + /// since the last scrolling event from a Mighty Mouse scroller. + pub const SCROLL_WHEEL_EVENT_POINT_DELTA_AXIS_2: CGEventField = 97; + + /// Key to access an integer field that indicates whether the event should + /// be ignored by the Inkwell subsystem. If the value is non-zero, the + /// event should be ignored. + pub const SCROLL_WHEEL_EVENT_INSTANT_MOUSER: CGEventField = 14; + + /// Key to access an integer field that contains the absolute X coordinate + /// in tablet space at full tablet resolution. + pub const TABLET_EVENT_POINT_X: CGEventField = 15; + + /// Key to access an integer field that contains the absolute Y coordinate + /// in tablet space at full tablet resolution. + pub const TABLET_EVENT_POINT_Y: CGEventField = 16; + + /// Key to access an integer field that contains the absolute Z coordinate + /// in tablet space at full tablet resolution. + pub const TABLET_EVENT_POINT_Z: CGEventField = 17; + + /// Key to access an integer field that contains the tablet button state. + /// Bit 0 is the first button, and a set bit represents a closed or pressed + /// button. Up to 16 buttons are supported. + pub const TABLET_EVENT_POINT_BUTTONS: CGEventField = 18; + + /// Key to access a double field that contains the tablet pen pressure. A + /// value of 0.0 represents no pressure, and 1.0 represents maximum + /// pressure. + pub const TABLET_EVENT_POINT_PRESSURE: CGEventField = 19; + + /// Key to access a double field that contains the horizontal tablet pen + /// tilt. A value of 0 represents no tilt, and 1 represents maximum tilt. + pub const TABLET_EVENT_TILT_X: CGEventField = 20; + + /// Key to access a double field that contains the vertical tablet pen + /// tilt. A value of 0 represents no tilt, and 1 represents maximum tilt. + pub const TABLET_EVENT_TILT_Y: CGEventField = 21; + + /// Key to access a double field that contains the tablet pen rotation. + pub const TABLET_EVENT_ROTATION: CGEventField = 22; + + /// Key to access a double field that contains the tangential pressure on + /// the device. A value of 0.0 represents no pressure, and 1.0 represents + /// maximum pressure. + pub const TABLET_EVENT_TANGENTIAL_PRESSURE: CGEventField = 23; + + /// Key to access an integer field that contains the system-assigned unique + /// device ID. + pub const TABLET_EVENT_DEVICE_ID: CGEventField = 24; + + /// Key to access an integer field that contains a vendor-specified value. + pub const TABLET_EVENT_VENDOR_1: CGEventField = 25; + + /// Key to access an integer field that contains a vendor-specified value. + pub const TABLET_EVENT_VENDOR_2: CGEventField = 26; + + /// Key to access an integer field that contains a vendor-specified value. + pub const TABLET_EVENT_VENDOR_3: CGEventField = 27; + + /// Key to access an integer field that contains the vendor-defined ID, + /// typically the USB vendor ID. + pub const TABLET_PROXIMITY_EVENT_VENDOR_ID: CGEventField = 28; + + /// Key to access an integer field that contains the vendor-defined tablet + /// ID, typically the USB product ID. + pub const TABLET_PROXIMITY_EVENT_TABLET_ID: CGEventField = 29; + + /// Key to access an integer field that contains the vendor-defined ID of + /// the pointing device. + pub const TABLET_PROXIMITY_EVENT_POINTER_ID: CGEventField = 30; + + /// Key to access an integer field that contains the system-assigned + /// device ID. + pub const TABLET_PROXIMITY_EVENT_DEVICE_ID: CGEventField = 31; + + /// Key to access an integer field that contains the system-assigned + /// unique tablet ID. + pub const TABLET_PROXIMITY_EVENT_SYSTEM_TABLET_ID: CGEventField = 32; + + /// Key to access an integer field that contains the vendor-assigned + /// pointer type. + pub const TABLET_PROXIMITY_EVENT_VENDOR_POINTER_TYPE: CGEventField = 33; + + /// Key to access an integer field that contains the vendor-defined + /// pointer serial number. + pub const TABLET_PROXIMITY_EVENT_VENDOR_POINTER_SERIAL_NUMBER: CGEventField = 34; + + /// Key to access an integer field that contains the vendor-defined unique + /// ID. + pub const TABLET_PROXIMITY_EVENT_VENDOR_UNIQUE_ID: CGEventField = 35; + + /// Key to access an integer field that contains the device capabilities + /// mask. + pub const TABLET_PROXIMITY_EVENT_CAPABILITY_MASK: CGEventField = 36; + + /// Key to access an integer field that contains the pointer type. + pub const TABLET_PROXIMITY_EVENT_POINTER_TYPE: CGEventField = 37; + + /// Key to access an integer field that indicates whether the pen is in + /// proximity to the tablet. The value is non-zero if the pen is in + /// proximity to the tablet and zero when leaving the tablet. + pub const TABLET_PROXIMITY_EVENT_ENTER_PROXIMITY: CGEventField = 38; + + /// Key to access a field that contains the event target process serial + /// number. The value is a 64-bit value. + pub const EVENT_TARGET_PROCESS_SERIAL_NUMBER: CGEventField = 39; + + /// Key to access a field that contains the event target Unix process ID. + pub const EVENT_TARGET_UNIX_PROCESS_ID: CGEventField = 40; + + /// Key to access a field that contains the event source Unix process ID. + pub const EVENT_SOURCE_UNIX_PROCESS_ID: CGEventField = 41; + + /// Key to access a field that contains the event source user-supplied + /// data, up to 64 bits. + pub const EVENT_SOURCE_USER_DATA: CGEventField = 42; + + /// Key to access a field that contains the event source Unix effective UID. + pub const EVENT_SOURCE_USER_ID: CGEventField = 43; + + /// Key to access a field that contains the event source Unix effective + /// GID. + pub const EVENT_SOURCE_GROUP_ID: CGEventField = 44; + + /// Key to access a field that contains the event source state ID used to + /// create this event. + pub const EVENT_SOURCE_STATE_ID: CGEventField = 45; + + /// Key to access an integer field that indicates whether a scrolling event + /// contains continuous, pixel-based scrolling data. The value is non-zero + /// when the scrolling data is pixel-based and zero when the scrolling data + /// is line-based. + pub const SCROLL_WHEEL_EVENT_IS_CONTINUOUS: CGEventField = 88; + + /// Added in 10.5; made public in 10.7. + pub const MOUSE_EVENT_WINDOW_UNDER_MOUSE_POINTER: CGEventField = 91; + pub const MOUSE_EVENT_WINDOW_UNDER_MOUSE_POINTER_THAT_CAN_HANDLE_THIS_EVENT: CGEventField = 92; +} + +// Constants that specify buttons on a one, two, or three-button mouse. +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub enum CGMouseButton { + Left, + Right, + Center, +} + +/// Possible tapping points for events. +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub enum CGEventTapLocation { + HID, + Session, + AnnotatedSession, +} + +// The next three enums are taken from: +// [Ref](https://github.com/phracker/MacOSX-SDKs/blob/ef9fe35d5691b6dd383c8c46d867a499817a01b6/MacOSX10.15.sdk/System/Library/Frameworks/CoreGraphics.framework/Versions/A/Headers/CGEventTypes.h) +/* Constants that specify where a new event tap is inserted into the list of +active event taps. */ +#[repr(u32)] +#[derive(Clone, Copy, Debug)] +pub enum CGEventTapPlacement { + HeadInsertEventTap = 0, + TailAppendEventTap, +} + +/* Constants that specify whether a new event tap is an active filter or a +passive listener. */ +#[repr(u32)] +#[derive(Clone, Copy, Debug)] +pub enum CGEventTapOptions { + Default = 0x00000000, + ListenOnly = 0x00000001, +} + +pub type CGEventMask = u64; +/* Generate an event mask for a single type of event. */ +macro_rules! CGEventMaskBit { + ($eventType:expr) => { + 1 << $eventType as CGEventMask + }; +} + +pub type CGEventTapProxy = *const c_void; +pub type CGEventTapCallBackFn<'tap_life> = + Box<dyn Fn(CGEventTapProxy, CGEventType, &CGEvent) -> Option<CGEvent> + 'tap_life>; +type CGEventTapCallBackInternal = unsafe extern "C" fn( + proxy: CGEventTapProxy, + etype: CGEventType, + event: ::sys::CGEventRef, + user_info: *const c_void, +) -> ::sys::CGEventRef; + +#[no_mangle] +unsafe extern "C" fn cg_event_tap_callback_internal( + _proxy: CGEventTapProxy, + _etype: CGEventType, + _event: ::sys::CGEventRef, + _user_info: *const c_void, +) -> ::sys::CGEventRef { + let callback = _user_info as *mut CGEventTapCallBackFn; + let event = CGEvent::from_ptr(_event); + let new_event = (*callback)(_proxy, _etype, &event); + let event = match new_event { + Some(new_event) => new_event, + None => event, + }; + ManuallyDrop::new(event).as_ptr() +} + + +/// ```no_run +///extern crate core_foundation; +///use core_foundation::runloop::{kCFRunLoopCommonModes, CFRunLoop}; +///use core_graphics::event::{CGEventTap, CGEventTapLocation, CGEventTapPlacement, CGEventTapOptions, CGEventType}; +///let current = CFRunLoop::get_current(); +///match CGEventTap::new( +/// CGEventTapLocation::HID, +/// CGEventTapPlacement::HeadInsertEventTap, +/// CGEventTapOptions::Default, +/// vec![CGEventType::MouseMoved], +/// |_a, _b, d| { +/// println!("{:?}", d.location()); +/// None +/// }, +/// ) { +/// Ok(tap) => unsafe { +/// let loop_source = tap +/// .mach_port +/// .create_runloop_source(0) +/// .expect("Somethings is bad "); +/// current.add_source(&loop_source, kCFRunLoopCommonModes); +/// tap.enable(); +/// CFRunLoop::run_current(); +/// }, +/// Err(_) => (assert!(false)), +/// } +/// ``` +pub struct CGEventTap<'tap_life> { + pub mach_port: CFMachPort, + pub callback_ref: + Box<dyn Fn(CGEventTapProxy, CGEventType, &CGEvent) -> Option<CGEvent> + 'tap_life>, +} + +impl<'tap_life> CGEventTap<'tap_life> { + pub fn new<F: Fn(CGEventTapProxy, CGEventType, &CGEvent) -> Option<CGEvent> + 'tap_life>( + tap: CGEventTapLocation, + place: CGEventTapPlacement, + options: CGEventTapOptions, + events_of_interest: std::vec::Vec<CGEventType>, + callback: F, + ) -> Result<CGEventTap<'tap_life>, ()> { + let event_mask: CGEventMask = events_of_interest + .iter() + .fold(CGEventType::Null as CGEventMask, |mask, &etype| { + mask | CGEventMaskBit!(etype) + }); + let cb = Box::new(Box::new(callback) as CGEventTapCallBackFn); + let cbr = Box::into_raw(cb); + unsafe { + let event_tap_ref = CGEventTapCreate( + tap, + place, + options, + event_mask, + cg_event_tap_callback_internal, + cbr as *const c_void, + ); + + if !event_tap_ref.is_null() { + Ok(Self { + mach_port: (CFMachPort::wrap_under_create_rule(event_tap_ref)), + callback_ref: Box::from_raw(cbr), + }) + } else { + Box::from_raw(cbr); + Err(()) + } + } + } + + pub fn enable(&self) { + unsafe { CGEventTapEnable(self.mach_port.as_concrete_TypeRef(), true) } + } +} + +foreign_type! { + #[doc(hidden)] + type CType = ::sys::CGEvent; + fn drop = |p| CFRelease(p as *mut _); + fn clone = |p| CFRetain(p as *const _) as *mut _; + pub struct CGEvent; + pub struct CGEventRef; +} + +impl CGEvent { + pub fn type_id() -> CFTypeID { + unsafe { + CGEventGetTypeID() + } + } + + pub fn new(source: CGEventSource) -> Result<CGEvent, ()> { + unsafe { + let event_ref = CGEventCreate(source.as_ptr()); + if !event_ref.is_null() { + Ok(Self::from_ptr(event_ref)) + } else { + Err(()) + } + } + } + + pub fn new_keyboard_event( + source: CGEventSource, + keycode: CGKeyCode, + keydown: bool + ) -> Result<CGEvent, ()> { + unsafe { + let event_ref = CGEventCreateKeyboardEvent(source.as_ptr(), keycode, keydown); + if !event_ref.is_null() { + Ok(Self::from_ptr(event_ref)) + } else { + Err(()) + } + } + } + + pub fn new_mouse_event( + source: CGEventSource, + mouse_type: CGEventType, + mouse_cursor_position: CGPoint, + mouse_button: CGMouseButton + ) -> Result<CGEvent, ()> { + unsafe { + let event_ref = CGEventCreateMouseEvent(source.as_ptr(), mouse_type, + mouse_cursor_position, mouse_button); + if !event_ref.is_null() { + Ok(Self::from_ptr(event_ref)) + } else { + Err(()) + } + } + } + + #[cfg(feature = "highsierra")] + pub fn new_scroll_event( + source: CGEventSource, + units: CGScrollEventUnit, + wheel_count: u32, + wheel1: i32, + wheel2: i32, + wheel3: i32, + ) -> Result<CGEvent, ()> { + unsafe { + let event_ref = CGEventCreateScrollWheelEvent2( + source.as_ptr(), + units, + wheel_count, + wheel1, + wheel2, + wheel3, + ); + if !event_ref.is_null() { + Ok(Self::from_ptr(event_ref)) + } else { + Err(()) + } + } + } + + pub fn post(&self, tap_location: CGEventTapLocation) { + unsafe { + CGEventPost(tap_location, self.as_ptr()); + } + } + + pub fn location(&self) -> CGPoint { + unsafe { + CGEventGetLocation(self.as_ptr()) + } + } + + #[cfg(feature = "elcapitan")] + pub fn post_to_pid(&self, pid: libc::pid_t) { + unsafe { + CGEventPostToPid(pid, self.as_ptr()); + } + } + + pub fn set_flags(&self, flags: CGEventFlags) { + unsafe { + CGEventSetFlags(self.as_ptr(), flags); + } + } + + pub fn get_flags(&self) -> CGEventFlags { + unsafe { + CGEventGetFlags(self.as_ptr()) + } + } + + pub fn set_type(&self, event_type: CGEventType) { + unsafe { + CGEventSetType(self.as_ptr(), event_type); + } + } + + pub fn get_type(&self) -> CGEventType { + unsafe { + CGEventGetType(self.as_ptr()) + } + } + + pub fn set_string_from_utf16_unchecked(&self, buf: &[u16]) { + let buflen = buf.len() as libc::c_ulong; + unsafe { + CGEventKeyboardSetUnicodeString(self.as_ptr(), buflen, buf.as_ptr()); + } + } + + pub fn set_string(&self, string: &str) { + let buf: Vec<u16> = string.encode_utf16().collect(); + self.set_string_from_utf16_unchecked(&buf); + } + + pub fn get_integer_value_field(&self, field: CGEventField) -> i64 { + unsafe { CGEventGetIntegerValueField(self.as_ptr(), field) } + } + + pub fn set_integer_value_field(&self, field: CGEventField, value: i64) { + unsafe { CGEventSetIntegerValueField(self.as_ptr(), field, value) } + } + + pub fn get_double_value_field(&self, field: CGEventField) -> f64 { + unsafe { CGEventGetDoubleValueField(self.as_ptr(), field) } + } + + pub fn set_double_value_field(&self, field: CGEventField, value: f64) { + unsafe { CGEventSetDoubleValueField(self.as_ptr(), field, value) } + } +} + +#[link(name = "CoreGraphics", kind = "framework")] +extern { + /// Return the type identifier for the opaque type `CGEventRef'. + fn CGEventGetTypeID() -> CFTypeID; + + /// Return a new event using the event source `source'. If `source' is NULL, + /// the default source is used. + fn CGEventCreate(source: ::sys::CGEventSourceRef) -> ::sys::CGEventRef; + + /// Return a new keyboard event. + /// + /// The event source may be taken from another event, or may be NULL. Based + /// on the virtual key code values entered, the appropriate key down, key up, + /// or flags changed events are generated. + /// + /// All keystrokes needed to generate a character must be entered, including + /// SHIFT, CONTROL, OPTION, and COMMAND keys. For example, to produce a 'Z', + /// the SHIFT key must be down, the 'z' key must go down, and then the SHIFT + /// and 'z' key must be released: + fn CGEventCreateKeyboardEvent(source: ::sys::CGEventSourceRef, keycode: CGKeyCode, + keydown: bool) -> ::sys::CGEventRef; + + /// Return a new mouse event. + /// + /// The event source may be taken from another event, or may be NULL. + /// `mouseType' should be one of the mouse event types. `mouseCursorPosition' + /// should be the position of the mouse cursor in global coordinates. + /// `mouseButton' should be the button that's changing state; `mouseButton' + /// is ignored unless `mouseType' is one of `kCGEventOtherMouseDown', + /// `kCGEventOtherMouseDragged', or `kCGEventOtherMouseUp'. + /// + /// The current implementation of the event system supports a maximum of + /// thirty-two buttons. Mouse button 0 is the primary button on the mouse. + /// Mouse button 1 is the secondary mouse button (right). Mouse button 2 is + /// the center button, and the remaining buttons are in USB device order. + fn CGEventCreateMouseEvent(source: ::sys::CGEventSourceRef, mouseType: CGEventType, + mouseCursorPosition: CGPoint, mouseButton: CGMouseButton) -> ::sys::CGEventRef; + + /// A non-variadic variant version of CGEventCreateScrollWheelEvent. + /// + /// Returns a new Quartz scrolling event. + /// + /// This function allows you to create a scrolling event and customize the + /// event before posting it to the event system. + #[cfg(feature = "highsierra")] + fn CGEventCreateScrollWheelEvent2( + source: ::sys::CGEventSourceRef, + units: CGScrollEventUnit, + wheelCount: u32, + wheel1: i32, + wheel2: i32, + wheel3: i32, + ) -> ::sys::CGEventRef; + + /// Post an event into the event stream at a specified location. + /// + /// This function posts the specified event immediately before any event taps + /// instantiated for that location, and the event passes through any such + /// taps. + fn CGEventPost(tapLocation: CGEventTapLocation, event: ::sys::CGEventRef); + + #[cfg(feature = "elcapitan")] + /// Post an event to a specified process ID + fn CGEventPostToPid(pid: libc::pid_t, event: ::sys::CGEventRef); + + /// Set the event flags of an event. + fn CGEventSetFlags(event: ::sys::CGEventRef, flags: CGEventFlags); + + /// Return the event flags of an event. + fn CGEventGetFlags(event: ::sys::CGEventRef) -> CGEventFlags; + + /// Return the location of an event in global display coordinates. + /// CGPointZero is returned if event is not a valid ::sys::CGEventRef. + fn CGEventGetLocation(event: ::sys::CGEventRef) -> CGPoint; + + /// Set the event type of an event. + fn CGEventSetType(event: ::sys::CGEventRef, eventType: CGEventType); + + /// Return the event type of an event (left mouse down, for example). + fn CGEventGetType(event: ::sys::CGEventRef) -> CGEventType; + + /// Set the Unicode string associated with a keyboard event. + /// + /// By default, the system translates the virtual key code in a keyboard + /// event into a Unicode string based on the keyboard ID in the event + /// source. This function allows you to manually override this string. + /// Note that application frameworks may ignore the Unicode string in a + /// keyboard event and do their own translation based on the virtual + /// keycode and perceived event state. + fn CGEventKeyboardSetUnicodeString(event: ::sys::CGEventRef, + length: libc::c_ulong, + string: *const u16); + + /// Return the integer value of a field in an event. + fn CGEventGetIntegerValueField(event: ::sys::CGEventRef, field: CGEventField) -> i64; + + /// Set the integer value of a field in an event. + /// + /// Before calling this function, the event type must be set using a typed + /// event creation function such as `CGEventCreateMouseEvent', or by + /// calling `CGEventSetType'. + /// + /// If you are creating a mouse event generated by a tablet, call this + /// function and specify the field `kCGMouseEventSubtype' with a value of + /// `kCGEventMouseSubtypeTabletPoint' or + /// `kCGEventMouseSubtypeTabletProximity' before setting other parameters. + fn CGEventSetIntegerValueField(event: ::sys::CGEventRef, field: CGEventField, value: i64); + + /// Return the floating-point value of a field in an event. + /// + /// In cases where the field value is represented within the event by a fixed + /// point number or an integer, the result is scaled to the appropriate range + /// as part of creating the floating-point representation. + fn CGEventGetDoubleValueField(event: ::sys::CGEventRef, field: CGEventField) -> f64; + + /// Set the floating-point value of a field in an event. + /// + /// Before calling this function, the event type must be set using a typed + /// event creation function such as `CGEventCreateMouseEvent', or by calling + /// `CGEventSetType'. + /// + /// In cases where the field’s value is represented within the event by a + /// fixed point number or integer, the value parameter is scaled as needed + /// and converted to the appropriate type. + fn CGEventSetDoubleValueField(event: ::sys::CGEventRef, field: CGEventField, value: f64); + + // ::sys::CGEventTapRef is actually an CFMachPortRef + fn CGEventTapCreate( + tap: CGEventTapLocation, + place: CGEventTapPlacement, + options: CGEventTapOptions, + eventsOfInterest: CGEventMask, + callback: CGEventTapCallBackInternal, + userInfo: *const c_void, + ) -> CFMachPortRef; + + fn CGEventTapEnable(tap: CFMachPortRef, enable: bool); + +} diff --git a/third_party/rust/core-graphics/src/event_source.rs b/third_party/rust/core-graphics/src/event_source.rs new file mode 100644 index 0000000000..ce13f5a91c --- /dev/null +++ b/third_party/rust/core-graphics/src/event_source.rs @@ -0,0 +1,48 @@ +use core_foundation::base::{CFRelease, CFRetain, CFTypeID}; +use foreign_types::ForeignType; + +/// Possible source states of an event source. +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub enum CGEventSourceStateID { + Private = -1, + CombinedSessionState = 0, + HIDSystemState = 1, +} + +foreign_type! { + #[doc(hidden)] + type CType = ::sys::CGEventSource; + fn drop = |p| CFRelease(p as *mut _); + fn clone = |p| CFRetain(p as *const _) as *mut _; + pub struct CGEventSource; + pub struct CGEventSourceRef; +} + +impl CGEventSource { + pub fn type_id() -> CFTypeID { + unsafe { + CGEventSourceGetTypeID() + } + } + + pub fn new(state_id: CGEventSourceStateID) -> Result<Self, ()> { + unsafe { + let event_source_ref = CGEventSourceCreate(state_id); + if !event_source_ref.is_null() { + Ok(Self::from_ptr(event_source_ref)) + } else { + Err(()) + } + } + } +} + +#[link(name = "CoreGraphics", kind = "framework")] +extern { + /// Return the type identifier for the opaque type `CGEventSourceRef'. + fn CGEventSourceGetTypeID() -> CFTypeID; + + /// Return a Quartz event source created with a specified source state. + fn CGEventSourceCreate(stateID: CGEventSourceStateID) -> ::sys::CGEventSourceRef; +} diff --git a/third_party/rust/core-graphics/src/font.rs b/third_party/rust/core-graphics/src/font.rs new file mode 100644 index 0000000000..adf7a14932 --- /dev/null +++ b/third_party/rust/core-graphics/src/font.rs @@ -0,0 +1,176 @@ +// Copyright 2013 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core_foundation::base::{CFRelease, CFRetain, CFType, CFTypeID, TCFType}; +use core_foundation::array::{CFArray, CFArrayRef}; +use core_foundation::data::{CFData, CFDataRef}; +use core_foundation::number::CFNumber; +use core_foundation::string::{CFString, CFStringRef}; +use core_foundation::dictionary::{CFDictionary, CFDictionaryRef}; +use data_provider::CGDataProvider; +use geometry::CGRect; + +use foreign_types::ForeignType; + +use libc::{c_int, size_t}; + +pub use core_graphics_types::base::CGGlyph; + +foreign_type! { + #[doc(hidden)] + type CType = ::sys::CGFont; + fn drop = |p| CFRelease(p as *mut _); + fn clone = |p| CFRetain(p as *const _) as *mut _; + pub struct CGFont; + pub struct CGFontRef; +} + +unsafe impl Send for CGFont {} +unsafe impl Sync for CGFont {} + +impl CGFont { + pub fn type_id() -> CFTypeID { + unsafe { + CGFontGetTypeID() + } + } + + pub fn from_data_provider(provider: CGDataProvider) -> Result<CGFont, ()> { + unsafe { + let font_ref = CGFontCreateWithDataProvider(provider.as_ptr()); + if !font_ref.is_null() { + Ok(CGFont::from_ptr(font_ref)) + } else { + Err(()) + } + } + } + + pub fn from_name(name: &CFString) -> Result<CGFont, ()> { + unsafe { + let font_ref = CGFontCreateWithFontName(name.as_concrete_TypeRef()); + if !font_ref.is_null() { + Ok(CGFont::from_ptr(font_ref)) + } else { + Err(()) + } + } + } + + pub fn create_copy_from_variations(&self, vars: &CFDictionary<CFString, CFNumber>) -> Result<CGFont, ()> { + unsafe { + let font_ref = CGFontCreateCopyWithVariations(self.as_ptr(), + vars.as_concrete_TypeRef()); + if !font_ref.is_null() { + Ok(CGFont::from_ptr(font_ref)) + } else { + Err(()) + } + } + } + + pub fn postscript_name(&self) -> CFString { + unsafe { + let string_ref = CGFontCopyPostScriptName(self.as_ptr()); + TCFType::wrap_under_create_rule(string_ref) + } + } + + pub fn get_glyph_b_boxes(&self, glyphs: &[CGGlyph], bboxes: &mut [CGRect]) -> bool { + unsafe { + assert!(bboxes.len() >= glyphs.len()); + CGFontGetGlyphBBoxes(self.as_ptr(), + glyphs.as_ptr(), + glyphs.len(), + bboxes.as_mut_ptr()) + } + } + + pub fn get_glyph_advances(&self, glyphs: &[CGGlyph], advances: &mut [c_int]) -> bool { + unsafe { + assert!(advances.len() >= glyphs.len()); + CGFontGetGlyphAdvances(self.as_ptr(), + glyphs.as_ptr(), + glyphs.len(), + advances.as_mut_ptr()) + } + } + + pub fn get_units_per_em(&self) -> c_int { + unsafe { + CGFontGetUnitsPerEm(self.as_ptr()) + } + } + + pub fn copy_table_tags(&self) -> CFArray<u32> { + unsafe { + TCFType::wrap_under_create_rule(CGFontCopyTableTags(self.as_ptr())) + } + } + + pub fn copy_table_for_tag(&self, tag: u32) -> Option<CFData> { + let data_ref = unsafe { CGFontCopyTableForTag(self.as_ptr(), tag) }; + if !data_ref.is_null() { + Some(unsafe { TCFType::wrap_under_create_rule(data_ref) }) + } else { + None + } + } + + pub fn copy_variations(&self) -> Option<CFDictionary<CFString, CFNumber>> { + let variations = unsafe { CGFontCopyVariations(self.as_ptr()) }; + if !variations.is_null() { + Some(unsafe { TCFType::wrap_under_create_rule(variations) }) + } else { + None + } + } + + pub fn copy_variation_axes(&self) -> Option<CFArray<CFDictionary<CFString, CFType>>> { + let axes = unsafe { CGFontCopyVariationAxes(self.as_ptr()) }; + if !axes.is_null() { + Some(unsafe { TCFType::wrap_under_create_rule(axes) }) + } else { + None + } + } +} + +#[link(name = "CoreGraphics", kind = "framework")] +extern { + // TODO: basically nothing has bindings (even commented-out) besides what we use. + fn CGFontCreateWithDataProvider(provider: ::sys::CGDataProviderRef) -> ::sys::CGFontRef; + fn CGFontCreateWithFontName(name: CFStringRef) -> ::sys::CGFontRef; + fn CGFontCreateCopyWithVariations(font: ::sys::CGFontRef, vars: CFDictionaryRef) -> ::sys::CGFontRef; + fn CGFontGetTypeID() -> CFTypeID; + + fn CGFontCopyPostScriptName(font: ::sys::CGFontRef) -> CFStringRef; + + // These do the same thing as CFRetain/CFRelease, except + // gracefully handle a NULL argument. We don't use them. + //fn CGFontRetain(font: ::sys::CGFontRef); + //fn CGFontRelease(font: ::sys::CGFontRef); + + fn CGFontGetGlyphBBoxes(font: ::sys::CGFontRef, + glyphs: *const CGGlyph, + count: size_t, + bboxes: *mut CGRect) + -> bool; + fn CGFontGetGlyphAdvances(font: ::sys::CGFontRef, + glyphs: *const CGGlyph, + count: size_t, + advances: *mut c_int) + -> bool; + fn CGFontGetUnitsPerEm(font: ::sys::CGFontRef) -> c_int; + + fn CGFontCopyTableTags(font: ::sys::CGFontRef) -> CFArrayRef; + fn CGFontCopyTableForTag(font: ::sys::CGFontRef, tag: u32) -> CFDataRef; + fn CGFontCopyVariations(font: ::sys::CGFontRef) -> CFDictionaryRef; + fn CGFontCopyVariationAxes(font: ::sys::CGFontRef) -> CFArrayRef; +} diff --git a/third_party/rust/core-graphics/src/geometry.rs b/third_party/rust/core-graphics/src/geometry.rs new file mode 100644 index 0000000000..fd4dc977e6 --- /dev/null +++ b/third_party/rust/core-graphics/src/geometry.rs @@ -0,0 +1,10 @@ +// Copyright 2013 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub use core_graphics_types::geometry::*;
\ No newline at end of file diff --git a/third_party/rust/core-graphics/src/gradient.rs b/third_party/rust/core-graphics/src/gradient.rs new file mode 100644 index 0000000000..5c6cde846e --- /dev/null +++ b/third_party/rust/core-graphics/src/gradient.rs @@ -0,0 +1,62 @@ +// Copyright 2013 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(non_upper_case_globals)] + +use base::CGFloat; +use color::CGColor; +use color_space::CGColorSpace; + +use core_foundation::array::{ CFArray, CFArrayRef }; +use core_foundation::base::{CFRelease, CFRetain, TCFType}; +use foreign_types::ForeignType; + +use libc::size_t; + +bitflags! { + #[repr(C)] + pub struct CGGradientDrawingOptions: u32 { + const CGGradientDrawsBeforeStartLocation = (1 << 0); + const CGGradientDrawsAfterEndLocation = (1 << 1); + } +} + +foreign_type! { + #[doc(hidden)] + type CType = ::sys::CGGradient; + fn drop = |p| CFRelease(p as *mut _); + fn clone = |p| CFRetain(p as *const _) as *mut _; + pub struct CGGradient; + pub struct CGGradientRef; +} + +impl CGGradient { + pub fn create_with_color_components(color_space: &CGColorSpace, components: &[CGFloat], locations: &[CGFloat], count: usize) -> CGGradient { + unsafe { + let result = CGGradientCreateWithColorComponents(color_space.as_ptr(), components.as_ptr(), locations.as_ptr(), count); + assert!(!result.is_null()); + Self::from_ptr(result) + } + } + + pub fn create_with_colors(color_space: &CGColorSpace, colors: &CFArray<CGColor>, locations: &[CGFloat]) -> CGGradient { + unsafe { + let result = CGGradientCreateWithColors(color_space.as_ptr(), colors.as_concrete_TypeRef(), locations.as_ptr()); + assert!(!result.is_null()); + Self::from_ptr(result) + } + } +} + +#[link(name = "CoreGraphics", kind = "framework")] +extern { + fn CGGradientCreateWithColorComponents(color_space: ::sys::CGColorSpaceRef, components: *const CGFloat, locations: *const CGFloat, count: size_t) -> ::sys::CGGradientRef; + fn CGGradientCreateWithColors(color_space: ::sys::CGColorSpaceRef, colors: CFArrayRef, locations: *const CGFloat) -> ::sys::CGGradientRef; +} + diff --git a/third_party/rust/core-graphics/src/image.rs b/third_party/rust/core-graphics/src/image.rs new file mode 100644 index 0000000000..f1b95096d9 --- /dev/null +++ b/third_party/rust/core-graphics/src/image.rs @@ -0,0 +1,165 @@ +use std::ptr; + +use base::CGFloat; +use core_foundation::base::{CFRetain, CFTypeID}; +use core_foundation::data::CFData; +use color_space::CGColorSpace; +use data_provider::{CGDataProviderRef, CGDataProvider}; +use geometry::CGRect; +use libc::size_t; +use foreign_types::{ForeignType, ForeignTypeRef}; + +#[repr(C)] +pub enum CGImageAlphaInfo { + CGImageAlphaNone, /* For example, RGB. */ + CGImageAlphaPremultipliedLast, /* For example, premultiplied RGBA */ + CGImageAlphaPremultipliedFirst, /* For example, premultiplied ARGB */ + CGImageAlphaLast, /* For example, non-premultiplied RGBA */ + CGImageAlphaFirst, /* For example, non-premultiplied ARGB */ + CGImageAlphaNoneSkipLast, /* For example, RBGX. */ + CGImageAlphaNoneSkipFirst, /* For example, XRBG. */ + CGImageAlphaOnly /* No color data, alpha data only */ +} + +#[repr(C)] +pub enum CGImageByteOrderInfo { + CGImageByteOrderMask = 0x7000, + CGImageByteOrder16Little = 1 << 12, + CGImageByteOrder32Little = 2 << 12, + CGImageByteOrder16Big = 3 << 12, + CGImageByteOrder32Big = 4 << 12 +} + +foreign_type! { + #[doc(hidden)] + type CType = ::sys::CGImage; + fn drop = CGImageRelease; + fn clone = |p| CFRetain(p as *const _) as *mut _; + pub struct CGImage; + pub struct CGImageRef; +} + +impl CGImage { + pub fn new(width: size_t, + height: size_t, + bits_per_component: size_t, + bits_per_pixel: size_t, + bytes_per_row: size_t, + colorspace: &CGColorSpace, + bitmap_info: u32, + provider: &CGDataProvider, + should_interpolate: bool, + rendering_intent: u32) + -> Self { + unsafe { + let result = CGImageCreate(width, + height, + bits_per_component, + bits_per_pixel, + bytes_per_row, + colorspace.as_ptr(), + bitmap_info, + provider.as_ptr(), + ptr::null_mut(), + should_interpolate, + rendering_intent); + assert!(!result.is_null()); + Self::from_ptr(result) + } + } + + pub fn type_id() -> CFTypeID { + unsafe { + CGImageGetTypeID() + } + } +} + +impl CGImageRef { + pub fn width(&self) -> size_t { + unsafe { + CGImageGetWidth(self.as_ptr()) + } + } + + pub fn height(&self) -> size_t { + unsafe { + CGImageGetHeight(self.as_ptr()) + } + } + + pub fn bits_per_component(&self) -> size_t { + unsafe { + CGImageGetBitsPerComponent(self.as_ptr()) + } + } + + pub fn bits_per_pixel(&self) -> size_t { + unsafe { + CGImageGetBitsPerPixel(self.as_ptr()) + } + } + + pub fn bytes_per_row(&self) -> size_t { + unsafe { + CGImageGetBytesPerRow(self.as_ptr()) + } + } + + pub fn color_space(&self) -> CGColorSpace { + unsafe { + let cs = CGImageGetColorSpace(self.as_ptr()); + CFRetain(cs as *mut _); + CGColorSpace::from_ptr(cs) + } + } + + /// 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 { + CGDataProviderRef::from_ptr(CGImageGetDataProvider(self.as_ptr())) + }; + data_provider.copy_data() + } + + /// Returns a cropped image. If the `rect` specifies a rectangle which lies outside of the + /// image bounds, the `None` is returned. + pub fn cropped(&self, rect: CGRect) -> Option<CGImage> { + let image_ptr = unsafe { CGImageCreateWithImageInRect(self.as_ptr(), rect) }; + if !image_ptr.is_null() { + Some(unsafe { CGImage::from_ptr(image_ptr) }) + } else { + None + } + } +} + +#[link(name = "CoreGraphics", kind = "framework")] +extern { + fn CGImageGetTypeID() -> CFTypeID; + fn CGImageGetWidth(image: ::sys::CGImageRef) -> size_t; + fn CGImageGetHeight(image: ::sys::CGImageRef) -> size_t; + fn CGImageGetBitsPerComponent(image: ::sys::CGImageRef) -> size_t; + fn CGImageGetBitsPerPixel(image: ::sys::CGImageRef) -> size_t; + fn CGImageGetBytesPerRow(image: ::sys::CGImageRef) -> size_t; + fn CGImageGetColorSpace(image: ::sys::CGImageRef) -> ::sys::CGColorSpaceRef; + fn CGImageGetDataProvider(image: ::sys::CGImageRef) -> ::sys::CGDataProviderRef; + fn CGImageRelease(image: ::sys::CGImageRef); + fn CGImageCreate(width: size_t, + height: size_t, + bitsPerComponent: size_t, + bitsPerPixel: size_t, + bytesPerRow: size_t, + space: ::sys::CGColorSpaceRef, + bitmapInfo: u32, + provider: ::sys::CGDataProviderRef, + decode: *const CGFloat, + shouldInterpolate: bool, + intent: u32) + -> ::sys::CGImageRef; + fn CGImageCreateWithImageInRect(image: ::sys::CGImageRef, rect: CGRect) -> ::sys::CGImageRef; + + //fn CGImageGetAlphaInfo(image: ::sys::CGImageRef) -> CGImageAlphaInfo; + //fn CGImageCreateCopyWithColorSpace(image: ::sys::CGImageRef, space: ::sys::CGColorSpaceRef) -> ::sys::CGImageRef +} diff --git a/third_party/rust/core-graphics/src/lib.rs b/third_party/rust/core-graphics/src/lib.rs new file mode 100644 index 0000000000..5238774e7c --- /dev/null +++ b/third_party/rust/core-graphics/src/lib.rs @@ -0,0 +1,43 @@ +// Copyright 2013 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate libc; + +#[macro_use] +extern crate core_foundation; + +#[macro_use] +extern crate bitflags; + +#[macro_use] +extern crate foreign_types; + +extern crate core_graphics_types; + +pub mod base; +pub mod color; +pub mod color_space; +pub mod context; +pub mod data_provider; +#[cfg(target_os = "macos")] +pub mod display; +#[cfg(target_os = "macos")] +pub mod event; +#[cfg(target_os = "macos")] +pub mod event_source; +pub mod font; +pub mod geometry; +pub mod gradient; +#[cfg(target_os = "macos")] +pub mod window; +#[cfg(target_os = "macos")] +pub mod private; +pub mod image; +pub mod path; +pub mod sys; diff --git a/third_party/rust/core-graphics/src/path.rs b/third_party/rust/core-graphics/src/path.rs new file mode 100644 index 0000000000..dc1c804644 --- /dev/null +++ b/third_party/rust/core-graphics/src/path.rs @@ -0,0 +1,129 @@ +// Copyright 2017 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub use sys::CGPathRef as SysCGPathRef; + +use core_foundation::base::{CFRelease, CFRetain, CFTypeID}; +use foreign_types::ForeignType; +use geometry::{CGAffineTransform, CGPoint, CGRect}; +use libc::c_void; +use std::fmt::{self, Debug, Formatter}; +use std::marker::PhantomData; +use std::ops::Deref; +use std::ptr; +use std::slice; + +foreign_type! { + #[doc(hidden)] + type CType = ::sys::CGPath; + fn drop = |p| CFRelease(p as *mut _); + fn clone = |p| CFRetain(p as *const _) as *mut _; + pub struct CGPath; + pub struct CGPathRef; +} + +impl CGPath { + pub fn from_rect(rect: CGRect, transform: Option<&CGAffineTransform>) -> CGPath { + unsafe { + let transform = match transform { + None => ptr::null(), + Some(transform) => transform as *const CGAffineTransform, + }; + CGPath(CGPathCreateWithRect(rect, transform)) + } + } + + pub fn type_id() -> CFTypeID { + unsafe { + CGPathGetTypeID() + } + } + + pub fn apply<'a, F>(&'a self, mut closure: &'a F) where F: FnMut(CGPathElementRef<'a>) { + unsafe { + CGPathApply(self.as_ptr(), &mut closure as *mut _ as *mut c_void, do_apply::<F>); + } + + unsafe extern "C" fn do_apply<'a, F>(info: *mut c_void, element: *const CGPathElement) + where F: FnMut(CGPathElementRef<'a>) { + let closure = info as *mut *mut F; + (**closure)(CGPathElementRef::new(element)) + } + } +} + +#[repr(i32)] +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum CGPathElementType { + MoveToPoint = 0, + AddLineToPoint = 1, + AddQuadCurveToPoint = 2, + AddCurveToPoint = 3, + CloseSubpath = 4, +} + +pub struct CGPathElementRef<'a> { + element: *const CGPathElement, + phantom: PhantomData<&'a CGPathElement>, +} + +impl<'a> CGPathElementRef<'a> { + fn new<'b>(element: *const CGPathElement) -> CGPathElementRef<'b> { + CGPathElementRef { + element: element, + phantom: PhantomData, + } + } +} + +impl<'a> Deref for CGPathElementRef<'a> { + type Target = CGPathElement; + fn deref(&self) -> &CGPathElement { + unsafe { + &*self.element + } + } +} + +#[repr(C)] +pub struct CGPathElement { + pub element_type: CGPathElementType, + points: *mut CGPoint, +} + +impl Debug for CGPathElement { + fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> { + write!(formatter, "{:?}: {:?}", self.element_type, self.points()) + } +} + +impl CGPathElement { + pub fn points(&self) -> &[CGPoint] { + unsafe { + match self.element_type { + CGPathElementType::CloseSubpath => &[], + CGPathElementType::MoveToPoint | CGPathElementType::AddLineToPoint => { + slice::from_raw_parts(self.points, 1) + } + CGPathElementType::AddQuadCurveToPoint => slice::from_raw_parts(self.points, 2), + CGPathElementType::AddCurveToPoint => slice::from_raw_parts(self.points, 3), + } + } + } +} + +type CGPathApplierFunction = unsafe extern "C" fn(info: *mut c_void, + element: *const CGPathElement); + +#[link(name = "CoreGraphics", kind = "framework")] +extern { + fn CGPathCreateWithRect(rect: CGRect, transform: *const CGAffineTransform) -> ::sys::CGPathRef; + fn CGPathApply(path: ::sys::CGPathRef, info: *mut c_void, function: CGPathApplierFunction); + fn CGPathGetTypeID() -> CFTypeID; +} diff --git a/third_party/rust/core-graphics/src/private.rs b/third_party/rust/core-graphics/src/private.rs new file mode 100644 index 0000000000..0bc193b408 --- /dev/null +++ b/third_party/rust/core-graphics/src/private.rs @@ -0,0 +1,116 @@ +// Copyright 2016 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Evil private APIs. +//! +//! These are liable to change at any time. Use with caution! + +use geometry::CGRect; +use libc::{c_int, c_uint}; +use std::ptr; + +pub struct CGSRegion { + region: ffi::CGSRegionRef, +} + +impl Drop for CGSRegion { + fn drop(&mut self) { + unsafe { + ffi::CGSRegionRelease(self.region) + } + } +} + +impl CGSRegion { + #[inline] + pub fn from_rect(rect: &CGRect) -> CGSRegion { + unsafe { + let mut region = ptr::null_mut(); + assert!(ffi::CGSNewRegionWithRect(rect, &mut region) == 0); + CGSRegion { + region: region, + } + } + } + + #[inline] + pub fn from_rects(rects: &[CGRect]) -> CGSRegion { + unsafe { + let mut region = ptr::null_mut(); + assert!(ffi::CGSNewRegionWithRectList(rects.as_ptr(), + rects.len() as c_uint, + &mut region) == 0); + CGSRegion { + region: region, + } + } + } +} + +/// This should always be memory-safe; the window server rejects any invalid surface IDs. +pub struct CGSSurface { + context_id: c_uint, + window_number: c_int, + surface_id: c_uint, +} + +impl CGSSurface { + #[inline] + pub fn from_ids(context_id: c_uint, window_number: c_int, surface_id: c_uint) -> CGSSurface { + CGSSurface { + context_id: context_id, + window_number: window_number, + surface_id: surface_id, + } + } + + #[inline] + pub fn id(&self) -> c_uint { + self.surface_id + } + + #[inline] + pub fn set_shape(&self, region: &CGSRegion) { + unsafe { + assert!(ffi::CGSSetSurfaceShape(self.context_id, + self.window_number, + self.surface_id, + region.region) == 0) + } + } +} + +mod ffi { + use geometry::CGRect; + use libc::{c_int, c_uint}; + + // This is an enum so that we can't easily make instances of this opaque type. + pub enum CGSRegionObject {} + + pub type CGError = OSStatus; + pub type CGSRegionRef = *mut CGSRegionObject; + pub type OSStatus = i32; + + #[link(name = "CoreGraphics", kind = "framework")] + extern { + pub fn CGSRegionRelease(region: CGSRegionRef); + pub fn CGSNewRegionWithRect(rect: *const CGRect, outRegion: *mut CGSRegionRef) -> CGError; + pub fn CGSNewRegionWithRectList(rects: *const CGRect, + rectCount: c_uint, + outRegion: *mut CGSRegionRef) + -> CGError; + + pub fn CGSSetSurfaceShape(contextID: c_uint, + windowNumber: c_int, + surfaceID: c_uint, + region: CGSRegionRef) + -> CGError; + } +} + diff --git a/third_party/rust/core-graphics/src/sys.rs b/third_party/rust/core-graphics/src/sys.rs new file mode 100644 index 0000000000..85df442d5f --- /dev/null +++ b/third_party/rust/core-graphics/src/sys.rs @@ -0,0 +1,44 @@ +use std::os::raw::c_void; + +pub enum CGImage {} +pub type CGImageRef = *mut CGImage; + +#[repr(C)] +pub struct __CGColor(c_void); + +pub type CGColorRef = *const __CGColor; + +pub enum CGColorSpace {} +pub type CGColorSpaceRef = *mut CGColorSpace; + +pub enum CGPath {} +pub type CGPathRef = *mut CGPath; + +pub enum CGDataProvider {} +pub type CGDataProviderRef = *mut CGDataProvider; + +pub enum CGFont {} +pub type CGFontRef = *mut CGFont; + +pub enum CGContext {} +pub type CGContextRef = *mut CGContext; + +pub enum CGGradient {} +pub type CGGradientRef = *mut CGGradient; + +#[cfg(target_os = "macos")] +mod macos { + pub enum CGEventTap {} + pub type CGEventTapRef = core_foundation::mach_port::CFMachPortRef; + pub enum CGEvent {} + pub type CGEventRef = *mut CGEvent; + + pub enum CGEventSource {} + pub type CGEventSourceRef = *mut CGEventSource; + + pub enum CGDisplayMode {} + pub type CGDisplayModeRef = *mut CGDisplayMode; +} + +#[cfg(target_os = "macos")] +pub use self::macos::*; diff --git a/third_party/rust/core-graphics/src/window.rs b/third_party/rust/core-graphics/src/window.rs new file mode 100644 index 0000000000..aa7293ff7f --- /dev/null +++ b/third_party/rust/core-graphics/src/window.rs @@ -0,0 +1,149 @@ +// Copyright 2018 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(non_upper_case_globals)] + +use core_foundation::array::{CFArray, CFArrayRef}; +use core_foundation::base::{CFType, TCFType}; +use core_foundation::dictionary::CFDictionary; +use core_foundation::string::{CFString, CFStringRef}; +use foreign_types::ForeignType; + +use geometry::CGRect; +use image::CGImage; +use sys; + +pub type CGWindowID = u32; + +pub type CGWindowSharingType = u32; +pub const kCGWindowSharingNone: CGWindowSharingType = 0; +pub const kCGWindowSharingReadOnly: CGWindowSharingType = 1; +pub const kCGWindowSharingReadWrite: CGWindowSharingType = 1; + +pub type CGWindowBackingType = u32; +pub const kCGWindowBackingStoreRetained: CGWindowBackingType = 0; +pub const kCGWindowBackingStoreNonretained: CGWindowBackingType = 1; +pub const kCGWindowBackingStoreBuffered: CGWindowBackingType = 2; + +pub type CGWindowListOption = u32; +pub const kCGWindowListOptionAll: CGWindowListOption = 1 << 0; +pub const kCGWindowListOptionOnScreenOnly: CGWindowListOption = 1 << 1; +pub const kCGWindowListOptionOnScreenAboveWindow: CGWindowListOption = 1 << 2; +pub const kCGWindowListOptionOnScreenBelowWindow: CGWindowListOption = 1 << 3; +pub const kCGWindowListOptionIncludingWindow: CGWindowListOption = 1 << 4; +pub const kCGWindowListOptionExcludeDesktopElements: CGWindowListOption = 1 << 5; + +pub type CGWindowImageOption = u32; +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 const kCGNullWindowID: CGWindowID = 0; + +pub fn copy_window_info(option: CGWindowListOption, relative_to_window: CGWindowID) + -> Option<CFArray> { + unsafe { + let array = CGWindowListCopyWindowInfo(option, relative_to_window); + if array.is_null() { + None + } else { + Some(TCFType::wrap_under_create_rule(array)) + } + } +} + +pub fn create_window_list(option: CGWindowListOption, relative_to_window: CGWindowID) + -> Option<CFArray<CGWindowID>> { + unsafe { + let array = CGWindowListCreate(option, relative_to_window); + if array.is_null() { + None + } else { + Some(TCFType::wrap_under_create_rule(array)) + } + } +} + +pub fn create_description_from_array(window_array: CFArray<CGWindowID>) -> + Option<CFArray<CFDictionary<CFString, CFType>>> { + unsafe { + let array = CGWindowListCreateDescriptionFromArray(window_array.as_concrete_TypeRef()); + if array.is_null() { + None + } else { + Some(TCFType::wrap_under_create_rule(array)) + } + } +} + +pub fn create_image(screen_bounds: CGRect, + list_option: CGWindowListOption, + window_id: CGWindowID, + image_option: CGWindowImageOption) + -> Option<CGImage> { + unsafe { + let image = CGWindowListCreateImage(screen_bounds, list_option, window_id, image_option); + if image.is_null() { + None + } else { + Some(CGImage::from_ptr(image)) + } + } +} + +pub fn create_image_from_array(screen_bounds: CGRect, + window_array: CFArray, + image_option: CGWindowImageOption) + -> Option<CGImage> { + unsafe { + let image = CGWindowListCreateImageFromArray(screen_bounds, + window_array.as_concrete_TypeRef(), + image_option); + if image.is_null() { + None + } else { + Some(CGImage::from_ptr(image)) + } + } +} + +#[link(name = "CoreGraphics", kind = "framework")] +extern { + pub static kCGWindowNumber: CFStringRef; + pub static kCGWindowStoreType: CFStringRef; + pub static kCGWindowLayer: CFStringRef; + pub static kCGWindowBounds: CFStringRef; + pub static kCGWindowSharingState: CFStringRef; + pub static kCGWindowAlpha: CFStringRef; + pub static kCGWindowOwnerPID: CFStringRef; + pub static kCGWindowMemoryUsage: CFStringRef; + pub static kCGWindowWorkspace: CFStringRef; + pub static kCGWindowOwnerName: CFStringRef; + pub static kCGWindowName: CFStringRef; + pub static kCGWindowIsOnscreen: CFStringRef; + pub static kCGWindowBackingLocationVideoMemory: CFStringRef; + + pub fn CGWindowListCopyWindowInfo(option: CGWindowListOption, relativeToWindow: CGWindowID) + -> CFArrayRef; + pub fn CGWindowListCreate(option: CGWindowListOption, relativeToWindow: CGWindowID) + -> CFArrayRef; + pub fn CGWindowListCreateDescriptionFromArray(windowArray: CFArrayRef) -> CFArrayRef; + pub fn CGWindowListCreateImage(screenBounds: CGRect, + listOption: CGWindowListOption, + windowID: CGWindowID, + imageOption: CGWindowImageOption) + -> *mut sys::CGImage; + pub fn CGWindowListCreateImageFromArray(screenBounds: CGRect, + windowArray: CFArrayRef, + imageOption: CGWindowImageOption) + -> *mut sys::CGImage; +} |