Search code examples
c++hextypedefunsigned-integerjuce

C++: Is there a simple way of 'mapping' the hex colour `0xff2a2620` to a more readable string 'lovelyBrown'?


I'm using the Juce Framework that has a setColour method like so:

g.setColour (Colour (0xff2a2620));

I instead would like to write something like more readable like:

g.setColour (Colour (lovelyBrown));, 'mapping' 0xff2a2620 to 'lovelyBrown'.

The method's prototype is:

explicit Colour (uint32 argb) noexcept; where uint32 is:

/** A platform-independent 32-bit unsigned integer type. */ typedef unsigned int uint32;

Juce has nice readable colour names already such as:

const Colour Colours::tomato (0xffff6347);, using a method to find the colour given a name:

static JUCE_API Colour findColourForName (const String& colourName, const Colour& defaultColour);

However, I don't want to modify or subclass their Colours class. I am wondering if there is a simpler way of 'mapping' 0xff2a2620 to 'lovelyBrown'?


Solution

  • Just as you say Juce provides...

    const Colour Colours::tomato (0xffff6347);
    

    ...you can add colours of your own:

    const Colour lovelyBrown (0xff2a2620);
    

    If you want a function to map from colour names to values at runtime, an easy and robust way is:

    std::map<std::string, Colour> colourMap;
    colourMap["lovelyBrown"] = lovelyBrown;
    // add more here...
    

    A slightly faster alternative is to have a contiguous array or vector of sorted colour names and use lower_bound to search. If you're not sure how to do that, you probably shouldn't... ;-P. (You'd either need to trust yourself/others to keep the list sorted in the source code, or do a runtime sort before first use, so there's a bit more risk/hassle+delocalisation respectively).


    Note:

    • a problem with using enum class Colours is that when you use the contained colour names, they must be prefixed by Colours::, so there's a discrepancy with the Juce-provided colour names:
        g.setColour (Colour (tomato));  // ok for provided colours
        g.setColour (Colour (Colours::lovelyBrown));  // oops, one of yours
    
    • more generally, using enum or enum class makes the colours a distinct type, which has subtle consequences: e.g. you can't just stream them a la cout << lovelyBrown without writing your own operator<<, you can't invert the red component a la lovelyBrown ^ 0xFF0000 etc. - again, these things can be done for the Juce-provided colours.