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 <LICENSE-APACHE or
5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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::{CFTypeID, TCFType};
13 use font::{CGFont, CGGlyph};
14 use geometry::{CGPoint, CGSize};
15 use gradient::{CGGradient, CGGradientDrawingOptions};
16 use color::CGColor;
17 use path::CGPathRef;
18 use libc::{c_int, size_t};
19 use std::os::raw::c_void;
20
21 use std::cmp;
22 use std::ptr;
23 use std::slice;
24 use geometry::{CGAffineTransform, CGRect};
25 use image::CGImage;
26 use foreign_types::{ForeignType, ForeignTypeRef};
27
28 #[repr(C)]
29 #[derive(Clone, Copy, Debug)]
30 pub enum CGBlendMode {
31 Normal = 0,
32 Multiply,
33 Screen,
34 Overlay,
35 Darken,
36 Lighten,
37 ColorDodge,
38 ColorBurn,
39 SoftLight,
40 HardLight,
41 Difference,
42 Exclusion,
43 Hue,
44 Saturation,
45 Color,
46 Luminosity,
47 // 10.5 and up:
48 Clear,
49 Copy,
50 SourceIn,
51 SourceOut,
52 SourceAtop,
53 DestinationOver,
54 DestinationIn,
55 DestinationOut,
56 DestinationAtop,
57 Xor,
58 PlusDarker,
59 PlusLighter,
60 }
61
62 #[repr(C)]
63 pub enum CGTextDrawingMode {
64 CGTextFill,
65 CGTextStroke,
66 CGTextFillStroke,
67 CGTextInvisible,
68 CGTextFillClip,
69 CGTextStrokeClip,
70 CGTextFillStrokeClip,
71 CGTextClip
72 }
73
74 #[repr(C)]
75 #[derive(Clone, Copy, Debug)]
76 pub enum CGLineCap {
77 CGLineCapButt,
78 CGLineCapRound,
79 CGLineCapSquare,
80 }
81
82 #[repr(C)]
83 #[derive(Clone, Copy, Debug)]
84 pub enum CGLineJoin {
85 CGLineJoinMiter,
86 CGLineJoinRound,
87 CGLineJoinBevel,
88 }
89
90 #[repr(C)]
91 #[derive(Clone, Copy, Debug)]
92 pub enum CGPathDrawingMode {
93 CGPathFill,
94 CGPathEOFill,
95 CGPathStroke,
96 CGPathFillStroke,
97 CGPathEOFillStroke,
98 }
99
100 #[repr(C)]
101 #[derive(Clone, Copy, Debug)]
102 pub enum CGInterpolationQuality {
103 CGInterpolationQualityDefault,
104 CGInterpolationQualityNone,
105 CGInterpolationQualityLow,
106 CGInterpolationQualityMedium,
107 CGInterpolationQualityHigh,
108 }
109
110 foreign_type! {
111 #[doc(hidden)]
112 type CType = ::sys::CGContext;
113 fn drop = |cs| CGContextRelease(cs);
114 fn clone = |p| CGContextRetain(p);
115 pub struct CGContext;
116 pub struct CGContextRef;
117 }
118
119 impl CGContext {
type_id() -> CFTypeID120 pub fn type_id() -> CFTypeID {
121 unsafe {
122 CGContextGetTypeID()
123 }
124 }
125
126 /// Creates a `CGContext` instance from an existing [`CGContextRef`] pointer.
127 ///
128 /// This funtion will internally call [`CGRetain`] and hence there is no need to call it explicitly.
129 ///
130 /// This function is particularly useful for cases when the context is not instantiated/managed
131 /// by the caller, but it's retrieve via other means (e.g., by calling the method [`NSGraphicsContext::CGContext`]
132 /// in a cocoa application).
133 ///
134 /// [`CGContextRef`]: https://developer.apple.com/documentation/coregraphics/cgcontextref
135 /// [`CGRetain`]: https://developer.apple.com/documentation/coregraphics/1586506-cgcontextretain
136 /// [`NSGraphicsContext::CGContext`]: https://developer.apple.com/documentation/appkit/nsgraphicscontext/1535352-currentcontext
from_existing_context_ptr(ctx: *mut ::sys::CGContext) -> CGContext137 pub unsafe fn from_existing_context_ptr(ctx: *mut ::sys::CGContext) -> CGContext {
138 CGContextRetain(ctx);
139 Self::from_ptr(ctx)
140 }
141
create_bitmap_context(data: Option<*mut c_void>, width: size_t, height: size_t, bits_per_component: size_t, bytes_per_row: size_t, space: &CGColorSpace, bitmap_info: u32) -> CGContext142 pub fn create_bitmap_context(data: Option<*mut c_void>,
143 width: size_t,
144 height: size_t,
145 bits_per_component: size_t,
146 bytes_per_row: size_t,
147 space: &CGColorSpace,
148 bitmap_info: u32)
149 -> CGContext {
150 unsafe {
151 let result = CGBitmapContextCreate(data.unwrap_or(ptr::null_mut()),
152 width,
153 height,
154 bits_per_component,
155 bytes_per_row,
156 space.as_ptr(),
157 bitmap_info);
158 assert!(!result.is_null());
159 Self::from_ptr(result)
160 }
161 }
162
data(&mut self) -> &mut [u8]163 pub fn data(&mut self) -> &mut [u8] {
164 unsafe {
165 slice::from_raw_parts_mut(
166 CGBitmapContextGetData(self.as_ptr()) as *mut u8,
167 (self.height() * self.bytes_per_row()) as usize)
168 }
169 }
170 }
171
172 impl CGContextRef {
flush(&self)173 pub fn flush(&self) {
174 unsafe {
175 CGContextFlush(self.as_ptr())
176 }
177 }
178
width(&self) -> size_t179 pub fn width(&self) -> size_t {
180 unsafe {
181 CGBitmapContextGetWidth(self.as_ptr())
182 }
183 }
184
height(&self) -> size_t185 pub fn height(&self) -> size_t {
186 unsafe {
187 CGBitmapContextGetHeight(self.as_ptr())
188 }
189 }
190
bytes_per_row(&self) -> size_t191 pub fn bytes_per_row(&self) -> size_t {
192 unsafe {
193 CGBitmapContextGetBytesPerRow(self.as_ptr())
194 }
195 }
196
clip_bounding_box(&self) -> CGRect197 pub fn clip_bounding_box(&self) -> CGRect {
198 unsafe {
199 CGContextGetClipBoundingBox(self.as_ptr())
200 }
201 }
202
set_fill_color(&self, color: &CGColor)203 pub fn set_fill_color(&self, color: &CGColor) {
204 unsafe {
205 CGContextSetFillColorWithColor(self.as_ptr(), color.as_concrete_TypeRef());
206 }
207 }
208
set_rgb_fill_color(&self, red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)209 pub fn set_rgb_fill_color(&self, red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
210 unsafe {
211 CGContextSetRGBFillColor(self.as_ptr(), red, green, blue, alpha)
212 }
213 }
214
set_rgb_stroke_color(&self, red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)215 pub fn set_rgb_stroke_color(&self, red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
216 unsafe {
217 CGContextSetRGBStrokeColor(self.as_ptr(), red, green, blue, alpha)
218 }
219 }
220
set_gray_fill_color(&self, gray: CGFloat, alpha: CGFloat)221 pub fn set_gray_fill_color(&self, gray: CGFloat, alpha: CGFloat) {
222 unsafe {
223 CGContextSetGrayFillColor(self.as_ptr(), gray, alpha)
224 }
225 }
226
set_blend_mode(&self, blend_mode: CGBlendMode)227 pub fn set_blend_mode(&self, blend_mode: CGBlendMode) {
228 unsafe {
229 CGContextSetBlendMode(self.as_ptr(), blend_mode)
230 }
231 }
232
set_allows_font_smoothing(&self, allows_font_smoothing: bool)233 pub fn set_allows_font_smoothing(&self, allows_font_smoothing: bool) {
234 unsafe {
235 CGContextSetAllowsFontSmoothing(self.as_ptr(), allows_font_smoothing)
236 }
237 }
238
set_font_smoothing_style(&self, style: i32)239 pub fn set_font_smoothing_style(&self, style: i32) {
240 unsafe {
241 CGContextSetFontSmoothingStyle(self.as_ptr(), style as _);
242 }
243 }
244
set_should_smooth_fonts(&self, should_smooth_fonts: bool)245 pub fn set_should_smooth_fonts(&self, should_smooth_fonts: bool) {
246 unsafe {
247 CGContextSetShouldSmoothFonts(self.as_ptr(), should_smooth_fonts)
248 }
249 }
250
set_allows_antialiasing(&self, allows_antialiasing: bool)251 pub fn set_allows_antialiasing(&self, allows_antialiasing: bool) {
252 unsafe {
253 CGContextSetAllowsAntialiasing(self.as_ptr(), allows_antialiasing)
254 }
255 }
256
set_should_antialias(&self, should_antialias: bool)257 pub fn set_should_antialias(&self, should_antialias: bool) {
258 unsafe {
259 CGContextSetShouldAntialias(self.as_ptr(), should_antialias)
260 }
261 }
262
set_allows_font_subpixel_quantization(&self, allows_font_subpixel_quantization: bool)263 pub fn set_allows_font_subpixel_quantization(&self, allows_font_subpixel_quantization: bool) {
264 unsafe {
265 CGContextSetAllowsFontSubpixelQuantization(self.as_ptr(), allows_font_subpixel_quantization)
266 }
267 }
268
set_should_subpixel_quantize_fonts(&self, should_subpixel_quantize_fonts: bool)269 pub fn set_should_subpixel_quantize_fonts(&self, should_subpixel_quantize_fonts: bool) {
270 unsafe {
271 CGContextSetShouldSubpixelQuantizeFonts(self.as_ptr(), should_subpixel_quantize_fonts)
272 }
273 }
274
set_allows_font_subpixel_positioning(&self, allows_font_subpixel_positioning: bool)275 pub fn set_allows_font_subpixel_positioning(&self, allows_font_subpixel_positioning: bool) {
276 unsafe {
277 CGContextSetAllowsFontSubpixelPositioning(self.as_ptr(), allows_font_subpixel_positioning)
278 }
279 }
280
set_should_subpixel_position_fonts(&self, should_subpixel_position_fonts: bool)281 pub fn set_should_subpixel_position_fonts(&self, should_subpixel_position_fonts: bool) {
282 unsafe {
283 CGContextSetShouldSubpixelPositionFonts(self.as_ptr(), should_subpixel_position_fonts)
284 }
285 }
286
set_text_drawing_mode(&self, mode: CGTextDrawingMode)287 pub fn set_text_drawing_mode(&self, mode: CGTextDrawingMode) {
288 unsafe {
289 CGContextSetTextDrawingMode(self.as_ptr(), mode)
290 }
291 }
292
set_line_cap(&self, cap: CGLineCap)293 pub fn set_line_cap(&self, cap: CGLineCap) {
294 unsafe {
295 CGContextSetLineCap(self.as_ptr(), cap)
296 }
297 }
298
set_line_dash(&self, phase: CGFloat, lengths: &[CGFloat])299 pub fn set_line_dash(&self, phase: CGFloat, lengths: &[CGFloat]) {
300 unsafe {
301 CGContextSetLineDash(self.as_ptr(), phase, lengths.as_ptr(), lengths.len())
302 }
303 }
304
set_line_join(&self, join: CGLineJoin)305 pub fn set_line_join(&self, join: CGLineJoin) {
306 unsafe {
307 CGContextSetLineJoin(self.as_ptr(), join)
308 }
309 }
310
set_line_width(&self, width: CGFloat)311 pub fn set_line_width(&self, width: CGFloat) {
312 unsafe {
313 CGContextSetLineWidth(self.as_ptr(), width)
314 }
315 }
316
set_miter_limit(&self, limit: CGFloat)317 pub fn set_miter_limit(&self, limit: CGFloat) {
318 unsafe {
319 CGContextSetMiterLimit(self.as_ptr(), limit)
320 }
321 }
322
add_path(&self, path: &CGPathRef)323 pub fn add_path(&self, path: &CGPathRef) {
324 unsafe {
325 CGContextAddPath(self.as_ptr(), path.as_ptr());
326 }
327 }
328
add_curve_to_point(&self, cp1x: CGFloat, cp1y: CGFloat, cp2x: CGFloat, cp2y: CGFloat, x: CGFloat, y: CGFloat)329 pub fn add_curve_to_point(&self,
330 cp1x: CGFloat,
331 cp1y: CGFloat,
332 cp2x: CGFloat,
333 cp2y: CGFloat,
334 x: CGFloat,
335 y: CGFloat) {
336 unsafe {
337 CGContextAddCurveToPoint(self.as_ptr(),
338 cp1x, cp1y,
339 cp2x, cp2y,
340 x, y);
341 }
342 }
343
add_quad_curve_to_point(&self, cpx: CGFloat, cpy: CGFloat, x: CGFloat, y: CGFloat)344 pub fn add_quad_curve_to_point(&self,
345 cpx: CGFloat,
346 cpy: CGFloat,
347 x: CGFloat,
348 y: CGFloat) {
349 unsafe {
350 CGContextAddQuadCurveToPoint(self.as_ptr(),
351 cpx, cpy,
352 x, y);
353 }
354 }
355
add_line_to_point(&self, x: CGFloat, y: CGFloat)356 pub fn add_line_to_point(&self, x: CGFloat, y: CGFloat) {
357 unsafe {
358 CGContextAddLineToPoint(self.as_ptr(), x, y);
359 }
360 }
361
begin_path(&self)362 pub fn begin_path(&self) {
363 unsafe {
364 CGContextBeginPath(self.as_ptr());
365 }
366 }
367
close_path(&self)368 pub fn close_path(&self) {
369 unsafe {
370 CGContextClosePath(self.as_ptr());
371 }
372 }
373
move_to_point(&self, x: CGFloat, y: CGFloat)374 pub fn move_to_point(&self, x: CGFloat, y: CGFloat) {
375 unsafe {
376 CGContextMoveToPoint(self.as_ptr(), x, y);
377 }
378 }
379
clip(&self)380 pub fn clip(&self) {
381 unsafe {
382 CGContextClip(self.as_ptr());
383 }
384 }
385
eo_clip(&self)386 pub fn eo_clip(&self) {
387 unsafe {
388 CGContextEOClip(self.as_ptr());
389 }
390 }
391
draw_path(&self, mode: CGPathDrawingMode)392 pub fn draw_path(&self, mode: CGPathDrawingMode) {
393 unsafe {
394 CGContextDrawPath(self.as_ptr(), mode);
395 }
396 }
397
fill_path(&self)398 pub fn fill_path(&self) {
399 unsafe {
400 CGContextFillPath(self.as_ptr());
401 }
402 }
403
eo_fill_path(&self)404 pub fn eo_fill_path(&self) {
405 unsafe {
406 CGContextEOFillPath(self.as_ptr());
407 }
408 }
409
stroke_path(&self)410 pub fn stroke_path(&self) {
411 unsafe {
412 CGContextStrokePath(self.as_ptr());
413 }
414 }
415
fill_rect(&self, rect: CGRect)416 pub fn fill_rect(&self, rect: CGRect) {
417 unsafe {
418 CGContextFillRect(self.as_ptr(), rect)
419 }
420 }
421
fill_rects(&self, rects: &[CGRect])422 pub fn fill_rects(&self, rects: &[CGRect]) {
423 unsafe {
424 CGContextFillRects(self.as_ptr(), rects.as_ptr(), rects.len())
425 }
426 }
427
clear_rect(&self, rect: CGRect)428 pub fn clear_rect(&self, rect: CGRect) {
429 unsafe {
430 CGContextClearRect(self.as_ptr(), rect)
431 }
432 }
433
stroke_rect(&self, rect: CGRect)434 pub fn stroke_rect(&self, rect: CGRect) {
435 unsafe {
436 CGContextStrokeRect(self.as_ptr(), rect)
437 }
438 }
439
stroke_rect_with_width(&self, rect: CGRect, width: CGFloat)440 pub fn stroke_rect_with_width(&self, rect: CGRect, width: CGFloat) {
441 unsafe {
442 CGContextStrokeRectWithWidth(self.as_ptr(), rect, width)
443 }
444 }
445
clip_to_rect(&self, rect: CGRect)446 pub fn clip_to_rect(&self, rect: CGRect) {
447 unsafe {
448 CGContextClipToRect(self.as_ptr(), rect)
449 }
450 }
451
clip_to_rects(&self, rects: &[CGRect])452 pub fn clip_to_rects(&self, rects: &[CGRect]) {
453 unsafe {
454 CGContextClipToRects(self.as_ptr(), rects.as_ptr(), rects.len())
455 }
456 }
457
clip_to_mask(&self, rect: CGRect, image: &CGImage)458 pub fn clip_to_mask(&self, rect: CGRect, image: &CGImage) {
459 unsafe {
460 CGContextClipToMask(self.as_ptr(), rect, image.as_ptr())
461 }
462 }
463
replace_path_with_stroked_path(&self)464 pub fn replace_path_with_stroked_path(&self) {
465 unsafe {
466 CGContextReplacePathWithStrokedPath(self.as_ptr())
467 }
468 }
469
fill_ellipse_in_rect(&self, rect: CGRect)470 pub fn fill_ellipse_in_rect(&self, rect: CGRect) {
471 unsafe {
472 CGContextFillEllipseInRect(self.as_ptr(), rect)
473 }
474 }
475
stroke_ellipse_in_rect(&self, rect: CGRect)476 pub fn stroke_ellipse_in_rect(&self, rect: CGRect) {
477 unsafe {
478 CGContextStrokeEllipseInRect(self.as_ptr(), rect)
479 }
480 }
481
stroke_line_segments(&self, points: &[CGPoint])482 pub fn stroke_line_segments(&self, points: &[CGPoint]) {
483 unsafe {
484 CGContextStrokeLineSegments(self.as_ptr(), points.as_ptr(), points.len())
485 }
486 }
487
set_interpolation_quality(&self, quality: CGInterpolationQuality)488 pub fn set_interpolation_quality(&self, quality: CGInterpolationQuality) {
489 unsafe {
490 CGContextSetInterpolationQuality(self.as_ptr(), quality);
491 }
492 }
493
get_interpolation_quality(&self) -> CGInterpolationQuality494 pub fn get_interpolation_quality(&self) -> CGInterpolationQuality {
495 unsafe {
496 CGContextGetInterpolationQuality(self.as_ptr())
497
498 }
499 }
500
draw_image(&self, rect: CGRect, image: &CGImage)501 pub fn draw_image(&self, rect: CGRect, image: &CGImage) {
502 unsafe {
503 CGContextDrawImage(self.as_ptr(), rect, image.as_ptr());
504 }
505 }
506
create_image(&self) -> Option<CGImage>507 pub fn create_image(&self) -> Option<CGImage> {
508 let image = unsafe { CGBitmapContextCreateImage(self.as_ptr()) };
509 if !image.is_null() {
510 Some(unsafe { CGImage::from_ptr(image) })
511 } else {
512 None
513 }
514 }
515
set_font(&self, font: &CGFont)516 pub fn set_font(&self, font: &CGFont) {
517 unsafe {
518 CGContextSetFont(self.as_ptr(), font.as_ptr())
519 }
520 }
521
set_font_size(&self, size: CGFloat)522 pub fn set_font_size(&self, size: CGFloat) {
523 unsafe {
524 CGContextSetFontSize(self.as_ptr(), size)
525 }
526 }
527
set_text_matrix(&self, t: &CGAffineTransform)528 pub fn set_text_matrix(&self, t: &CGAffineTransform) {
529 unsafe {
530 CGContextSetTextMatrix(self.as_ptr(), *t)
531 }
532 }
533
set_text_position(&self, x: CGFloat, y: CGFloat)534 pub fn set_text_position(&self, x: CGFloat, y: CGFloat) {
535 unsafe {
536 CGContextSetTextPosition(self.as_ptr(), x, y)
537 }
538 }
539
show_glyphs_at_positions(&self, glyphs: &[CGGlyph], positions: &[CGPoint])540 pub fn show_glyphs_at_positions(&self, glyphs: &[CGGlyph], positions: &[CGPoint]) {
541 unsafe {
542 let count = cmp::min(glyphs.len(), positions.len());
543 CGContextShowGlyphsAtPositions(self.as_ptr(),
544 glyphs.as_ptr(),
545 positions.as_ptr(),
546 count)
547 }
548 }
549
save(&self)550 pub fn save(&self) {
551 unsafe {
552 CGContextSaveGState(self.as_ptr());
553 }
554 }
555
restore(&self)556 pub fn restore(&self) {
557 unsafe {
558 CGContextRestoreGState(self.as_ptr());
559 }
560 }
561
translate(&self, tx: CGFloat, ty: CGFloat)562 pub fn translate(&self, tx: CGFloat, ty: CGFloat) {
563 unsafe {
564 CGContextTranslateCTM(self.as_ptr(), tx, ty);
565 }
566 }
567
scale(&self, sx: CGFloat, sy: CGFloat)568 pub fn scale(&self, sx: CGFloat, sy: CGFloat) {
569 unsafe {
570 CGContextScaleCTM(self.as_ptr(), sx, sy);
571 }
572 }
573
rotate(&self, angle: CGFloat)574 pub fn rotate(&self, angle: CGFloat) {
575 unsafe {
576 CGContextRotateCTM(self.as_ptr(), angle);
577 }
578 }
579
get_ctm(&self) -> CGAffineTransform580 pub fn get_ctm(&self) -> CGAffineTransform {
581 unsafe {
582 CGContextGetCTM(self.as_ptr())
583 }
584 }
585
concat_ctm(&self, transform: CGAffineTransform)586 pub fn concat_ctm(&self, transform: CGAffineTransform) {
587 unsafe {
588 CGContextConcatCTM(self.as_ptr(), transform)
589 }
590 }
591
draw_linear_gradient(&self, gradient: &CGGradient, start_point: CGPoint, end_point: CGPoint, options: CGGradientDrawingOptions)592 pub fn draw_linear_gradient(&self, gradient: &CGGradient, start_point: CGPoint, end_point: CGPoint, options: CGGradientDrawingOptions) {
593 unsafe {
594 CGContextDrawLinearGradient(self.as_ptr(), gradient.as_ptr(), start_point, end_point, options);
595 }
596 }
597
draw_radial_gradient(&self, gradient: &CGGradient, start_center: CGPoint, start_radius: CGFloat, end_center: CGPoint, end_radius: CGFloat, options: CGGradientDrawingOptions)598 pub fn draw_radial_gradient(&self, gradient: &CGGradient, start_center: CGPoint, start_radius: CGFloat, end_center: CGPoint, end_radius: CGFloat, options: CGGradientDrawingOptions) {
599 unsafe {
600 CGContextDrawRadialGradient(self.as_ptr(), gradient.as_ptr(), start_center, start_radius, end_center, end_radius, options);
601 }
602 }
603
set_shadow(&self, offset: CGSize, blur: CGFloat)604 pub fn set_shadow(&self, offset: CGSize, blur: CGFloat) {
605 unsafe {
606 CGContextSetShadow(self.as_ptr(), offset, blur);
607 }
608 }
609
set_shadow_with_color(&self, offset: CGSize, blur: CGFloat, color: &CGColor)610 pub fn set_shadow_with_color(&self, offset: CGSize, blur: CGFloat, color: &CGColor) {
611 unsafe {
612 CGContextSetShadowWithColor(self.as_ptr(), offset, blur, color.as_concrete_TypeRef());
613 }
614 }
615 }
616
617 #[test]
create_bitmap_context_test()618 fn create_bitmap_context_test() {
619 use geometry::*;
620
621 let cs = CGColorSpace::create_device_rgb();
622 let ctx = CGContext::create_bitmap_context(None,
623 16, 8,
624 8, 0,
625 &cs,
626 ::base::kCGImageAlphaPremultipliedLast);
627 ctx.set_rgb_fill_color(1.,0.,1.,1.);
628 ctx.set_miter_limit(4.);
629 ctx.fill_rect(CGRect::new(&CGPoint::new(0.,0.), &CGSize::new(8.,8.)));
630 let img = ctx.create_image().unwrap();
631 assert_eq!(16, img.width());
632 assert_eq!(8, img.height());
633 assert_eq!(8, img.bits_per_component());
634 assert_eq!(32, img.bits_per_pixel());
635 let data = img.data();
636 assert_eq!(255, data.bytes()[0]);
637 assert_eq!(0, data.bytes()[1]);
638 assert_eq!(255, data.bytes()[2]);
639 assert_eq!(255, data.bytes()[3]);
640 }
641
642 #[link(name = "CoreGraphics", kind = "framework")]
643 extern {
CGContextRetain(c: ::sys::CGContextRef) -> ::sys::CGContextRef644 fn CGContextRetain(c: ::sys::CGContextRef) -> ::sys::CGContextRef;
CGContextRelease(c: ::sys::CGContextRef)645 fn CGContextRelease(c: ::sys::CGContextRef);
646
CGBitmapContextCreate(data: *mut c_void, width: size_t, height: size_t, bitsPerComponent: size_t, bytesPerRow: size_t, space: ::sys::CGColorSpaceRef, bitmapInfo: u32) -> ::sys::CGContextRef647 fn CGBitmapContextCreate(data: *mut c_void,
648 width: size_t,
649 height: size_t,
650 bitsPerComponent: size_t,
651 bytesPerRow: size_t,
652 space: ::sys::CGColorSpaceRef,
653 bitmapInfo: u32)
654 -> ::sys::CGContextRef;
CGBitmapContextGetData(context: ::sys::CGContextRef) -> *mut c_void655 fn CGBitmapContextGetData(context: ::sys::CGContextRef) -> *mut c_void;
CGBitmapContextGetWidth(context: ::sys::CGContextRef) -> size_t656 fn CGBitmapContextGetWidth(context: ::sys::CGContextRef) -> size_t;
CGBitmapContextGetHeight(context: ::sys::CGContextRef) -> size_t657 fn CGBitmapContextGetHeight(context: ::sys::CGContextRef) -> size_t;
CGBitmapContextGetBytesPerRow(context: ::sys::CGContextRef) -> size_t658 fn CGBitmapContextGetBytesPerRow(context: ::sys::CGContextRef) -> size_t;
CGBitmapContextCreateImage(context: ::sys::CGContextRef) -> ::sys::CGImageRef659 fn CGBitmapContextCreateImage(context: ::sys::CGContextRef) -> ::sys::CGImageRef;
CGContextGetTypeID() -> CFTypeID660 fn CGContextGetTypeID() -> CFTypeID;
CGContextGetClipBoundingBox(c: ::sys::CGContextRef) -> CGRect661 fn CGContextGetClipBoundingBox(c: ::sys::CGContextRef) -> CGRect;
CGContextFlush(c: ::sys::CGContextRef)662 fn CGContextFlush(c: ::sys::CGContextRef);
CGContextSetBlendMode(c: ::sys::CGContextRef, blendMode: CGBlendMode)663 fn CGContextSetBlendMode(c: ::sys::CGContextRef, blendMode: CGBlendMode);
CGContextSetAllowsFontSmoothing(c: ::sys::CGContextRef, allowsFontSmoothing: bool)664 fn CGContextSetAllowsFontSmoothing(c: ::sys::CGContextRef, allowsFontSmoothing: bool);
CGContextSetShouldSmoothFonts(c: ::sys::CGContextRef, shouldSmoothFonts: bool)665 fn CGContextSetShouldSmoothFonts(c: ::sys::CGContextRef, shouldSmoothFonts: bool);
CGContextSetFontSmoothingStyle(c: ::sys::CGContextRef, style: c_int)666 fn CGContextSetFontSmoothingStyle(c: ::sys::CGContextRef, style: c_int);
CGContextSetAllowsAntialiasing(c: ::sys::CGContextRef, allowsAntialiasing: bool)667 fn CGContextSetAllowsAntialiasing(c: ::sys::CGContextRef, allowsAntialiasing: bool);
CGContextSetShouldAntialias(c: ::sys::CGContextRef, shouldAntialias: bool)668 fn CGContextSetShouldAntialias(c: ::sys::CGContextRef, shouldAntialias: bool);
CGContextSetAllowsFontSubpixelQuantization(c: ::sys::CGContextRef, allowsFontSubpixelQuantization: bool)669 fn CGContextSetAllowsFontSubpixelQuantization(c: ::sys::CGContextRef,
670 allowsFontSubpixelQuantization: bool);
CGContextSetShouldSubpixelQuantizeFonts(c: ::sys::CGContextRef, shouldSubpixelQuantizeFonts: bool)671 fn CGContextSetShouldSubpixelQuantizeFonts(c: ::sys::CGContextRef,
672 shouldSubpixelQuantizeFonts: bool);
CGContextSetAllowsFontSubpixelPositioning(c: ::sys::CGContextRef, allowsFontSubpixelPositioning: bool)673 fn CGContextSetAllowsFontSubpixelPositioning(c: ::sys::CGContextRef,
674 allowsFontSubpixelPositioning: bool);
CGContextSetShouldSubpixelPositionFonts(c: ::sys::CGContextRef, shouldSubpixelPositionFonts: bool)675 fn CGContextSetShouldSubpixelPositionFonts(c: ::sys::CGContextRef,
676 shouldSubpixelPositionFonts: bool);
CGContextSetTextDrawingMode(c: ::sys::CGContextRef, mode: CGTextDrawingMode)677 fn CGContextSetTextDrawingMode(c: ::sys::CGContextRef, mode: CGTextDrawingMode);
CGContextSetFillColorWithColor(c: ::sys::CGContextRef, color: ::sys::CGColorRef)678 fn CGContextSetFillColorWithColor(c: ::sys::CGContextRef, color: ::sys::CGColorRef);
CGContextSetLineCap(c: ::sys::CGContextRef, cap: CGLineCap)679 fn CGContextSetLineCap(c: ::sys::CGContextRef, cap: CGLineCap);
CGContextSetLineDash(c: ::sys::CGContextRef, phase: CGFloat, lengths: *const CGFloat, count: size_t)680 fn CGContextSetLineDash(c: ::sys::CGContextRef, phase: CGFloat, lengths: *const CGFloat, count: size_t);
CGContextSetLineJoin(c: ::sys::CGContextRef, join: CGLineJoin)681 fn CGContextSetLineJoin(c: ::sys::CGContextRef, join: CGLineJoin);
CGContextSetLineWidth(c: ::sys::CGContextRef, width: CGFloat)682 fn CGContextSetLineWidth(c: ::sys::CGContextRef, width: CGFloat);
CGContextSetMiterLimit(c: ::sys::CGContextRef, limit: CGFloat)683 fn CGContextSetMiterLimit(c: ::sys::CGContextRef, limit: CGFloat);
684
CGContextAddPath(c: ::sys::CGContextRef, path: ::sys::CGPathRef)685 fn CGContextAddPath(c: ::sys::CGContextRef, path: ::sys::CGPathRef);
CGContextAddCurveToPoint(c: ::sys::CGContextRef, cp1x: CGFloat, cp1y: CGFloat, cp2x: CGFloat, cp2y: CGFloat, x: CGFloat, y: CGFloat)686 fn CGContextAddCurveToPoint(c: ::sys::CGContextRef,
687 cp1x: CGFloat,
688 cp1y: CGFloat,
689 cp2x: CGFloat,
690 cp2y: CGFloat,
691 x: CGFloat,
692 y: CGFloat);
CGContextAddQuadCurveToPoint(c: ::sys::CGContextRef, cpx: CGFloat, cpy: CGFloat, x: CGFloat, y: CGFloat)693 fn CGContextAddQuadCurveToPoint(c: ::sys::CGContextRef,
694 cpx: CGFloat,
695 cpy: CGFloat,
696 x: CGFloat,
697 y: CGFloat);
CGContextAddLineToPoint(c: ::sys::CGContextRef, x: CGFloat, y: CGFloat)698 fn CGContextAddLineToPoint(c: ::sys::CGContextRef,
699 x: CGFloat,
700 y: CGFloat);
CGContextBeginPath(c: ::sys::CGContextRef)701 fn CGContextBeginPath(c: ::sys::CGContextRef);
CGContextClosePath(c: ::sys::CGContextRef)702 fn CGContextClosePath(c: ::sys::CGContextRef);
CGContextMoveToPoint(c: ::sys::CGContextRef, x: CGFloat, y: CGFloat)703 fn CGContextMoveToPoint(c: ::sys::CGContextRef,
704 x: CGFloat,
705 y: CGFloat);
CGContextDrawPath(c: ::sys::CGContextRef, mode: CGPathDrawingMode)706 fn CGContextDrawPath(c: ::sys::CGContextRef, mode: CGPathDrawingMode);
CGContextFillPath(c: ::sys::CGContextRef)707 fn CGContextFillPath(c: ::sys::CGContextRef);
CGContextEOFillPath(c: ::sys::CGContextRef)708 fn CGContextEOFillPath(c: ::sys::CGContextRef);
CGContextClip(c: ::sys::CGContextRef)709 fn CGContextClip(c: ::sys::CGContextRef);
CGContextEOClip(c: ::sys::CGContextRef)710 fn CGContextEOClip(c: ::sys::CGContextRef);
CGContextStrokePath(c: ::sys::CGContextRef)711 fn CGContextStrokePath(c: ::sys::CGContextRef);
CGContextSetRGBFillColor(context: ::sys::CGContextRef, red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)712 fn CGContextSetRGBFillColor(context: ::sys::CGContextRef,
713 red: CGFloat,
714 green: CGFloat,
715 blue: CGFloat,
716 alpha: CGFloat);
CGContextSetRGBStrokeColor(context: ::sys::CGContextRef, red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)717 fn CGContextSetRGBStrokeColor(context: ::sys::CGContextRef,
718 red: CGFloat,
719 green: CGFloat,
720 blue: CGFloat,
721 alpha: CGFloat);
CGContextSetGrayFillColor(context: ::sys::CGContextRef, gray: CGFloat, alpha: CGFloat)722 fn CGContextSetGrayFillColor(context: ::sys::CGContextRef, gray: CGFloat, alpha: CGFloat);
CGContextClearRect(context: ::sys::CGContextRef, rect: CGRect)723 fn CGContextClearRect(context: ::sys::CGContextRef,
724 rect: CGRect);
CGContextFillRect(context: ::sys::CGContextRef, rect: CGRect)725 fn CGContextFillRect(context: ::sys::CGContextRef,
726 rect: CGRect);
CGContextFillRects(context: ::sys::CGContextRef, rects: *const CGRect, count: size_t)727 fn CGContextFillRects(context: ::sys::CGContextRef,
728 rects: *const CGRect,
729 count: size_t);
CGContextStrokeRect(context: ::sys::CGContextRef, rect: CGRect)730 fn CGContextStrokeRect(context: ::sys::CGContextRef,
731 rect: CGRect);
CGContextStrokeRectWithWidth(context: ::sys::CGContextRef, rect: CGRect, width: CGFloat)732 fn CGContextStrokeRectWithWidth(context: ::sys::CGContextRef,
733 rect: CGRect,
734 width: CGFloat);
CGContextClipToRect(context: ::sys::CGContextRef, rect: CGRect)735 fn CGContextClipToRect(context: ::sys::CGContextRef,
736 rect: CGRect);
CGContextClipToRects(context: ::sys::CGContextRef, rects: *const CGRect, count: size_t)737 fn CGContextClipToRects(context: ::sys::CGContextRef,
738 rects: *const CGRect,
739 count: size_t);
CGContextClipToMask(ctx: ::sys::CGContextRef, rect: CGRect, mask: ::sys::CGImageRef)740 fn CGContextClipToMask(ctx: ::sys::CGContextRef, rect: CGRect, mask: ::sys::CGImageRef);
CGContextReplacePathWithStrokedPath(context: ::sys::CGContextRef)741 fn CGContextReplacePathWithStrokedPath(context: ::sys::CGContextRef);
CGContextFillEllipseInRect(context: ::sys::CGContextRef, rect: CGRect)742 fn CGContextFillEllipseInRect(context: ::sys::CGContextRef,
743 rect: CGRect);
CGContextStrokeEllipseInRect(context: ::sys::CGContextRef, rect: CGRect)744 fn CGContextStrokeEllipseInRect(context: ::sys::CGContextRef,
745 rect: CGRect);
CGContextStrokeLineSegments(context: ::sys::CGContextRef, points: *const CGPoint, count: size_t)746 fn CGContextStrokeLineSegments(context: ::sys::CGContextRef,
747 points: *const CGPoint,
748 count: size_t);
CGContextDrawImage(c: ::sys::CGContextRef, rect: CGRect, image: ::sys::CGImageRef)749 fn CGContextDrawImage(c: ::sys::CGContextRef, rect: CGRect, image: ::sys::CGImageRef);
CGContextSetInterpolationQuality(c: ::sys::CGContextRef, quality: CGInterpolationQuality)750 fn CGContextSetInterpolationQuality(c: ::sys::CGContextRef, quality: CGInterpolationQuality);
CGContextGetInterpolationQuality(c: ::sys::CGContextRef) -> CGInterpolationQuality751 fn CGContextGetInterpolationQuality(c: ::sys::CGContextRef) -> CGInterpolationQuality;
CGContextSetFont(c: ::sys::CGContextRef, font: ::sys::CGFontRef)752 fn CGContextSetFont(c: ::sys::CGContextRef, font: ::sys::CGFontRef);
CGContextSetFontSize(c: ::sys::CGContextRef, size: CGFloat)753 fn CGContextSetFontSize(c: ::sys::CGContextRef, size: CGFloat);
CGContextSetTextMatrix(c: ::sys::CGContextRef, t: CGAffineTransform)754 fn CGContextSetTextMatrix(c: ::sys::CGContextRef, t: CGAffineTransform);
CGContextSetTextPosition(c: ::sys::CGContextRef, x: CGFloat, y: CGFloat)755 fn CGContextSetTextPosition(c: ::sys::CGContextRef, x: CGFloat, y: CGFloat);
CGContextShowGlyphsAtPositions(c: ::sys::CGContextRef, glyphs: *const CGGlyph, positions: *const CGPoint, count: size_t)756 fn CGContextShowGlyphsAtPositions(c: ::sys::CGContextRef,
757 glyphs: *const CGGlyph,
758 positions: *const CGPoint,
759 count: size_t);
760
CGContextSaveGState(c: ::sys::CGContextRef)761 fn CGContextSaveGState(c: ::sys::CGContextRef);
CGContextRestoreGState(c: ::sys::CGContextRef)762 fn CGContextRestoreGState(c: ::sys::CGContextRef);
CGContextTranslateCTM(c: ::sys::CGContextRef, tx: CGFloat, ty: CGFloat)763 fn CGContextTranslateCTM(c: ::sys::CGContextRef, tx: CGFloat, ty: CGFloat);
CGContextScaleCTM(c: ::sys::CGContextRef, sx: CGFloat, sy: CGFloat)764 fn CGContextScaleCTM(c: ::sys::CGContextRef, sx: CGFloat, sy: CGFloat);
CGContextRotateCTM(c: ::sys::CGContextRef, angle: CGFloat)765 fn CGContextRotateCTM(c: ::sys::CGContextRef, angle: CGFloat);
CGContextGetCTM(c: ::sys::CGContextRef) -> CGAffineTransform766 fn CGContextGetCTM(c: ::sys::CGContextRef) -> CGAffineTransform;
CGContextConcatCTM(c: ::sys::CGContextRef, transform: CGAffineTransform)767 fn CGContextConcatCTM(c: ::sys::CGContextRef, transform: CGAffineTransform);
768
CGContextDrawLinearGradient(c: ::sys::CGContextRef, gradient: ::sys::CGGradientRef, startPoint: CGPoint, endPoint: CGPoint, options: CGGradientDrawingOptions)769 fn CGContextDrawLinearGradient(c: ::sys::CGContextRef, gradient: ::sys::CGGradientRef, startPoint: CGPoint, endPoint: CGPoint, options: CGGradientDrawingOptions);
CGContextDrawRadialGradient(c: ::sys::CGContextRef, gradient: ::sys::CGGradientRef, startCenter: CGPoint, startRadius: CGFloat, endCenter:CGPoint, endRadius:CGFloat, options: CGGradientDrawingOptions)770 fn CGContextDrawRadialGradient(c: ::sys::CGContextRef, gradient: ::sys::CGGradientRef, startCenter: CGPoint, startRadius: CGFloat, endCenter:CGPoint, endRadius:CGFloat, options: CGGradientDrawingOptions);
771
CGContextSetShadow(c: ::sys::CGContextRef, offset: CGSize, blur: CGFloat)772 fn CGContextSetShadow(c: ::sys::CGContextRef, offset: CGSize, blur: CGFloat);
CGContextSetShadowWithColor(c: ::sys::CGContextRef, offset: CGSize, blur: CGFloat, color: ::sys::CGColorRef)773 fn CGContextSetShadowWithColor(c: ::sys::CGContextRef, offset: CGSize, blur: CGFloat, color: ::sys::CGColorRef);
774 }
775
776