playdate_graphics/
lib.rs

1//! Playdate graphics API
2#![cfg_attr(not(test), no_std)]
3
4extern crate sys;
5extern crate alloc;
6pub extern crate color;
7
8pub mod error;
9pub mod text;
10pub mod bitmap {
11	mod bitmap;
12	pub mod api;
13	pub mod table;
14	pub use bitmap::*;
15}
16pub mod video;
17pub mod api;
18
19use core::ffi::c_float;
20use core::ffi::c_int;
21use error::ApiError;
22
23pub use sys::ffi::LCDBitmapFlip as BitmapFlip;
24pub use sys::ffi::LCDBitmapDrawMode as BitmapDrawMode;
25pub use sys::ffi::LCDLineCapStyle as LineCapStyle;
26
27use sys::ffi::LCDColor;
28use sys::ffi::LCD_ROWS;
29use sys::ffi::LCD_ROWSIZE;
30use sys::ffi::LCDPolygonFillRule;
31use sys::ffi::LCDSolidColor;
32
33pub use bitmap::debug_bitmap;
34pub use bitmap::display_buffer_bitmap;
35pub use bitmap::copy_frame_buffer_bitmap;
36pub use bitmap::set_stencil;
37pub use bitmap::set_stencil_tiled;
38pub use bitmap::set_draw_mode;
39pub use bitmap::push_context;
40pub use bitmap::pop_context;
41
42
43unsafe fn as_slice_mut(buf: *mut u8) -> Result<&'static mut [u8], ApiError> {
44	if !buf.is_null() {
45		Ok(core::slice::from_raw_parts_mut(
46		                                   buf,
47		                                   (LCD_ROWSIZE * LCD_ROWS) as usize,
48		))
49	} else {
50		Err(sys::error::NullPtrError.into())
51	}
52}
53
54
55/// Returns the current display frame buffer.
56/// Rows are 32-bit aligned, so the row stride is 52 bytes, with the extra 2 bytes per row ignored.
57/// Bytes are MSB-ordered; i.e., the pixel in column 0 is the 0x80 bit of the first byte of the row.
58///
59/// This function is shorthand for [`Graphics::get_frame`],
60/// using default ZST end-point.
61///
62/// Equivalent to [`sys::ffi::playdate_graphics::getFrame`].
63#[doc(alias = "sys::ffi::playdate_graphics::getFrame")]
64#[inline(always)]
65pub fn get_frame() -> Result<&'static mut [u8], ApiError> { Graphics::Default().get_frame() }
66
67
68/// Returns the raw bits in the display buffer,
69/// __the last completed frame__.
70///
71/// This function is shorthand for [`Graphics::get_display_frame`],
72/// using default ZST end-point.
73///
74/// Equivalent to [`sys::ffi::playdate_graphics::getDisplayFrame`].
75#[doc(alias = "sys::ffi::playdate_graphics::getDisplayFrame")]
76#[inline(always)]
77pub fn get_display_frame() -> Result<&'static mut [u8], ApiError> { Graphics::Default().get_display_frame() }
78
79/// After updating pixels in the buffer returned by [`get_frame`],
80/// you must tell the graphics system which rows were updated.
81///
82/// This function marks a contiguous range of rows as updated
83/// (e.g., `markUpdatedRows(0, LCD_ROWS-1)` tells the system to update the entire display).
84///
85/// Both `start` and `end` are __included__ in the range.
86///
87/// This function is shorthand for [`Graphics::mark_updated_rows`],
88/// using default ZST end-point.
89///
90/// Equivalent to [`sys::ffi::playdate_graphics::markUpdatedRows`].
91#[doc(alias = "sys::ffi::playdate_graphics::markUpdatedRows")]
92#[inline(always)]
93pub fn mark_updated_rows(start: c_int, end: c_int) { Graphics::Default().mark_updated_rows(start, end) }
94
95/// Manually flushes the current frame buffer out to the display.
96/// This function is automatically called after each pass through the run loop,
97/// so there shouldn’t be any need to call it yourself.
98///
99/// This function is shorthand for [`Graphics::display`],
100/// using default ZST end-point.
101///
102/// Equivalent to [`sys::ffi::playdate_graphics::display`].
103#[doc(alias = "sys::ffi::playdate_graphics::display")]
104#[inline(always)]
105pub fn display() { Graphics::Default().display() }
106
107/// Clears the entire display, filling it with `color`.
108///
109/// This function is shorthand for [`Graphics::always`],
110/// using default ZST end-point.
111///
112/// Equivalent to [`sys::ffi::playdate_graphics::clear`].
113#[doc(alias = "sys::ffi::playdate_graphics::clear")]
114#[inline(always)]
115pub fn clear(color: color::Color) { clear_raw(color.into()) }
116
117
118/// Clears the entire display, filling it with `color`.
119///
120/// Same as [`clear`], but without conversion `Color` -> `LCDColor`.
121/// That conversion is really cheap,
122/// so this function is useful if you're working with `LCDColor` directly.
123///
124/// This function is shorthand for [`Graphics::clear_raw`],
125/// using default ZST end-point.
126///
127/// Equivalent to [`sys::ffi::playdate_graphics::clear`].
128#[doc(alias = "sys::ffi::playdate_graphics::clear")]
129#[inline(always)]
130pub fn clear_raw(color: LCDColor) { Graphics::Default().clear_raw(color) }
131
132/// Sets the current clip rect in __screen__ coordinates.
133///
134/// This function is shorthand for [`Graphics::set_screen_clip_rect`],
135/// using default ZST end-point.
136///
137/// Equivalent to [`sys::ffi::playdate_graphics::setScreenClipRect`].
138#[doc(alias = "sys::ffi::playdate_graphics::setScreenClipRect")]
139#[inline(always)]
140pub fn set_screen_clip_rect(x: c_int, y: c_int, width: c_int, height: c_int) {
141	Graphics::Default().set_screen_clip_rect(x, y, width, height)
142}
143
144/// Offsets the origin point for all drawing calls to `x, y` (can be negative).
145///
146/// This is useful, for example, for centering a "camera"
147/// on a sprite that is moving around a world larger than the screen.
148///
149/// This function is shorthand for [`Graphics::set_draw_offset`],
150/// using default ZST end-point.
151///
152/// Equivalent to [`sys::ffi::playdate_graphics::setDrawOffset`].
153#[doc(alias = "sys::ffi::playdate_graphics::setDrawOffset")]
154#[inline(always)]
155pub fn set_draw_offset(dx: c_int, dy: c_int) { Graphics::Default().set_draw_offset(dx, dy) }
156
157/// Sets the current clip rect, using __world__ coordinates that is,
158/// the given rectangle will be translated by the current drawing offset.
159///
160/// The clip rect is cleared at the beginning of each update.
161///
162/// This function is shorthand for [`Graphics::set_clip_rect`],
163/// using default ZST end-point.
164///
165/// Equivalent to [`sys::ffi::playdate_graphics::setClipRect`].
166#[doc(alias = "sys::ffi::playdate_graphics::setClipRect")]
167#[inline(always)]
168pub fn set_clip_rect(x: c_int, y: c_int, width: c_int, height: c_int) {
169	Graphics::Default().set_clip_rect(x, y, width, height)
170}
171
172/// Clears the current clip rect.
173///
174/// This function is shorthand for [`Graphics::clear_clip_rect`],
175/// using default ZST end-point.
176///
177/// Equivalent to [`sys::ffi::playdate_graphics::clearClipRect`].
178#[doc(alias = "sys::ffi::playdate_graphics::clearClipRect")]
179#[inline(always)]
180pub fn clear_clip_rect() { Graphics::Default().clear_clip_rect() }
181
182/// Sets the background color shown when the display is offset
183/// or for clearing dirty areas in the sprite system.
184///
185/// This function is shorthand for [`Graphics::set_background_color`],
186/// using default ZST end-point.
187///
188/// Equivalent to [`sys::ffi::playdate_graphics::setBackgroundColor`].
189#[doc(alias = "sys::ffi::playdate_graphics::setBackgroundColor")]
190#[inline(always)]
191pub fn set_background_color(color: LCDSolidColor) { Graphics::Default().set_background_color(color) }
192
193
194//
195// Geometry
196//
197
198/// Fills the polygon with vertices at the given coordinates
199/// (an array of `2 * num_points` ints containing alternating x and y values)
200/// using the given `color` and fill, or winding, `rule`.
201///
202/// See [wikipedia](https://en.wikipedia.org/wiki/Nonzero-rule) for an explanation of the winding rule.
203///
204/// This function is shorthand for [`Graphics::fill_polygon`],
205/// using default ZST end-point.
206///
207/// Equivalent to [`sys::ffi::playdate_graphics::fillPolygon`].
208#[doc(alias = "sys::ffi::playdate_graphics::fillPolygon")]
209#[inline(always)]
210pub fn fill_polygon(num_points: c_int, coords: &mut [c_int], color: LCDColor, rule: LCDPolygonFillRule) {
211	Graphics::Default().fill_polygon(num_points, coords, color, rule)
212}
213
214/// Draws a line from `x1, y1` to `x2, y2` with a stroke width of `width`.
215///
216/// This function is shorthand for [`Graphics::draw_line`],
217/// using default ZST end-point.
218///
219/// Equivalent to [`sys::ffi::playdate_graphics::drawLine`].
220#[doc(alias = "sys::ffi::playdate_graphics::drawLine")]
221#[inline(always)]
222pub fn draw_line(x1: c_int, y1: c_int, x2: c_int, y2: c_int, width: c_int, color: LCDColor) {
223	Graphics::Default().draw_line(x1, y1, x2, y2, width, color)
224}
225
226/// Draws a filled triangle with points at `x1, y1`, `x2, y2`, and `x3, y3`.
227///
228/// This function is shorthand for [`Graphics::fill_triangle`],
229/// using default ZST end-point.
230///
231/// Equivalent to [`sys::ffi::playdate_graphics::fillTriangle`].
232#[doc(alias = "sys::ffi::playdate_graphics::fillTriangle")]
233#[inline(always)]
234pub fn fill_triangle(x1: c_int, y1: c_int, x2: c_int, y2: c_int, x3: c_int, y3: c_int, color: LCDColor) {
235	Graphics::Default().fill_triangle(x1, y1, x2, y2, x3, y3, color);
236}
237
238/// Draws a `width` by `height` rect at `x, y`.
239///
240/// This function is shorthand for [`Graphics::draw_rect`],
241/// using default ZST end-point.
242///
243/// Equivalent to [`sys::ffi::playdate_graphics::drawRect`].
244#[doc(alias = "sys::ffi::playdate_graphics::drawRect")]
245#[inline(always)]
246pub fn draw_rect(x: c_int, y: c_int, width: c_int, height: c_int, color: LCDColor) {
247	Graphics::Default().draw_rect(x, y, width, height, color)
248}
249
250/// Draws a filled `width` by `height` rect at `x, y`.
251///
252/// This function is shorthand for [`Graphics::fill_rect`],
253/// using default ZST end-point.
254///
255/// Equivalent to [`sys::ffi::playdate_graphics::fillRect`].
256#[doc(alias = "sys::ffi::playdate_graphics::fillRect")]
257#[inline(always)]
258pub fn fill_rect(x: c_int, y: c_int, width: c_int, height: c_int, color: LCDColor) {
259	Graphics::Default().fill_rect(x, y, width, height, color)
260}
261
262/// Draw an ellipse stroked inside the rect.
263///
264/// Draws an ellipse inside the rectangle `x, y, width, height` of width `line_width`
265/// (inset from the rectangle bounds).
266///
267/// If `start_angle != end_angle`, this draws an arc between the given angles.
268///
269/// Angles are given in degrees, clockwise from due north.
270///
271/// This function is shorthand for [`Graphics::draw_ellipse`],
272/// using default ZST end-point.
273///
274/// Equivalent to [`sys::ffi::playdate_graphics::drawEllipse`].
275#[doc(alias = "sys::ffi::playdate_graphics::drawEllipse")]
276#[inline(always)]
277pub fn draw_ellipse(x: c_int,
278                    y: c_int,
279                    width: c_int,
280                    height: c_int,
281                    line_width: c_int,
282                    start_angle: c_float,
283                    end_angle: c_float,
284                    color: LCDColor) {
285	Graphics::Default().draw_ellipse(x, y, width, height, line_width, start_angle, end_angle, color)
286}
287
288/// Fills an ellipse inside the rectangle `x, y, width, height`.
289///
290/// If `start_angle != end_angle`, this draws a wedge/Pacman between the given angles.
291///
292/// Angles are given in degrees, clockwise from due north.
293///
294/// This function is shorthand for [`Graphics::fill_ellipse`],
295/// using default ZST end-point.
296///
297/// Equivalent to [`sys::ffi::playdate_graphics::fillEllipse`].
298#[doc(alias = "sys::ffi::playdate_graphics::fillEllipse")]
299#[inline(always)]
300pub fn fill_ellipse(x: c_int,
301                    y: c_int,
302                    width: c_int,
303                    height: c_int,
304                    start_angle: c_float,
305                    end_angle: c_float,
306                    color: LCDColor) {
307	Graphics::Default().fill_ellipse(x, y, width, height, start_angle, end_angle, color)
308}
309
310
311/// Sets the end cap style used in the line drawing functions.
312///
313/// This function is shorthand for [`Graphics::set_line_cap_style`],
314/// using default ZST end-point.
315///
316/// Equivalent to [`sys::ffi::playdate_graphics::setLineCapStyle`].
317#[doc(alias = "sys::ffi::playdate_graphics::setLineCapStyle")]
318#[inline(always)]
319pub fn set_line_cap_style(end_cap_style: LineCapStyle) { Graphics::Default().set_line_cap_style(end_cap_style) }
320
321
322#[derive(Debug, Clone, Copy)]
323pub struct Graphics<Api = api::Default>(Api);
324
325impl Graphics<api::Default> {
326	/// Creates default [`Graphics`] without type parameter requirement.
327	///
328	/// Uses ZST [`api::Default`].
329	#[allow(non_snake_case)]
330	pub fn Default() -> Self { Self(Default::default()) }
331}
332
333impl Graphics<api::Cache> {
334	/// Creates [`Graphics`] without type parameter requirement.
335	///
336	/// Uses [`api::Cache`].
337	#[allow(non_snake_case)]
338	pub fn Cached() -> Self { Self(Default::default()) }
339}
340
341impl<Api: Default + api::Api> Default for Graphics<Api> {
342	fn default() -> Self { Self(Default::default()) }
343}
344
345impl<Api: Default + api::Api> Graphics<Api> {
346	pub fn new() -> Self { Self(Default::default()) }
347}
348
349impl<Api: api::Api> Graphics<Api> {
350	pub fn new_with(api: Api) -> Self { Self(api) }
351}
352
353impl<Api: api::Api> Graphics<Api> {
354	/// Sets the pixel at `(x,y)` in the current drawing context (by default the screen) to the given `color`.
355	/// Be aware that setting a pixel at a time is not very efficient:
356	/// In our testing, more than around 20,000 calls in a tight loop will drop the frame rate below 30 fps.
357	///
358	/// Equivalent to [`sys::ffi::playdate_graphics::setPixel`]
359	#[doc(alias = "sys::ffi::playdate_graphics::setPixel")]
360	#[inline(always)]
361	pub fn set_pixel(&self, x: c_int, y: c_int, color: color::Color) { self.set_pixel_raw(x, y, color.into()) }
362
363	/// Same as [`set_pixel`][Graphics::set_pixel], but without conversion [`Color`][color::Color] -> [`LCDColor`].
364	///
365	/// Equivalent to [`sys::ffi::playdate_graphics::setPixel`]
366	#[doc(alias = "sys::ffi::playdate_graphics::setPixel")]
367	#[inline(always)]
368	pub fn set_pixel_raw(&self, x: c_int, y: c_int, color: LCDColor) {
369		let f = self.0.set_pixel();
370		unsafe { f(x, y, color) }
371	}
372
373
374	/// Returns the current display frame buffer.
375	/// Rows are 32-bit aligned, so the row stride is 52 bytes, with the extra 2 bytes per row ignored.
376	/// Bytes are MSB-ordered; i.e., the pixel in column 0 is the 0x80 bit of the first byte of the row.
377	///
378	/// Equivalent to [`sys::ffi::playdate_graphics::getFrame`].
379	#[doc(alias = "sys::ffi::playdate_graphics::getFrame")]
380	pub fn get_frame(&self) -> Result<&'static mut [u8], ApiError> {
381		let f = self.0.get_frame();
382		unsafe { as_slice_mut(f()) }
383	}
384
385
386	/// Returns the raw bits in the display buffer,
387	/// __the last completed frame__.
388	///
389	/// Equivalent to [`sys::ffi::playdate_graphics::getDisplayFrame`].
390	#[doc(alias = "sys::ffi::playdate_graphics::getDisplayFrame")]
391	pub fn get_display_frame(&self) -> Result<&'static mut [u8], ApiError> {
392		let f = self.0.get_display_frame();
393		unsafe { as_slice_mut(f()) }
394	}
395
396	/// After updating pixels in the buffer returned by [`get_frame`],
397	/// you must tell the graphics system which rows were updated.
398	///
399	/// This function marks a contiguous range of rows as updated
400	/// (e.g., `markUpdatedRows(0, LCD_ROWS-1)` tells the system to update the entire display).
401	///
402	/// Both `start` and `end` are __included__ in the range.
403	///
404	/// Equivalent to [`sys::ffi::playdate_graphics::markUpdatedRows`].
405	#[doc(alias = "sys::ffi::playdate_graphics::markUpdatedRows")]
406	pub fn mark_updated_rows(&self, start: c_int, end: c_int) {
407		let f = self.0.mark_updated_rows();
408		unsafe { f(start, end) }
409	}
410
411	/// Manually flushes the current frame buffer out to the display.
412	/// This function is automatically called after each pass through the run loop,
413	/// so there shouldn’t be any need to call it yourself.
414	///
415	/// Equivalent to [`sys::ffi::playdate_graphics::display`].
416	#[doc(alias = "sys::ffi::playdate_graphics::display")]
417	pub fn display(&self) {
418		let f = self.0.display();
419		unsafe { f() }
420	}
421
422	/// Clears the entire display, filling it with `color`.
423	///
424	/// Equivalent to [`sys::ffi::playdate_graphics::clear`].
425	#[doc(alias = "sys::ffi::playdate_graphics::clear")]
426	#[inline(always)]
427	pub fn clear(&self, color: color::Color) { clear_raw(color.into()) }
428
429
430	/// Clears the entire display, filling it with `color`.
431	///
432	/// Same as [`clear`], but without conversion `Color` -> `LCDColor`.
433	/// That conversion is really cheap,
434	/// so this function is useful if you're working with `LCDColor` directly.
435	///
436	/// Equivalent to [`sys::ffi::playdate_graphics::clear`].
437	#[doc(alias = "sys::ffi::playdate_graphics::clear")]
438	pub fn clear_raw(&self, color: LCDColor) {
439		let f = self.0.clear();
440		unsafe { f(color) }
441	}
442
443	/// Sets the current clip rect in __screen__ coordinates.
444	///
445	/// Equivalent to [`sys::ffi::playdate_graphics::setScreenClipRect`].
446	#[doc(alias = "sys::ffi::playdate_graphics::setScreenClipRect")]
447	pub fn set_screen_clip_rect(&self, x: c_int, y: c_int, width: c_int, height: c_int) {
448		let f = self.0.set_screen_clip_rect();
449		unsafe { f(x, y, width, height) }
450	}
451
452	/// Offsets the origin point for all drawing calls to `x, y` (can be negative).
453	///
454	/// This is useful, for example, for centering a "camera"
455	/// on a sprite that is moving around a world larger than the screen.
456	///
457	/// Equivalent to [`sys::ffi::playdate_graphics::setDrawOffset`].
458	#[doc(alias = "sys::ffi::playdate_graphics::setDrawOffset")]
459	pub fn set_draw_offset(&self, dx: c_int, dy: c_int) {
460		let f = self.0.set_draw_offset();
461		unsafe { f(dx, dy) }
462	}
463
464	/// Sets the current clip rect, using __world__ coordinates that is,
465	/// the given rectangle will be translated by the current drawing offset.
466	///
467	/// The clip rect is cleared at the beginning of each update.
468	///
469	/// Equivalent to [`sys::ffi::playdate_graphics::setClipRect`].
470	#[doc(alias = "sys::ffi::playdate_graphics::setClipRect")]
471	pub fn set_clip_rect(&self, x: c_int, y: c_int, width: c_int, height: c_int) {
472		let f = self.0.set_clip_rect();
473		unsafe { f(x, y, width, height) }
474	}
475
476	/// Clears the current clip rect.
477	///
478	/// Equivalent to [`sys::ffi::playdate_graphics::clearClipRect`].
479	#[doc(alias = "sys::ffi::playdate_graphics::clearClipRect")]
480	pub fn clear_clip_rect(&self) {
481		let f = self.0.clear_clip_rect();
482		unsafe { f() }
483	}
484
485	/// Sets the background color shown when the display is offset
486	/// or for clearing dirty areas in the sprite system.
487	///
488	/// Equivalent to [`sys::ffi::playdate_graphics::setBackgroundColor`].
489	#[doc(alias = "sys::ffi::playdate_graphics::setBackgroundColor")]
490	pub fn set_background_color(&self, color: LCDSolidColor) {
491		let f = self.0.set_background_color();
492		unsafe { f(color) }
493	}
494
495
496	//
497	// Geometry
498	//
499
500	/// Fills the polygon with vertices at the given coordinates
501	/// (an array of `2 * num_points` ints containing alternating x and y values)
502	/// using the given `color` and fill, or winding, `rule`.
503	///
504	/// See [wikipedia](https://en.wikipedia.org/wiki/Nonzero-rule) for an explanation of the winding rule.
505	///
506	/// Equivalent to [`sys::ffi::playdate_graphics::fillPolygon`].
507	#[doc(alias = "sys::ffi::playdate_graphics::fillPolygon")]
508	pub fn fill_polygon(&self,
509	                    num_points: c_int,
510	                    coords: &mut [c_int],
511	                    color: LCDColor,
512	                    rule: LCDPolygonFillRule) {
513		let f = self.0.fill_polygon();
514		unsafe { f(num_points, coords.as_mut_ptr(), color, rule) }
515	}
516
517	/// Draws a line from `x1, y1` to `x2, y2` with a stroke width of `width`.
518	///
519	/// Equivalent to [`sys::ffi::playdate_graphics::drawLine`].
520	#[doc(alias = "sys::ffi::playdate_graphics::drawLine")]
521	pub fn draw_line(&self, x1: c_int, y1: c_int, x2: c_int, y2: c_int, width: c_int, color: LCDColor) {
522		let f = self.0.draw_line();
523		unsafe { f(x1, y1, x2, y2, width, color) }
524	}
525
526	/// Draws a filled triangle with points at `x1, y1`, `x2, y2`, and `x3, y3`.
527	///
528	/// Equivalent to [`sys::ffi::playdate_graphics::fillTriangle`].
529	#[doc(alias = "sys::ffi::playdate_graphics::fillTriangle")]
530	pub fn fill_triangle(&self,
531	                     x1: c_int,
532	                     y1: c_int,
533	                     x2: c_int,
534	                     y2: c_int,
535	                     x3: c_int,
536	                     y3: c_int,
537	                     color: LCDColor) {
538		let f = self.0.fill_triangle();
539		unsafe { f(x1, y1, x2, y2, x3, y3, color) }
540	}
541
542	/// Draws a `width` by `height` rect at `x, y`.
543	///
544	/// Equivalent to [`sys::ffi::playdate_graphics::drawRect`].
545	#[doc(alias = "sys::ffi::playdate_graphics::drawRect")]
546	pub fn draw_rect(&self, x: c_int, y: c_int, width: c_int, height: c_int, color: LCDColor) {
547		let f = self.0.draw_rect();
548		unsafe { f(x, y, width, height, color) }
549	}
550
551	/// Draws a filled `width` by `height` rect at `x, y`.
552	///
553	/// Equivalent to [`sys::ffi::playdate_graphics::fillRect`].
554	#[doc(alias = "sys::ffi::playdate_graphics::fillRect")]
555	pub fn fill_rect(&self, x: c_int, y: c_int, width: c_int, height: c_int, color: LCDColor) {
556		let f = self.0.fill_rect();
557		unsafe { f(x, y, width, height, color) }
558	}
559
560	/// Draw an ellipse stroked inside the rect.
561	///
562	/// Draws an ellipse inside the rectangle `x, y, width, height` of width `line_width`
563	/// (inset from the rectangle bounds).
564	///
565	/// If `start_angle != end_angle`, this draws an arc between the given angles.
566	///
567	/// Angles are given in degrees, clockwise from due north.
568	///
569	/// Equivalent to [`sys::ffi::playdate_graphics::drawEllipse`].
570	#[doc(alias = "sys::ffi::playdate_graphics::drawEllipse")]
571	pub fn draw_ellipse(&self,
572	                    x: c_int,
573	                    y: c_int,
574	                    width: c_int,
575	                    height: c_int,
576	                    line_width: c_int,
577	                    start_angle: c_float,
578	                    end_angle: c_float,
579	                    color: LCDColor) {
580		let f = self.0.draw_ellipse();
581		unsafe { f(x, y, width, height, line_width, start_angle, end_angle, color) }
582	}
583
584	/// Fills an ellipse inside the rectangle `x, y, width, height`.
585	///
586	/// If `start_angle != end_angle`, this draws a wedge/Pacman between the given angles.
587	///
588	/// Angles are given in degrees, clockwise from due north.
589	///
590	/// Equivalent to [`sys::ffi::playdate_graphics::fillEllipse`].
591	#[doc(alias = "sys::ffi::playdate_graphics::fillEllipse")]
592	pub fn fill_ellipse(&self,
593	                    x: c_int,
594	                    y: c_int,
595	                    width: c_int,
596	                    height: c_int,
597	                    start_angle: c_float,
598	                    end_angle: c_float,
599	                    color: LCDColor) {
600		let f = self.0.fill_ellipse();
601		unsafe { f(x, y, width, height, start_angle, end_angle, color) }
602	}
603
604
605	/// Sets the end cap style used in the line drawing functions.
606	///
607	/// Equivalent to [`sys::ffi::playdate_graphics::setLineCapStyle`].
608	#[doc(alias = "sys::ffi::playdate_graphics::setLineCapStyle")]
609	pub fn set_line_cap_style(&self, end_cap_style: LineCapStyle) {
610		let f = self.0.set_line_cap_style();
611		unsafe { f(end_cap_style) }
612	}
613}
614
615
616pub trait BitmapFlipExt {
617	#![allow(non_upper_case_globals)]
618	const Unflipped: BitmapFlip = BitmapFlip::kBitmapUnflipped;
619	const FlippedX: BitmapFlip = BitmapFlip::kBitmapFlippedX;
620	const FlippedY: BitmapFlip = BitmapFlip::kBitmapFlippedY;
621	const FlippedXY: BitmapFlip = BitmapFlip::kBitmapFlippedXY;
622}
623
624impl BitmapFlipExt for BitmapFlip {}
625
626
627pub trait BitmapDrawModeExt {
628	#![allow(non_upper_case_globals)]
629	const Copy: BitmapDrawMode = BitmapDrawMode::kDrawModeCopy;
630	const WhiteTransparent: BitmapDrawMode = BitmapDrawMode::kDrawModeWhiteTransparent;
631	const BlackTransparent: BitmapDrawMode = BitmapDrawMode::kDrawModeBlackTransparent;
632	const FillWhite: BitmapDrawMode = BitmapDrawMode::kDrawModeFillWhite;
633	const FillBlack: BitmapDrawMode = BitmapDrawMode::kDrawModeFillBlack;
634	const XOR: BitmapDrawMode = BitmapDrawMode::kDrawModeXOR;
635	const NXOR: BitmapDrawMode = BitmapDrawMode::kDrawModeNXOR;
636	const Inverted: BitmapDrawMode = BitmapDrawMode::kDrawModeInverted;
637}
638
639impl BitmapDrawModeExt for BitmapDrawMode {}
640
641
642pub trait LineCapStyleExt {
643	#![allow(non_upper_case_globals)]
644	const Butt: LineCapStyle = LineCapStyle::kLineCapStyleButt;
645	const Square: LineCapStyle = LineCapStyle::kLineCapStyleSquare;
646	const Round: LineCapStyle = LineCapStyle::kLineCapStyleRound;
647}
648impl LineCapStyleExt for LineCapStyle {}