        ColourSpecConvert
        
        X Windows colour specification converter for blackhome.
        
        
        Although intended as part of the  blackhome  theme/app  management
        system  for the blackbox w.m., this code is stand-alone and can be
        used to provide format conversion and colour name  handling.   The
        file colourSpecConvertTest.cc gives a sample implementation.
        
        First change directory to the colourSpecConvert directory
        
        cd ~/.blackhome/config/rfe/colourSpecConvert
        
        then do 'make'.  The binary is invoked with
        
        colourSpecConvertTest "colourSpec"
        
        examples:  in the directory containing the binary,
        
        ./colourSpecConvertTest "115 23 218"
        ./colourSpecConvertTest "plum"
        

        ColourSpecConvert:  public methods.
        
        int setRgbTxtPath ( char * )
        int setResourceFilePath ( char * )
        int setReturnSize ( int )
        int setfReturnSize ( int )
        int setColour ( char * )
        char * hashColour ( void )
        char * rgbColour ( void )
        char * rgbiColour ( void )
        char * namedColour ( void )
        char * intColour ( void )
        char * analyseColour ( void )
        char * aliasColour ( void )
        unsigned int redInt ( void )
        unsigned int greenInt ( void )
        unsigned int blueInt ( void )
        
        
        setRgbTxtPath ( path to 'rgb.txt' )
        
         If this is specified (a common location is /usr/X11/lib/rgb.txt),
        then ColourSpecConvert has access to named colours in addition  to
        recognising  numeric  formats.  This allows interconversion of al-
        phabetic and numeric colour expressions.
        
        The path to the system tgb.txt file should be set once only  after
        an  instance  of the class has been declared (or the method of the
        class used to set the path will not exist).
        
        // include to access the class
        #include "ColourSpecConvert.h"
        
        // first declare  an  instance  of  the  ColourSpecConvert  class:
        ColourSpecConvert *myConvert = new ColourSpecConvert;
        
        //  then set the path to rgb.txt using
        myConvert->setRgbTextPath ( "/var/X11R6/lib/rgb.txt" );
        // or whatever your path to rgb.txt is
        
        Remember to set the path correctly if you  wish  to  access  named
        colours.
        
        
        setResourceFilePath ( path to .colourAliasList )
        
        This  specifies  a user-defined path to the colour alias list file
        '.colourAliasList'.  The default is '~/.blackhome/config'
        
        example:
        
        setResourceFilePath ( "."  );
        // .colourAliasList is in the current dir.
        
        
        setReturnSize ( number of bits per colour component )
        
        Allows  specification  of the magnitude of returned red, green and
        blue values.  Allowed bit size is 4, 8, 12, 16.  The default value
        is 8.
        
        Example:   using  setReturnSize  (  8  ), hashColour() returns the
        string '#rrggbb' and rgbColour() returns 'rgb:rr/gg/bb',  i.e.  8-
        bit values.
        
        Example:
        myConvert->setReturnSize ( 16 ); // return 16-bit colour
        myConvert->setColour ( "rgb:2e9/3a3b/47' ); //  supply  rgb  format
        myConvert->hashColour(); // returns '#02e93a3b0047'
        
        and

        myConvert->setReturnSize ( 8 );
        myConvert->hashColour(); // returns '#033a00'
        
        
        setfReturnSize ( number of digits after decimal point )
        
        Allows specification of rgbi floating point format.  Allowed  val-
        ues  are  descibed in the 'sprintf' manual page.  A suitable value
        is 4. The default value is 4.
        
        Example:  setfReturnSize ( 3 ) specifies that the  format  of  the
        floating  point  numbers  in  the  string returned by rgbiColour()
        should    have    3    digits    after    the    decimal    point:
        'rgbi:r.rrr/g.ggg/b.bbb'.
        
        
        setColour ( colour specification string )
        
        This  is  the  main  method of the class, used to set its internal
        representation of the colour specified, which can  be  anything  X
        understands  as  a  colour  specified by r, g and b values.  After
        this has been done, access functions allow you to retrieve equiva-
        lent  representations  in  other formats, until the internal class
        representation is set  to  another  colour  with  a  further  call
        to'setColour ( colour )'.
        
        Examples:
        
        setReturnSize ( 4 );
        setColour( "#3d4" );
        
        // supply a 4-bit colour representation, signify 4-bit depth
        
        rgbiColour();
        
        // returns'rgbi:0.20/0.87/0.27 with 'setfReturnSize(2)'.
        
        rgbColour();
        
        // returns 'rgb:03/0d/04' with 'setReturnSize(8)'.
        
        setColour ( "seashell" );        
        // sets a new colour
        
        hashColour();
        
        // returns  '#fff5ee'  and  after  'setReturnSize(16)' returns
        // '#fffff5f5eeee'.  Digit promotion occurs since colours
        // specified  by name are held internally in 16-bit form.
        // Other specifications equivalent to
        // 'seashell' may be similarly retrieved.
        
        
        hashColour()
        
        Returns the value specified by a call to setColour ( colour  )  in
        truncated  rgb format, '#rgb', where r,g,b can be from 1 to 4 hex-
        adecimal digits, depending on the value specified by setReturnSize
        ( bits per pixel ).
        
        
        rgbColour()
        
        Returns  the  value specified by a call to setColour ( colour ) in
        rgb format, 'rgb:r/g/b', where r,g,b can be from 1 to 4 hex.  dig-
        its, depending on the value specified by setReturnSize ( bits ).
        
        
        rgbiColour()
        
        Returns  the  value  specified by a call to setColour() in indexed
        rgb format, 'rgbi:r/g/b', where r,g,b are  floating-point  values.
        The number of significant digits depends on the value specified by
        setfReturnSize ( digits ).
        
        
        namedColour()
        
        Returns the named colour in rgb.txt, if any,  whose  8-bit  colour
        specification  exactly matches that derived from the colour speci-
        fied by setColour ( colour ).
        
        example:
        
        setColour ( "rgb:a0/20/f0" );
        namedColour(); // returns the string 'purple'
        
        
        intColour()
        
        Returns  the  integer values corresponding to those specified by a
        call to setColour ( colour ). These may be 4, 8, 12 or 16-bit val-
        ues,  depending on the number of digits specified by setReturnSize
        ( digits ).
        
        examples:
        
        setfReturnSize ( 4 );
        // 4 significant decimal digits
        setReturnSize (  8  );
        setColour ( "rgb:fff/1f3/2a" );
        intColour();  // returns the string '255 31 3'
        rgbiColour(); // returns '1.0000/0.1219/0.0103'
        
        setReturnSize ( 12 );
        intColour();  // returns the string '4095 499 42'
        rgbiColour(); // returns '1.0000/0.1219/0.0103'
        
        setReturnSize ( 16 );
        intColour();  // returns the string '4095 499 42'
	rgbColor();   // returns the string 'rgb:0fff/01f3/002a'
        rgbiColour(); // returns '0.0625/0.00076/0.0006'
        // note:  no digit promotion in the latter case.
        
        
        analyseColour()
        
        Returns a string containing a description of the colour  specified
        by setColour ( colour ). The colour is analysed according to rules
        for generating secondary and tertiary colours,  an  attempt  being
        made  to characterise the specified colour in terms of some combi-
        nation of these.
        
        Colours are described by a combination of intensity and hue,  e.g.
        'pale blue', 'deep violet'.
        
        Intensity descriptions are:
        
        bright: used for the most intense and 'pure' colours, e,g. primary
        
        pale:
        
        light:
        
        mid:
        
        deep:
        
        dark:
        
        shadow: reserved for 'coloured near-black' shades
        
        These lead to fairly broad changes of hue within the  range  of  a
        single  intensity-descriptive  term,  but produces vaguely useable
        descriptions.
        
        Hues are characterised by their combination of  primaries,  secon-
        daries and tertiaries:
        
        gray There is an equal balance between two of the components; this
             specifies a tint or shade of the third colour
        
        red, green, blue;
        
        yellow, magenta, cyan;
        
        citrus ( yellow-green ), aqua ( blue-green ), violet.
        
        Suggestions for better names for the  tertiaries  welcome!   There
        are  distinct problems arising from the nature of human vision and
        the amount of alteration in red and blue components a  colour  can
        have  and  still be called 'green'.  This leads to a wide range of
        hues called 'green' compared to, say, the fairly narrow  range  of
        hues which are acceptably 'yellow'.
        
        examples:
		
        setReturnSize ( 8 );
        setColour ( "purple" );
        analyseColour();  // returns 'bright blue deep violet'
        
        setColour ( "rgbi:0.71/0.13/0.809" );
        analyseColour();  //  returns 'light blue deep violet'
        
        setColour ( "0 0 255" );
        analyseColour();  // returns 'shadow gray pale blue'
        
        setReturnSize ( 16 );
        analyseColour();  // returns  'shadow gray shadow blue'  since  we
                          // have only specified 8 of 16 possible bits.
        
        setColour ( "seashell" );
        analyseColour();  // returns 'bright red bright yellow'
        
        
        aliasColour()
        
        Returns a string arbitrarily descriptive of the colour whose  con-
        stituents are specified by analyseColour().
        
        This  is  based on the existence in the file .colourAliasList of a
        line consisting of the string returned by analyseColour() followed
        by two lines each describing an alias for that string.
        
        The reason there are two aliases allowed per analysed colour spec-
        ification is that where a colour name results from  one  component
        merely  being specified as in excess of the other two, a consider-
        able difference in hue can occur depending on the  latter's  rela-
        tive  balance.   Within the context of one of these two being more
        or less than half of the other, there is a similarity in hue; out-
        side  of this, disparity results.  An example of this is turqoise,
        which may be either a 'green' or a 'blue' turqoise.  A further ex-
        ample  is the distinction between the juniper green / bottle green
        pair, where one is more 'faded', the other more 'vibrant'.
        
        The .colourAliasList allows the user to  specify  nice  names  for
        colours; simply put the line generated by analyseColour() into the
        file, and add two lines 'u1' and 'u2', one each one two subsequent
        lines: you might have

        mid green mid violet
        u1
        u2
        
        in  .colourAliasList.   Then  save this file, and the next call to
        aliasColour() will return either the string  'u1'  or  the  string
        'u2'.  So then you know which of the two available aliases to sub-
        stitute by your chosen name.  The other can remain in place  until
        it occurs somewhere, and then named appropriately.
        
        This  system  at  least  has  the  merit of not insisting, as does
        rgb.txt, that 'light pink' is a deeper  shade  than  'pink'.   Al-
        though it doesn't stop you aliasing 'mid red' as 'sea green'.
        
        It  should  be  noted that aliasColour() prepends a further inten-
        sity-descriptive term to the analysis; this an attempt  to  deter-
        mine a specification for the overall intensity of the r, g, b com-
        bination whose component descriptions  separately  constitute  the
        analysis.   So  there is plenty of scope for getting it not-quite-
        right.  The rather crude method for calculating intensity  in  the
        private method describeShade could do with refinement.
        

        redInt()
        greenInt()
        blueInt()
        
        These  are  convenience  functions which return integer values for
        the components of the the colour specified by setColour ( colour ),
        to avoid having to extract them from a string.
        In any case,  intColour() returns integers whose magnitude is scal-
        ed by setReturnSize().
