├── .gitignore ├── .travis.yml ├── COPYRIGHT ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md └── src ├── base.rs ├── color_space.rs ├── context.rs ├── data_provider.rs ├── display.rs ├── event.rs ├── event_source.rs ├── font.rs ├── geometry.rs ├── image.rs ├── lib.rs ├── path.rs ├── private.rs └── sys.rs /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *# 3 | *.o 4 | *.a 5 | *.so 6 | *.dylib 7 | *.dSYM 8 | *.dll 9 | *.dummy 10 | cocoa-test 11 | build 12 | /target 13 | /doc 14 | /Cargo.lock 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | os: osx 3 | rust: 4 | - nightly 5 | - beta 6 | - stable 7 | 8 | script: 9 | - cargo test 10 | - cargo test --features="elcapitan" 11 | 12 | notifications: 13 | webhooks: http://build.servo.org:54856/travis 14 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Licensed under the Apache License, Version 2.0 or the MIT license 3 | , at your 4 | option. All files in the project carrying such notice may not be 5 | copied, modified, or distributed except according to those terms. 6 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "core-graphics" 3 | description = "Bindings to Core Graphics for OS X" 4 | homepage = "https://github.com/servo/core-graphics-rs" 5 | repository = "https://github.com/servo/core-graphics-rs" 6 | version = "0.13.0" 7 | authors = ["The Servo Project Developers"] 8 | license = "MIT / Apache-2.0" 9 | 10 | [features] 11 | default = [] 12 | elcapitan = [] 13 | 14 | [dependencies] 15 | bitflags = "1.0" 16 | core-foundation = "0.5" 17 | foreign-types = "0.3.0" 18 | libc = "0.2" 19 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2013 Mozilla Foundation 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # core-graphics-rs 2 | 3 | [![Build Status](https://travis-ci.org/servo/core-graphics-rs.svg?branch=master)](https://travis-ci.org/servo/core-graphics-rs) 4 | -------------------------------------------------------------------------------- /src/base.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Servo Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution. 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | // this file defines CGFloat, as well as stubbed data types. 11 | 12 | #![allow(non_camel_case_types)] 13 | #![allow(non_upper_case_globals)] 14 | 15 | use libc; 16 | 17 | #[cfg(any(target_arch = "x86", 18 | target_arch = "arm", 19 | target_arch = "aarch64"))] 20 | pub type boolean_t = libc::c_int; 21 | #[cfg(target_arch = "x86_64")] 22 | pub type boolean_t = libc::c_uint; 23 | 24 | #[cfg(target_pointer_width = "64")] 25 | pub type CGFloat = libc::c_double; 26 | #[cfg(not(target_pointer_width = "64"))] 27 | pub type CGFloat = libc::c_float; 28 | 29 | pub type CGError = libc::int32_t; 30 | 31 | pub const kCGImageAlphaNone: u32 = 0; 32 | pub const kCGImageAlphaPremultipliedLast: u32 = 1; 33 | pub const kCGImageAlphaPremultipliedFirst: u32 = 2; 34 | pub const kCGImageAlphaLast: u32 = 3; 35 | pub const kCGImageAlphaFirst: u32 = 4; 36 | pub const kCGImageAlphaNoneSkipLast: u32 = 5; 37 | pub const kCGImageAlphaNoneSkipFirst: u32 = 6; 38 | 39 | pub const kCGBitmapByteOrderDefault: u32 = (0 << 12); 40 | pub const kCGBitmapByteOrder16Little: u32 = (1 << 12); 41 | pub const kCGBitmapByteOrder32Little: u32 = (2 << 12); 42 | pub const kCGBitmapByteOrder16Big: u32 = (3 << 12); 43 | pub const kCGBitmapByteOrder32Big: u32 = (4 << 12); 44 | 45 | #[cfg(target_endian = "big")] 46 | pub const kCGBitmapByteOrder16Host: u32 = kCGBitmapByteOrder16Big; 47 | #[cfg(target_endian = "big")] 48 | pub const kCGBitmapByteOrder32Host: u32 = kCGBitmapByteOrder32Big; 49 | 50 | #[cfg(target_endian = "little")] 51 | pub const kCGBitmapByteOrder16Host: u32 = kCGBitmapByteOrder16Little; 52 | #[cfg(target_endian = "little")] 53 | pub const kCGBitmapByteOrder32Host: u32 = kCGBitmapByteOrder32Little; 54 | -------------------------------------------------------------------------------- /src/color_space.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Servo Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution. 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | use core_foundation::base::{CFRelease, CFRetain, CFTypeID}; 11 | use core_foundation::string::CFStringRef; 12 | use foreign_types::ForeignType; 13 | 14 | foreign_type! { 15 | #[doc(hidden)] 16 | type CType = ::sys::CGColorSpace; 17 | fn drop = |p| CFRelease(p as *mut _); 18 | fn clone = |p| CFRetain(p as *const _) as *mut _; 19 | pub struct CGColorSpace; 20 | pub struct CGColorSpaceRef; 21 | } 22 | 23 | impl CGColorSpace { 24 | pub fn type_id() -> CFTypeID { 25 | unsafe { 26 | CGColorSpaceGetTypeID() 27 | } 28 | } 29 | 30 | pub fn create_with_name(name: CFStringRef) -> Option { 31 | unsafe { 32 | let p = CGColorSpaceCreateWithName(name); 33 | if !p.is_null() {Some(CGColorSpace::from_ptr(p))} else {None} 34 | } 35 | } 36 | 37 | pub fn create_device_rgb() -> CGColorSpace { 38 | unsafe { 39 | let result = CGColorSpaceCreateDeviceRGB(); 40 | CGColorSpace::from_ptr(result) 41 | } 42 | } 43 | } 44 | 45 | #[link(name = "CoreGraphics", kind = "framework")] 46 | extern { 47 | pub static kCGColorSpaceSRGB: CFStringRef; 48 | pub static kCGColorSpaceAdobeRGB1998: CFStringRef; 49 | pub static kCGColorSpaceGenericGray: CFStringRef; 50 | pub static kCGColorSpaceGenericRGB: CFStringRef; 51 | pub static kCGColorSpaceGenericCMYK: CFStringRef; 52 | pub static kCGColorSpaceGenericRGBLinear: CFStringRef; 53 | pub static kCGColorSpaceGenericGrayGamma2_2: CFStringRef; 54 | 55 | fn CGColorSpaceCreateDeviceRGB() -> ::sys::CGColorSpaceRef; 56 | fn CGColorSpaceCreateWithName(name: CFStringRef) -> ::sys::CGColorSpaceRef; 57 | fn CGColorSpaceGetTypeID() -> CFTypeID; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /src/context.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Servo Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution. 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | use base::CGFloat; 11 | use color_space::CGColorSpace; 12 | use core_foundation::base::{CFRelease, CFRetain, CFTypeID}; 13 | use font::{CGFont, CGGlyph}; 14 | use geometry::CGPoint; 15 | use libc::{c_void, c_int, size_t}; 16 | 17 | use std::cmp; 18 | use std::ptr; 19 | use std::slice; 20 | use geometry::{CGAffineTransform, CGRect}; 21 | use image::CGImage; 22 | use foreign_types::ForeignType; 23 | 24 | #[repr(C)] 25 | pub enum CGTextDrawingMode { 26 | CGTextFill, 27 | CGTextStroke, 28 | CGTextFillStroke, 29 | CGTextInvisible, 30 | CGTextFillClip, 31 | CGTextStrokeClip, 32 | CGTextClip 33 | } 34 | 35 | foreign_type! { 36 | #[doc(hidden)] 37 | type CType = ::sys::CGContext; 38 | fn drop = |cs| CFRelease(cs as *mut _); 39 | fn clone = |p| CFRetain(p as *const _) as *mut _; 40 | pub struct CGContext; 41 | pub struct CGContextRef; 42 | } 43 | 44 | impl CGContext { 45 | pub fn type_id() -> CFTypeID { 46 | unsafe { 47 | CGContextGetTypeID() 48 | } 49 | } 50 | 51 | pub fn create_bitmap_context(data: Option<*mut c_void>, 52 | width: size_t, 53 | height: size_t, 54 | bits_per_component: size_t, 55 | bytes_per_row: size_t, 56 | space: &CGColorSpace, 57 | bitmap_info: u32) 58 | -> CGContext { 59 | unsafe { 60 | let result = CGBitmapContextCreate(data.unwrap_or(ptr::null_mut()), 61 | width, 62 | height, 63 | bits_per_component, 64 | bytes_per_row, 65 | space.as_ptr(), 66 | bitmap_info); 67 | assert!(!result.is_null()); 68 | Self::from_ptr(result) 69 | } 70 | } 71 | 72 | pub fn data(&mut self) -> &mut [u8] { 73 | unsafe { 74 | slice::from_raw_parts_mut( 75 | CGBitmapContextGetData(self.as_ptr()) as *mut u8, 76 | (self.height() * self.bytes_per_row()) as usize) 77 | } 78 | } 79 | 80 | pub fn width(&self) -> size_t { 81 | unsafe { 82 | CGBitmapContextGetWidth(self.as_ptr()) 83 | } 84 | } 85 | 86 | pub fn height(&self) -> size_t { 87 | unsafe { 88 | CGBitmapContextGetHeight(self.as_ptr()) 89 | } 90 | } 91 | 92 | pub fn bytes_per_row(&self) -> size_t { 93 | unsafe { 94 | CGBitmapContextGetBytesPerRow(self.as_ptr()) 95 | } 96 | } 97 | 98 | pub fn set_rgb_fill_color(&self, red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) { 99 | unsafe { 100 | CGContextSetRGBFillColor(self.as_ptr(), red, green, blue, alpha) 101 | } 102 | } 103 | 104 | pub fn set_allows_font_smoothing(&self, allows_font_smoothing: bool) { 105 | unsafe { 106 | CGContextSetAllowsFontSmoothing(self.as_ptr(), allows_font_smoothing) 107 | } 108 | } 109 | 110 | pub fn set_font_smoothing_style(&self, style: i32) { 111 | unsafe { 112 | CGContextSetFontSmoothingStyle(self.as_ptr(), style as _); 113 | } 114 | } 115 | 116 | pub fn set_should_smooth_fonts(&self, should_smooth_fonts: bool) { 117 | unsafe { 118 | CGContextSetShouldSmoothFonts(self.as_ptr(), should_smooth_fonts) 119 | } 120 | } 121 | 122 | pub fn set_allows_antialiasing(&self, allows_antialiasing: bool) { 123 | unsafe { 124 | CGContextSetAllowsAntialiasing(self.as_ptr(), allows_antialiasing) 125 | } 126 | } 127 | 128 | pub fn set_should_antialias(&self, should_antialias: bool) { 129 | unsafe { 130 | CGContextSetShouldAntialias(self.as_ptr(), should_antialias) 131 | } 132 | } 133 | 134 | pub fn set_allows_font_subpixel_quantization(&self, allows_font_subpixel_quantization: bool) { 135 | unsafe { 136 | CGContextSetAllowsFontSubpixelQuantization(self.as_ptr(), allows_font_subpixel_quantization) 137 | } 138 | } 139 | 140 | pub fn set_should_subpixel_quantize_fonts(&self, should_subpixel_quantize_fonts: bool) { 141 | unsafe { 142 | CGContextSetShouldSubpixelQuantizeFonts(self.as_ptr(), should_subpixel_quantize_fonts) 143 | } 144 | } 145 | 146 | pub fn set_allows_font_subpixel_positioning(&self, allows_font_subpixel_positioning: bool) { 147 | unsafe { 148 | CGContextSetAllowsFontSubpixelPositioning(self.as_ptr(), allows_font_subpixel_positioning) 149 | } 150 | } 151 | 152 | pub fn set_should_subpixel_position_fonts(&self, should_subpixel_position_fonts: bool) { 153 | unsafe { 154 | CGContextSetShouldSubpixelPositionFonts(self.as_ptr(), should_subpixel_position_fonts) 155 | } 156 | } 157 | 158 | pub fn set_text_drawing_mode(&self, mode: CGTextDrawingMode) { 159 | unsafe { 160 | CGContextSetTextDrawingMode(self.as_ptr(), mode) 161 | } 162 | } 163 | 164 | pub fn fill_rect(&self, rect: CGRect) { 165 | unsafe { 166 | CGContextFillRect(self.as_ptr(), rect) 167 | } 168 | } 169 | 170 | pub fn draw_image(&self, rect: CGRect, image: &CGImage) { 171 | unsafe { 172 | CGContextDrawImage(self.as_ptr(), rect, image.as_ptr()); 173 | } 174 | } 175 | 176 | pub fn create_image(&self) -> Option { 177 | let image = unsafe { CGBitmapContextCreateImage(self.as_ptr()) }; 178 | if !image.is_null() { 179 | Some(unsafe { CGImage::from_ptr(image) }) 180 | } else { 181 | None 182 | } 183 | } 184 | 185 | pub fn set_font(&self, font: &CGFont) { 186 | unsafe { 187 | CGContextSetFont(self.as_ptr(), font.as_ptr()) 188 | } 189 | } 190 | 191 | pub fn set_font_size(&self, size: CGFloat) { 192 | unsafe { 193 | CGContextSetFontSize(self.as_ptr(), size) 194 | } 195 | } 196 | 197 | pub fn set_text_matrix(&self, t: &CGAffineTransform) { 198 | unsafe { 199 | CGContextSetTextMatrix(self.as_ptr(), *t) 200 | } 201 | } 202 | 203 | pub fn show_glyphs_at_positions(&self, glyphs: &[CGGlyph], positions: &[CGPoint]) { 204 | unsafe { 205 | let count = cmp::min(glyphs.len(), positions.len()); 206 | CGContextShowGlyphsAtPositions(self.as_ptr(), 207 | glyphs.as_ptr(), 208 | positions.as_ptr(), 209 | count) 210 | } 211 | } 212 | } 213 | 214 | #[test] 215 | fn create_bitmap_context_test() { 216 | use geometry::*; 217 | 218 | let cs = CGColorSpace::create_device_rgb(); 219 | let ctx = CGContext::create_bitmap_context(None, 220 | 16, 8, 221 | 8, 0, 222 | &cs, 223 | ::base::kCGImageAlphaPremultipliedLast); 224 | ctx.set_rgb_fill_color(1.,0.,1.,1.); 225 | ctx.fill_rect(CGRect::new(&CGPoint::new(0.,0.), &CGSize::new(8.,8.))); 226 | let img = ctx.create_image().unwrap(); 227 | assert_eq!(16, img.width()); 228 | assert_eq!(8, img.height()); 229 | assert_eq!(8, img.bits_per_component()); 230 | assert_eq!(32, img.bits_per_pixel()); 231 | let data = img.data(); 232 | assert_eq!(255, data.bytes()[0]); 233 | assert_eq!(0, data.bytes()[1]); 234 | assert_eq!(255, data.bytes()[2]); 235 | assert_eq!(255, data.bytes()[3]); 236 | } 237 | 238 | #[link(name = "CoreGraphics", kind = "framework")] 239 | extern { 240 | fn CGBitmapContextCreate(data: *mut c_void, 241 | width: size_t, 242 | height: size_t, 243 | bitsPerComponent: size_t, 244 | bytesPerRow: size_t, 245 | space: ::sys::CGColorSpaceRef, 246 | bitmapInfo: u32) 247 | -> ::sys::CGContextRef; 248 | fn CGBitmapContextGetData(context: ::sys::CGContextRef) -> *mut c_void; 249 | fn CGBitmapContextGetWidth(context: ::sys::CGContextRef) -> size_t; 250 | fn CGBitmapContextGetHeight(context: ::sys::CGContextRef) -> size_t; 251 | fn CGBitmapContextGetBytesPerRow(context: ::sys::CGContextRef) -> size_t; 252 | fn CGBitmapContextCreateImage(context: ::sys::CGContextRef) -> ::sys::CGImageRef; 253 | fn CGContextGetTypeID() -> CFTypeID; 254 | fn CGContextSetAllowsFontSmoothing(c: ::sys::CGContextRef, allowsFontSmoothing: bool); 255 | fn CGContextSetShouldSmoothFonts(c: ::sys::CGContextRef, shouldSmoothFonts: bool); 256 | fn CGContextSetFontSmoothingStyle(c: ::sys::CGContextRef, style: c_int); 257 | fn CGContextSetAllowsAntialiasing(c: ::sys::CGContextRef, allowsAntialiasing: bool); 258 | fn CGContextSetShouldAntialias(c: ::sys::CGContextRef, shouldAntialias: bool); 259 | fn CGContextSetAllowsFontSubpixelQuantization(c: ::sys::CGContextRef, 260 | allowsFontSubpixelQuantization: bool); 261 | fn CGContextSetShouldSubpixelQuantizeFonts(c: ::sys::CGContextRef, 262 | shouldSubpixelQuantizeFonts: bool); 263 | fn CGContextSetAllowsFontSubpixelPositioning(c: ::sys::CGContextRef, 264 | allowsFontSubpixelPositioning: bool); 265 | fn CGContextSetShouldSubpixelPositionFonts(c: ::sys::CGContextRef, 266 | shouldSubpixelPositionFonts: bool); 267 | fn CGContextSetTextDrawingMode(c: ::sys::CGContextRef, mode: CGTextDrawingMode); 268 | fn CGContextSetRGBFillColor(context: ::sys::CGContextRef, 269 | red: CGFloat, 270 | green: CGFloat, 271 | blue: CGFloat, 272 | alpha: CGFloat); 273 | fn CGContextFillRect(context: ::sys::CGContextRef, 274 | rect: CGRect); 275 | fn CGContextDrawImage(c: ::sys::CGContextRef, rect: CGRect, image: ::sys::CGImageRef); 276 | fn CGContextSetFont(c: ::sys::CGContextRef, font: ::sys::CGFontRef); 277 | fn CGContextSetFontSize(c: ::sys::CGContextRef, size: CGFloat); 278 | fn CGContextSetTextMatrix(c: ::sys::CGContextRef, t: CGAffineTransform); 279 | fn CGContextShowGlyphsAtPositions(c: ::sys::CGContextRef, 280 | glyphs: *const CGGlyph, 281 | positions: *const CGPoint, 282 | count: size_t); 283 | } 284 | 285 | -------------------------------------------------------------------------------- /src/data_provider.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Servo Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution. 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | use core_foundation::base::{CFRelease, CFRetain, CFTypeID, TCFType}; 11 | use core_foundation::data::{CFData, CFDataRef}; 12 | 13 | use libc::{c_void, size_t, off_t}; 14 | use std::mem; 15 | use std::sync::Arc; 16 | 17 | use foreign_types::{ForeignType, ForeignTypeRef}; 18 | 19 | pub type CGDataProviderGetBytesCallback = Option size_t>; 20 | pub type CGDataProviderReleaseInfoCallback = Option; 21 | pub type CGDataProviderRewindCallback = Option; 22 | pub type CGDataProviderSkipBytesCallback = Option; 23 | pub type CGDataProviderSkipForwardCallback = Option off_t>; 24 | 25 | pub type CGDataProviderGetBytePointerCallback = Option *mut c_void>; 26 | pub type CGDataProviderGetBytesAtOffsetCallback = Option; 27 | pub type CGDataProviderReleaseBytePointerCallback = Option; 28 | pub type CGDataProviderReleaseDataCallback = Option; 29 | pub type CGDataProviderGetBytesAtPositionCallback = Option; 30 | 31 | foreign_type! { 32 | #[doc(hidden)] 33 | type CType = ::sys::CGDataProvider; 34 | fn drop = |cs| CFRelease(cs as *mut _); 35 | fn clone = |p| CFRetain(p as *const _) as *mut _; 36 | pub struct CGDataProvider; 37 | pub struct CGDataProviderRef; 38 | } 39 | 40 | impl CGDataProvider { 41 | pub fn type_id() -> CFTypeID { 42 | unsafe { 43 | CGDataProviderGetTypeID() 44 | } 45 | } 46 | 47 | /// Creates a data provider from the given reference-counted buffer. 48 | /// 49 | /// The `CGDataProvider` object takes ownership of the reference. Once the data provider 50 | /// is destroyed, the reference count of the buffer is automatically decremented. 51 | pub fn from_buffer(buffer: Arc>) -> Self { 52 | unsafe { 53 | let ptr = (*buffer).as_ptr() as *const c_void; 54 | let len = buffer.len() as size_t; 55 | let info = mem::transmute::>, *mut c_void>(buffer); 56 | let result = CGDataProviderCreateWithData(info, ptr, len, Some(release)); 57 | return CGDataProvider::from_ptr(result); 58 | } 59 | 60 | unsafe extern "C" fn release(info: *mut c_void, _: *const c_void, _: size_t) { 61 | drop(mem::transmute::<*mut c_void, Arc>>(info)) 62 | } 63 | } 64 | } 65 | 66 | impl CGDataProviderRef { 67 | /// Creates a copy of the data from the underlying `CFDataProviderRef`. 68 | pub fn copy_data(&self) -> CFData { 69 | unsafe { CFData::wrap_under_create_rule(CGDataProviderCopyData(self.as_ptr())) } 70 | } 71 | } 72 | 73 | #[link(name = "CoreGraphics", kind = "framework")] 74 | extern { 75 | fn CGDataProviderCopyData(provider: ::sys::CGDataProviderRef) -> CFDataRef; 76 | //fn CGDataProviderCreateDirect 77 | //fn CGDataProviderCreateSequential 78 | //fn CGDataProviderCreateWithCFData 79 | fn CGDataProviderCreateWithData(info: *mut c_void, 80 | data: *const c_void, 81 | size: size_t, 82 | releaseData: CGDataProviderReleaseDataCallback 83 | ) -> ::sys::CGDataProviderRef; 84 | //fn CGDataProviderCreateWithFilename(filename: *c_char) -> CGDataProviderRef; 85 | //fn CGDataProviderCreateWithURL 86 | fn CGDataProviderGetTypeID() -> CFTypeID; 87 | //fn CGDataProviderRelease(provider: CGDataProviderRef); 88 | //fn CGDataProviderRetain(provider: CGDataProviderRef) -> CGDataProviderRef; 89 | } 90 | -------------------------------------------------------------------------------- /src/display.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Servo Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution. 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | #![allow(non_upper_case_globals)] 11 | 12 | use libc; 13 | use std::ptr; 14 | pub use base::{CGError, boolean_t}; 15 | pub use geometry::{CGRect, CGPoint, CGSize}; 16 | 17 | use core_foundation::base::{CFRetain, TCFType}; 18 | use image::CGImage; 19 | use foreign_types::ForeignType; 20 | 21 | pub type CGDirectDisplayID = libc::uint32_t; 22 | pub type CGWindowID = libc::uint32_t; 23 | 24 | pub const kCGNullWindowID: CGWindowID = 0 as CGWindowID; 25 | 26 | 27 | pub type CGWindowListOption = libc::uint32_t; 28 | 29 | pub const kCGWindowListOptionAll: CGWindowListOption = 0; 30 | pub const kCGWindowListOptionOnScreenOnly: CGWindowListOption = 1 << 0; 31 | pub const kCGWindowListOptionOnScreenAboveWindow: CGWindowListOption = 1 << 1; 32 | pub const kCGWindowListOptionOnScreenBelowWindow: CGWindowListOption = 1 << 2; 33 | pub const kCGWindowListOptionIncludingWindow: CGWindowListOption = 1 << 3; 34 | pub const kCGWindowListExcludeDesktopElements: CGWindowListOption = 1 << 4; 35 | 36 | pub type CGWindowImageOption = libc::uint32_t; 37 | 38 | pub const kCGWindowImageDefault: CGWindowImageOption = 0; 39 | pub const kCGWindowImageBoundsIgnoreFraming: CGWindowImageOption = 1 << 0; 40 | pub const kCGWindowImageShouldBeOpaque: CGWindowImageOption = 1 << 1; 41 | pub const kCGWindowImageOnlyShadows: CGWindowImageOption = 1 << 2; 42 | pub const kCGWindowImageBestResolution: CGWindowImageOption = 1 << 3; 43 | pub const kCGWindowImageNominalResolution: CGWindowImageOption = 1 << 4; 44 | 45 | pub use core_foundation::dictionary::{ CFDictionary, CFDictionaryRef, CFDictionaryGetValueIfPresent }; 46 | pub use core_foundation::array::{ CFArray, CFArrayRef }; 47 | pub use core_foundation::array::{ CFArrayGetCount, CFArrayGetValueAtIndex }; 48 | pub use core_foundation::base::{ CFIndex, CFRelease, CFTypeRef }; 49 | 50 | #[derive(Copy, Clone, Debug)] 51 | pub struct CGDisplay { 52 | pub id: CGDirectDisplayID, 53 | } 54 | 55 | foreign_type! { 56 | #[doc(hidden)] 57 | type CType = ::sys::CGDisplayMode; 58 | fn drop = CGDisplayModeRelease; 59 | fn clone = |p| CFRetain(p as *const _) as *mut _; 60 | pub struct CGDisplayMode; 61 | pub struct CGDisplayModeRef; 62 | } 63 | 64 | impl CGDisplay { 65 | #[inline] 66 | pub fn new(id: CGDirectDisplayID) -> CGDisplay { 67 | CGDisplay { id: id } 68 | } 69 | 70 | /// Returns the the main display. 71 | #[inline] 72 | pub fn main() -> CGDisplay { 73 | CGDisplay::new(unsafe { CGMainDisplayID() }) 74 | } 75 | 76 | /// Returns the bounds of a display in the global display coordinate space. 77 | #[inline] 78 | pub fn bounds(&self) -> CGRect { 79 | unsafe { CGDisplayBounds(self.id) } 80 | } 81 | 82 | /// Returns information about a display's current configuration. 83 | #[inline] 84 | pub fn display_mode(&self) -> Option { 85 | unsafe { 86 | let mode_ref = CGDisplayCopyDisplayMode(self.id); 87 | if !mode_ref.is_null() { 88 | Some(CGDisplayMode::from_ptr(mode_ref)) 89 | } else { 90 | None 91 | } 92 | } 93 | } 94 | 95 | /// Returns an image containing the contents of the specified display. 96 | #[inline] 97 | pub fn image(&self) -> Option { 98 | unsafe { 99 | let image_ref = CGDisplayCreateImage(self.id); 100 | if !image_ref.is_null() { 101 | Some(CGImage::from_ptr(image_ref)) 102 | } else { 103 | None 104 | } 105 | } 106 | } 107 | 108 | /// Returns a composite image based on a dynamically generated list of 109 | /// windows. 110 | #[inline] 111 | pub fn screenshot( 112 | bounds: CGRect, 113 | list_option: CGWindowListOption, 114 | window_id: CGWindowID, 115 | image_option: CGWindowImageOption, 116 | ) -> Option { 117 | unsafe { 118 | let image_ref = CGWindowListCreateImage(bounds, list_option, window_id, image_option); 119 | if !image_ref.is_null() { 120 | Some(CGImage::from_ptr(image_ref)) 121 | } else { 122 | None 123 | } 124 | } 125 | } 126 | 127 | /// Returns a composite image of the specified windows. 128 | #[inline] 129 | pub fn screenshot_from_windows( 130 | bounds: CGRect, 131 | windows: CFArray, 132 | image_option: CGWindowImageOption, 133 | ) -> Option { 134 | unsafe { 135 | let image_ref = CGWindowListCreateImageFromArray( 136 | bounds, 137 | windows.as_concrete_TypeRef(), 138 | image_option, 139 | ); 140 | if !image_ref.is_null() { 141 | Some(CGImage::from_ptr(image_ref)) 142 | } else { 143 | None 144 | } 145 | } 146 | } 147 | 148 | /// Generates and returns information about the selected windows in the 149 | /// current user session. 150 | pub fn window_list_info( 151 | option: CGWindowListOption, 152 | relative_to_window: Option, 153 | ) -> Option { 154 | let relative_to_window = relative_to_window.unwrap_or(kCGNullWindowID); 155 | let array_ref = unsafe { CGWindowListCopyWindowInfo(option, relative_to_window) }; 156 | if array_ref != ptr::null() { 157 | Some(unsafe { TCFType::wrap_under_create_rule(array_ref) }) 158 | } else { 159 | None 160 | } 161 | } 162 | 163 | /// Returns a Boolean value indicating whether a display is active. 164 | #[inline] 165 | pub fn is_active(&self) -> bool { 166 | unsafe { CGDisplayIsActive(self.id) != 0 } 167 | } 168 | 169 | /// Returns a boolean indicating whether a display is always in a 170 | /// mirroring set. 171 | #[inline] 172 | pub fn is_always_in_mirror_set(&self) -> bool { 173 | unsafe { CGDisplayIsAlwaysInMirrorSet(self.id) != 0 } 174 | } 175 | 176 | /// Returns a boolean indicating whether a display is sleeping (and is 177 | /// therefore not drawable.) 178 | #[inline] 179 | pub fn is_asleep(&self) -> bool { 180 | unsafe { CGDisplayIsAsleep(self.id) != 0 } 181 | } 182 | 183 | /// Returns a boolean indicating whether a display is built-in, such as 184 | /// the internal display in portable systems. 185 | #[inline] 186 | pub fn is_builtin(&self) -> bool { 187 | unsafe { CGDisplayIsBuiltin(self.id) != 0 } 188 | } 189 | 190 | /// Returns a boolean indicating whether a display is in a hardware 191 | /// mirroring set. 192 | #[inline] 193 | pub fn is_in_hw_mirror_set(&self) -> bool { 194 | unsafe { CGDisplayIsInHWMirrorSet(self.id) != 0 } 195 | } 196 | 197 | /// Returns a boolean indicating whether a display is in a mirroring set. 198 | #[inline] 199 | pub fn is_in_mirror_set(&self) -> bool { 200 | unsafe { CGDisplayIsInMirrorSet(self.id) != 0 } 201 | } 202 | 203 | /// Returns a boolean indicating whether a display is the main display. 204 | #[inline] 205 | pub fn is_main(&self) -> bool { 206 | unsafe { CGDisplayIsMain(self.id) != 0 } 207 | } 208 | 209 | /// Returns a boolean indicating whether a display is connected or online. 210 | #[inline] 211 | pub fn is_online(&self) -> bool { 212 | unsafe { CGDisplayIsOnline(self.id) != 0 } 213 | } 214 | 215 | /// Returns a boolean indicating whether Quartz is using OpenGL-based 216 | /// window acceleration (Quartz Extreme) to render in a display. 217 | #[inline] 218 | pub fn uses_open_gl_acceleration(&self) -> bool { 219 | unsafe { CGDisplayUsesOpenGLAcceleration(self.id) != 0 } 220 | } 221 | 222 | /// Returns a boolean indicating whether a display is running in a stereo 223 | /// graphics mode. 224 | #[inline] 225 | pub fn is_stereo(&self) -> bool { 226 | unsafe { CGDisplayIsStereo(self.id) != 0 } 227 | } 228 | 229 | /// For a secondary display in a mirroring set, returns the primary 230 | /// display. 231 | #[inline] 232 | pub fn mirrors_display(&self) -> CGDirectDisplayID { 233 | unsafe { CGDisplayMirrorsDisplay(self.id) } 234 | } 235 | 236 | /// Returns the primary display in a hardware mirroring set. 237 | #[inline] 238 | pub fn primary_display(&self) -> CGDirectDisplayID { 239 | unsafe { CGDisplayPrimaryDisplay(self.id) } 240 | } 241 | 242 | /// Returns the rotation angle of a display in degrees. 243 | #[inline] 244 | pub fn rotation(&self) -> f64 { 245 | unsafe { CGDisplayRotation(self.id) } 246 | } 247 | 248 | /// Returns the width and height of a display in millimeters. 249 | #[inline] 250 | pub fn screen_size(&self) -> CGSize { 251 | unsafe { CGDisplayScreenSize(self.id) } 252 | } 253 | 254 | /// Returns the serial number of a display monitor. 255 | #[inline] 256 | pub fn serial_number(&self) -> u32 { 257 | unsafe { CGDisplaySerialNumber(self.id) } 258 | } 259 | 260 | /// Returns the logical unit number of a display. 261 | #[inline] 262 | pub fn unit_number(&self) -> u32 { 263 | unsafe { CGDisplayUnitNumber(self.id) } 264 | } 265 | 266 | /// Returns the vendor number of the specified display's monitor. 267 | #[inline] 268 | pub fn vendor_number(&self) -> u32 { 269 | unsafe { CGDisplayVendorNumber(self.id) } 270 | } 271 | 272 | /// Returns the model number of a display monitor. 273 | #[inline] 274 | pub fn model_number(&self) -> u32 { 275 | unsafe { CGDisplayModelNumber(self.id) } 276 | } 277 | 278 | /// Returns the display height in pixel units. 279 | #[inline] 280 | pub fn pixels_high(&self) -> u64 { 281 | unsafe { CGDisplayPixelsHigh(self.id) as u64 } 282 | } 283 | 284 | /// Returns the display width in pixel units. 285 | #[inline] 286 | pub fn pixels_wide(&self) -> u64 { 287 | unsafe { CGDisplayPixelsWide(self.id) as u64 } 288 | } 289 | 290 | /// Provides a list of displays that are active (or drawable). 291 | #[inline] 292 | pub fn active_displays() -> Result, CGError> { 293 | let count = try!(CGDisplay::active_display_count()); 294 | let mut buf: Vec = vec![0; count as usize]; 295 | let result = 296 | unsafe { CGGetActiveDisplayList(count as u32, buf.as_mut_ptr(), ptr::null_mut()) }; 297 | if result == 0 { 298 | Ok(buf) 299 | } else { 300 | Err(result) 301 | } 302 | } 303 | 304 | /// Provides count of displays that are active (or drawable). 305 | #[inline] 306 | pub fn active_display_count() -> Result { 307 | let mut count: libc::uint32_t = 0; 308 | let result = unsafe { CGGetActiveDisplayList(0, ptr::null_mut(), &mut count) }; 309 | if result == 0 { 310 | Ok(count as u32) 311 | } else { 312 | Err(result) 313 | } 314 | } 315 | 316 | /// Hides the mouse cursor, and increments the hide cursor count. 317 | #[inline] 318 | pub fn hide_cursor(&self) -> Result<(), CGError> { 319 | let result = unsafe { CGDisplayHideCursor(self.id) }; 320 | if result == 0 { 321 | Ok(()) 322 | } else { 323 | Err(result) 324 | } 325 | } 326 | 327 | /// Decrements the hide cursor count, and shows the mouse cursor if the 328 | /// count is 0. 329 | #[inline] 330 | pub fn show_cursor(&self) -> Result<(), CGError> { 331 | let result = unsafe { CGDisplayShowCursor(self.id) }; 332 | if result == 0 { 333 | Ok(()) 334 | } else { 335 | Err(result) 336 | } 337 | } 338 | 339 | /// Moves the mouse cursor to a specified point relative to the display 340 | /// origin (the upper-left corner of the display). 341 | #[inline] 342 | pub fn move_cursor_to_point(&self, point: CGPoint) -> Result<(), CGError> { 343 | let result = unsafe { CGDisplayMoveCursorToPoint(self.id, point) }; 344 | if result == 0 { 345 | Ok(()) 346 | } else { 347 | Err(result) 348 | } 349 | } 350 | 351 | /// Moves the mouse cursor without generating events. 352 | #[inline] 353 | pub fn warp_mouse_cursor_position(point: CGPoint) -> Result<(), CGError> { 354 | let result = unsafe { CGWarpMouseCursorPosition(point) }; 355 | if result == 0 { 356 | Ok(()) 357 | } else { 358 | Err(result) 359 | } 360 | } 361 | 362 | /// Connects or disconnects the mouse and cursor while an application is 363 | /// in the foreground. 364 | #[inline] 365 | pub fn associate_mouse_and_mouse_cursor_position(connected: bool) -> Result<(), CGError> { 366 | let result = unsafe { CGAssociateMouseAndMouseCursorPosition(connected as boolean_t) }; 367 | if result == 0 { 368 | Ok(()) 369 | } else { 370 | Err(result) 371 | } 372 | } 373 | } 374 | 375 | impl CGDisplayMode { 376 | #[inline] 377 | pub fn height(&self) -> u64 { 378 | unsafe { CGDisplayModeGetHeight(self.as_ptr()) as u64 } 379 | } 380 | 381 | #[inline] 382 | pub fn width(&self) -> u64 { 383 | unsafe { CGDisplayModeGetWidth(self.as_ptr()) as u64 } 384 | } 385 | 386 | #[inline] 387 | pub fn pixel_height(&self) -> u64 { 388 | unsafe { CGDisplayModeGetPixelHeight(self.as_ptr()) as u64 } 389 | } 390 | 391 | #[inline] 392 | pub fn pixel_width(&self) -> u64 { 393 | unsafe { CGDisplayModeGetPixelWidth(self.as_ptr()) as u64 } 394 | } 395 | 396 | #[inline] 397 | pub fn refresh_rate(&self) -> f64 { 398 | unsafe { CGDisplayModeGetRefreshRate(self.as_ptr()) } 399 | } 400 | } 401 | 402 | #[link(name = "CoreGraphics", kind = "framework")] 403 | extern "C" { 404 | pub static CGRectNull: CGRect; 405 | pub static CGRectInfinite: CGRect; 406 | 407 | pub fn CGDisplayModeRelease(mode: ::sys::CGDisplayModeRef); 408 | 409 | pub fn CGMainDisplayID() -> CGDirectDisplayID; 410 | pub fn CGDisplayIsActive(display: CGDirectDisplayID) -> boolean_t; 411 | pub fn CGDisplayIsAlwaysInMirrorSet(display: CGDirectDisplayID) -> boolean_t; 412 | pub fn CGDisplayIsAsleep(display: CGDirectDisplayID) -> boolean_t; 413 | pub fn CGDisplayIsBuiltin(display: CGDirectDisplayID) -> boolean_t; 414 | pub fn CGDisplayIsInHWMirrorSet(display: CGDirectDisplayID) -> boolean_t; 415 | pub fn CGDisplayIsInMirrorSet(display: CGDirectDisplayID) -> boolean_t; 416 | pub fn CGDisplayIsMain(display: CGDirectDisplayID) -> boolean_t; 417 | pub fn CGDisplayIsOnline(display: CGDirectDisplayID) -> boolean_t; 418 | pub fn CGDisplayIsStereo(display: CGDirectDisplayID) -> boolean_t; 419 | pub fn CGDisplayMirrorsDisplay(display: CGDirectDisplayID) -> CGDirectDisplayID; 420 | pub fn CGDisplayPrimaryDisplay(display: CGDirectDisplayID) -> CGDirectDisplayID; 421 | pub fn CGDisplayRotation(display: CGDirectDisplayID) -> libc::c_double; 422 | pub fn CGDisplayScreenSize(display: CGDirectDisplayID) -> CGSize; 423 | pub fn CGDisplaySerialNumber(display: CGDirectDisplayID) -> libc::uint32_t; 424 | pub fn CGDisplayUnitNumber(display: CGDirectDisplayID) -> libc::uint32_t; 425 | pub fn CGDisplayUsesOpenGLAcceleration(display: CGDirectDisplayID) -> boolean_t; 426 | pub fn CGDisplayVendorNumber(display: CGDirectDisplayID) -> libc::uint32_t; 427 | pub fn CGGetActiveDisplayList( 428 | max_displays: libc::uint32_t, 429 | active_displays: *mut CGDirectDisplayID, 430 | display_count: *mut libc::uint32_t, 431 | ) -> CGError; 432 | pub fn CGDisplayModelNumber(display: CGDirectDisplayID) -> libc::uint32_t; 433 | pub fn CGDisplayPixelsHigh(display: CGDirectDisplayID) -> libc::size_t; 434 | pub fn CGDisplayPixelsWide(display: CGDirectDisplayID) -> libc::size_t; 435 | pub fn CGDisplayBounds(display: CGDirectDisplayID) -> CGRect; 436 | pub fn CGDisplayCreateImage(display: CGDirectDisplayID) -> ::sys::CGImageRef; 437 | 438 | pub fn CGDisplayCopyDisplayMode(display: CGDirectDisplayID) -> ::sys::CGDisplayModeRef; 439 | pub fn CGDisplayModeGetHeight(mode: ::sys::CGDisplayModeRef) -> libc::size_t; 440 | pub fn CGDisplayModeGetWidth(mode: ::sys::CGDisplayModeRef) -> libc::size_t; 441 | pub fn CGDisplayModeGetPixelHeight(mode: ::sys::CGDisplayModeRef) -> libc::size_t; 442 | pub fn CGDisplayModeGetPixelWidth(mode: ::sys::CGDisplayModeRef) -> libc::size_t; 443 | pub fn CGDisplayModeGetRefreshRate(mode: ::sys::CGDisplayModeRef) -> libc::c_double; 444 | 445 | // mouse stuff 446 | pub fn CGDisplayHideCursor(display: CGDirectDisplayID) -> CGError; 447 | pub fn CGDisplayShowCursor(display: CGDirectDisplayID) -> CGError; 448 | pub fn CGDisplayMoveCursorToPoint(display: CGDirectDisplayID, point: CGPoint) -> CGError; 449 | pub fn CGWarpMouseCursorPosition(point: CGPoint) -> CGError; 450 | pub fn CGAssociateMouseAndMouseCursorPosition(connected: boolean_t) -> CGError; 451 | 452 | // Window Services Reference 453 | pub fn CGWindowListCopyWindowInfo( 454 | option: CGWindowListOption, 455 | relativeToWindow: CGWindowID, 456 | ) -> CFArrayRef; 457 | pub fn CGWindowListCreateImage( 458 | screenBounds: CGRect, 459 | listOptions: CGWindowListOption, 460 | windowId: CGWindowID, 461 | imageOptions: CGWindowImageOption, 462 | ) -> ::sys::CGImageRef; 463 | pub fn CGWindowListCreateImageFromArray( 464 | screenBounds: CGRect, 465 | windowArray: CFArrayRef, 466 | imageOptions: CGWindowImageOption, 467 | ) -> ::sys::CGImageRef; 468 | } 469 | -------------------------------------------------------------------------------- /src/event.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_upper_case_globals)] 2 | 3 | use core_foundation::base::{CFRelease, CFRetain, CFTypeID}; 4 | use geometry::CGPoint; 5 | use event_source::CGEventSource; 6 | 7 | use libc; 8 | 9 | use foreign_types::ForeignType; 10 | 11 | pub type CGEventField = libc::uint32_t; 12 | pub type CGKeyCode = libc::uint16_t; 13 | 14 | /// Flags for events 15 | /// 16 | /// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h) 17 | bitflags! { 18 | #[repr(C)] 19 | pub struct CGEventFlags: u64 { 20 | const CGEventFlagNull = 0; 21 | 22 | // Device-independent modifier key bits. 23 | const CGEventFlagAlphaShift = 0x00010000; 24 | const CGEventFlagShift = 0x00020000; 25 | const CGEventFlagControl = 0x00040000; 26 | const CGEventFlagAlternate = 0x00080000; 27 | const CGEventFlagCommand = 0x00100000; 28 | 29 | // Special key identifiers. 30 | const CGEventFlagHelp = 0x00400000; 31 | const CGEventFlagSecondaryFn = 0x00800000; 32 | 33 | // Identifies key events from numeric keypad area on extended keyboards. 34 | const CGEventFlagNumericPad = 0x00200000; 35 | 36 | // Indicates if mouse/pen movement events are not being coalesced 37 | const CGEventFlagNonCoalesced = 0x00000100; 38 | } 39 | } 40 | 41 | /// Key codes for keys that are independent of keyboard layout. 42 | /// 43 | /// [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) 44 | #[repr(C)] 45 | pub struct KeyCode; 46 | impl KeyCode { 47 | pub const RETURN: CGKeyCode = 0x24; 48 | pub const TAB: CGKeyCode = 0x30; 49 | pub const SPACE: CGKeyCode = 0x31; 50 | pub const DELETE: CGKeyCode = 0x33; 51 | pub const ESCAPE: CGKeyCode = 0x35; 52 | pub const COMMAND: CGKeyCode = 0x37; 53 | pub const SHIFT: CGKeyCode = 0x38; 54 | pub const CAPS_LOCK: CGKeyCode = 0x39; 55 | pub const OPTION: CGKeyCode = 0x3A; 56 | pub const CONTROL: CGKeyCode = 0x3B; 57 | pub const RIGHT_COMMAND: CGKeyCode = 0x36; 58 | pub const RIGHT_SHIFT: CGKeyCode = 0x3C; 59 | pub const RIGHT_OPTION: CGKeyCode = 0x3D; 60 | pub const RIGHT_CONTROL: CGKeyCode = 0x3E; 61 | pub const FUNCTION: CGKeyCode = 0x3F; 62 | pub const VOLUME_UP: CGKeyCode = 0x48; 63 | pub const VOLUME_DOWN: CGKeyCode = 0x49; 64 | pub const MUTE: CGKeyCode = 0x4A; 65 | pub const F1: CGKeyCode = 0x7A; 66 | pub const F2: CGKeyCode = 0x78; 67 | pub const F3: CGKeyCode = 0x63; 68 | pub const F4: CGKeyCode = 0x76; 69 | pub const F5: CGKeyCode = 0x60; 70 | pub const F6: CGKeyCode = 0x61; 71 | pub const F7: CGKeyCode = 0x62; 72 | pub const F8: CGKeyCode = 0x64; 73 | pub const F9: CGKeyCode = 0x65; 74 | pub const F10: CGKeyCode = 0x6D; 75 | pub const F11: CGKeyCode = 0x67; 76 | pub const F12: CGKeyCode = 0x6F; 77 | pub const F13: CGKeyCode = 0x69; 78 | pub const F14: CGKeyCode = 0x6B; 79 | pub const F15: CGKeyCode = 0x71; 80 | pub const F16: CGKeyCode = 0x6A; 81 | pub const F17: CGKeyCode = 0x40; 82 | pub const F18: CGKeyCode = 0x4F; 83 | pub const F19: CGKeyCode = 0x50; 84 | pub const F20: CGKeyCode = 0x5A; 85 | pub const HELP: CGKeyCode = 0x72; 86 | pub const HOME: CGKeyCode = 0x73; 87 | pub const PAGE_UP: CGKeyCode = 0x74; 88 | pub const FORWARD_DELETE: CGKeyCode = 0x75; 89 | pub const END: CGKeyCode = 0x77; 90 | pub const PAGE_DOWN: CGKeyCode = 0x79; 91 | pub const LEFT_ARROW: CGKeyCode = 0x7B; 92 | pub const RIGHT_ARROW: CGKeyCode = 0x7C; 93 | pub const DOWN_ARROW: CGKeyCode = 0x7D; 94 | pub const UP_ARROW: CGKeyCode = 0x7E; 95 | } 96 | 97 | /// Constants that specify the different types of input events. 98 | /// 99 | /// [Ref](http://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-700/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h) 100 | #[repr(C)] 101 | #[derive(Clone, Copy, Debug)] 102 | pub enum CGEventType { 103 | Null = 0, 104 | 105 | // Mouse events. 106 | LeftMouseDown = 1, 107 | LeftMouseUp = 2, 108 | RightMouseDown = 3, 109 | RightMouseUp = 4, 110 | MouseMoved = 5, 111 | LeftMouseDragged = 6, 112 | RightMouseDragged = 7, 113 | 114 | // Keyboard events. 115 | KeyDown = 10, 116 | KeyUp = 11, 117 | FlagsChanged = 12, 118 | 119 | // Specialized control devices. 120 | ScrollWheel = 22, 121 | TabletPointer = 23, 122 | TabletProximity = 24, 123 | OtherMouseDown = 25, 124 | OtherMouseUp = 26, 125 | OtherMouseDragged = 27, 126 | 127 | // Out of band event types. These are delivered to the event tap callback 128 | // to notify it of unusual conditions that disable the event tap. 129 | TapDisabledByTimeout = 0xFFFFFFFE, 130 | TapDisabledByUserInput = 0xFFFFFFFF, 131 | } 132 | 133 | /// Constants used as keys to access specialized fields in low-level events. 134 | /// 135 | /// [Ref](https://developer.apple.com/documentation/coregraphics/cgeventfield) 136 | pub struct EventField; 137 | impl EventField { 138 | /// Key to access an integer field that contains the mouse button event 139 | /// number. Matching mouse-down and mouse-up events will have the same 140 | /// event number. 141 | pub const MOUSE_EVENT_NUMBER: CGEventField = 0; 142 | 143 | /// Key to access an integer field that contains the mouse button click 144 | /// state. A click state of 1 represents a single click. A click state of 145 | /// 2 represents a double-click. A click state of 3 represents a 146 | /// triple-click. 147 | pub const MOUSE_EVENT_CLICK_STATE: CGEventField = 1; 148 | 149 | /// Key to access a double field that contains the mouse button pressure. 150 | /// The pressure value may range from 0 to 1, with 0 representing the 151 | /// mouse being up. This value is commonly set by tablet pens mimicking a 152 | /// mouse. 153 | pub const MOUSE_EVENT_PRESSURE: CGEventField = 2; 154 | 155 | /// Key to access an integer field that contains the mouse button number. 156 | pub const MOUSE_EVENT_BUTTON_NUMBER: CGEventField = 3; 157 | 158 | /// Key to access an integer field that contains the horizontal mouse 159 | /// delta since the last mouse movement event. 160 | pub const MOUSE_EVENT_DELTA_X: CGEventField = 4; 161 | 162 | /// Key to access an integer field that contains the vertical mouse delta 163 | /// since the last mouse movement event. 164 | pub const MOUSE_EVENT_DELTA_Y: CGEventField = 5; 165 | 166 | /// Key to access an integer field. The value is non-zero if the event 167 | /// should be ignored by the Inkwell subsystem. 168 | pub const MOUSE_EVENT_INSTANT_MOUSER: CGEventField = 6; 169 | 170 | /// Key to access an integer field that encodes the mouse event subtype as 171 | /// a `kCFNumberIntType'. 172 | pub const MOUSE_EVENT_SUB_TYPE: CGEventField = 7; 173 | 174 | /// Key to access an integer field, non-zero when this is an autorepeat of 175 | /// a key-down, and zero otherwise. 176 | pub const KEYBOARD_EVENT_AUTOREPEAT: CGEventField = 8; 177 | 178 | /// Key to access an integer field that contains the virtual keycode of the 179 | /// key-down or key-up event. 180 | pub const KEYBOARD_EVENT_KEYCODE: CGEventField = 9; 181 | 182 | /// Key to access an integer field that contains the keyboard type 183 | /// identifier. 184 | pub const KEYBOARD_EVENT_KEYBOARD_TYPE: CGEventField = 10; 185 | 186 | /// Key to access an integer field that contains scrolling data. This field 187 | /// typically contains the change in vertical position since the last 188 | /// scrolling event from a Mighty Mouse scroller or a single-wheel mouse 189 | /// scroller. 190 | pub const SCROLL_WHEEL_EVENT_DELTA_AXIS_1: CGEventField = 11; 191 | 192 | /// Key to access an integer field that contains scrolling data. This field 193 | /// typically contains the change in horizontal position since the last 194 | /// scrolling event from a Mighty Mouse scroller. 195 | pub const SCROLL_WHEEL_EVENT_DELTA_AXIS_2: CGEventField = 12; 196 | 197 | /// Key to access a field that contains scrolling data. The scrolling data 198 | /// represents a line-based or pixel-based change in vertical position 199 | /// since the last scrolling event from a Mighty Mouse scroller or a 200 | /// single-wheel mouse scroller. The scrolling data uses a fixed-point 201 | /// 16.16 signed integer format. If this key is passed to 202 | /// `CGEventGetDoubleValueField', the fixed-point value is converted to a 203 | /// double value. 204 | pub const SCROLL_WHEEL_EVENT_FIXED_POINT_DELTA_AXIS_1: CGEventField = 93; 205 | 206 | /// Key to access a field that contains scrolling data. The scrolling data 207 | /// represents a line-based or pixel-based change in horizontal position 208 | /// since the last scrolling event from a Mighty Mouse scroller. The 209 | /// scrolling data uses a fixed-point 16.16 signed integer format. If this 210 | /// key is passed to `CGEventGetDoubleValueField', the fixed-point value is 211 | /// converted to a double value. 212 | pub const SCROLL_WHEEL_EVENT_FIXED_POINT_DELTA_AXIS_2: CGEventField = 94; 213 | 214 | /// Key to access an integer field that contains pixel-based scrolling 215 | /// data. The scrolling data represents the change in vertical position 216 | /// since the last scrolling event from a Mighty Mouse scroller or a 217 | /// single-wheel mouse scroller. 218 | pub const SCROLL_WHEEL_EVENT_POINT_DELTA_AXIS_1: CGEventField = 96; 219 | 220 | /// Key to access an integer field that contains pixel-based scrolling 221 | /// data. The scrolling data represents the change in horizontal position 222 | /// since the last scrolling event from a Mighty Mouse scroller. 223 | pub const SCROLL_WHEEL_EVENT_POINT_DELTA_AXIS_2: CGEventField = 97; 224 | 225 | /// Key to access an integer field that indicates whether the event should 226 | /// be ignored by the Inkwell subsystem. If the value is non-zero, the 227 | /// event should be ignored. 228 | pub const SCROLL_WHEEL_EVENT_INSTANT_MOUSER: CGEventField = 14; 229 | 230 | /// Key to access an integer field that contains the absolute X coordinate 231 | /// in tablet space at full tablet resolution. 232 | pub const TABLET_EVENT_POINT_X: CGEventField = 15; 233 | 234 | /// Key to access an integer field that contains the absolute Y coordinate 235 | /// in tablet space at full tablet resolution. 236 | pub const TABLET_EVENT_POINT_Y: CGEventField = 16; 237 | 238 | /// Key to access an integer field that contains the absolute Z coordinate 239 | /// in tablet space at full tablet resolution. 240 | pub const TABLET_EVENT_POINT_Z: CGEventField = 17; 241 | 242 | /// Key to access an integer field that contains the tablet button state. 243 | /// Bit 0 is the first button, and a set bit represents a closed or pressed 244 | /// button. Up to 16 buttons are supported. 245 | pub const TABLET_EVENT_POINT_BUTTONS: CGEventField = 18; 246 | 247 | /// Key to access a double field that contains the tablet pen pressure. A 248 | /// value of 0.0 represents no pressure, and 1.0 represents maximum 249 | /// pressure. 250 | pub const TABLET_EVENT_POINT_PRESSURE: CGEventField = 19; 251 | 252 | /// Key to access a double field that contains the horizontal tablet pen 253 | /// tilt. A value of 0 represents no tilt, and 1 represents maximum tilt. 254 | pub const TABLET_EVENT_TILT_X: CGEventField = 20; 255 | 256 | /// Key to access a double field that contains the vertical tablet pen 257 | /// tilt. A value of 0 represents no tilt, and 1 represents maximum tilt. 258 | pub const TABLET_EVENT_TILT_Y: CGEventField = 21; 259 | 260 | /// Key to access a double field that contains the tablet pen rotation. 261 | pub const TABLET_EVENT_ROTATION: CGEventField = 22; 262 | 263 | /// Key to access a double field that contains the tangential pressure on 264 | /// the device. A value of 0.0 represents no pressure, and 1.0 represents 265 | /// maximum pressure. 266 | pub const TABLET_EVENT_TANGENTIAL_PRESSURE: CGEventField = 23; 267 | 268 | /// Key to access an integer field that contains the system-assigned unique 269 | /// device ID. 270 | pub const TABLET_EVENT_DEVICE_ID: CGEventField = 24; 271 | 272 | /// Key to access an integer field that contains a vendor-specified value. 273 | pub const TABLET_EVENT_VENDOR_1: CGEventField = 25; 274 | 275 | /// Key to access an integer field that contains a vendor-specified value. 276 | pub const TABLET_EVENT_VENDOR_2: CGEventField = 26; 277 | 278 | /// Key to access an integer field that contains a vendor-specified value. 279 | pub const TABLET_EVENT_VENDOR_3: CGEventField = 27; 280 | 281 | /// Key to access an integer field that contains the vendor-defined ID, 282 | /// typically the USB vendor ID. 283 | pub const TABLET_PROXIMITY_EVENT_VENDOR_ID: CGEventField = 28; 284 | 285 | /// Key to access an integer field that contains the vendor-defined tablet 286 | /// ID, typically the USB product ID. 287 | pub const TABLET_PROXIMITY_EVENT_TABLET_ID: CGEventField = 29; 288 | 289 | /// Key to access an integer field that contains the vendor-defined ID of 290 | /// the pointing device. 291 | pub const TABLET_PROXIMITY_EVENT_POINTER_ID: CGEventField = 30; 292 | 293 | /// Key to access an integer field that contains the system-assigned 294 | /// device ID. 295 | pub const TABLET_PROXIMITY_EVENT_DEVICE_ID: CGEventField = 31; 296 | 297 | /// Key to access an integer field that contains the system-assigned 298 | /// unique tablet ID. 299 | pub const TABLET_PROXIMITY_EVENT_SYSTEM_TABLET_ID: CGEventField = 32; 300 | 301 | /// Key to access an integer field that contains the vendor-assigned 302 | /// pointer type. 303 | pub const TABLET_PROXIMITY_EVENT_VENDOR_POINTER_TYPE: CGEventField = 33; 304 | 305 | /// Key to access an integer field that contains the vendor-defined 306 | /// pointer serial number. 307 | pub const TABLET_PROXIMITY_EVENT_VENDOR_POINTER_SERIAL_NUMBER: CGEventField = 34; 308 | 309 | /// Key to access an integer field that contains the vendor-defined unique 310 | /// ID. 311 | pub const TABLET_PROXIMITY_EVENT_VENDOR_UNIQUE_ID: CGEventField = 35; 312 | 313 | /// Key to access an integer field that contains the device capabilities 314 | /// mask. 315 | pub const TABLET_PROXIMITY_EVENT_CAPABILITY_MASK: CGEventField = 36; 316 | 317 | /// Key to access an integer field that contains the pointer type. 318 | pub const TABLET_PROXIMITY_EVENT_POINTER_TYPE: CGEventField = 37; 319 | 320 | /// Key to access an integer field that indicates whether the pen is in 321 | /// proximity to the tablet. The value is non-zero if the pen is in 322 | /// proximity to the tablet and zero when leaving the tablet. 323 | pub const TABLET_PROXIMITY_EVENT_ENTER_PROXIMITY: CGEventField = 38; 324 | 325 | /// Key to access a field that contains the event target process serial 326 | /// number. The value is a 64-bit value. 327 | pub const EVENT_TARGET_PROCESS_SERIAL_NUMBER: CGEventField = 39; 328 | 329 | /// Key to access a field that contains the event target Unix process ID. 330 | pub const EVENT_TARGET_UNIX_PROCESS_ID: CGEventField = 40; 331 | 332 | /// Key to access a field that contains the event source Unix process ID. 333 | pub const EVENT_SOURCE_UNIX_PROCESS_ID: CGEventField = 41; 334 | 335 | /// Key to access a field that contains the event source user-supplied 336 | /// data, up to 64 bits. 337 | pub const EVENT_SOURCE_USER_DATA: CGEventField = 42; 338 | 339 | /// Key to access a field that contains the event source Unix effective UID. 340 | pub const EVENT_SOURCE_USER_ID: CGEventField = 43; 341 | 342 | /// Key to access a field that contains the event source Unix effective 343 | /// GID. 344 | pub const EVENT_SOURCE_GROUP_ID: CGEventField = 44; 345 | 346 | /// Key to access a field that contains the event source state ID used to 347 | /// create this event. 348 | pub const EVENT_SOURCE_STATE_ID: CGEventField = 45; 349 | 350 | /// Key to access an integer field that indicates whether a scrolling event 351 | /// contains continuous, pixel-based scrolling data. The value is non-zero 352 | /// when the scrolling data is pixel-based and zero when the scrolling data 353 | /// is line-based. 354 | pub const SCROLL_WHEEL_EVENT_IS_CONTINUOUS: CGEventField = 88; 355 | 356 | /// Added in 10.5; made public in 10.7. 357 | pub const MOUSE_EVENT_WINDOW_UNDER_MOUSE_POINTER: CGEventField = 91; 358 | pub const MOUSE_EVENT_WINDOW_UNDER_MOUSE_POINTER_THAT_CAN_HANDLE_THIS_EVENT: CGEventField = 92; 359 | } 360 | 361 | // Constants that specify buttons on a one, two, or three-button mouse. 362 | #[repr(C)] 363 | #[derive(Clone, Copy, Debug)] 364 | pub enum CGMouseButton { 365 | Left, 366 | Right, 367 | Center, 368 | } 369 | 370 | /// Possible tapping points for events. 371 | #[repr(C)] 372 | #[derive(Clone, Copy, Debug)] 373 | pub enum CGEventTapLocation { 374 | HID, 375 | Session, 376 | AnnotatedSession, 377 | } 378 | 379 | foreign_type! { 380 | #[doc(hidden)] 381 | type CType = ::sys::CGEvent; 382 | fn drop = |p| CFRelease(p as *mut _); 383 | fn clone = |p| CFRetain(p as *const _) as *mut _; 384 | pub struct CGEvent; 385 | pub struct CGEventRef; 386 | } 387 | 388 | impl CGEvent { 389 | pub fn type_id() -> CFTypeID { 390 | unsafe { 391 | CGEventGetTypeID() 392 | } 393 | } 394 | 395 | pub fn new(source: CGEventSource) -> Result { 396 | unsafe { 397 | let event_ref = CGEventCreate(source.as_ptr()); 398 | if !event_ref.is_null() { 399 | Ok(Self::from_ptr(event_ref)) 400 | } else { 401 | Err(()) 402 | } 403 | } 404 | } 405 | 406 | pub fn new_keyboard_event( 407 | source: CGEventSource, 408 | keycode: CGKeyCode, 409 | keydown: bool 410 | ) -> Result { 411 | unsafe { 412 | let event_ref = CGEventCreateKeyboardEvent(source.as_ptr(), keycode, keydown); 413 | if !event_ref.is_null() { 414 | Ok(Self::from_ptr(event_ref)) 415 | } else { 416 | Err(()) 417 | } 418 | } 419 | } 420 | 421 | pub fn new_mouse_event( 422 | source: CGEventSource, 423 | mouse_type: CGEventType, 424 | mouse_cursor_position: CGPoint, 425 | mouse_button: CGMouseButton 426 | ) -> Result { 427 | unsafe { 428 | let event_ref = CGEventCreateMouseEvent(source.as_ptr(), mouse_type, 429 | mouse_cursor_position, mouse_button); 430 | if !event_ref.is_null() { 431 | Ok(Self::from_ptr(event_ref)) 432 | } else { 433 | Err(()) 434 | } 435 | } 436 | } 437 | 438 | pub fn post(&self, tap_location: CGEventTapLocation) { 439 | unsafe { 440 | CGEventPost(tap_location, self.as_ptr()); 441 | } 442 | } 443 | 444 | pub fn location(&self) -> CGPoint { 445 | unsafe { 446 | CGEventGetLocation(self.as_ptr()) 447 | } 448 | } 449 | 450 | #[cfg(feature = "elcapitan")] 451 | pub fn post_to_pid(&self, pid: libc::pid_t) { 452 | unsafe { 453 | CGEventPostToPid(pid, self.as_ptr()); 454 | } 455 | } 456 | 457 | pub fn set_flags(&self, flags: CGEventFlags) { 458 | unsafe { 459 | CGEventSetFlags(self.as_ptr(), flags); 460 | } 461 | } 462 | 463 | pub fn get_flags(&self) -> CGEventFlags { 464 | unsafe { 465 | CGEventGetFlags(self.as_ptr()) 466 | } 467 | } 468 | 469 | pub fn set_type(&self, event_type: CGEventType) { 470 | unsafe { 471 | CGEventSetType(self.as_ptr(), event_type); 472 | } 473 | } 474 | 475 | pub fn get_type(&self) -> CGEventType { 476 | unsafe { 477 | CGEventGetType(self.as_ptr()) 478 | } 479 | } 480 | 481 | pub fn set_string_from_utf16_unchecked(&self, buf: &[u16]) { 482 | let buflen = buf.len() as libc::c_ulong; 483 | unsafe { 484 | CGEventKeyboardSetUnicodeString(self.as_ptr(), buflen, buf.as_ptr()); 485 | } 486 | } 487 | 488 | pub fn set_string(&self, string: &str) { 489 | let buf: Vec = string.encode_utf16().collect(); 490 | self.set_string_from_utf16_unchecked(&buf); 491 | } 492 | 493 | pub fn get_integer_value_field(&self, field: CGEventField) -> i64 { 494 | unsafe { CGEventGetIntegerValueField(self.as_ptr(), field) } 495 | } 496 | 497 | pub fn set_integer_value_field(&self, field: CGEventField, value: i64) { 498 | unsafe { CGEventSetIntegerValueField(self.as_ptr(), field, value) } 499 | } 500 | 501 | pub fn get_double_value_field(&self, field: CGEventField) -> f64 { 502 | unsafe { CGEventGetDoubleValueField(self.as_ptr(), field) } 503 | } 504 | 505 | pub fn set_double_value_field(&self, field: CGEventField, value: f64) { 506 | unsafe { CGEventSetDoubleValueField(self.as_ptr(), field, value) } 507 | } 508 | } 509 | 510 | #[link(name = "CoreGraphics", kind = "framework")] 511 | extern { 512 | /// Return the type identifier for the opaque type `CGEventRef'. 513 | fn CGEventGetTypeID() -> CFTypeID; 514 | 515 | /// Return a new event using the event source `source'. If `source' is NULL, 516 | /// the default source is used. 517 | fn CGEventCreate(source: ::sys::CGEventSourceRef) -> ::sys::CGEventRef; 518 | 519 | /// Return a new keyboard event. 520 | /// 521 | /// The event source may be taken from another event, or may be NULL. Based 522 | /// on the virtual key code values entered, the appropriate key down, key up, 523 | /// or flags changed events are generated. 524 | /// 525 | /// All keystrokes needed to generate a character must be entered, including 526 | /// SHIFT, CONTROL, OPTION, and COMMAND keys. For example, to produce a 'Z', 527 | /// the SHIFT key must be down, the 'z' key must go down, and then the SHIFT 528 | /// and 'z' key must be released: 529 | fn CGEventCreateKeyboardEvent(source: ::sys::CGEventSourceRef, keycode: CGKeyCode, 530 | keydown: bool) -> ::sys::CGEventRef; 531 | 532 | /// Return a new mouse event. 533 | /// 534 | /// The event source may be taken from another event, or may be NULL. 535 | /// `mouseType' should be one of the mouse event types. `mouseCursorPosition' 536 | /// should be the position of the mouse cursor in global coordinates. 537 | /// `mouseButton' should be the button that's changing state; `mouseButton' 538 | /// is ignored unless `mouseType' is one of `kCGEventOtherMouseDown', 539 | /// `kCGEventOtherMouseDragged', or `kCGEventOtherMouseUp'. 540 | /// 541 | /// The current implementation of the event system supports a maximum of 542 | /// thirty-two buttons. Mouse button 0 is the primary button on the mouse. 543 | /// Mouse button 1 is the secondary mouse button (right). Mouse button 2 is 544 | /// the center button, and the remaining buttons are in USB device order. 545 | fn CGEventCreateMouseEvent(source: ::sys::CGEventSourceRef, mouseType: CGEventType, 546 | mouseCursorPosition: CGPoint, mouseButton: CGMouseButton) -> ::sys::CGEventRef; 547 | 548 | /// Post an event into the event stream at a specified location. 549 | /// 550 | /// This function posts the specified event immediately before any event taps 551 | /// instantiated for that location, and the event passes through any such 552 | /// taps. 553 | fn CGEventPost(tapLocation: CGEventTapLocation, event: ::sys::CGEventRef); 554 | 555 | #[cfg(feature = "elcapitan")] 556 | /// Post an event to a specified process ID 557 | fn CGEventPostToPid(pid: libc::pid_t, event: ::sys::CGEventRef); 558 | 559 | /// Set the event flags of an event. 560 | fn CGEventSetFlags(event: ::sys::CGEventRef, flags: CGEventFlags); 561 | 562 | /// Return the event flags of an event. 563 | fn CGEventGetFlags(event: ::sys::CGEventRef) -> CGEventFlags; 564 | 565 | /// Return the location of an event in global display coordinates. 566 | /// CGPointZero is returned if event is not a valid ::sys::CGEventRef. 567 | fn CGEventGetLocation(event: ::sys::CGEventRef) -> CGPoint; 568 | 569 | /// Set the event type of an event. 570 | fn CGEventSetType(event: ::sys::CGEventRef, eventType: CGEventType); 571 | 572 | /// Return the event type of an event (left mouse down, for example). 573 | fn CGEventGetType(event: ::sys::CGEventRef) -> CGEventType; 574 | 575 | /// Set the Unicode string associated with a keyboard event. 576 | /// 577 | /// By default, the system translates the virtual key code in a keyboard 578 | /// event into a Unicode string based on the keyboard ID in the event 579 | /// source. This function allows you to manually override this string. 580 | /// Note that application frameworks may ignore the Unicode string in a 581 | /// keyboard event and do their own translation based on the virtual 582 | /// keycode and perceived event state. 583 | fn CGEventKeyboardSetUnicodeString(event: ::sys::CGEventRef, 584 | length: libc::c_ulong, 585 | string: *const u16); 586 | 587 | /// Return the integer value of a field in an event. 588 | fn CGEventGetIntegerValueField(event: ::sys::CGEventRef, field: CGEventField) -> i64; 589 | 590 | /// Set the integer value of a field in an event. 591 | /// 592 | /// Before calling this function, the event type must be set using a typed 593 | /// event creation function such as `CGEventCreateMouseEvent', or by 594 | /// calling `CGEventSetType'. 595 | /// 596 | /// If you are creating a mouse event generated by a tablet, call this 597 | /// function and specify the field `kCGMouseEventSubtype' with a value of 598 | /// `kCGEventMouseSubtypeTabletPoint' or 599 | /// `kCGEventMouseSubtypeTabletProximity' before setting other parameters. 600 | fn CGEventSetIntegerValueField(event: ::sys::CGEventRef, field: CGEventField, value: i64); 601 | 602 | /// Return the floating-point value of a field in an event. 603 | /// 604 | /// In cases where the field value is represented within the event by a fixed 605 | /// point number or an integer, the result is scaled to the appropriate range 606 | /// as part of creating the floating-point representation. 607 | fn CGEventGetDoubleValueField(event: ::sys::CGEventRef, field: CGEventField) -> f64; 608 | 609 | /// Set the floating-point value of a field in an event. 610 | /// 611 | /// Before calling this function, the event type must be set using a typed 612 | /// event creation function such as `CGEventCreateMouseEvent', or by calling 613 | /// `CGEventSetType'. 614 | /// 615 | /// In cases where the field’s value is represented within the event by a 616 | /// fixed point number or integer, the value parameter is scaled as needed 617 | /// and converted to the appropriate type. 618 | fn CGEventSetDoubleValueField(event: ::sys::CGEventRef, field: CGEventField, value: f64); 619 | } 620 | -------------------------------------------------------------------------------- /src/event_source.rs: -------------------------------------------------------------------------------- 1 | use core_foundation::base::{CFRelease, CFRetain, CFTypeID}; 2 | use foreign_types::ForeignType; 3 | 4 | /// Possible source states of an event source. 5 | #[repr(C)] 6 | #[derive(Clone, Copy, Debug)] 7 | pub enum CGEventSourceStateID { 8 | Private = -1, 9 | CombinedSessionState = 0, 10 | HIDSystemState = 1, 11 | } 12 | 13 | foreign_type! { 14 | #[doc(hidden)] 15 | type CType = ::sys::CGEventSource; 16 | fn drop = |p| CFRelease(p as *mut _); 17 | fn clone = |p| CFRetain(p as *const _) as *mut _; 18 | pub struct CGEventSource; 19 | pub struct CGEventSourceRef; 20 | } 21 | 22 | impl CGEventSource { 23 | pub fn type_id() -> CFTypeID { 24 | unsafe { 25 | CGEventSourceGetTypeID() 26 | } 27 | } 28 | 29 | pub fn new(state_id: CGEventSourceStateID) -> Result { 30 | unsafe { 31 | let event_source_ref = CGEventSourceCreate(state_id); 32 | if !event_source_ref.is_null() { 33 | Ok(Self::from_ptr(event_source_ref)) 34 | } else { 35 | Err(()) 36 | } 37 | } 38 | } 39 | } 40 | 41 | #[link(name = "CoreGraphics", kind = "framework")] 42 | extern { 43 | /// Return the type identifier for the opaque type `CGEventSourceRef'. 44 | fn CGEventSourceGetTypeID() -> CFTypeID; 45 | 46 | /// Return a Quartz event source created with a specified source state. 47 | fn CGEventSourceCreate(stateID: CGEventSourceStateID) -> ::sys::CGEventSourceRef; 48 | } 49 | -------------------------------------------------------------------------------- /src/font.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Servo Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution. 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | use std::ptr; 11 | use core_foundation::base::{CFRelease, CFRetain, CFTypeID, TCFType}; 12 | use core_foundation::array::{CFArray, CFArrayRef}; 13 | use core_foundation::data::{CFData, CFDataRef}; 14 | use core_foundation::string::{CFString, CFStringRef}; 15 | use core_foundation::dictionary::{CFDictionary, CFDictionaryRef}; 16 | use data_provider::CGDataProvider; 17 | use geometry::CGRect; 18 | 19 | use foreign_types::ForeignType; 20 | 21 | use libc::{self, c_int, size_t}; 22 | 23 | pub type CGGlyph = libc::c_ushort; 24 | 25 | foreign_type! { 26 | #[doc(hidden)] 27 | type CType = ::sys::CGFont; 28 | fn drop = |p| CFRelease(p as *mut _); 29 | fn clone = |p| CFRetain(p as *const _) as *mut _; 30 | pub struct CGFont; 31 | pub struct CGFontRef; 32 | } 33 | 34 | unsafe impl Send for CGFont {} 35 | unsafe impl Sync for CGFont {} 36 | 37 | impl CGFont { 38 | pub fn type_id() -> CFTypeID { 39 | unsafe { 40 | CGFontGetTypeID() 41 | } 42 | } 43 | 44 | pub fn from_data_provider(provider: CGDataProvider) -> Result { 45 | unsafe { 46 | let font_ref = CGFontCreateWithDataProvider(provider.as_ptr()); 47 | if !font_ref.is_null() { 48 | Ok(CGFont::from_ptr(font_ref)) 49 | } else { 50 | Err(()) 51 | } 52 | } 53 | } 54 | 55 | pub fn from_name(name: &CFString) -> Result { 56 | unsafe { 57 | let font_ref = CGFontCreateWithFontName(name.as_concrete_TypeRef()); 58 | if !font_ref.is_null() { 59 | Ok(CGFont::from_ptr(font_ref)) 60 | } else { 61 | Err(()) 62 | } 63 | } 64 | } 65 | 66 | pub fn create_copy_from_variations(&self, vars: &CFDictionary) -> Result { 67 | unsafe { 68 | let font_ref = CGFontCreateCopyWithVariations(self.as_ptr(), 69 | vars.as_concrete_TypeRef()); 70 | if !font_ref.is_null() { 71 | Ok(CGFont::from_ptr(font_ref)) 72 | } else { 73 | Err(()) 74 | } 75 | } 76 | } 77 | 78 | pub fn postscript_name(&self) -> CFString { 79 | unsafe { 80 | let string_ref = CGFontCopyPostScriptName(self.as_ptr()); 81 | TCFType::wrap_under_create_rule(string_ref) 82 | } 83 | } 84 | 85 | pub fn get_glyph_b_boxes(&self, glyphs: &[CGGlyph], bboxes: &mut [CGRect]) -> bool { 86 | unsafe { 87 | assert!(bboxes.len() >= glyphs.len()); 88 | CGFontGetGlyphBBoxes(self.as_ptr(), 89 | glyphs.as_ptr(), 90 | glyphs.len(), 91 | bboxes.as_mut_ptr()) 92 | } 93 | } 94 | 95 | pub fn get_glyph_advances(&self, glyphs: &[CGGlyph], advances: &mut [c_int]) -> bool { 96 | unsafe { 97 | assert!(advances.len() >= glyphs.len()); 98 | CGFontGetGlyphAdvances(self.as_ptr(), 99 | glyphs.as_ptr(), 100 | glyphs.len(), 101 | advances.as_mut_ptr()) 102 | } 103 | } 104 | 105 | pub fn get_units_per_em(&self) -> c_int { 106 | unsafe { 107 | CGFontGetUnitsPerEm(self.as_ptr()) 108 | } 109 | } 110 | 111 | pub fn copy_table_tags(&self) -> CFArray { 112 | unsafe { 113 | TCFType::wrap_under_create_rule(CGFontCopyTableTags(self.as_ptr())) 114 | } 115 | } 116 | 117 | pub fn copy_table_for_tag(&self, tag: u32) -> Option { 118 | let data_ref = unsafe { CGFontCopyTableForTag(self.as_ptr(), tag) }; 119 | if data_ref != ptr::null() { 120 | Some(unsafe { TCFType::wrap_under_create_rule(data_ref) }) 121 | } else { 122 | None 123 | } 124 | } 125 | } 126 | 127 | #[link(name = "CoreGraphics", kind = "framework")] 128 | extern { 129 | // TODO: basically nothing has bindings (even commented-out) besides what we use. 130 | fn CGFontCreateWithDataProvider(provider: ::sys::CGDataProviderRef) -> ::sys::CGFontRef; 131 | fn CGFontCreateWithFontName(name: CFStringRef) -> ::sys::CGFontRef; 132 | fn CGFontCreateCopyWithVariations(font: ::sys::CGFontRef, vars: CFDictionaryRef) -> ::sys::CGFontRef; 133 | fn CGFontGetTypeID() -> CFTypeID; 134 | 135 | fn CGFontCopyPostScriptName(font: ::sys::CGFontRef) -> CFStringRef; 136 | 137 | // These do the same thing as CFRetain/CFRelease, except 138 | // gracefully handle a NULL argument. We don't use them. 139 | //fn CGFontRetain(font: ::sys::CGFontRef); 140 | //fn CGFontRelease(font: ::sys::CGFontRef); 141 | 142 | fn CGFontGetGlyphBBoxes(font: ::sys::CGFontRef, 143 | glyphs: *const CGGlyph, 144 | count: size_t, 145 | bboxes: *mut CGRect) 146 | -> bool; 147 | fn CGFontGetGlyphAdvances(font: ::sys::CGFontRef, 148 | glyphs: *const CGGlyph, 149 | count: size_t, 150 | advances: *mut c_int) 151 | -> bool; 152 | fn CGFontGetUnitsPerEm(font: ::sys::CGFontRef) -> c_int; 153 | 154 | fn CGFontCopyTableTags(font: ::sys::CGFontRef) -> CFArrayRef; 155 | fn CGFontCopyTableForTag(font: ::sys::CGFontRef, tag: u32) -> CFDataRef; 156 | } 157 | -------------------------------------------------------------------------------- /src/geometry.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Servo Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution. 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | use base::CGFloat; 11 | use core_foundation::base::TCFType; 12 | use core_foundation::dictionary::CFDictionary; 13 | 14 | pub const CG_ZERO_POINT: CGPoint = CGPoint { 15 | x: 0.0, 16 | y: 0.0, 17 | }; 18 | 19 | pub const CG_ZERO_SIZE: CGSize = CGSize { 20 | width: 0.0, 21 | height: 0.0, 22 | }; 23 | 24 | pub const CG_ZERO_RECT: CGRect = CGRect { 25 | origin: CG_ZERO_POINT, 26 | size: CG_ZERO_SIZE, 27 | }; 28 | 29 | pub const CG_AFFINE_TRANSFORM_IDENTITY: CGAffineTransform = CGAffineTransform { 30 | a: 1.0, b: 0.0, 31 | c: 0.0, d: 1.0, 32 | tx: 0.0, ty: 0.0, 33 | }; 34 | 35 | #[repr(C)] 36 | #[derive(Clone, Copy, Debug, Default)] 37 | pub struct CGSize { 38 | pub width: CGFloat, 39 | pub height: CGFloat, 40 | } 41 | 42 | impl CGSize { 43 | #[inline] 44 | pub fn new(width: CGFloat, height: CGFloat) -> CGSize { 45 | CGSize { 46 | width: width, 47 | height: height, 48 | } 49 | } 50 | 51 | #[inline] 52 | pub fn apply_transform(&self, t: &CGAffineTransform) -> CGSize { 53 | unsafe { 54 | ffi::CGSizeApplyAffineTransform(*self, *t) 55 | } 56 | } 57 | } 58 | 59 | #[repr(C)] 60 | #[derive(Clone, Copy, Debug, Default)] 61 | pub struct CGPoint { 62 | pub x: CGFloat, 63 | pub y: CGFloat, 64 | } 65 | 66 | impl CGPoint { 67 | #[inline] 68 | pub fn new(x: CGFloat, y: CGFloat) -> CGPoint { 69 | CGPoint { 70 | x: x, 71 | y: y, 72 | } 73 | } 74 | 75 | #[inline] 76 | pub fn apply_transform(&self, t: &CGAffineTransform) -> CGPoint { 77 | unsafe { 78 | ffi::CGPointApplyAffineTransform(*self, *t) 79 | } 80 | } 81 | } 82 | 83 | #[repr(C)] 84 | #[derive(Clone, Copy, Debug, Default)] 85 | pub struct CGRect { 86 | pub origin: CGPoint, 87 | pub size: CGSize 88 | } 89 | 90 | impl CGRect { 91 | #[inline] 92 | pub fn new(origin: &CGPoint, size: &CGSize) -> CGRect { 93 | CGRect { 94 | origin: *origin, 95 | size: *size, 96 | } 97 | } 98 | 99 | #[inline] 100 | pub fn inset(&self, size: &CGSize) -> CGRect { 101 | unsafe { 102 | ffi::CGRectInset(*self, size.width, size.height) 103 | } 104 | } 105 | 106 | #[inline] 107 | pub fn from_dict_representation(dict: &CFDictionary) -> Option { 108 | let mut rect = CGRect::new(&CGPoint::new(0., 0.), &CGSize::new(0., 0.)); 109 | let result = unsafe { 110 | ffi::CGRectMakeWithDictionaryRepresentation(dict.as_concrete_TypeRef(), &mut rect) 111 | }; 112 | if result == 0 { 113 | None 114 | } else { 115 | Some(rect) 116 | } 117 | } 118 | 119 | #[inline] 120 | pub fn is_empty(&self) -> bool { 121 | unsafe { 122 | // I use one, as it seems that `YES` is not available from this crate. 123 | ffi::CGRectIsEmpty(*self) == 1 124 | } 125 | } 126 | 127 | #[inline] 128 | pub fn is_intersects(&self, other: &CGRect) -> bool { 129 | unsafe { 130 | // I use one, as it seems that `YES` is not available from this crate. 131 | ffi::CGRectIntersectsRect(*self, *other) == 1 132 | } 133 | } 134 | 135 | #[inline] 136 | pub fn apply_transform(&self, t: &CGAffineTransform) -> CGRect { 137 | unsafe { 138 | ffi::CGRectApplyAffineTransform(*self, *t) 139 | } 140 | } 141 | } 142 | 143 | #[repr(C)] 144 | #[derive(Clone, Copy, Debug, Default)] 145 | pub struct CGAffineTransform { 146 | pub a: CGFloat, 147 | pub b: CGFloat, 148 | pub c: CGFloat, 149 | pub d: CGFloat, 150 | pub tx: CGFloat, 151 | pub ty: CGFloat, 152 | } 153 | 154 | impl CGAffineTransform { 155 | #[inline] 156 | pub fn new( 157 | a: CGFloat, 158 | b: CGFloat, 159 | c: CGFloat, 160 | d: CGFloat, 161 | tx: CGFloat, 162 | ty: CGFloat, 163 | ) -> CGAffineTransform { 164 | CGAffineTransform { a, b, c, d, tx, ty } 165 | } 166 | 167 | #[inline] 168 | pub fn invert(&self) -> CGAffineTransform { 169 | unsafe { 170 | ffi::CGAffineTransformInvert(*self) 171 | } 172 | } 173 | } 174 | 175 | mod ffi { 176 | use base::{CGFloat, boolean_t}; 177 | use geometry::{CGAffineTransform, CGPoint, CGRect, CGSize}; 178 | use core_foundation::dictionary::CFDictionaryRef; 179 | 180 | #[link(name = "CoreGraphics", kind = "framework")] 181 | extern { 182 | pub fn CGRectInset(rect: CGRect, dx: CGFloat, dy: CGFloat) -> CGRect; 183 | pub fn CGRectMakeWithDictionaryRepresentation(dict: CFDictionaryRef, 184 | rect: *mut CGRect) -> boolean_t; 185 | pub fn CGRectIsEmpty(rect: CGRect) -> boolean_t; 186 | pub fn CGRectIntersectsRect(rect1: CGRect, rect2: CGRect) -> boolean_t; 187 | 188 | pub fn CGAffineTransformInvert(t: CGAffineTransform) -> CGAffineTransform; 189 | 190 | pub fn CGPointApplyAffineTransform(point: CGPoint, t: CGAffineTransform) -> CGPoint; 191 | pub fn CGRectApplyAffineTransform(rect: CGRect, t: CGAffineTransform) -> CGRect; 192 | pub fn CGSizeApplyAffineTransform(size: CGSize, t: CGAffineTransform) -> CGSize; 193 | } 194 | } 195 | 196 | -------------------------------------------------------------------------------- /src/image.rs: -------------------------------------------------------------------------------- 1 | use core_foundation::base::{CFRetain, CFTypeID}; 2 | use core_foundation::data::CFData; 3 | use color_space::CGColorSpace; 4 | use data_provider::CGDataProviderRef; 5 | use libc::size_t; 6 | use foreign_types::{ForeignType, ForeignTypeRef}; 7 | 8 | #[repr(C)] 9 | pub enum CGImageAlphaInfo { 10 | CGImageAlphaNone, /* For example, RGB. */ 11 | CGImageAlphaPremultipliedLast, /* For example, premultiplied RGBA */ 12 | CGImageAlphaPremultipliedFirst, /* For example, premultiplied ARGB */ 13 | CGImageAlphaLast, /* For example, non-premultiplied RGBA */ 14 | CGImageAlphaFirst, /* For example, non-premultiplied ARGB */ 15 | CGImageAlphaNoneSkipLast, /* For example, RBGX. */ 16 | CGImageAlphaNoneSkipFirst, /* For example, XRBG. */ 17 | CGImageAlphaOnly /* No color data, alpha data only */ 18 | } 19 | 20 | #[repr(C)] 21 | pub enum CGImageByteOrderInfo { 22 | CGImageByteOrderMask = 0x7000, 23 | CGImageByteOrder16Little = (1 << 12), 24 | CGImageByteOrder32Little = (2 << 12), 25 | CGImageByteOrder16Big = (3 << 12), 26 | CGImageByteOrder32Big = (4 << 12) 27 | } 28 | 29 | foreign_type! { 30 | #[doc(hidden)] 31 | type CType = ::sys::CGImage; 32 | fn drop = CGImageRelease; 33 | fn clone = |p| CFRetain(p as *const _) as *mut _; 34 | pub struct CGImage; 35 | pub struct CGImageRef; 36 | } 37 | 38 | impl CGImage { 39 | pub fn type_id() -> CFTypeID { 40 | unsafe { 41 | CGImageGetTypeID() 42 | } 43 | } 44 | } 45 | 46 | impl CGImageRef { 47 | pub fn width(&self) -> size_t { 48 | unsafe { 49 | CGImageGetWidth(self.as_ptr()) 50 | } 51 | } 52 | 53 | pub fn height(&self) -> size_t { 54 | unsafe { 55 | CGImageGetHeight(self.as_ptr()) 56 | } 57 | } 58 | 59 | pub fn bits_per_component(&self) -> size_t { 60 | unsafe { 61 | CGImageGetBitsPerComponent(self.as_ptr()) 62 | } 63 | } 64 | 65 | pub fn bits_per_pixel(&self) -> size_t { 66 | unsafe { 67 | CGImageGetBitsPerPixel(self.as_ptr()) 68 | } 69 | } 70 | 71 | pub fn bytes_per_row(&self) -> size_t { 72 | unsafe { 73 | CGImageGetBytesPerRow(self.as_ptr()) 74 | } 75 | } 76 | 77 | pub fn color_space(&self) -> CGColorSpace { 78 | unsafe { 79 | let cs = CGImageGetColorSpace(self.as_ptr()); 80 | CFRetain(cs as *mut _); 81 | CGColorSpace::from_ptr(cs) 82 | } 83 | } 84 | 85 | /// Returns the raw image bytes wrapped in `CFData`. Note, the returned `CFData` owns the 86 | /// underlying buffer. 87 | pub fn data(&self) -> CFData { 88 | let data_provider = unsafe { 89 | CGDataProviderRef::from_ptr(CGImageGetDataProvider(self.as_ptr())) 90 | }; 91 | data_provider.copy_data() 92 | } 93 | } 94 | 95 | #[link(name = "CoreGraphics", kind = "framework")] 96 | extern { 97 | fn CGImageGetTypeID() -> CFTypeID; 98 | fn CGImageGetWidth(image: ::sys::CGImageRef) -> size_t; 99 | fn CGImageGetHeight(image: ::sys::CGImageRef) -> size_t; 100 | fn CGImageGetBitsPerComponent(image: ::sys::CGImageRef) -> size_t; 101 | fn CGImageGetBitsPerPixel(image: ::sys::CGImageRef) -> size_t; 102 | fn CGImageGetBytesPerRow(image: ::sys::CGImageRef) -> size_t; 103 | fn CGImageGetColorSpace(image: ::sys::CGImageRef) -> ::sys::CGColorSpaceRef; 104 | fn CGImageGetDataProvider(image: ::sys::CGImageRef) -> ::sys::CGDataProviderRef; 105 | fn CGImageRelease(image: ::sys::CGImageRef); 106 | 107 | //fn CGImageGetAlphaInfo(image: ::sys::CGImageRef) -> CGImageAlphaInfo; 108 | //fn CGImageCreateCopyWithColorSpace(image: ::sys::CGImageRef, space: ::sys::CGColorSpaceRef) -> ::sys::CGImageRef 109 | } 110 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Servo Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution. 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | extern crate libc; 11 | extern crate core_foundation; 12 | 13 | #[macro_use] 14 | #[cfg(target_os = "macos")] 15 | extern crate bitflags; 16 | 17 | #[macro_use] 18 | extern crate foreign_types; 19 | 20 | pub mod base; 21 | pub mod color_space; 22 | pub mod context; 23 | pub mod data_provider; 24 | #[cfg(target_os = "macos")] 25 | pub mod display; 26 | #[cfg(target_os = "macos")] 27 | pub mod event; 28 | #[cfg(target_os = "macos")] 29 | pub mod event_source; 30 | pub mod font; 31 | pub mod geometry; 32 | #[cfg(target_os = "macos")] 33 | pub mod private; 34 | pub mod image; 35 | pub mod path; 36 | mod sys; 37 | -------------------------------------------------------------------------------- /src/path.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Servo Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution. 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | use core_foundation::base::{CFRelease, CFRetain, CFTypeID}; 11 | use foreign_types::ForeignType; 12 | use geometry::CGPoint; 13 | use libc::c_void; 14 | use std::fmt::{self, Debug, Formatter}; 15 | use std::marker::PhantomData; 16 | use std::ops::Deref; 17 | use std::slice; 18 | 19 | foreign_type! { 20 | #[doc(hidden)] 21 | type CType = ::sys::CGPath; 22 | fn drop = |p| CFRelease(p as *mut _); 23 | fn clone = |p| CFRetain(p as *const _) as *mut _; 24 | pub struct CGPath; 25 | pub struct CGPathRef; 26 | } 27 | 28 | impl CGPath { 29 | pub fn type_id() -> CFTypeID { 30 | unsafe { 31 | CGPathGetTypeID() 32 | } 33 | } 34 | 35 | pub fn apply<'a, F>(&'a self, mut closure: &'a F) where F: FnMut(CGPathElementRef<'a>) { 36 | unsafe { 37 | CGPathApply(self.as_ptr(), &mut closure as *mut _ as *mut c_void, do_apply::); 38 | } 39 | 40 | unsafe extern "C" fn do_apply<'a, F>(info: *mut c_void, element: *const CGPathElement) 41 | where F: FnMut(CGPathElementRef<'a>) { 42 | let closure = info as *mut *mut F; 43 | (**closure)(CGPathElementRef::new(element)) 44 | } 45 | } 46 | } 47 | 48 | #[repr(i32)] 49 | #[derive(Clone, Copy, Debug, PartialEq)] 50 | pub enum CGPathElementType { 51 | MoveToPoint = 0, 52 | AddLineToPoint = 1, 53 | AddQuadCurveToPoint = 2, 54 | AddCurveToPoint = 3, 55 | CloseSubpath = 4, 56 | } 57 | 58 | pub struct CGPathElementRef<'a> { 59 | element: *const CGPathElement, 60 | phantom: PhantomData<&'a CGPathElement>, 61 | } 62 | 63 | impl<'a> CGPathElementRef<'a> { 64 | fn new<'b>(element: *const CGPathElement) -> CGPathElementRef<'b> { 65 | CGPathElementRef { 66 | element: element, 67 | phantom: PhantomData, 68 | } 69 | } 70 | } 71 | 72 | impl<'a> Deref for CGPathElementRef<'a> { 73 | type Target = CGPathElement; 74 | fn deref(&self) -> &CGPathElement { 75 | unsafe { 76 | &*self.element 77 | } 78 | } 79 | } 80 | 81 | #[repr(C)] 82 | pub struct CGPathElement { 83 | pub element_type: CGPathElementType, 84 | points: *mut CGPoint, 85 | } 86 | 87 | impl Debug for CGPathElement { 88 | fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> { 89 | write!(formatter, "{:?}: {:?}", self.element_type, self.points()) 90 | } 91 | } 92 | 93 | impl CGPathElement { 94 | pub fn points(&self) -> &[CGPoint] { 95 | unsafe { 96 | match self.element_type { 97 | CGPathElementType::CloseSubpath => &[], 98 | CGPathElementType::MoveToPoint | CGPathElementType::AddLineToPoint => { 99 | slice::from_raw_parts(self.points, 1) 100 | } 101 | CGPathElementType::AddQuadCurveToPoint => slice::from_raw_parts(self.points, 2), 102 | CGPathElementType::AddCurveToPoint => slice::from_raw_parts(self.points, 3), 103 | } 104 | } 105 | } 106 | } 107 | 108 | type CGPathApplierFunction = unsafe extern "C" fn(info: *mut c_void, 109 | element: *const CGPathElement); 110 | 111 | #[link(name = "CoreGraphics", kind = "framework")] 112 | extern { 113 | fn CGPathApply(path: ::sys::CGPathRef, info: *mut c_void, function: CGPathApplierFunction); 114 | fn CGPathGetTypeID() -> CFTypeID; 115 | } 116 | -------------------------------------------------------------------------------- /src/private.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Servo Project Developers. See the COPYRIGHT 2 | // file at the top-level directory of this distribution. 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | //! Evil private APIs. 11 | //! 12 | //! These are liable to change at any time. Use with caution! 13 | 14 | use geometry::CGRect; 15 | use libc::{c_int, c_uint}; 16 | use std::ptr; 17 | 18 | pub struct CGSRegion { 19 | region: ffi::CGSRegionRef, 20 | } 21 | 22 | impl Drop for CGSRegion { 23 | fn drop(&mut self) { 24 | unsafe { 25 | ffi::CGSRegionRelease(self.region) 26 | } 27 | } 28 | } 29 | 30 | impl CGSRegion { 31 | #[inline] 32 | pub fn from_rect(rect: &CGRect) -> CGSRegion { 33 | unsafe { 34 | let mut region = ptr::null_mut(); 35 | assert!(ffi::CGSNewRegionWithRect(rect, &mut region) == 0); 36 | CGSRegion { 37 | region: region, 38 | } 39 | } 40 | } 41 | 42 | #[inline] 43 | pub fn from_rects(rects: &[CGRect]) -> CGSRegion { 44 | unsafe { 45 | let mut region = ptr::null_mut(); 46 | assert!(ffi::CGSNewRegionWithRectList(rects.as_ptr(), 47 | rects.len() as c_uint, 48 | &mut region) == 0); 49 | CGSRegion { 50 | region: region, 51 | } 52 | } 53 | } 54 | } 55 | 56 | /// This should always be memory-safe; the window server rejects any invalid surface IDs. 57 | pub struct CGSSurface { 58 | context_id: c_uint, 59 | window_number: c_int, 60 | surface_id: c_uint, 61 | } 62 | 63 | impl CGSSurface { 64 | #[inline] 65 | pub fn from_ids(context_id: c_uint, window_number: c_int, surface_id: c_uint) -> CGSSurface { 66 | CGSSurface { 67 | context_id: context_id, 68 | window_number: window_number, 69 | surface_id: surface_id, 70 | } 71 | } 72 | 73 | #[inline] 74 | pub fn id(&self) -> c_uint { 75 | self.surface_id 76 | } 77 | 78 | #[inline] 79 | pub fn set_shape(&self, region: &CGSRegion) { 80 | unsafe { 81 | assert!(ffi::CGSSetSurfaceShape(self.context_id, 82 | self.window_number, 83 | self.surface_id, 84 | region.region) == 0) 85 | } 86 | } 87 | } 88 | 89 | mod ffi { 90 | use geometry::CGRect; 91 | use libc::{c_int, c_uint}; 92 | 93 | // This is an enum so that we can't easily make instances of this opaque type. 94 | pub enum CGSRegionObject {} 95 | 96 | pub type CGError = OSStatus; 97 | pub type CGSRegionRef = *mut CGSRegionObject; 98 | pub type OSStatus = i32; 99 | 100 | #[link(name = "CoreGraphics", kind = "framework")] 101 | extern { 102 | pub fn CGSRegionRelease(region: CGSRegionRef); 103 | pub fn CGSNewRegionWithRect(rect: *const CGRect, outRegion: *mut CGSRegionRef) -> CGError; 104 | pub fn CGSNewRegionWithRectList(rects: *const CGRect, 105 | rectCount: c_uint, 106 | outRegion: *mut CGSRegionRef) 107 | -> CGError; 108 | 109 | pub fn CGSSetSurfaceShape(contextID: c_uint, 110 | windowNumber: c_int, 111 | surfaceID: c_uint, 112 | region: CGSRegionRef) 113 | -> CGError; 114 | } 115 | } 116 | 117 | -------------------------------------------------------------------------------- /src/sys.rs: -------------------------------------------------------------------------------- 1 | pub enum CGImage {} 2 | pub type CGImageRef = *mut CGImage; 3 | 4 | pub enum CGColorSpace {} 5 | pub type CGColorSpaceRef = *mut CGColorSpace; 6 | 7 | pub enum CGPath {} 8 | pub type CGPathRef = *mut CGPath; 9 | 10 | pub enum CGDataProvider {} 11 | pub type CGDataProviderRef = *mut CGDataProvider; 12 | 13 | pub enum CGFont {} 14 | pub type CGFontRef = *mut CGFont; 15 | 16 | pub enum CGContext {} 17 | pub type CGContextRef = *mut CGContext; 18 | 19 | #[cfg(target_os = "macos")] 20 | mod macos { 21 | pub enum CGEvent {} 22 | pub type CGEventRef = *mut CGEvent; 23 | 24 | pub enum CGEventSource {} 25 | pub type CGEventSourceRef = *mut CGEventSource; 26 | 27 | pub enum CGDisplayMode {} 28 | pub type CGDisplayModeRef = *mut CGDisplayMode; 29 | } 30 | 31 | #[cfg(target_os = "macos")] 32 | pub use self::macos::*; 33 | --------------------------------------------------------------------------------