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