Skip to content

Commit

Permalink
Generalize Color class to absolute colors.
Browse files Browse the repository at this point in the history
This addresses concerns raised in issue diagrams#66 by letting the backend
choose which color space to render Color instances to. Functions are
provided for backwards compatibility with the old semantics, which were
to always render out to companded sRGB space.
  • Loading branch information
nand committed Nov 20, 2012
1 parent c7d2923 commit bfc8be9
Showing 1 changed file with 30 additions and 19 deletions.
49 changes: 30 additions & 19 deletions src/Diagrams/Attributes.hs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ module Diagrams.Attributes (
-- ** Opacity
, Opacity, getOpacity, opacity

-- ** Converting colors
, toRGBAUsingSpace, colorToSRGBA, colorToRGBA

-- * Lines
-- ** Width
, LineWidth, getLineWidth, lineWidth, lw
Expand All @@ -55,7 +58,8 @@ module Diagrams.Attributes (
import Diagrams.Core

import Data.Colour
import qualified Data.Colour.SRGB as RGB
import Data.Colour.RGBSpace
import Data.Colour.SRGB (sRGBSpace)

import Data.Typeable

Expand All @@ -78,9 +82,8 @@ import Data.Semigroup
-- both the 'Data.Colour.Colour' and 'Data.Colour.AlphaColour' types
-- from the "Data.Colour" library.
class Color c where
-- | Convert a color to red, green, blue, and alpha channels in the
-- range [0,1].
colorToRGBA :: c -> (Double,Double,Double,Double)
-- | Convert a color to its standard representation, AlphaColour
toAlphaColour :: c -> AlphaColour Double

-- | An existential wrapper for instances of the 'Color' class.
data SomeColor = forall c. Color c => SomeColor c
Expand Down Expand Up @@ -146,29 +149,37 @@ fcA :: HasStyle a => AlphaColour Double -> a -> a
fcA = fillColor

instance (Floating a, Real a) => Color (Colour a) where
colorToRGBA col = (r,g,b,1)
where c' = RGB.toSRGB . colourConvert $ col
r = RGB.channelRed c'
g = RGB.channelGreen c'
b = RGB.channelBlue c'
toAlphaColour = opaque . colourConvert

instance (Floating a, Real a) => Color (AlphaColour a) where
colorToRGBA col = (r,g,b,a)
where col' = alphaColourConvert col
a = alphaChannel col'
c' = RGB.toSRGB . alphaToColour $ col'
r = RGB.channelRed c'
g = RGB.channelGreen c'
b = RGB.channelBlue c'
toAlphaColour = alphaColourConvert

instance Color SomeColor where
colorToRGBA (SomeColor c) = colorToRGBA c
toAlphaColour (SomeColor c) = toAlphaColour c

instance Color LineColor where
colorToRGBA (LineColor (Last c)) = colorToRGBA c
toAlphaColour (LineColor (Last c)) = toAlphaColour c

instance Color FillColor where
colorToRGBA (FillColor (Last c)) = colorToRGBA c
toAlphaColour (FillColor (Last c)) = toAlphaColour c

-- | Convert to an RGB space while preserving the alpha channel.
toRGBAUsingSpace :: Color c => RGBSpace Double -> c
-> (Double, Double, Double, Double)
toRGBAUsingSpace s col = (r,g,b,a)
where c' = toAlphaColour col
c = toRGBUsingSpace s (alphaToColour c')
a = alphaChannel c'
r = channelRed c
g = channelGreen c
b = channelBlue c

-- | Convert to sRGBA.
colorToSRGBA, colorToRGBA :: Color c => c -> (Double, Double, Double, Double)
colorToSRGBA = toRGBAUsingSpace sRGBSpace

colorToRGBA = colorToSRGBA
{-# DEPRECATED colorToRGBA "Renamed to colorToSRGBA." #-}

alphaToColour :: (Floating a, Ord a, Fractional a) => AlphaColour a -> Colour a
alphaToColour ac | alphaChannel ac == 0 = ac `over` black
Expand Down

3 comments on commit bfc8be9

@byorgey
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just now getting a chance to look at this, it looks pretty good to me. Just to make sure I'm understanding right, this wouldn't necessitate any changes to existing backends (as long as they want to continue using sRGB), right?

@haasn
Copy link
Owner

@haasn haasn commented on bfc8be9 Dec 23, 2012

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only if they add new instances of Color. But yes, all they'd get is a DEPRECATED warning.

@byorgey
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, right, so we should update backends to use colorToSRGBA instead of colorToRGBA, but they will continue to work in the meantime.

Please sign in to comment.