| 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 | |