1 | use std::fmt; |
2 | |
3 | use skia_bindings::{self as sb, SkPixelGeometry, SkSurfaceProps}; |
4 | |
5 | use crate::{prelude::*, scalar}; |
6 | |
7 | // TODO: use the enum rewriter and strip underscores? |
8 | #[derive (Copy, Clone, PartialEq, Eq, Debug, Default)] |
9 | #[repr (i32)] |
10 | pub enum PixelGeometry { |
11 | #[default] |
12 | Unknown = SkPixelGeometry::kUnknown_SkPixelGeometry as _, |
13 | RGBH = SkPixelGeometry::kRGB_H_SkPixelGeometry as _, |
14 | BGRH = SkPixelGeometry::kBGR_H_SkPixelGeometry as _, |
15 | RGBV = SkPixelGeometry::kRGB_V_SkPixelGeometry as _, |
16 | BGRV = SkPixelGeometry::kBGR_V_SkPixelGeometry as _, |
17 | } |
18 | |
19 | native_transmutable!(SkPixelGeometry, PixelGeometry, pixel_geometry_layout); |
20 | |
21 | impl PixelGeometry { |
22 | pub fn is_rgb(self) -> bool { |
23 | self == PixelGeometry::RGBH || self == PixelGeometry::RGBV |
24 | } |
25 | |
26 | pub fn is_bgr(self) -> bool { |
27 | self == PixelGeometry::BGRH || self == PixelGeometry::BGRV |
28 | } |
29 | |
30 | pub fn is_h(self) -> bool { |
31 | self == PixelGeometry::RGBH || self == PixelGeometry::BGRH |
32 | } |
33 | |
34 | pub fn is_v(self) -> bool { |
35 | self == PixelGeometry::RGBV || self == PixelGeometry::BGRV |
36 | } |
37 | } |
38 | |
39 | bitflags! { |
40 | #[derive (Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] |
41 | pub struct SurfacePropsFlags: u32 { |
42 | #[allow (clippy::unnecessary_cast)] |
43 | const DEFAULT = sb::SkSurfaceProps_Flags_kDefault_Flag as u32; |
44 | #[allow (clippy::unnecessary_cast)] |
45 | const USE_DEVICE_INDEPENDENT_FONTS = |
46 | sb::SkSurfaceProps_Flags_kUseDeviceIndependentFonts_Flag as u32; |
47 | #[allow (clippy::unnecessary_cast)] |
48 | const DYNAMIC_MSAA = |
49 | sb::SkSurfaceProps_Flags_kDynamicMSAA_Flag as u32; |
50 | #[allow (clippy::unnecessary_cast)] |
51 | const ALWAYS_DITHER = |
52 | sb::SkSurfaceProps_Flags_kAlwaysDither_Flag as u32; |
53 | } |
54 | } |
55 | |
56 | impl Default for SurfacePropsFlags { |
57 | fn default() -> Self { |
58 | SurfacePropsFlags::empty() |
59 | } |
60 | } |
61 | |
62 | #[derive (Copy, Clone)] |
63 | #[repr (transparent)] |
64 | pub struct SurfaceProps(SkSurfaceProps); |
65 | |
66 | native_transmutable!(SkSurfaceProps, SurfaceProps, surface_props_layout); |
67 | |
68 | impl PartialEq for SurfaceProps { |
69 | fn eq(&self, other: &Self) -> bool { |
70 | unsafe { sb::C_SkSurfaceProps_Equals(self.native(), rhs:other.native()) } |
71 | } |
72 | } |
73 | |
74 | impl Eq for SurfaceProps {} |
75 | |
76 | impl Default for SurfaceProps { |
77 | fn default() -> Self { |
78 | SurfaceProps::new(flags:Default::default(), pixel_geometry:Default::default()) |
79 | } |
80 | } |
81 | |
82 | impl fmt::Debug for SurfaceProps { |
83 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
84 | f&mut DebugStruct<'_, '_>.debug_struct("SurfaceProps" ) |
85 | .field("flags" , &self.flags()) |
86 | .field("pixel_geometry" , &self.pixel_geometry()) |
87 | .field("text_contrast" , &self.text_contrast()) |
88 | .field(name:"text_gamma" , &self.text_gamma()) |
89 | .finish() |
90 | } |
91 | } |
92 | |
93 | impl SurfaceProps { |
94 | pub fn new(flags: SurfacePropsFlags, pixel_geometry: PixelGeometry) -> SurfaceProps { |
95 | Self::from_native_c(unsafe { |
96 | SkSurfaceProps::new1(flags.bits(), pixel_geometry.into_native()) |
97 | }) |
98 | } |
99 | |
100 | pub fn new_with_text_properties( |
101 | flags: SurfacePropsFlags, |
102 | pixel_geometry: PixelGeometry, |
103 | text_contrast: scalar, |
104 | text_gamma: scalar, |
105 | ) -> SurfaceProps { |
106 | Self::from_native_c(unsafe { |
107 | SkSurfaceProps::new2( |
108 | flags.bits(), |
109 | pixel_geometry.into_native(), |
110 | text_contrast, |
111 | text_gamma, |
112 | ) |
113 | }) |
114 | } |
115 | |
116 | pub fn flags(self) -> SurfacePropsFlags { |
117 | SurfacePropsFlags::from_bits_truncate(self.native().fFlags) |
118 | } |
119 | |
120 | #[must_use ] |
121 | pub fn clone_with_pixel_geometry(&self, new_pixel_geometry: PixelGeometry) -> Self { |
122 | Self::new_with_text_properties( |
123 | self.flags(), |
124 | new_pixel_geometry, |
125 | self.text_contrast(), |
126 | self.text_gamma(), |
127 | ) |
128 | } |
129 | |
130 | pub const MAX_CONTRAST_INCLUSIVE: scalar = 1.; |
131 | pub const MIN_CONTRAST_INCLUSIVE: scalar = 0.; |
132 | pub const MAX_GAMMA_EXCLUSIVE: scalar = 4.; |
133 | pub const MIN_GAMMA_INCLUSIVE: scalar = 0.; |
134 | |
135 | pub fn pixel_geometry(self) -> PixelGeometry { |
136 | PixelGeometry::from_native_c(self.native().fPixelGeometry) |
137 | } |
138 | |
139 | pub fn text_contrast(self) -> scalar { |
140 | self.native().fTextContrast |
141 | } |
142 | |
143 | pub fn text_gamma(self) -> scalar { |
144 | self.native().fTextGamma |
145 | } |
146 | |
147 | pub fn is_use_device_independent_fonts(self) -> bool { |
148 | self.flags() |
149 | .contains(SurfacePropsFlags::USE_DEVICE_INDEPENDENT_FONTS) |
150 | } |
151 | |
152 | pub fn is_always_dither(self) -> bool { |
153 | self.flags().contains(SurfacePropsFlags::ALWAYS_DITHER) |
154 | } |
155 | } |
156 | |
157 | #[test ] |
158 | fn create() { |
159 | let props = SurfaceProps::new( |
160 | SurfacePropsFlags::USE_DEVICE_INDEPENDENT_FONTS, |
161 | PixelGeometry::RGBH, |
162 | ); |
163 | assert_eq!( |
164 | SurfacePropsFlags::USE_DEVICE_INDEPENDENT_FONTS, |
165 | props.flags() |
166 | ); |
167 | assert_eq!(PixelGeometry::RGBH, props.pixel_geometry()); |
168 | assert!(props.is_use_device_independent_fonts()); |
169 | } |
170 | |