skia_safe/core/
surface_props.rs

1use std::fmt;
2
3use skia_bindings::{self as sb, SkPixelGeometry, SkSurfaceProps};
4
5use crate::{prelude::*, scalar};
6
7// TODO: use the enum rewriter and strip underscores?
8#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
9#[repr(i32)]
10pub 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
19native_transmutable!(SkPixelGeometry, PixelGeometry, pixel_geometry_layout);
20
21impl 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
39bitflags! {
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
56impl Default for SurfacePropsFlags {
57    fn default() -> Self {
58        SurfacePropsFlags::empty()
59    }
60}
61
62#[derive(Copy, Clone)]
63#[repr(transparent)]
64pub struct SurfaceProps(SkSurfaceProps);
65
66native_transmutable!(SkSurfaceProps, SurfaceProps, surface_props_layout);
67
68impl PartialEq for SurfaceProps {
69    fn eq(&self, other: &Self) -> bool {
70        unsafe { sb::C_SkSurfaceProps_Equals(self.native(), other.native()) }
71    }
72}
73
74impl Eq for SurfaceProps {}
75
76impl Default for SurfaceProps {
77    fn default() -> Self {
78        SurfaceProps::new(Default::default(), Default::default())
79    }
80}
81
82impl fmt::Debug for SurfaceProps {
83    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84        f.debug_struct("SurfaceProps")
85            .field("flags", &self.flags())
86            .field("pixel_geometry", &self.pixel_geometry())
87            .field("text_contrast", &self.text_contrast())
88            .field("text_gamma", &self.text_gamma())
89            .finish()
90    }
91}
92
93impl 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]
158fn 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}