Repository: ManimCommunity/manim
File: manim/utils/color/core.py (Python)

Code before:
        dark: Self | None = None,
    ) -> Self:
        """Returns one of two colors, light or dark (by default white or black),
        that contrasts with the current color (depending on its luminance).
        This is typically used to set text in a contrasting color that ensures
        it is readable against a background of the current color.

        Parameters
        ----------
        threshold : float, optional
            The luminance threshold that dictates whether the current color is
            considered light or dark (and thus whether to return the dark or
            light color, respectively), by default 0.5
        light : ManimColor, optional
            The light color to return if the current color is considered dark,
            by default pure white
        dark : ManimColor, optional
            The dark color to return if the current color is considered light,
            by default pure black

        Returns
        -------
        ManimColor
            The contrasting ManimColor
        """
        r, g, b = self.to_rgb()
        luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b
        if luminance < threshold:
            if light is not None:
                return light
            return self.from_rgb((1.0, 1.0, 1.0), 1.0)
        else:
            if dark is not None:
                return dark
            return self.from_rgb((0.0, 0.0, 0.0), 1.0)

    def opacity(self, opacity: float) -> Self:
        """Creates a new ManimColor with the given opacity and the same color value as before

        Parameters
        ----------
        opacity : float
            The new opacity value to be used

        Returns
        -------
        ManimColor
            The new ManimColor with the same color value but the new opacity
        """
        tmp = self._internal_space.copy()
        tmp[-1] = opacity

Review comment (suggestion):
We should use the exisisting ManimColor constants for black and white; they can be accessed by adding a local import in the method (not at the top of the file, to avoid introducing an import loop):

```suggestion
        from manim.utils.color.manim_colors import WHITE, BLACK

        r, g, b = self.to_rgb()
```

Code after:
        return self.interpolate(white, blend).opacity(alpha)

    def contrasting(
        self,
        threshold: float = 0.5,
        light: Self | None = None,
        dark: Self | None = None,
    ) -> Self:
        """Returns one of two colors, light or dark (by default white or black),
        that contrasts with the current color (depending on its luminance).
        This is typically used to set text in a contrasting color that ensures
        it is readable against a background of the current color.

        Parameters
        ----------
        threshold : float, optional
            The luminance threshold that dictates whether the current color is
            considered light or dark (and thus whether to return the dark or
            light color, respectively), by default 0.5
        light : ManimColor, optional
            The light color to return if the current color is considered dark,
            by default pure white
        dark : ManimColor, optional
            The dark color to return if the current color is considered light,
            by default pure black

        Returns
        -------
        ManimColor
            The contrasting ManimColor
        """
        from manim.utils.color.manim_colors import BLACK, WHITE

        luminance, _, _ = colorsys.rgb_to_yiq(*self.to_rgb())
        if luminance < threshold:
            if light is not None:
                return light
            return self._from_internal(WHITE._internal_value)
        else:
            if dark is not None:
                return dark
            return self._from_internal(BLACK._internal_value)

    def opacity(self, opacity: float) -> Self:
        """Creates a new ManimColor with the given opacity and the same color value as before

        Parameters
        ----------
        opacity : float
            The new opacity value to be used