RazrFalcon / tiny-skia

A tiny Skia subset ported to Rust
BSD 3-Clause "New" or "Revised" License
1.05k stars 67 forks source link

Color types should implement Debug, Display, Eq, Hash, Ord #80

Open Pr0methean opened 1 year ago

Pr0methean commented 1 year ago

It would be handy if the color types implemented Debug, Display, Eq, Hash and Ord, rather than my having to create a wrapper that does, and also if the non-premultiplied ones treated all fully-transparent "colors" as equal. For Clone, Copy, Debug, Eq the derived implementations are adequate; here are my implementations of the others. The Ord, PartialEq, Display, Hash implementations should be possible to optimize noticeably for the types that are backed by a u32 rather than by four u8s.

impl PartialOrd for ComparableColor {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for ComparableColor {
    fn cmp(&self, other: &Self) -> Ordering {
        if self.alpha == 0 && other.alpha == 0 {
            Ordering::Equal
        }
        let mut ordering = self.alpha.cmp(*(other.alpha));
        if ordering == Ordering::Equal {
            ordering = self.blue.cmp(*(other.blue));
            if ordering == Ordering::Equal {
                ordering = self.green.cmp(*(other.green));
                if ordering == Ordering::Equal {
                    ordering = self.red.cmp(*(other.red));
                }
            }
        }
        ordering
    }
}

impl Display for ComparableColor {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        if self.alpha == 0 {
            write!(f, "transparent")
        } else {
            write!(f, "#{:02x}{:02x}{:02x}{:02x}", self.red, self.green, self.blue, self.alpha)
        }
    }
}

impl PartialEq<Self> for ComparableColor {
    fn eq(&self, other: &Self) -> bool {
        (self.alpha == 0 && other.alpha == 0) ||
            (self.red == other.red
                && self.green == other.green
                && self.blue == other.blue
                && self.alpha == other.alpha)
    }
}

impl Hash for ComparableColor {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.alpha.hash(state);
        if self.alpha != 0 {
            self.red.hash(state);
            self.green.hash(state);
            self.blue.hash(state);
        }
    }
}