1use crate::bindgen::FPDF_DWORD;
4use crate::error::PdfiumError;
5
6#[derive(Debug, Copy, Clone)]
14pub struct PdfColor {
15 r: u8,
16 g: u8,
17 b: u8,
18 a: u8,
19}
20
21impl PdfColor {
22 pub const WHITE: PdfColor = PdfColor::new(255, 255, 255, 255);
23 pub const BLACK: PdfColor = PdfColor::new(0, 0, 0, 255);
24
25 #[deprecated(
26 since = "0.8.6",
27 note = "The SOLID_ prefix is superfluous. Use PdfColor::WHITE instead."
28 )]
29 pub const SOLID_WHITE: PdfColor = PdfColor::new(255, 255, 255, 255);
30 #[deprecated(
31 since = "0.8.6",
32 note = "The SOLID_ prefix is superfluous. Use PdfColor::RED instead."
33 )]
34 pub const SOLID_RED: PdfColor = PdfColor::new(255, 0, 0, 255);
35 #[deprecated(
36 since = "0.8.6",
37 note = "The SOLID_ prefix is superfluous. Use PdfColor::GREEN instead."
38 )]
39 pub const SOLID_GREEN: PdfColor = PdfColor::new(0, 255, 0, 255);
40 #[deprecated(
41 since = "0.8.6",
42 note = "The SOLID_ prefix is superfluous. Use PdfColor::BLUE instead."
43 )]
44 pub const SOLID_BLUE: PdfColor = PdfColor::new(0, 0, 255, 255);
45 #[deprecated(
46 since = "0.8.6",
47 note = "The SOLID_ prefix is superfluous. Use PdfColor::MAGENTA instead."
48 )]
49 pub const SOLID_MAGENTA: PdfColor = PdfColor::new(255, 0, 255, 255);
50 #[deprecated(
51 since = "0.8.6",
52 note = "The SOLID_ prefix is superfluous. Use PdfColor::CYAN instead."
53 )]
54 pub const SOLID_CYAN: PdfColor = PdfColor::new(0, 255, 255, 255);
55 #[deprecated(
56 since = "0.8.6",
57 note = "The SOLID_ prefix is superfluous. Use PdfColor::YELLOW instead."
58 )]
59 pub const SOLID_YELLOW: PdfColor = PdfColor::new(255, 255, 0, 255);
60 #[deprecated(
61 since = "0.8.6",
62 note = "The SOLID_ prefix is superfluous. Use PdfColor::BLACK instead."
63 )]
64 pub const SOLID_BLACK: PdfColor = PdfColor::new(0, 0, 0, 255);
65
66 pub const GREY_90: PdfColor = PdfColor::new(230, 230, 230, 255);
67 pub const GREY_80: PdfColor = PdfColor::new(204, 204, 204, 255);
68 pub const GREY_70: PdfColor = PdfColor::new(179, 179, 179, 255);
69 pub const GREY_60: PdfColor = PdfColor::new(153, 153, 153, 255);
70 pub const GREY_50: PdfColor = PdfColor::new(128, 128, 128, 255);
71 pub const GREY_40: PdfColor = PdfColor::new(102, 102, 102, 255);
72 pub const GREY_30: PdfColor = PdfColor::new(77, 77, 77, 255);
73 pub const GREY_20: PdfColor = PdfColor::new(51, 51, 51, 255);
74 pub const GREY_10: PdfColor = PdfColor::new(26, 26, 26, 255);
75
76 pub const LIME: PdfColor = PdfColor::new(0, 255, 0, 255);
79 pub const BLUE: PdfColor = PdfColor::new(0, 0, 255, 255);
80 pub const YELLOW: PdfColor = PdfColor::new(255, 255, 0, 255);
81 pub const CYAN: PdfColor = PdfColor::new(0, 255, 255, 255);
82 pub const MAGENTA: PdfColor = PdfColor::new(255, 0, 255, 255);
83 pub const SILVER: PdfColor = PdfColor::new(192, 192, 192, 255);
84 pub const OLIVE: PdfColor = PdfColor::new(128, 128, 0, 255);
85 pub const PURPLE: PdfColor = PdfColor::new(128, 0, 128, 255);
86 pub const TEAL: PdfColor = PdfColor::new(0, 128, 128, 255);
87 pub const NAVY: PdfColor = PdfColor::new(0, 0, 128, 255);
88 pub const MAROON: PdfColor = PdfColor::new(128, 0, 0, 255);
89 pub const DARK_RED: PdfColor = PdfColor::new(139, 0, 0, 255);
90 pub const BROWN: PdfColor = PdfColor::new(165, 42, 42, 255);
91 pub const FIREBRICK: PdfColor = PdfColor::new(178, 34, 34, 255);
92 pub const CRIMSON: PdfColor = PdfColor::new(220, 20, 60, 255);
93 pub const RED: PdfColor = PdfColor::new(255, 0, 0, 255);
94 pub const TOMATO: PdfColor = PdfColor::new(255, 99, 71, 255);
95 pub const CORAL: PdfColor = PdfColor::new(255, 127, 80, 255);
96 pub const INDIAN_RED: PdfColor = PdfColor::new(205, 92, 92, 255);
97 pub const LIGHT_CORAL: PdfColor = PdfColor::new(240, 128, 128, 255);
98 pub const DARK_SALMON: PdfColor = PdfColor::new(233, 150, 122, 255);
99 pub const SALMON: PdfColor = PdfColor::new(250, 128, 114, 255);
100 pub const LIGHT_SALMON: PdfColor = PdfColor::new(255, 160, 122, 255);
101 pub const ORANGE_RED: PdfColor = PdfColor::new(255, 69, 0, 255);
102 pub const DARK_ORANGE: PdfColor = PdfColor::new(255, 140, 0, 255);
103 pub const ORANGE: PdfColor = PdfColor::new(255, 165, 0, 255);
104 pub const GOLD: PdfColor = PdfColor::new(255, 215, 0, 255);
105 pub const DARK_GOLDEN_ROD: PdfColor = PdfColor::new(184, 134, 11, 255);
106 pub const GOLDEN_ROD: PdfColor = PdfColor::new(218, 165, 32, 255);
107 pub const PALE_GOLDEN_ROD: PdfColor = PdfColor::new(238, 232, 170, 255);
108 pub const DARK_KHAKI: PdfColor = PdfColor::new(189, 183, 107, 255);
109 pub const KHAKI: PdfColor = PdfColor::new(240, 230, 140, 255);
110 pub const YELLOW_GREEN: PdfColor = PdfColor::new(154, 205, 50, 255);
111 pub const DARK_OLIVE_GREEN: PdfColor = PdfColor::new(85, 107, 47, 255);
112 pub const OLIVE_DRAB: PdfColor = PdfColor::new(107, 142, 35, 255);
113 pub const LAWN_GREEN: PdfColor = PdfColor::new(124, 252, 0, 255);
114 pub const CHARTREUSE: PdfColor = PdfColor::new(127, 255, 0, 255);
115 pub const GREEN_YELLOW: PdfColor = PdfColor::new(173, 255, 47, 255);
116 pub const DARK_GREEN: PdfColor = PdfColor::new(0, 100, 0, 255);
117 pub const GREEN: PdfColor = PdfColor::new(0, 128, 0, 255);
118 pub const FOREST_GREEN: PdfColor = PdfColor::new(34, 139, 34, 255);
119 pub const LIME_GREEN: PdfColor = PdfColor::new(50, 205, 50, 255);
120 pub const LIGHT_GREEN: PdfColor = PdfColor::new(144, 238, 144, 255);
121 pub const PALE_GREEN: PdfColor = PdfColor::new(152, 251, 152, 255);
122 pub const DARK_SEA_GREEN: PdfColor = PdfColor::new(143, 188, 143, 255);
123 pub const MEDIUM_SPRING_GREEN: PdfColor = PdfColor::new(0, 250, 154, 255);
124 pub const SPRING_GREEN: PdfColor = PdfColor::new(0, 255, 127, 255);
125 pub const SEA_GREEN: PdfColor = PdfColor::new(46, 139, 87, 255);
126 pub const MEDIUM_AQUA_MARINE: PdfColor = PdfColor::new(102, 205, 170, 255);
127 pub const MEDIUM_SEA_GREEN: PdfColor = PdfColor::new(60, 179, 113, 255);
128 pub const LIGHT_SEA_GREEN: PdfColor = PdfColor::new(32, 178, 170, 255);
129 pub const DARK_SLATE_GRAY: PdfColor = PdfColor::new(47, 79, 79, 255);
130 pub const DARK_CYAN: PdfColor = PdfColor::new(0, 139, 139, 255);
131 pub const AQUA: PdfColor = PdfColor::new(0, 255, 255, 255);
132 pub const LIGHT_CYAN: PdfColor = PdfColor::new(224, 255, 255, 255);
133 pub const DARK_TURQUOISE: PdfColor = PdfColor::new(0, 206, 209, 255);
134 pub const TURQUOISE: PdfColor = PdfColor::new(64, 224, 208, 255);
135 pub const MEDIUM_TURQUOISE: PdfColor = PdfColor::new(72, 209, 204, 255);
136 pub const PALE_TURQUOISE: PdfColor = PdfColor::new(175, 238, 238, 255);
137 pub const AQUA_MARINE: PdfColor = PdfColor::new(127, 255, 212, 255);
138 pub const POWDER_BLUE: PdfColor = PdfColor::new(176, 224, 230, 255);
139 pub const CADET_BLUE: PdfColor = PdfColor::new(95, 158, 160, 255);
140 pub const STEEL_BLUE: PdfColor = PdfColor::new(70, 130, 180, 255);
141 pub const CORNFLOWER_BLUE: PdfColor = PdfColor::new(100, 149, 237, 255);
142 pub const DEEP_SKY_BLUE: PdfColor = PdfColor::new(0, 191, 255, 255);
143 pub const DODGER_BLUE: PdfColor = PdfColor::new(30, 144, 255, 255);
144 pub const LIGHT_BLUE: PdfColor = PdfColor::new(173, 216, 230, 255);
145 pub const SKY_BLUE: PdfColor = PdfColor::new(135, 206, 235, 255);
146 pub const LIGHT_SKY_BLUE: PdfColor = PdfColor::new(135, 206, 250, 255);
147 pub const MIDNIGHT_BLUE: PdfColor = PdfColor::new(25, 25, 112, 255);
148 pub const DARK_BLUE: PdfColor = PdfColor::new(0, 0, 139, 255);
149 pub const MEDIUM_BLUE: PdfColor = PdfColor::new(0, 0, 205, 255);
150 pub const ROYAL_BLUE: PdfColor = PdfColor::new(65, 105, 225, 255);
151 pub const BLUE_VIOLET: PdfColor = PdfColor::new(138, 43, 226, 255);
152 pub const INDIGO: PdfColor = PdfColor::new(75, 0, 130, 255);
153 pub const DARK_SLATE_BLUE: PdfColor = PdfColor::new(72, 61, 139, 255);
154 pub const SLATE_BLUE: PdfColor = PdfColor::new(106, 90, 205, 255);
155 pub const MEDIUM_SLATE_BLUE: PdfColor = PdfColor::new(123, 104, 238, 255);
156 pub const MEDIUM_PURPLE: PdfColor = PdfColor::new(147, 112, 219, 255);
157 pub const DARK_MAGENTA: PdfColor = PdfColor::new(139, 0, 139, 255);
158 pub const DARK_VIOLET: PdfColor = PdfColor::new(148, 0, 211, 255);
159 pub const DARK_ORCHID: PdfColor = PdfColor::new(153, 50, 204, 255);
160 pub const MEDIUM_ORCHID: PdfColor = PdfColor::new(186, 85, 211, 255);
161 pub const THISTLE: PdfColor = PdfColor::new(216, 191, 216, 255);
162 pub const PLUM: PdfColor = PdfColor::new(221, 160, 221, 255);
163 pub const VIOLET: PdfColor = PdfColor::new(238, 130, 238, 255);
164 pub const ORCHID: PdfColor = PdfColor::new(218, 112, 214, 255);
165 pub const MEDIUM_VIOLET_RED: PdfColor = PdfColor::new(199, 21, 133, 255);
166 pub const PALE_VIOLET_RED: PdfColor = PdfColor::new(219, 112, 147, 255);
167 pub const DEEP_PINK: PdfColor = PdfColor::new(255, 20, 147, 255);
168 pub const HOT_PINK: PdfColor = PdfColor::new(255, 105, 180, 255);
169 pub const LIGHT_PINK: PdfColor = PdfColor::new(255, 182, 193, 255);
170 pub const PINK: PdfColor = PdfColor::new(255, 192, 203, 255);
171 pub const ANTIQUE_WHITE: PdfColor = PdfColor::new(250, 235, 215, 255);
172 pub const BEIGE: PdfColor = PdfColor::new(245, 245, 220, 255);
173 pub const BISQUE: PdfColor = PdfColor::new(255, 228, 196, 255);
174 pub const BLANCHED_ALMOND: PdfColor = PdfColor::new(255, 235, 205, 255);
175 pub const WHEAT: PdfColor = PdfColor::new(245, 222, 179, 255);
176 pub const CORN_SILK: PdfColor = PdfColor::new(255, 248, 220, 255);
177 pub const LEMON_CHIFFON: PdfColor = PdfColor::new(255, 250, 205, 255);
178 pub const LIGHT_GOLDEN_ROD_YELLOW: PdfColor = PdfColor::new(250, 250, 210, 255);
179 pub const LIGHT_YELLOW: PdfColor = PdfColor::new(255, 255, 224, 255);
180 pub const SADDLE_BROWN: PdfColor = PdfColor::new(139, 69, 19, 255);
181 pub const SIENNA: PdfColor = PdfColor::new(160, 82, 45, 255);
182 pub const CHOCOLATE: PdfColor = PdfColor::new(210, 105, 30, 255);
183 pub const PERU: PdfColor = PdfColor::new(205, 133, 63, 255);
184 pub const SANDY_BROWN: PdfColor = PdfColor::new(244, 164, 96, 255);
185 pub const BURLY_WOOD: PdfColor = PdfColor::new(222, 184, 135, 255);
186 pub const TAN: PdfColor = PdfColor::new(210, 180, 140, 255);
187 pub const ROSY_BROWN: PdfColor = PdfColor::new(188, 143, 143, 255);
188 pub const MOCCASIN: PdfColor = PdfColor::new(255, 228, 181, 255);
189 pub const NAVAJO_WHITE: PdfColor = PdfColor::new(255, 222, 173, 255);
190 pub const PEACH_PUFF: PdfColor = PdfColor::new(255, 218, 185, 255);
191 pub const MISTY_ROSE: PdfColor = PdfColor::new(255, 228, 225, 255);
192 pub const LAVENDER_BLUSH: PdfColor = PdfColor::new(255, 240, 245, 255);
193 pub const LINEN: PdfColor = PdfColor::new(250, 240, 230, 255);
194 pub const OLD_LACE: PdfColor = PdfColor::new(253, 245, 230, 255);
195 pub const PAPAYA_WHIP: PdfColor = PdfColor::new(255, 239, 213, 255);
196 pub const SEA_SHELL: PdfColor = PdfColor::new(255, 245, 238, 255);
197 pub const MINT_CREAM: PdfColor = PdfColor::new(245, 255, 250, 255);
198 pub const SLATE_GRAY: PdfColor = PdfColor::new(112, 128, 144, 255);
199 pub const LIGHT_SLATE_GRAY: PdfColor = PdfColor::new(119, 136, 153, 255);
200 pub const LIGHT_STEEL_BLUE: PdfColor = PdfColor::new(176, 196, 222, 255);
201 pub const LAVENDER: PdfColor = PdfColor::new(230, 230, 250, 255);
202 pub const FLORAL_WHITE: PdfColor = PdfColor::new(255, 250, 240, 255);
203 pub const ALICE_BLUE: PdfColor = PdfColor::new(240, 248, 255, 255);
204 pub const GHOST_WHITE: PdfColor = PdfColor::new(248, 248, 255, 255);
205 pub const HONEYDEW: PdfColor = PdfColor::new(240, 255, 240, 255);
206 pub const IVORY: PdfColor = PdfColor::new(255, 255, 240, 255);
207 pub const AZURE: PdfColor = PdfColor::new(240, 255, 255, 255);
208 pub const SNOW: PdfColor = PdfColor::new(255, 250, 250, 255);
209 pub const DIM_GREY: PdfColor = PdfColor::new(105, 105, 105, 255);
210 pub const GREY: PdfColor = PdfColor::new(128, 128, 128, 255);
211 pub const DARK_GREY: PdfColor = PdfColor::new(169, 169, 169, 255);
212 pub const LIGHT_GREY: PdfColor = PdfColor::new(211, 211, 211, 255);
213 pub const GAINSBORO: PdfColor = PdfColor::new(220, 220, 220, 255);
214 pub const WHITE_SMOKE: PdfColor = PdfColor::new(245, 245, 245, 255);
215
216 #[inline]
217 #[allow(dead_code)]
219 pub(crate) const fn from_pdfium(argb: FPDF_DWORD) -> Self {
220 Self::new(
221 ((argb & 0xFF0000) >> 16) as u8,
222 ((argb & 0xFF00) >> 8) as u8,
223 (argb & 0xFF) as u8,
224 ((argb & 0xFF000000) >> 24) as u8,
225 )
226 }
227
228 #[inline]
230 pub const fn new(red: u8, green: u8, blue: u8, alpha: u8) -> Self {
231 Self {
232 r: red,
233 g: green,
234 b: blue,
235 a: alpha,
236 }
237 }
238
239 pub fn from_hex(hex: &str) -> Result<Self, PdfiumError> {
244 if hex.starts_with('#') {
245 match hex.len() {
246 7 => {
247 FPDF_DWORD::from_str_radix(&hex[1..hex.len()], 16)
251 .map(PdfColor::from_pdfium)
252 .map(|color| color.with_alpha(255))
253 .map_err(PdfiumError::ParseHexadecimalColorError)
254 }
255 9 => {
256 FPDF_DWORD::from_str_radix(&hex[1..hex.len()], 16)
259 .map(PdfColor::from_pdfium)
260 .map_err(PdfiumError::ParseHexadecimalColorError)
261 }
262 _ => Err(PdfiumError::ParseHexadecimalColorUnexpectedLength),
263 }
264 } else {
265 Err(PdfiumError::ParseHexadecimalColorMissingLeadingHash)
266 }
267 }
268
269 #[inline]
271 pub const fn mix(a: &PdfColor, b: &PdfColor) -> Self {
272 a.mix_with(b)
273 }
274
275 #[inline]
277 pub const fn mix_with(&self, other: &PdfColor) -> Self {
278 Self {
279 r: (self.r + other.r) / 2,
280 g: (self.g + other.g) / 2,
281 b: (self.b + other.b) / 2,
282 a: (self.a + other.a) / 2,
283 }
284 }
285
286 #[inline]
289 pub const fn with_alpha(&self, alpha: u8) -> Self {
290 Self {
291 r: self.r,
292 g: self.g,
293 b: self.b,
294 a: alpha,
295 }
296 }
297
298 #[inline]
301 pub fn alpha(&self) -> u8 {
302 self.a
303 }
304
305 #[inline]
307 pub fn red(&self) -> u8 {
308 self.r
309 }
310
311 #[inline]
313 pub fn green(&self) -> u8 {
314 self.g
315 }
316
317 #[inline]
319 pub fn blue(&self) -> u8 {
320 self.b
321 }
322
323 #[inline]
327 pub fn to_hex(&self) -> String {
328 format!("{:02X?}{:02X?}{:02X?}", self.r, self.g, self.b)
329 }
330
331 #[inline]
335 pub fn to_hex_with_alpha(&self) -> String {
336 format!(
337 "{:02X?}{:02X?}{:02X?}{:02X?}",
338 self.a, self.r, self.g, self.b
339 )
340 }
341
342 #[inline]
345 pub(crate) fn as_pdfium_color(&self) -> FPDF_DWORD {
346 let (alpha, r, g, b) = self.color_components();
347
348 ((alpha << 24) | (b << 16) | (g << 8) | r) as FPDF_DWORD
349 }
350
351 #[inline]
354 pub(crate) fn as_pdfium_color_with_alpha(&self) -> (FPDF_DWORD, u8) {
355 let (alpha, r, g, b) = self.color_components();
356
357 (
358 ((0xFF << 24) | (b << 16) | (g << 8) | r) as FPDF_DWORD,
359 alpha as u8,
360 )
361 }
362
363 #[inline]
365 fn color_components(&self) -> (FPDF_DWORD, FPDF_DWORD, FPDF_DWORD, FPDF_DWORD) {
366 (
367 self.a as FPDF_DWORD,
368 self.r as FPDF_DWORD,
369 self.g as FPDF_DWORD,
370 self.b as FPDF_DWORD,
371 )
372 }
373}
374
375#[cfg(test)]
376mod tests {
377 use crate::prelude::*;
378
379 #[test]
380 fn test_from_hex() {
381 assert_eq!(
382 PdfColor::from_hex("#800080").unwrap().color_components(),
383 PdfColor::PURPLE.color_components()
384 );
385 assert_eq!(
386 PdfColor::from_hex("#FF800080").unwrap().color_components(),
387 PdfColor::PURPLE.color_components()
388 );
389 assert_eq!(
390 PdfColor::from_hex("#40800080").unwrap().color_components(),
391 PdfColor::PURPLE.with_alpha(64).color_components()
392 );
393 }
394
395 #[test]
396 fn test_to_hex() {
397 assert_eq!(PdfColor::PURPLE.to_hex(), "800080");
398 assert_eq!(PdfColor::PURPLE.with_alpha(64).to_hex(), "800080");
399 assert_eq!(PdfColor::PURPLE.to_hex_with_alpha(), "FF800080");
400 assert_eq!(
401 PdfColor::PURPLE.with_alpha(64).to_hex_with_alpha(),
402 "40800080"
403 );
404 }
405}