Hello List,
a while ago I filed a bug in launchpad about how Inkscape treats color spaces and does its display color management (https://bugs.launchpad.net/inkscape/+bug/1457053).
As requested by Tavmjong I wrote up some further explanations in the hope that it helps people understand the problem and maybe start some discussion.
First of all I beg your pardon for the wall of text. If you know about color spaces just skip the "Theory" part.
In the following description I will only talk about RGB color spaces. For things like CMYK the same reasoning applies but I want to keep it simple. For the sake of readability. I will also simplify a terrible lot to keep this beginner friendly and easy to understand. Like, seriously simplify. No need to point that out. I am also aware that some of the limitations might be coming from the SVG specs or are at least implied in there (like the mandatory blending in gamma corrected or linear sRGB).
Theory
When we talk about (RGB, see above) colors we often only mention three numbers representing the value for each of the red, green and blue channel. In general 0 means "nothing" and 255 (8 bit values) or 1.0 (float values) means "full power". I will use the float notation here since it's easier to calculate in the head. Thus, something like (1, 0, 0) means "the reddest red" and (1, 1, 1) is "white".
Now, there is a problem once you want to display such a color: What does "full power" or "the reddest red" actually mean? That's where color spaces come into play. They define a set of "primaries" that tell us what "red", "green" and "blue" actually mean. They are defined in absolute, real world means (most often in XYZ) that directly relate to specific wavelengths of light and precisely define a color that can be displayed. With that knowledge it's possible to say that (1, 0, 0) is not just some reddest red, but what it looks exactly like. Every other color inside the [0..1] range per channel can thus be defined, too. Some popular color spaces are sRGB and AdobeRGB in the RGB world. The CMYK world has things like "ISO Coated v2".
Of course there is more than just one color space and most have different primaries. The colors that can be described with a given set of primaries is called the "gamut" of a color space – not to be confused with the color space's "gamma"! We will ignore the latter.
Now that we know that the same triplet of numbers does mean something different in different color spaces we also understand that the numbers alone are meaningless without a color space. Since there is a terribly large number of images – both raster and vector – without any color profile information attached there is the common default of assuming sRGB.
When looking at articles about color spaces there are almost always images of a horse shoe formed colorful diagram with a triangle on top (like https://commons.wikimedia.org/wiki/File:CIE1931xy_gamut_comparison.svg). The background horse shoe represents all possible colors a typical human can see while the corners of the triangle are just the aforementioned primaries. The area of the triangle covers the colors that the colorspace can display*. With the AdobeRGB triangle being bigger than the sRGB one (and completely covering it) we can easily see that AdobeRGB contains colors that are not expressible in sRGB.
Besides these well known and standardized color spaces used to define colors in images there are also device color spaces that describe what colors some physical appliance can display. For now we will concentrate on monitor profiles since they are also RGB but of course also printers with four or even more colors can be measured and their primaries be determined. See the SWOP CMYK gamut in the sample image for a typical result of that. Back in the days of CRTs there was that prototypical monitor that exactly covered the sRGB color space – it's where it originated from. Nowadays with LCD displays and all that diverging technologies there isn't one typical display profile any longer. It turns out that most laptops and consumer grade displays cover less than sRGB while some high end monitors reach AdobeRGB or even wider gamuts. Therefore it's important to have proper color management in place so that the (1, 0, 0) you put into an image looks the same everywhere and not like an orange on some screens and a fire truck on another.
Current state of Inkscape
I have to admit that it's a while since I looked at the relevant code so my memory might be missing some details, but I am quite sure that the general picture I'm going to paint is in the right ballpark.
When Inkscape displays "normal" colors they are untagged, 8 bit values. So it's just something of the form (255, 0, 255) for a nice magenta. According to the SVG specs (http://www.w3.org/TR/SVG/color.html) this is implicitly assumed to be sRGB. Using the CMS mode of the Fill&Stroke dialog the user can also specify the color space to be something else, for example AdobeRGB. While the value set in that mode gets propagated to the SVG as-is and be tagged with its color space, internally it will be converted to sRGB. When the user also specified a display profile the result of the renderer will in the end be transformed from sRGB (that's what all the colors Inkscape works with are) to the display profile.
Problems
While in theory this seems to be a sound way to deal with colors – transforming everything to sRGB as the internal working space – it poses a few problems in practice. First and foremost there is the usage of 8 bit values. It doesn't allow very fine steps between tonalities. And the bigger the color space's gamut gets the worse it becomes. That is especially true when doing blending in linear space and not gamma corrected (never mind that detail, it's not the important part here). Just look at the diagram again. The same number of steps (255 in case of 8 bit values) have to stretch a wider range of real world colors, so every intermediate step gets bigger. Another problem with 8 bit colors is that there is nothing below 0 and nothing above 255. At first that might not look like a problem, after all, (255, 0, 0) is the reddest red. There is nothing more red, so why think about numbers that are bigger? Well, because as we have seen earlier, it's only the reddest red in its own color space. When looked at it in any bigger color space it's just an average red, there are redder reds. Therefore the transformation of colors into sRGB will leave wrong results when anything that is not inside the sRGB gamut is being transformed to it and at the same time clipped to the 8 bit range. The result can't be mapped back to the original color any longer. Even when the display is able to cover all the AdobeRGB colors and the user specifies the colors in that color space the displayed results will map everything outside of the sRGB gamut to its inside (there are several way to do that clamping, you can just cut the values off, scale them nicely, ... but at the end of the day they are not what they used to be).
To show the results of this clamping have a look at https://launchpadlibrarian.net/206984719/canvas_cms.png. Every row contains the same color value (shown on the left) four times, just tagged with different color spaces. So the first row should show the reddest red in AdobeRGB, sRGB and Laptop (some color space SMALLER than sRGB). We will ignore the GRB column, it's just there to show that color management was actually turned on. We notice that the first two columns look the same though. The reason is the clamping Inkscape does. The reddest red of AdobeRGB (i.e., its red primary) is far outside of sRGB's gamut. So Inkscape clamps the color and moves it to the closest sRGB contains: the reddest red sRGB knows. The same happens for green and blue. Once that happened every further step won't distinguish between the colors that once were very different and no matter what display profile is set the result will look the same. Because it is. Now for the third column. The Laptop profile has a smaller gamut than sRGB so when converting its primaries to sRGB they can be represented in the 8 bit range and are shown correctly in the resulting image.
A better world
All of this isn't that great for anything that is supposed to have correct colors and not be limited to sRGB. That might be less of a concern for Web graphics, but once you think about printing (most CMYK profiles are not inside the sRGB gamut) or even just seeing your work on a good monitor you have a problem.
The first step would be to get rid of the 8 bit limitation. Not only would that allow for smoother gradients (remember that step size? With float they become virtually arbitrarily small!) but floats also allow to transform colors to a smaller gamut without clipping them since the values can be bigger than 1.0. Of course, all color math has to be checked if it would still work with values bigger than "full power" and there are cases where it will fail. Thus as a second step it would be helpful to either replace sRGB with something bigger for the internal working space (not exactly what the SVG specs allow :-() or maybe even keep all colors in their original color space and only do transformations where needed. Since there are even problems when doing some computations in a gamut that can express all colors but isn't the original one it might even be a good idea to let the user specify a color space of the whole document so that all colors that are not tagged are treated as that color space instead of sRGB, i.e., specify the working space (again, not what the SVG specs call for). For documents not mixing colors of different color spaces that might be the best solution – just take all colors as-is, handle them like Inkscape already does (with the exception that it should really really do it in float and not 8 bit) and in the end convert from the document working space to the display color space.
* Actually this is just the colors with maximum saturation, the set of all colors isn't a triangle but skewed box in 3D space. In order to compare color spaces it's enough to look at this projection though.
Thanks for reading Tobias