1use crate::prelude::*;
2use skia_bindings::{self as sb, SkFontStyle, SkFontStyle_Weight, SkFontStyle_Width};
3use std::{fmt, ops::Deref};
4
5/// Wrapper type of a font weight.
6///
7/// Use Weight::from() to create a weight from an i32.
8/// Use *weight to pull out the wrapped value of the Weight.
9#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
10#[repr(transparent)]
11pub struct Weight(i32);
12
13native_transmutable!(i32, Weight, weight_layout);
14
15impl From<i32> for Weight {
16 fn from(weight: i32) -> Self {
17 Weight(weight)
18 }
19}
20
21impl Deref for Weight {
22 type Target = i32;
23 fn deref(&self) -> &Self::Target {
24 &self.0
25 }
26}
27
28#[allow(non_upper_case_globals)]
29impl Weight {
30 pub const INVISIBLE: Self = Self(SkFontStyle_Weight::kInvisible_Weight as _);
31 pub const THIN: Self = Self(SkFontStyle_Weight::kThin_Weight as _);
32 pub const EXTRA_LIGHT: Self = Self(SkFontStyle_Weight::kExtraLight_Weight as _);
33 pub const LIGHT: Self = Self(SkFontStyle_Weight::kLight_Weight as _);
34 pub const NORMAL: Self = Self(SkFontStyle_Weight::kNormal_Weight as _);
35 pub const MEDIUM: Self = Self(SkFontStyle_Weight::kMedium_Weight as _);
36 pub const SEMI_BOLD: Self = Self(SkFontStyle_Weight::kSemiBold_Weight as _);
37 pub const BOLD: Self = Self(SkFontStyle_Weight::kBold_Weight as _);
38 pub const EXTRA_BOLD: Self = Self(SkFontStyle_Weight::kExtraBold_Weight as _);
39 pub const BLACK: Self = Self(SkFontStyle_Weight::kBlack_Weight as _);
40 pub const EXTRA_BLACK: Self = Self(SkFontStyle_Weight::kExtraBlack_Weight as _);
41}
42
43/// Wrapper type for the width of a font.
44///
45/// To create a width of a font from an i32, use Width::from().
46/// To access the underlying value of the font weight, dereference *weight.
47#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
48#[repr(transparent)]
49pub struct Width(i32);
50
51native_transmutable!(i32, Width, width_layout);
52
53impl From<i32> for Width {
54 fn from(width: i32) -> Self {
55 Width(width)
56 }
57}
58
59impl Deref for Width {
60 type Target = i32;
61 fn deref(&self) -> &Self::Target {
62 &self.0
63 }
64}
65
66#[allow(non_upper_case_globals)]
67impl Width {
68 pub const ULTRA_CONDENSED: Self = Self(SkFontStyle_Width::kUltraCondensed_Width as _);
69 pub const EXTRA_CONDENSED: Self = Self(SkFontStyle_Width::kExtraCondensed_Width as _);
70 pub const CONDENSED: Self = Self(SkFontStyle_Width::kCondensed_Width as _);
71 pub const SEMI_CONDENSED: Self = Self(SkFontStyle_Width::kSemiCondensed_Width as _);
72 pub const NORMAL: Self = Self(SkFontStyle_Width::kNormal_Width as _);
73 pub const SEMI_EXPANDED: Self = Self(SkFontStyle_Width::kSemiExpanded_Width as _);
74 pub const EXPANDED: Self = Self(SkFontStyle_Width::kExpanded_Width as _);
75 pub const EXTRA_EXPANDED: Self = Self(SkFontStyle_Width::kExtraExpanded_Width as _);
76 pub const ULTRA_EXPANDED: Self = Self(SkFontStyle_Width::kUltraExpanded_Width as _);
77}
78
79pub use skia_bindings::SkFontStyle_Slant as Slant;
80variant_name!(Slant::Upright);
81
82// TODO: implement Display
83#[derive(Copy, Clone)]
84#[repr(transparent)]
85pub struct FontStyle(SkFontStyle);
86
87native_transmutable!(SkFontStyle, FontStyle, font_style_layout);
88
89impl PartialEq for FontStyle {
90 fn eq(&self, rhs: &Self) -> bool {
91 unsafe { sb::C_SkFontStyle_Equals(self.native(), rhs:rhs.native()) }
92 }
93}
94
95impl Default for FontStyle {
96 fn default() -> Self {
97 FontStyle::construct(|fs: *mut SkFontStyle| unsafe { sb::C_SkFontStyle_Construct(uninitialized:fs) })
98 }
99}
100
101impl fmt::Debug for FontStyle {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 f&mut DebugStruct<'_, '_>.debug_struct("FontStyle")
104 .field("weight", &self.weight())
105 .field("width", &self.width())
106 .field(name:"slant", &self.slant())
107 .finish()
108 }
109}
110
111impl FontStyle {
112 pub fn new(weight: Weight, width: Width, slant: Slant) -> Self {
113 Self::construct(|fs| unsafe {
114 sb::C_SkFontStyle_Construct2(fs, weight.into_native(), width.into_native(), slant)
115 })
116 }
117
118 pub fn weight(self) -> Weight {
119 Weight::from_native_c(unsafe { sb::C_SkFontStyle_weight(self.native()) })
120 }
121
122 pub fn width(self) -> Width {
123 Width::from_native_c(unsafe { sb::C_SkFontStyle_width(self.native()) })
124 }
125
126 pub fn slant(self) -> Slant {
127 unsafe { sb::C_SkFontStyle_slant(self.native()) }
128 }
129
130 pub fn normal() -> FontStyle {
131 *font_style_static::NORMAL
132 }
133
134 pub fn bold() -> FontStyle {
135 *font_style_static::BOLD
136 }
137
138 pub fn italic() -> FontStyle {
139 *font_style_static::ITALIC
140 }
141
142 pub fn bold_italic() -> FontStyle {
143 *font_style_static::BOLD_ITALIC
144 }
145}
146
147mod font_style_static {
148 use super::{FontStyle, Slant, Weight, Width};
149
150 lazy_static! {
151 pub static ref NORMAL: FontStyle =
152 FontStyle::new(Weight::NORMAL, Width::NORMAL, Slant::Upright);
153 pub static ref BOLD: FontStyle =
154 FontStyle::new(Weight::BOLD, Width::NORMAL, Slant::Upright);
155 pub static ref ITALIC: FontStyle =
156 FontStyle::new(Weight::NORMAL, Width::NORMAL, Slant::Italic);
157 pub static ref BOLD_ITALIC: FontStyle =
158 FontStyle::new(Weight::BOLD, Width::NORMAL, Slant::Italic);
159 }
160}
161
162#[test]
163fn test_equality() {
164 let style: FontStyle = Default::default();
165 let style2: FontStyle = Default::default();
166 assert!(style == style2);
167}
168