Next / Previous / Contents / Shipman's homepage

14.8. PickList.__readColorLine(): Process one line from rgb.txt

This method reads and processes one line from the rgb.txt file. For a description of the format, see Section 14.7, “PickList.__readColorsFile(): Process the rgb.txt file”.

# - - -   P i c k L i s t . _ _ r e a d C o l o r L i n e

    def __readColorLine ( self, index, rawLine ):
        """Process one line from the rgb.txt file.

          [ (index is a nonnegative integer) and
            (rawLine is a string) ->
              if rawLine is a comment -> I
              else if rawLine is valid ->
                  self.__colorMap  +:=  an entry mapping the
                      uppercased color name |-> a tuple (index,
                      the color from that line as a Color instance),
                      the name from that line)
              else -> raise IOError ]

First we remove any trailing whitespace. This will take care of any newline character.

        #-- 1 --
        # [ line  :=  rawLine with trailing whitespace removed ]
        line  =  rawLine.rstrip()

If the line is a comment, return.

        #-- 2 --
        if  line.startswith('!'):

Python's string .split() method does a nice job of breaking the line into fields. In this call, there are two arguments. The first argument is the delimiter; passing None to this argument has the effect of using any contiguous string of whitespace characters as a delimiter. The second argument specifies an upper limit to the number of fields removed from the front of the string. By passing a value of 3 to this argument, we never get more than four fields; this will avoid splitting up color names that contain embedded spaces.

        #-- 3 --
        # [ fieldList  :=  line split on whitespace regions, but never
        #                  more than the first four ]
        fieldList  =  line.split ( None, 3 )

Now for some validity tests. There should be exactly four fields. Also, the first three must contain strings that can be converted to integers. For conversion of the integer values, see Section 14.9, “PickList.__convert8(): Convert an 8-bit number”.

        #-- 4 --
        if len(fieldList) < 4:
            raise IOError, "rgb.txt lines must have four fields"
            colorName  =  fieldList[-1]

        #-- 5 --
        # [ if the first three elements of fieldList can be
        #   converted to integers in [0,255] ->
        #       red8    :=  int(fieldList[0])
        #       green8  :=  int(fieldList[1])
        #       blue8   :=  int(fieldList[2])
        #   else -> raise IOError ]
        red8    =  self.__convert8 ( fieldList[0] )
        green8  =  self.__convert8 ( fieldList[1] )
        blue8   =  self.__convert8 ( fieldList[2] )

The Color class constructor expects values in the range [0,MAX_PARAM]. One possibility is just to multiply the values by 256, and that's probably sufficiently accurate. A rejected possibility was to duplicate the value, e.g., 0x80 becomes 0x8080, and 0xff becomes 0xffff. If anyone ever convinces me that it makes a difference, I'll change it.

        #-- 6 --
        # [ color  :=  a new Color instance made from red8, green8,
        #              and blue8, each shifted left 8 bits ]
        color  =  Color ( red8<<8, green8<<8,
                          blue8<<8 )

Finally, add a new entry to self.__colorMap for this color.

        #-- 7 --
        colorKey  =  colorName.upper()
        colorTuple  =  (index, color, colorName)
        self.__colorMap [ colorKey ]  =  colorTuple