1use cxx::{type_id, ExternType};
7use std::fmt;
8use std::mem::MaybeUninit;
9
10use crate::{GlobalColor, QString};
11
12#[cxx::bridge]
13mod ffi {
14 #[repr(i32)]
16 #[namespace = "rust::cxxqtlib1"]
17 enum QColorNameFormat {
18 HexRgb,
20 HexArgb,
22 }
23
24 #[repr(i32)]
26 #[namespace = "rust::cxxqtlib1"]
27 enum QColorSpec {
28 Invalid,
29 Rgb,
30 Hsv,
31 Cmyk,
32 Hsl,
33 ExtendedRgb,
34 }
35
36 #[namespace = "Qt"]
37 extern "C++" {
38 include!("cxx-qt-lib/qt.h");
39 type GlobalColor = crate::GlobalColor;
40 }
41
42 unsafe extern "C++" {
43 include!("cxx-qt-lib/qcolor.h");
44 type QColor = super::QColor;
45 include!("cxx-qt-lib/qstring.h");
46 type QString = crate::QString;
47 include!("cxx-qt-lib/qstringlist.h");
48 type QStringList = crate::QStringList;
49
50 #[Self = "QColor"]
52 #[rust_name = "color_names"]
53 fn colorNames() -> QStringList;
54
55 #[Self = "QColor"]
57 #[rust_name = "from_cmyka"]
58 fn fromCmyk(c: i32, m: i32, y: i32, k: i32, a: i32) -> QColor;
59
60 #[Self = "QColor"]
62 #[rust_name = "from_hsva"]
63 fn fromHsv(h: i32, s: i32, v: i32, a: i32) -> QColor;
64
65 #[Self = "QColor"]
69 #[rust_name = "from_rgba"]
70 fn fromRgb(red: i32, green: i32, blue: i32, alpha: i32) -> QColor;
71
72 #[Self = "QColor"]
74 #[rust_name = "from_hsla"]
75 fn fromHsl(h: i32, s: i32, l: i32, a: i32) -> QColor;
76
77 fn alpha(self: &QColor) -> i32;
79 fn black(self: &QColor) -> i32;
81 fn blue(self: &QColor) -> i32;
83 #[rust_name = "convert_to"]
85 fn convertTo(self: &QColor, color_spec: QColorSpec) -> QColor;
86 fn cyan(self: &QColor) -> i32;
88 fn darker(self: &QColor, factor: i32) -> QColor;
94 fn green(self: &QColor) -> i32;
96 #[rust_name = "hsl_hue"]
98 fn hslHue(self: &QColor) -> i32;
99 #[rust_name = "hsl_saturation"]
101 fn hslSaturation(self: &QColor) -> i32;
102 #[rust_name = "hsv_hue"]
104 fn hsvHue(self: &QColor) -> i32;
105 #[rust_name = "hsv_saturation"]
107 fn hsvSaturation(self: &QColor) -> i32;
108 fn hue(self: &QColor) -> i32;
112 #[rust_name = "is_valid"]
114 fn isValid(self: &QColor) -> bool;
115 fn lighter(self: &QColor, factor: i32) -> QColor;
121 fn lightness(self: &QColor) -> i32;
123 fn magenta(self: &QColor) -> i32;
125 fn name(self: &QColor, format: QColorNameFormat) -> QString;
127 fn red(self: &QColor) -> i32;
129 fn saturation(self: &QColor) -> i32;
133 #[rust_name = "set_alpha"]
135 fn setAlpha(self: &mut QColor, alpha: i32);
136 #[rust_name = "set_blue"]
138 fn setBlue(self: &mut QColor, blue: i32);
139 #[rust_name = "set_cmyk"]
143 fn setCmyk(self: &mut QColor, c: i32, m: i32, y: i32, k: i32, a: i32);
144 #[rust_name = "set_green"]
146 fn setGreen(self: &mut QColor, green: i32);
147 #[rust_name = "set_hsl"]
151 fn setHsl(self: &mut QColor, h: i32, s: i32, l: i32, a: i32);
152 #[rust_name = "set_hsv"]
156 fn setHsv(self: &mut QColor, h: i32, s: i32, v: i32, a: i32);
157 #[rust_name = "set_red"]
159 fn setRed(self: &mut QColor, red: i32);
160 #[rust_name = "set_rgb"]
164 fn setRgb(self: &mut QColor, r: i32, g: i32, b: i32, a: i32);
165 fn spec(self: &QColor) -> QColorSpec;
167 #[rust_name = "to_cmyk"]
169 fn toCmyk(self: &QColor) -> QColor;
170 #[rust_name = "to_extended_rgb"]
172 fn toExtendedRgb(self: &QColor) -> QColor;
173 #[rust_name = "to_hsl"]
175 fn toHsl(self: &QColor) -> QColor;
176 #[rust_name = "to_hsv"]
178 fn toHsv(self: &QColor) -> QColor;
179 #[rust_name = "to_rgb"]
181 fn toRgb(self: &QColor) -> QColor;
182 fn value(self: &QColor) -> i32;
184 fn yellow(self: &QColor) -> i32;
186 }
187
188 #[namespace = "rust::cxxqtlib1"]
189 unsafe extern "C++" {
190 type QColorNameFormat;
191 type QColorSpec;
192
193 #[doc(hidden)]
194 #[rust_name = "qcolor_init_from_cmyk_f"]
195 fn qcolorInitFromCmykF(c: f32, m: f32, y: f32, k: f32, a: f32) -> QColor;
196 #[doc(hidden)]
197 #[rust_name = "qcolor_init_from_hsl_f"]
198 fn qcolorInitFromHslF(h: f32, s: f32, l: f32, a: f32) -> QColor;
199 #[doc(hidden)]
200 #[rust_name = "qcolor_init_from_hsv_f"]
201 fn qcolorInitFromHsvF(h: f32, s: f32, v: f32, a: f32) -> QColor;
202 #[doc(hidden)]
203 #[rust_name = "qcolor_init_from_rgb_f"]
204 fn qcolorInitFromRgbF(red: f32, green: f32, blue: f32, alpha: f32) -> QColor;
205
206 #[doc(hidden)]
207 #[rust_name = "qcolor_alpha_f"]
208 fn qcolorAlphaF(color: &QColor) -> f32;
209 #[doc(hidden)]
210 #[rust_name = "qcolor_black_f"]
211 fn qcolorBlackF(color: &QColor) -> f32;
212 #[doc(hidden)]
213 #[rust_name = "qcolor_blue_f"]
214 fn qcolorBlueF(color: &QColor) -> f32;
215 #[doc(hidden)]
216 #[rust_name = "qcolor_cyan_f"]
217 fn qcolorCyanF(color: &QColor) -> f32;
218 #[doc(hidden)]
219 #[rust_name = "qcolor_green_f"]
220 fn qcolorGreenF(color: &QColor) -> f32;
221 #[doc(hidden)]
222 #[rust_name = "qcolor_hsl_hue_f"]
223 fn qcolorHslHueF(color: &QColor) -> f32;
224 #[doc(hidden)]
225 #[rust_name = "qcolor_hsl_saturation_f"]
226 fn qcolorHslSaturationF(color: &QColor) -> f32;
227 #[doc(hidden)]
228 #[rust_name = "qcolor_hsv_hue_f"]
229 fn qcolorHsvHueF(color: &QColor) -> f32;
230 #[doc(hidden)]
231 #[rust_name = "qcolor_hsv_saturation_f"]
232 fn qcolorHsvSaturationF(color: &QColor) -> f32;
233 #[doc(hidden)]
234 #[rust_name = "qcolor_hue_f"]
235 fn qcolorHueF(color: &QColor) -> f32;
236 #[doc(hidden)]
237 #[rust_name = "qcolor_lightness_f"]
238 fn qcolorLightnessF(color: &QColor) -> f32;
239 #[doc(hidden)]
240 #[rust_name = "qcolor_magenta_f"]
241 fn qcolorMagentaF(color: &QColor) -> f32;
242 #[doc(hidden)]
243 #[rust_name = "qcolor_red_f"]
244 fn qcolorRedF(color: &QColor) -> f32;
245 #[doc(hidden)]
246 #[rust_name = "qcolor_saturation_f"]
247 fn qcolorSaturationF(color: &QColor) -> f32;
248 #[doc(hidden)]
249 #[rust_name = "qcolor_set_alpha_f"]
250 fn qcolorSetAlphaF(color: &mut QColor, alpha: f32);
251 #[doc(hidden)]
252 #[rust_name = "qcolor_set_blue_f"]
253 fn qcolorSetBlueF(color: &mut QColor, blue: f32);
254 #[doc(hidden)]
255 #[rust_name = "qcolor_set_cmyk_f"]
256 fn qcolorSetCmykF(color: &mut QColor, c: f32, m: f32, y: f32, k: f32, a: f32);
257 #[doc(hidden)]
258 #[rust_name = "qcolor_set_green_f"]
259 fn qcolorSetGreenF(color: &mut QColor, green: f32);
260 #[doc(hidden)]
261 #[rust_name = "qcolor_set_hsl_f"]
262 fn qcolorSetHslF(color: &mut QColor, h: f32, s: f32, l: f32, a: f32);
263 #[doc(hidden)]
264 #[rust_name = "qcolor_set_hsv_f"]
265 fn qcolorSetHsvF(color: &mut QColor, h: f32, s: f32, v: f32, a: f32);
266 #[doc(hidden)]
267 #[rust_name = "qcolor_set_red_f"]
268 fn qcolorSetRedF(color: &mut QColor, red: f32);
269 #[doc(hidden)]
270 #[rust_name = "qcolor_set_rgb_f"]
271 fn qcolorSetRgbF(color: &mut QColor, r: f32, g: f32, b: f32, a: f32);
272 #[doc(hidden)]
273 #[rust_name = "qcolor_value_f"]
274 fn qcolorValueF(color: &QColor) -> f32;
275 #[doc(hidden)]
276 #[rust_name = "qcolor_yellow_f"]
277 fn qcolorYellowF(color: &QColor) -> f32;
278 }
279
280 #[namespace = "rust::cxxqtlib1"]
281 unsafe extern "C++" {
282 include!("cxx-qt-lib/common.h");
283
284 #[doc(hidden)]
285 #[rust_name = "qcolor_init_default"]
286 fn construct() -> QColor;
287 #[doc(hidden)]
288 #[rust_name = "qcolor_init_from_qstring"]
289 fn construct(name: &QString) -> QColor;
290 #[doc(hidden)]
291 #[rust_name = "qcolor_init_from_globalcolor"]
292 fn construct(color: GlobalColor) -> QColor;
293 #[doc(hidden)]
294 #[rust_name = "qcolor_eq"]
295 fn operatorEq(a: &QColor, b: &QColor) -> bool;
296 }
297}
298
299pub use ffi::{QColorNameFormat, QColorSpec};
300
301#[derive(Clone)]
305#[repr(C)]
306pub struct QColor {
307 _cspec: MaybeUninit<i32>,
308 _ct: MaybeUninit<[u16; 5]>,
309}
310
311impl QColor {
312 pub fn alpha_f(&self) -> f32 {
314 ffi::qcolor_alpha_f(self)
315 }
316
317 pub fn black_f(&self) -> f32 {
319 ffi::qcolor_black_f(self)
320 }
321
322 pub fn blue_f(&self) -> f32 {
324 ffi::qcolor_blue_f(self)
325 }
326
327 pub fn cyan_f(&self) -> f32 {
329 ffi::qcolor_cyan_f(self)
330 }
331
332 pub fn from_cmyk(c: i32, m: i32, y: i32, k: i32) -> Self {
334 Self::from_cmyka(c, m, y, k, 255)
335 }
336
337 pub fn from_cmyk_f(c: f32, m: f32, y: f32, k: f32) -> Self {
339 ffi::qcolor_init_from_cmyk_f(c, m, y, k, 1.0)
340 }
341
342 pub fn from_cmyka_f(c: f32, m: f32, y: f32, k: f32, a: f32) -> Self {
344 ffi::qcolor_init_from_cmyk_f(c, m, y, k, a)
345 }
346
347 pub fn from_hsl(h: i32, s: i32, l: i32) -> Self {
349 Self::from_hsla(h, s, l, 255)
350 }
351
352 pub fn from_hsl_f(h: f32, s: f32, l: f32) -> Self {
354 ffi::qcolor_init_from_hsl_f(h, s, l, 1.0)
355 }
356
357 pub fn from_hsla_f(h: f32, s: f32, l: f32, a: f32) -> Self {
359 ffi::qcolor_init_from_hsl_f(h, s, l, a)
360 }
361
362 pub fn from_hsv(h: i32, s: i32, v: i32) -> Self {
364 Self::from_hsva(h, s, v, 255)
365 }
366
367 pub fn from_hsv_f(h: f32, s: f32, v: f32) -> Self {
369 ffi::qcolor_init_from_hsv_f(h, s, v, 1.0)
370 }
371
372 pub fn from_hsva_f(h: f32, s: f32, v: f32, a: f32) -> Self {
374 ffi::qcolor_init_from_hsv_f(h, s, v, a)
375 }
376
377 pub fn from_rgb(red: i32, green: i32, blue: i32) -> Self {
381 Self::from_rgba(red, green, blue, 255)
382 }
383
384 pub fn from_rgb_f(red: f32, green: f32, blue: f32) -> Self {
386 ffi::qcolor_init_from_rgb_f(red, green, blue, 1.0)
387 }
388
389 pub fn from_rgba_f(red: f32, green: f32, blue: f32, alpha: f32) -> Self {
391 ffi::qcolor_init_from_rgb_f(red, green, blue, alpha)
392 }
393
394 pub fn green_f(&self) -> f32 {
396 ffi::qcolor_green_f(self)
397 }
398
399 pub fn hsl_hue_f(&self) -> f32 {
401 ffi::qcolor_hsl_hue_f(self)
402 }
403
404 pub fn hsl_saturation_f(&self) -> f32 {
406 ffi::qcolor_hsl_saturation_f(self)
407 }
408
409 pub fn hsv_hue_f(&self) -> f32 {
411 ffi::qcolor_hsv_hue_f(self)
412 }
413
414 pub fn hsv_saturation_f(&self) -> f32 {
416 ffi::qcolor_hsv_saturation_f(self)
417 }
418
419 pub fn hue_f(self: &QColor) -> f32 {
423 ffi::qcolor_hue_f(self)
424 }
425
426 pub fn lightness_f(&self) -> f32 {
428 ffi::qcolor_lightness_f(self)
429 }
430
431 pub fn magenta_f(&self) -> f32 {
433 ffi::qcolor_magenta_f(self)
434 }
435
436 pub fn red_f(&self) -> f32 {
438 ffi::qcolor_red_f(self)
439 }
440
441 pub fn saturation_f(&self) -> f32 {
445 ffi::qcolor_saturation_f(self)
446 }
447
448 pub fn set_alpha_f(&mut self, alpha: f32) {
450 ffi::qcolor_set_alpha_f(self, alpha);
451 }
452
453 pub fn set_blue_f(&mut self, blue: f32) {
457 ffi::qcolor_set_blue_f(self, blue);
458 }
459
460 pub fn set_cmyk_f(&mut self, c: f32, m: f32, y: f32, k: f32, a: f32) {
464 ffi::qcolor_set_cmyk_f(self, c, m, y, k, a);
465 }
466
467 pub fn set_green_f(&mut self, green: f32) {
471 ffi::qcolor_set_green_f(self, green);
472 }
473
474 pub fn set_hsl_f(&mut self, h: f32, s: f32, l: f32, a: f32) {
478 ffi::qcolor_set_hsl_f(self, h, s, l, a);
479 }
480
481 pub fn set_hsv_f(&mut self, h: f32, s: f32, v: f32, a: f32) {
485 ffi::qcolor_set_hsv_f(self, h, s, v, a);
486 }
487
488 pub fn set_red_f(&mut self, red: f32) {
492 ffi::qcolor_set_red_f(self, red);
493 }
494
495 pub fn set_rgb_f(&mut self, r: f32, g: f32, b: f32, a: f32) {
499 ffi::qcolor_set_rgb_f(self, r, g, b, a);
500 }
501
502 pub fn value_f(self: &QColor) -> f32 {
504 ffi::qcolor_value_f(self)
505 }
506
507 pub fn yellow_f(self: &QColor) -> f32 {
509 ffi::qcolor_yellow_f(self)
510 }
511}
512
513impl Default for QColor {
514 fn default() -> Self {
518 ffi::qcolor_init_default()
519 }
520}
521
522impl From<GlobalColor> for QColor {
523 fn from(color: GlobalColor) -> Self {
525 ffi::qcolor_init_from_globalcolor(color)
526 }
527}
528
529impl TryFrom<&str> for QColor {
530 type Error = &'static str;
531
532 fn try_from(value: &str) -> Result<Self, Self::Error> {
533 Self::try_from(&QString::from(value))
534 }
535}
536
537impl TryFrom<&String> for QColor {
538 type Error = &'static str;
539
540 fn try_from(value: &String) -> Result<Self, Self::Error> {
541 Self::try_from(value.as_str())
542 }
543}
544
545impl TryFrom<&QString> for QColor {
546 type Error = &'static str;
547
548 fn try_from(value: &QString) -> Result<Self, Self::Error> {
549 let color = ffi::qcolor_init_from_qstring(value);
550 if color.is_valid() {
551 Ok(color)
552 } else {
553 Err("Invalid color")
554 }
555 }
556}
557
558impl std::cmp::PartialEq for QColor {
559 fn eq(&self, other: &Self) -> bool {
560 ffi::qcolor_eq(self, other)
561 }
562}
563
564impl std::cmp::Eq for QColor {}
565
566impl fmt::Display for QColor {
567 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
568 if f.width().is_some() || f.precision().is_some() {
569 #[allow(clippy::recursive_format_impl)]
570 return f.pad(&self.to_string());
571 }
572 let r = self.red();
574 let g = self.green();
575 let b = self.blue();
576 let a = self.alpha();
577 write!(f, "RGBA({r}, {g}, {b}, {a})")
578 }
579}
580
581impl fmt::Debug for QColor {
582 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
585 let r = self.red();
587 let g = self.green();
588 let b = self.blue();
589 let a = self.alpha();
590 let fg = if (r + b + g) < 384 { 255 } else { 0 };
592 write!(f, "\x1b[48;2;{r};{g};{b}m\x1b[38;2;{fg};{fg};{fg}mRGBA({r}, {g}, {b}, {a})\x1b[39m\x1b[49m")
594 }
595}
596
597#[cfg(feature = "rgb")]
598impl From<&rgb::RGB8> for QColor {
599 fn from(value: &rgb::RGB8) -> Self {
600 Self::from_rgb(value.r as i32, value.g as i32, value.b as i32)
601 }
602}
603
604#[cfg(feature = "rgb")]
605impl From<&rgb::RGBA8> for QColor {
606 fn from(value: &rgb::RGBA8) -> Self {
607 Self::from_rgba(
608 value.r as i32,
609 value.g as i32,
610 value.b as i32,
611 value.a as i32,
612 )
613 }
614}
615
616#[cfg(feature = "rgb")]
617impl From<&QColor> for rgb::RGB8 {
618 fn from(value: &QColor) -> Self {
619 Self {
620 r: value.red() as u8,
621 g: value.green() as u8,
622 b: value.blue() as u8,
623 }
624 }
625}
626
627#[cfg(feature = "rgb")]
628impl From<&QColor> for rgb::RGBA8 {
629 fn from(value: &QColor) -> Self {
630 Self {
631 r: value.red() as u8,
632 g: value.green() as u8,
633 b: value.blue() as u8,
634 a: value.alpha() as u8,
635 }
636 }
637}
638
639unsafe impl ExternType for QColor {
643 type Id = type_id!("QColor");
644 type Kind = cxx::kind::Trivial;
645}
646
647#[cfg(test)]
648mod tests {
649 #[cfg(feature = "rgb")]
650 use super::*;
651
652 #[cfg(feature = "rgb")]
653 #[test]
654 fn test_rgb() {
655 let color = rgb::RGB8 {
656 r: 0,
657 g: 100,
658 b: 255,
659 };
660 let qcolor = QColor::from(&color);
661 assert_eq!(qcolor.red(), 0);
662 assert_eq!(qcolor.green(), 100);
663 assert_eq!(qcolor.blue(), 255);
664 assert_eq!(qcolor.alpha(), 255);
665
666 let rgb_color = rgb::RGB8::from(&qcolor);
667 assert_eq!(color, rgb_color);
668 }
669
670 #[cfg(feature = "rgb")]
671 #[test]
672 fn test_rgba() {
673 let color = rgb::RGBA8 {
674 r: 0,
675 g: 100,
676 b: 255,
677 a: 100,
678 };
679 let qcolor = QColor::from(&color);
680 assert_eq!(qcolor.red(), 0);
681 assert_eq!(qcolor.green(), 100);
682 assert_eq!(qcolor.blue(), 255);
683 assert_eq!(qcolor.alpha(), 100);
684
685 let rgba_color = rgb::RGBA8::from(&qcolor);
686 assert_eq!(color, rgba_color);
687 }
688
689 #[test]
690 fn test_display_fmt() {
691 let qcolor = QColor::from_rgba(50, 100, 150, 200);
692 assert_eq!(format!("{qcolor:-<30}"), "RGBA(50, 100, 150, 200)-------");
693 }
694}