1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3pub enum BackgroundMode {
4 Transparent,
6 Solid,
8}
9
10impl BackgroundMode {
11 pub fn to_raw(&self) -> i32 {
13 match self {
14 BackgroundMode::Transparent => wxdragon_sys::WXD_TRANSPARENT as i32,
15 BackgroundMode::Solid => wxdragon_sys::WXD_SOLID as i32,
16 }
17 }
18}
19
20widget_style_enum!(
21 name: PenStyle,
22 doc: "Style flags for DC pen.",
23 variants: {
24 Solid: wxdragon_sys::WXD_PENSTYLE_SOLID, "Solid line style.",
25 Dot: wxdragon_sys::WXD_PENSTYLE_DOT, "Dotted line style.",
26 LongDash: wxdragon_sys::WXD_PENSTYLE_LONG_DASH, "Long dashed line style.",
27 ShortDash: wxdragon_sys::WXD_PENSTYLE_SHORT_DASH, "Short dashed line style.",
28 DotDash: wxdragon_sys::WXD_PENSTYLE_DOT_DASH, "Dot and dash line style.",
29 Transparent: wxdragon_sys::WXD_PENSTYLE_TRANSPARENT, "Transparent pen.",
30 Stipple: wxdragon_sys::WXD_PENSTYLE_STIPPLE, "Stippled pen.",
31 UserDash: wxdragon_sys::WXD_PENSTYLE_USER_DASH, "User-defined dash pattern.",
32 BDiagonalHatch: wxdragon_sys::WXD_PENSTYLE_BDIAGONAL_HATCH, "Backward diagonal hatch pattern.",
33 CrossDiagHatch: wxdragon_sys::WXD_PENSTYLE_CROSSDIAG_HATCH, "Cross-diagonal hatch pattern.",
34 FDiagonalHatch: wxdragon_sys::WXD_PENSTYLE_FDIAGONAL_HATCH, "Forward diagonal hatch pattern.",
35 CrossHatch: wxdragon_sys::WXD_PENSTYLE_CROSS_HATCH, "Cross hatch pattern.",
36 HorizontalHatch: wxdragon_sys::WXD_PENSTYLE_HORIZONTAL_HATCH, "Horizontal hatch pattern.",
37 VerticalHatch: wxdragon_sys::WXD_PENSTYLE_VERTICAL_HATCH, "Vertical hatch pattern."
38 },
39 default_variant: Solid
40);
41
42widget_style_enum!(
43 name: BrushStyle,
44 doc: "Style flags for DC brush.",
45 variants: {
46 Solid: wxdragon_sys::WXD_BRUSHSTYLE_SOLID, "Solid brush.",
47 Transparent: wxdragon_sys::WXD_BRUSHSTYLE_TRANSPARENT, "Transparent brush.",
48 BDiagonalHatch: wxdragon_sys::WXD_BRUSHSTYLE_BDIAGONAL_HATCH, "Backward diagonal hatch pattern.",
49 CrossDiagHatch: wxdragon_sys::WXD_BRUSHSTYLE_CROSSDIAG_HATCH, "Cross-diagonal hatch pattern.",
50 FDiagonalHatch: wxdragon_sys::WXD_BRUSHSTYLE_FDIAGONAL_HATCH, "Forward diagonal hatch pattern.",
51 CrossHatch: wxdragon_sys::WXD_BRUSHSTYLE_CROSS_HATCH, "Cross hatch pattern.",
52 HorizontalHatch: wxdragon_sys::WXD_BRUSHSTYLE_HORIZONTAL_HATCH, "Horizontal hatch pattern.",
53 VerticalHatch: wxdragon_sys::WXD_BRUSHSTYLE_VERTICAL_HATCH, "Vertical hatch pattern.",
54 Stipple: wxdragon_sys::WXD_BRUSHSTYLE_STIPPLE, "Stippled brush.",
55 StippleMaskOpaque: wxdragon_sys::WXD_BRUSHSTYLE_STIPPLE_MASK_OPAQUE, "Stippled brush with opaque mask.",
56 StippleMask: wxdragon_sys::WXD_BRUSHSTYLE_STIPPLE_MASK, "Stippled brush with mask."
57 },
58 default_variant: Solid
59);
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub enum PolygonFillMode {
64 OddEven,
66 Winding,
68}
69
70impl PolygonFillMode {
71 pub fn to_raw(&self) -> i32 {
73 match self {
74 PolygonFillMode::OddEven => wxdragon_sys::WXD_ODDEVEN_RULE as i32,
75 PolygonFillMode::Winding => wxdragon_sys::WXD_WINDING_RULE as i32,
76 }
77 }
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq)]
82pub enum FloodFillMode {
83 Surface,
85 Border,
87}
88
89impl FloodFillMode {
90 pub fn to_raw(&self) -> i32 {
92 match self {
93 FloodFillMode::Surface => wxdragon_sys::WXD_FLOOD_SURFACE as i32,
94 FloodFillMode::Border => wxdragon_sys::WXD_FLOOD_BORDER as i32,
95 }
96 }
97}
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq)]
101pub enum LogicalFunction {
102 Clear,
103 Xor,
104 Invert,
105 OrReverse,
106 AndReverse,
107 Copy,
108 And,
109 AndInvert,
110 NoOp,
111 Nor,
112 Equiv,
113 SrcInvert,
114 OrInvert,
115 Nand,
116 Or,
117 Set,
118}
119
120impl LogicalFunction {
121 pub fn to_raw(&self) -> i32 {
123 match self {
124 LogicalFunction::Clear => wxdragon_sys::WXD_CLEAR as i32,
125 LogicalFunction::Xor => wxdragon_sys::WXD_XOR as i32,
126 LogicalFunction::Invert => wxdragon_sys::WXD_INVERT as i32,
127 LogicalFunction::OrReverse => wxdragon_sys::WXD_OR_REVERSE as i32,
128 LogicalFunction::AndReverse => wxdragon_sys::WXD_AND_REVERSE as i32,
129 LogicalFunction::Copy => wxdragon_sys::WXD_COPY as i32,
130 LogicalFunction::And => wxdragon_sys::WXD_AND as i32,
131 LogicalFunction::AndInvert => wxdragon_sys::WXD_AND_INVERT as i32,
132 LogicalFunction::NoOp => wxdragon_sys::WXD_NO_OP as i32,
133 LogicalFunction::Nor => wxdragon_sys::WXD_NOR as i32,
134 LogicalFunction::Equiv => wxdragon_sys::WXD_EQUIV as i32,
135 LogicalFunction::SrcInvert => wxdragon_sys::WXD_SRC_INVERT as i32,
136 LogicalFunction::OrInvert => wxdragon_sys::WXD_OR_INVERT as i32,
137 LogicalFunction::Nand => wxdragon_sys::WXD_NAND as i32,
138 LogicalFunction::Or => wxdragon_sys::WXD_OR as i32,
139 LogicalFunction::Set => wxdragon_sys::WXD_SET as i32,
140 }
141 }
142
143 pub fn from_raw(value: i32) -> Self {
145 match value {
146 _ if value == wxdragon_sys::WXD_CLEAR as i32 => LogicalFunction::Clear,
147 _ if value == wxdragon_sys::WXD_XOR as i32 => LogicalFunction::Xor,
148 _ if value == wxdragon_sys::WXD_INVERT as i32 => LogicalFunction::Invert,
149 _ if value == wxdragon_sys::WXD_OR_REVERSE as i32 => LogicalFunction::OrReverse,
150 _ if value == wxdragon_sys::WXD_AND_REVERSE as i32 => LogicalFunction::AndReverse,
151 _ if value == wxdragon_sys::WXD_COPY as i32 => LogicalFunction::Copy,
152 _ if value == wxdragon_sys::WXD_AND as i32 => LogicalFunction::And,
153 _ if value == wxdragon_sys::WXD_AND_INVERT as i32 => LogicalFunction::AndInvert,
154 _ if value == wxdragon_sys::WXD_NO_OP as i32 => LogicalFunction::NoOp,
155 _ if value == wxdragon_sys::WXD_NOR as i32 => LogicalFunction::Nor,
156 _ if value == wxdragon_sys::WXD_EQUIV as i32 => LogicalFunction::Equiv,
157 _ if value == wxdragon_sys::WXD_SRC_INVERT as i32 => LogicalFunction::SrcInvert,
158 _ if value == wxdragon_sys::WXD_OR_INVERT as i32 => LogicalFunction::OrInvert,
159 _ if value == wxdragon_sys::WXD_NAND as i32 => LogicalFunction::Nand,
160 _ if value == wxdragon_sys::WXD_OR as i32 => LogicalFunction::Or,
161 _ if value == wxdragon_sys::WXD_SET as i32 => LogicalFunction::Set,
162 _ => LogicalFunction::Copy,
163 }
164 }
165}
166
167#[derive(Debug, Clone, Copy, PartialEq, Eq)]
169pub enum MapMode {
170 Text,
171 Lometric,
172 Twips,
173 Metric,
174}
175
176impl MapMode {
177 pub fn to_raw(&self) -> i32 {
179 match self {
180 MapMode::Text => wxdragon_sys::WXD_MM_TEXT as i32,
181 MapMode::Lometric => wxdragon_sys::WXD_MM_LOMETRIC as i32,
182 MapMode::Twips => wxdragon_sys::WXD_MM_TWIPS as i32,
183 MapMode::Metric => wxdragon_sys::WXD_MM_METRIC as i32,
184 }
185 }
186
187 pub fn from_raw(value: i32) -> Self {
189 match value {
190 _ if value == wxdragon_sys::WXD_MM_TEXT as i32 => MapMode::Text,
191 _ if value == wxdragon_sys::WXD_MM_LOMETRIC as i32 => MapMode::Lometric,
192 _ if value == wxdragon_sys::WXD_MM_TWIPS as i32 => MapMode::Twips,
193 _ if value == wxdragon_sys::WXD_MM_METRIC as i32 => MapMode::Metric,
194 _ => MapMode::Text,
195 }
196 }
197}
198
199#[derive(Debug, Clone, Copy, PartialEq, Eq)]
201pub struct TextAlignment {
202 bits: i32,
203}
204
205impl TextAlignment {
206 pub const INVALID: Self = Self {
207 bits: wxdragon_sys::WXD_ALIGN_INVALID as i32,
208 };
209 pub const LEFT: Self = Self {
210 bits: wxdragon_sys::WXD_ALIGN_LEFT as i32,
211 };
212 pub const TOP: Self = Self {
213 bits: wxdragon_sys::WXD_ALIGN_TOP as i32,
214 };
215 pub const RIGHT: Self = Self {
216 bits: wxdragon_sys::WXD_ALIGN_RIGHT as i32,
217 };
218 pub const BOTTOM: Self = Self {
219 bits: wxdragon_sys::WXD_ALIGN_BOTTOM as i32,
220 };
221 pub const CENTER_HORIZONTAL: Self = Self {
222 bits: wxdragon_sys::WXD_ALIGN_CENTRE_HORIZONTAL as i32,
223 };
224 pub const CENTER_VERTICAL: Self = Self {
225 bits: wxdragon_sys::WXD_ALIGN_CENTRE_VERTICAL as i32,
226 };
227 pub const CENTER: Self = Self {
228 bits: wxdragon_sys::WXD_ALIGN_CENTRE as i32,
229 };
230
231 pub const fn bits(&self) -> i32 {
232 self.bits
233 }
234
235 pub const fn from_bits(bits: i32) -> Self {
236 Self { bits }
237 }
238}
239
240impl std::ops::BitOr for TextAlignment {
241 type Output = Self;
242 fn bitor(self, rhs: Self) -> Self::Output {
243 Self {
244 bits: self.bits | rhs.bits,
245 }
246 }
247}
248
249impl std::ops::BitOrAssign for TextAlignment {
250 fn bitor_assign(&mut self, rhs: Self) {
251 self.bits |= rhs.bits;
252 }
253}
254
255#[derive(Debug, Clone, Copy, PartialEq, Eq)]
257pub enum GradientDirection {
258 North,
259 South,
260 East,
261 West,
262}
263
264impl GradientDirection {
265 pub fn to_raw(&self) -> i32 {
267 match self {
268 GradientDirection::North => wxdragon_sys::WXD_NORTH as i32,
269 GradientDirection::South => wxdragon_sys::WXD_SOUTH as i32,
270 GradientDirection::East => wxdragon_sys::WXD_EAST as i32,
271 GradientDirection::West => wxdragon_sys::WXD_WEST as i32,
272 }
273 }
274}
275
276#[derive(Debug, Clone, Copy, PartialEq, Eq)]
278pub struct Point {
279 pub x: i32,
280 pub y: i32,
281}
282
283impl Point {
284 pub fn new(x: i32, y: i32) -> Self {
285 Self { x, y }
286 }
287}
288
289impl From<Point> for wxdragon_sys::wxd_Point {
290 fn from(point: Point) -> Self {
291 wxdragon_sys::wxd_Point { x: point.x, y: point.y }
292 }
293}
294
295impl From<wxdragon_sys::wxd_Point> for Point {
296 fn from(point: wxdragon_sys::wxd_Point) -> Self {
297 Point { x: point.x, y: point.y }
298 }
299}
300
301#[derive(Debug, Clone, Copy, PartialEq, Eq)]
303pub struct Rect {
304 pub x: i32,
305 pub y: i32,
306 pub width: i32,
307 pub height: i32,
308}
309
310impl Rect {
311 pub fn new(x: i32, y: i32, width: i32, height: i32) -> Self {
312 Self { x, y, width, height }
313 }
314}
315
316impl From<Rect> for wxdragon_sys::wxd_Rect {
317 fn from(rect: Rect) -> Self {
318 wxdragon_sys::wxd_Rect {
319 x: rect.x,
320 y: rect.y,
321 width: rect.width,
322 height: rect.height,
323 }
324 }
325}
326
327impl From<wxdragon_sys::wxd_Rect> for Rect {
328 fn from(rect: wxdragon_sys::wxd_Rect) -> Self {
329 Rect {
330 x: rect.x,
331 y: rect.y,
332 width: rect.width,
333 height: rect.height,
334 }
335 }
336}
337
338pub mod auto_buffered_paint_dc;
339pub mod client_dc;
340pub mod memory_dc;
341pub mod paint_dc;
342pub mod screen_dc;
343pub mod window_dc;
344
345pub use auto_buffered_paint_dc::AutoBufferedPaintDC;
346pub use client_dc::ClientDC;
347pub use memory_dc::MemoryDC;
348pub use paint_dc::PaintDC;
349pub use screen_dc::ScreenDC;
350pub use window_dc::WindowDC;
351
352pub use crate::bitmap::Bitmap;
354pub use crate::color::Colour;
355pub use crate::font::Font;
356
357#[derive(Debug, Clone, Copy)]
359pub struct BlitConfig {
360 pub dest_x: i32,
361 pub dest_y: i32,
362 pub width: i32,
363 pub height: i32,
364 pub src_x: i32,
365 pub src_y: i32,
366 pub logical_func: LogicalFunction,
367 pub use_mask: bool,
368 pub src_mask_x: i32,
369 pub src_mask_y: i32,
370}
371
372impl BlitConfig {
373 pub fn new(dest_x: i32, dest_y: i32, width: i32, height: i32, src_x: i32, src_y: i32) -> Self {
374 Self {
375 dest_x,
376 dest_y,
377 width,
378 height,
379 src_x,
380 src_y,
381 logical_func: LogicalFunction::Copy,
382 use_mask: false,
383 src_mask_x: -1,
384 src_mask_y: -1,
385 }
386 }
387
388 pub fn with_logical_func(mut self, logical_func: LogicalFunction) -> Self {
389 self.logical_func = logical_func;
390 self
391 }
392
393 pub fn with_mask(mut self, src_mask_x: i32, src_mask_y: i32) -> Self {
394 self.use_mask = true;
395 self.src_mask_x = src_mask_x;
396 self.src_mask_y = src_mask_y;
397 self
398 }
399}
400
401#[derive(Debug, Clone, Copy)]
403pub struct StretchBlitConfig {
404 pub dest_x: i32,
405 pub dest_y: i32,
406 pub dest_width: i32,
407 pub dest_height: i32,
408 pub src_x: i32,
409 pub src_y: i32,
410 pub src_width: i32,
411 pub src_height: i32,
412 pub logical_func: LogicalFunction,
413 pub use_mask: bool,
414 pub src_mask_x: i32,
415 pub src_mask_y: i32,
416}
417
418impl StretchBlitConfig {
419 pub fn with_logical_func(mut self, logical_func: LogicalFunction) -> Self {
420 self.logical_func = logical_func;
421 self
422 }
423
424 pub fn with_mask(mut self, src_mask_x: i32, src_mask_y: i32) -> Self {
425 self.use_mask = true;
426 self.src_mask_x = src_mask_x;
427 self.src_mask_y = src_mask_y;
428 self
429 }
430}
431
432pub trait DeviceContext {
434 fn dc_ptr(&self) -> *mut wxdragon_sys::wxd_DC_t;
436
437 fn clear(&self) {
439 unsafe {
440 wxdragon_sys::wxd_DC_Clear(self.dc_ptr());
441 }
442 }
443
444 fn set_background(&self, colour: Colour) {
446 unsafe {
447 wxdragon_sys::wxd_DC_SetBackground(self.dc_ptr(), colour.into());
448 }
449 }
450
451 fn set_background_mode(&self, mode: BackgroundMode) {
453 unsafe {
454 wxdragon_sys::wxd_DC_SetBackgroundMode(self.dc_ptr(), mode.to_raw());
455 }
456 }
457
458 fn set_text_background(&self, colour: Colour) {
460 unsafe {
461 wxdragon_sys::wxd_DC_SetTextBackground(self.dc_ptr(), colour.into());
462 }
463 }
464
465 fn set_text_foreground(&self, colour: Colour) {
467 unsafe {
468 wxdragon_sys::wxd_DC_SetTextForeground(self.dc_ptr(), colour.into());
469 }
470 }
471
472 fn set_font(&self, font: &Font) {
474 unsafe {
475 wxdragon_sys::wxd_DC_SetFont(self.dc_ptr(), font.as_ptr());
476 }
477 }
478
479 fn set_pen(&self, colour: Colour, width: i32, style: PenStyle) {
481 unsafe {
482 wxdragon_sys::wxd_DC_SetPen(self.dc_ptr(), colour.into(), width, style.bits() as i32);
483 }
484 }
485
486 fn set_brush(&self, colour: Colour, style: BrushStyle) {
488 unsafe {
489 wxdragon_sys::wxd_DC_SetBrush(self.dc_ptr(), colour.into(), style.bits() as i32);
490 }
491 }
492
493 fn draw_point(&self, x: i32, y: i32) {
495 unsafe {
496 wxdragon_sys::wxd_DC_DrawPoint(self.dc_ptr(), x, y);
497 }
498 }
499
500 fn draw_line(&self, x1: i32, y1: i32, x2: i32, y2: i32) {
502 unsafe {
503 wxdragon_sys::wxd_DC_DrawLine(self.dc_ptr(), x1, y1, x2, y2);
504 }
505 }
506
507 fn draw_rectangle(&self, x: i32, y: i32, width: i32, height: i32) {
509 unsafe {
510 wxdragon_sys::wxd_DC_DrawRectangle(self.dc_ptr(), x, y, width, height);
511 }
512 }
513
514 fn draw_circle(&self, x: i32, y: i32, radius: i32) {
516 unsafe {
517 wxdragon_sys::wxd_DC_DrawCircle(self.dc_ptr(), x, y, radius);
518 }
519 }
520
521 fn draw_ellipse(&self, x: i32, y: i32, width: i32, height: i32) {
523 unsafe {
524 wxdragon_sys::wxd_DC_DrawEllipse(self.dc_ptr(), x, y, width, height);
525 }
526 }
527
528 fn draw_rounded_rectangle(&self, x: i32, y: i32, width: i32, height: i32, radius: f64) {
530 unsafe {
531 wxdragon_sys::wxd_DC_DrawRoundedRectangle(self.dc_ptr(), x, y, width, height, radius);
532 }
533 }
534
535 fn draw_text(&self, text: &str, x: i32, y: i32) {
537 use std::ffi::CString;
538 if let Ok(c_text) = CString::new(text) {
539 unsafe {
540 wxdragon_sys::wxd_DC_DrawText(self.dc_ptr(), c_text.as_ptr(), x, y);
541 }
542 }
543 }
544
545 fn draw_bitmap(&self, bitmap: &Bitmap, x: i32, y: i32, transparent: bool) {
547 unsafe { wxdragon_sys::wxd_DC_DrawBitmap(self.dc_ptr(), bitmap.as_const_ptr(), x, y, transparent) };
548 }
549
550 fn get_size(&self) -> (i32, i32) {
552 unsafe {
553 let size = wxdragon_sys::wxd_DC_GetSize(self.dc_ptr());
554 (size.width, size.height)
555 }
556 }
557
558 fn get_text_extent(&self, text: &str) -> (i32, i32) {
560 use std::ffi::CString;
561 if let Ok(c_text) = CString::new(text) {
562 let mut width = 0;
563 let mut height = 0;
564 unsafe { wxdragon_sys::wxd_DC_GetTextExtent(self.dc_ptr(), c_text.as_ptr(), &mut width, &mut height) };
565 (width, height)
566 } else {
567 (0, 0)
568 }
569 }
570
571 fn set_clipping_region(&self, x: i32, y: i32, width: i32, height: i32) {
573 unsafe {
574 wxdragon_sys::wxd_DC_SetClippingRegion(self.dc_ptr(), x, y, width, height);
575 }
576 }
577
578 fn destroy_clipping_region(&self) {
580 unsafe { wxdragon_sys::wxd_DC_DestroyClippingRegion(self.dc_ptr()) };
581 }
582
583 fn draw_polygon(&self, points: &[Point], x_offset: i32, y_offset: i32, fill_mode: PolygonFillMode) {
585 if points.is_empty() {
586 return;
587 }
588
589 let mut ffi_points: Vec<wxdragon_sys::wxd_Point> = points.iter().map(|p| (*p).into()).collect();
590
591 unsafe {
592 wxdragon_sys::wxd_DC_DrawPolygon(
593 self.dc_ptr(),
594 ffi_points.len() as i32,
595 ffi_points.as_mut_ptr(),
596 x_offset,
597 y_offset,
598 fill_mode.to_raw(),
599 )
600 };
601 }
602
603 fn draw_elliptic_arc(&self, x: i32, y: i32, width: i32, height: i32, start_angle: f64, end_angle: f64) {
605 unsafe { wxdragon_sys::wxd_DC_DrawEllipticArc(self.dc_ptr(), x, y, width, height, start_angle, end_angle) };
606 }
607
608 fn draw_lines(&self, points: &[Point], x_offset: i32, y_offset: i32) {
610 if points.is_empty() {
611 return;
612 }
613
614 let mut ffi_points: Vec<wxdragon_sys::wxd_Point> = points.iter().map(|p| (*p).into()).collect();
615
616 unsafe {
617 wxdragon_sys::wxd_DC_DrawLines(
618 self.dc_ptr(),
619 ffi_points.len() as i32,
620 ffi_points.as_mut_ptr(),
621 x_offset,
622 y_offset,
623 )
624 };
625 }
626
627 fn draw_arc(&self, x1: i32, y1: i32, x2: i32, y2: i32, xc: i32, yc: i32) {
629 unsafe {
630 wxdragon_sys::wxd_DC_DrawArc(self.dc_ptr(), x1, y1, x2, y2, xc, yc);
631 }
632 }
633
634 fn draw_spline(&self, points: &[Point]) {
636 if points.is_empty() {
637 return;
638 }
639
640 let mut ffi_points: Vec<wxdragon_sys::wxd_Point> = points.iter().map(|p| (*p).into()).collect();
641
642 unsafe { wxdragon_sys::wxd_DC_DrawSpline(self.dc_ptr(), ffi_points.len() as i32, ffi_points.as_mut_ptr()) };
643 }
644
645 fn draw_rotated_text(&self, text: &str, x: i32, y: i32, angle: f64) {
647 use std::ffi::CString;
648 if let Ok(c_text) = CString::new(text) {
649 unsafe { wxdragon_sys::wxd_DC_DrawRotatedText(self.dc_ptr(), c_text.as_ptr(), x, y, angle) };
650 }
651 }
652
653 fn draw_label(&self, text: &str, rect: Rect, alignment: TextAlignment, index_accel: i32) {
655 use std::ffi::CString;
656 if let Ok(c_text) = CString::new(text) {
657 unsafe { wxdragon_sys::wxd_DC_DrawLabel(self.dc_ptr(), c_text.as_ptr(), rect.into(), alignment.bits(), index_accel) };
658 }
659 }
660
661 fn blit(&self, source: &dyn DeviceContext, config: BlitConfig) -> bool {
663 unsafe {
664 wxdragon_sys::wxd_DC_Blit(
665 self.dc_ptr(),
666 config.dest_x,
667 config.dest_y,
668 config.width,
669 config.height,
670 source.dc_ptr(),
671 config.src_x,
672 config.src_y,
673 config.logical_func.to_raw(),
674 config.use_mask,
675 config.src_mask_x,
676 config.src_mask_y,
677 )
678 }
679 }
680
681 fn stretch_blit(&self, source: &dyn DeviceContext, config: StretchBlitConfig) -> bool {
683 unsafe {
684 wxdragon_sys::wxd_DC_StretchBlit(
685 self.dc_ptr(),
686 config.dest_x,
687 config.dest_y,
688 config.dest_width,
689 config.dest_height,
690 source.dc_ptr(),
691 config.src_x,
692 config.src_y,
693 config.src_width,
694 config.src_height,
695 config.logical_func.to_raw(),
696 config.use_mask,
697 config.src_mask_x,
698 config.src_mask_y,
699 )
700 }
701 }
702
703 fn set_clipping_region_from_points(&self, points: &[Point]) {
705 if points.is_empty() {
706 return;
707 }
708
709 let mut ffi_points: Vec<wxdragon_sys::wxd_Point> = points.iter().map(|p| (*p).into()).collect();
710
711 unsafe {
712 wxdragon_sys::wxd_DC_SetClippingRegionFromPoints(self.dc_ptr(), ffi_points.len() as i32, ffi_points.as_mut_ptr())
713 };
714 }
715
716 fn get_clipping_box(&self) -> Rect {
718 let mut x = 0;
719 let mut y = 0;
720 let mut width = 0;
721 let mut height = 0;
722
723 unsafe { wxdragon_sys::wxd_DC_GetClippingBox(self.dc_ptr(), &mut x, &mut y, &mut width, &mut height) };
724
725 Rect::new(x, y, width, height)
726 }
727
728 fn set_device_origin(&self, x: i32, y: i32) {
730 unsafe { wxdragon_sys::wxd_DC_SetDeviceOrigin(self.dc_ptr(), x, y) };
731 }
732
733 fn set_logical_origin(&self, x: i32, y: i32) {
735 unsafe { wxdragon_sys::wxd_DC_SetLogicalOrigin(self.dc_ptr(), x, y) };
736 }
737
738 fn set_user_scale(&self, x_scale: f64, y_scale: f64) {
740 unsafe { wxdragon_sys::wxd_DC_SetUserScale(self.dc_ptr(), x_scale, y_scale) };
741 }
742
743 fn set_logical_scale(&self, x_scale: f64, y_scale: f64) {
745 unsafe { wxdragon_sys::wxd_DC_SetLogicalScale(self.dc_ptr(), x_scale, y_scale) };
746 }
747
748 fn set_map_mode(&self, mode: MapMode) {
750 unsafe { wxdragon_sys::wxd_DC_SetMapMode(self.dc_ptr(), mode.to_raw()) };
751 }
752
753 fn get_device_origin(&self) -> Point {
755 let origin = unsafe { wxdragon_sys::wxd_DC_GetDeviceOrigin(self.dc_ptr()) };
756 origin.into()
757 }
758
759 fn get_logical_origin(&self) -> Point {
761 let origin = unsafe { wxdragon_sys::wxd_DC_GetLogicalOrigin(self.dc_ptr()) };
762 origin.into()
763 }
764
765 fn get_user_scale(&self) -> (f64, f64) {
767 let mut x_scale = 0.0;
768 let mut y_scale = 0.0;
769
770 unsafe { wxdragon_sys::wxd_DC_GetUserScale(self.dc_ptr(), &mut x_scale, &mut y_scale) };
771
772 (x_scale, y_scale)
773 }
774
775 fn get_logical_scale(&self) -> (f64, f64) {
777 let mut x_scale = 0.0;
778 let mut y_scale = 0.0;
779
780 unsafe { wxdragon_sys::wxd_DC_GetLogicalScale(self.dc_ptr(), &mut x_scale, &mut y_scale) };
781
782 (x_scale, y_scale)
783 }
784
785 fn get_map_mode(&self) -> MapMode {
787 let mode = unsafe { wxdragon_sys::wxd_DC_GetMapMode(self.dc_ptr()) };
788 MapMode::from_raw(mode)
789 }
790
791 fn device_to_logical_x(&self, x: i32) -> i32 {
793 unsafe { wxdragon_sys::wxd_DC_DeviceToLogicalX(self.dc_ptr(), x) }
794 }
795
796 fn device_to_logical_y(&self, y: i32) -> i32 {
798 unsafe { wxdragon_sys::wxd_DC_DeviceToLogicalY(self.dc_ptr(), y) }
799 }
800
801 fn logical_to_device_x(&self, x: i32) -> i32 {
803 unsafe { wxdragon_sys::wxd_DC_LogicalToDeviceX(self.dc_ptr(), x) }
804 }
805
806 fn logical_to_device_y(&self, y: i32) -> i32 {
808 unsafe { wxdragon_sys::wxd_DC_LogicalToDeviceY(self.dc_ptr(), y) }
809 }
810
811 fn get_size_mm(&self) -> (i32, i32) {
813 let size = unsafe { wxdragon_sys::wxd_DC_GetSizeMM(self.dc_ptr()) };
814 (size.width, size.height)
815 }
816
817 fn get_full_text_extent(&self, text: &str, font: Option<&Font>) -> (i32, i32, i32, i32) {
819 use std::ffi::CString;
820 if let Ok(c_text) = CString::new(text) {
821 let mut width = 0;
822 let mut height = 0;
823 let mut descent = 0;
824 let mut external_leading = 0;
825
826 unsafe {
827 wxdragon_sys::wxd_DC_GetFullTextExtent(
828 self.dc_ptr(),
829 c_text.as_ptr(),
830 &mut width,
831 &mut height,
832 &mut descent,
833 &mut external_leading,
834 font.map(|f| f.as_ptr()).unwrap_or(std::ptr::null_mut()),
835 );
836 }
837 (width, height, descent, external_leading)
838 } else {
839 (0, 0, 0, 0)
840 }
841 }
842
843 fn get_multi_line_text_extent(&self, text: &str, font: Option<&Font>) -> (i32, i32, i32) {
845 use std::ffi::CString;
846 if let Ok(c_text) = CString::new(text) {
847 let mut width = 0;
848 let mut height = 0;
849 let mut height_line = 0;
850
851 unsafe {
852 wxdragon_sys::wxd_DC_GetMultiLineTextExtent(
853 self.dc_ptr(),
854 c_text.as_ptr(),
855 &mut width,
856 &mut height,
857 &mut height_line,
858 font.map(|f| f.as_ptr()).unwrap_or(std::ptr::null_mut()),
859 );
860 }
861 (width, height, height_line)
862 } else {
863 (0, 0, 0)
864 }
865 }
866
867 fn get_char_height(&self) -> i32 {
869 unsafe { wxdragon_sys::wxd_DC_GetCharHeight(self.dc_ptr()) }
870 }
871
872 fn get_char_width(&self) -> i32 {
874 unsafe { wxdragon_sys::wxd_DC_GetCharWidth(self.dc_ptr()) }
875 }
876
877 fn get_background(&self) -> Colour {
879 let colour = unsafe { wxdragon_sys::wxd_DC_GetBackground(self.dc_ptr()) };
880 Colour::new(colour.r, colour.g, colour.b, colour.a)
881 }
882
883 fn get_background_mode(&self) -> BackgroundMode {
885 let mode = unsafe { wxdragon_sys::wxd_DC_GetBackgroundMode(self.dc_ptr()) };
886 if mode == wxdragon_sys::WXD_TRANSPARENT as i32 {
887 BackgroundMode::Transparent
888 } else {
889 BackgroundMode::Solid
890 }
891 }
892
893 fn get_text_background(&self) -> Colour {
895 let colour = unsafe { wxdragon_sys::wxd_DC_GetTextBackground(self.dc_ptr()) };
896 Colour::new(colour.r, colour.g, colour.b, colour.a)
897 }
898
899 fn get_text_foreground(&self) -> Colour {
901 let colour = unsafe { wxdragon_sys::wxd_DC_GetTextForeground(self.dc_ptr()) };
902 Colour::new(colour.r, colour.g, colour.b, colour.a)
903 }
904
905 fn get_ppi(&self) -> (i32, i32) {
907 let ppi = unsafe { wxdragon_sys::wxd_DC_GetPPI(self.dc_ptr()) };
908 (ppi.width, ppi.height)
909 }
910
911 fn get_content_scale_factor(&self) -> f64 {
913 unsafe { wxdragon_sys::wxd_DC_GetContentScaleFactor(self.dc_ptr()) }
914 }
915
916 fn gradient_fill_linear(&self, rect: Rect, initial_colour: Colour, dest_colour: Colour, direction: GradientDirection) {
918 unsafe {
919 wxdragon_sys::wxd_DC_GradientFillLinear(
920 self.dc_ptr(),
921 rect.into(),
922 initial_colour.into(),
923 dest_colour.into(),
924 direction.to_raw(),
925 )
926 };
927 }
928
929 fn gradient_fill_concentric(&self, rect: Rect, initial_colour: Colour, dest_colour: Colour, circle_center: Point) {
931 unsafe {
932 wxdragon_sys::wxd_DC_GradientFillConcentric(
933 self.dc_ptr(),
934 rect.into(),
935 initial_colour.into(),
936 dest_colour.into(),
937 circle_center.into(),
938 )
939 };
940 }
941
942 fn flood_fill(&self, x: i32, y: i32, colour: Colour, style: FloodFillMode) -> bool {
944 unsafe { wxdragon_sys::wxd_DC_FloodFill(self.dc_ptr(), x, y, colour.into(), style.to_raw()) }
945 }
946
947 fn set_logical_function(&self, function: LogicalFunction) {
949 unsafe { wxdragon_sys::wxd_DC_SetLogicalFunction(self.dc_ptr(), function.to_raw()) };
950 }
951
952 fn get_logical_function(&self) -> LogicalFunction {
954 let function = unsafe { wxdragon_sys::wxd_DC_GetLogicalFunction(self.dc_ptr()) };
955 LogicalFunction::from_raw(function)
956 }
957}