; docformat = 'rst' ; ; NAME: ; cgDefaultColor ; ; PURPOSE: ; The purpose of this function is to choose a default color for Coyote Graphics routines. ; ;******************************************************************************************; ; ; ; Copyright (c) 2011, by Fanning Software Consulting, Inc. All rights reserved. ; ; ; ; Redistribution and use in source and binary forms, with or without ; ; modification, are permitted provided that the following conditions are met: ; ; ; ; * Redistributions of source code must retain the above copyright ; ; notice, this list of conditions and the following disclaimer. ; ; * Redistributions in binary form must reproduce the above copyright ; ; notice, this list of conditions and the following disclaimer in the ; ; documentation and/or other materials provided with the distribution. ; ; * Neither the name of Fanning Software Consulting, Inc. nor the names of its ; ; contributors may be used to endorse or promote products derived from this ; ; software without specific prior written permission. ; ; ; ; THIS SOFTWARE IS PROVIDED BY FANNING SOFTWARE CONSULTING, INC. ''AS IS'' AND ANY ; ; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ; ; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT ; ; SHALL FANNING SOFTWARE CONSULTING, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, ; ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED ; ; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; ; ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ; ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ; ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ; ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ; ;******************************************************************************************; ; ;+ ; The purpose of this function is to choose a default color for Coyote Graphics routines. ; ; :Categories: ; Graphics ; ; :Returns: ; Returns a scalar or vector (depends on the type of the input color) of color ; names (strings) to be used as the "color" in Coyote Graphics routines. If the ; MODE is 1 and the inputColor is of type LONG, then the return value is an array ; or scalar of type LONG. ; ; :Params: ; inputcolour: in, optional ; The input color. May be undefined, a byte, integer, long, or string. If the ; device is in indexed color mode at the time the request is made, then all, ; byte, integer, and long values will be treated as indices into the current ; color table. The variable may be a vector. ; ; :Keywords: ; background: in, optional, type=boolean ; If this keyword is set, the color is treated as a background color. Otherwise, ; it is treated as a drawing color. ; default: in, optional ; A color of any type allowed as the `inputColour`. Used if the `inputColour` is undefined. ; mode: in, optional, type=boolean ; The color mode. A 0 mean indexed color mode. A 1 means decomposed color mode. ; If not supplied in the call, the color mode is determined at run-time with `cgGetColorState`. ; The color mode is *always* determined at run time if the current graphics device ; is the PostScript device. ; traditional: in, optional, type=boolean, default=0 ; Set this keyword if you are using the traditional color scheme of white foreground ; and black background. If this keyword is set, and the current graphics device is ; the PostScript device, the colors will be reversed, in the traditional IDL graphics ; way. ; ; :Examples: ; Use as a device independent way to get a color:: ; background = cgDefaultColor(bColor, /Background) ; color = cgDefaultColor(bColor) ; cgPlot, cgDemoData, Background=background, Color=color ; ; ; :Author: ; FANNING SOFTWARE CONSULTING:: ; David W. Fanning ; 1645 Sheely Drive ; Fort Collins, CO 80526 USA ; Phone: 970-221-0438 ; E-mail: david@idlcoyote.com ; Coyote's Guide to IDL Programming: http://www.idlcoyote.com ; ; :History: ; Change History:: ; Written, 24 December 2011. David W. Fanning. ; Modified to make sure a LONG integer in indexed color mode is in the range 0-255. 10 Jan 2012. DWF. ; Modified to make sure MODE is always determined at run-time for PostScript device. 14 Jan 2012. DWF. ; Allow other data types to be treated as color table index numbers, as long as they are in the ; range 0 to 255, and the MODE indicates indexed color. 7 March 2012. DWF. ; Modified so that the variable MODE will not change in the calling program program. 8 March 2012. DWF. ; Made FOR loop counter a LONG integer. 3 July 2012. DWF. ; More work on getting the MODE correct to handle LONG integers properly. Now, in PostScript, we get ; the current mode, except if we have been told what mode to be in. 21 July 2012. DWF. ; For numerical values less than 256, in indexed color state, I now return the values ; directly to the user. This should significantly speed up many Coyote Graphics ; processes. 14 December 2012. DWF. ; Modified to return byte and integer values as LONG decomposed integers, if decomposed ; mode is currently in effect. 14 December 2012. DWF. ; Now setting all background colors to WHITE, not BACKGROUND. 16 Dec 2012. DWF. ; Whoops! Forgot one of the background colors in the Traditional section. 11 Jan 2013. DWF. ; Made the counters in the loops long integers to accommodate large color vectors. 29 Apr 2013. Joe Sapp. ; Better error handling if/when long integers are used in indexed color mode. 17 Sept 2013. DWF. ; ; :Copyright: ; Copyright (c) 2011, Fanning Software Consulting, Inc. ;- FUNCTION cgDefaultColor, inputColour, $ BACKGROUND=background, $ DEFAULT=default, $ MODE=mode, $ TRADITIONAL=traditional ; Return to the caller on error. On_Error, 2 ; Default values and variables needed for the program. background = Keyword_Set(background) IF N_Elements(inputColour) NE 0 THEN inputColor = inputColour ; Getting the mode correct is critical for handling LONG integers correctly. ; If we are doing this in PostScript, then we have to get the mode while we ; are in the PostScript file (since we try to draw in DECOMPOSED mode always). ; But, if we are TOLD what mode to use, we have to honor that, even in PostScript. IF ((N_Elements(mode) EQ 0) || (!D.Name EQ 'PS')) THEN BEGIN thisMode = cgGetColorState() IF (N_Elements(mode) NE 0) THEN thisMode = Keyword_Set(mode) ENDIF ELSE thisMode = Keyword_Set(mode) traditional = Keyword_Set(traditional) thisDevice = !D.Name ; Is the color undefined? If so, is there a default color to assign? IF N_Elements(inputColor) EQ 0 THEN BEGIN IF N_Elements(default) NE 0 THEN inputColor = default ENDIF ; Is the input color still undefined? IF (N_Elements(inputColor) EQ 0) THEN BEGIN IF background THEN BEGIN IF traditional THEN BEGIN CASE thisDevice OF 'PS': inputColor = 'WHITE' 'Z': inputColor = 'BLACK' ELSE: inputColor = 'BLACK' ENDCASE ENDIF ELSE BEGIN CASE thisDevice OF 'PS': inputColor = 'WHITE' 'Z': inputColor = 'WHITE' ELSE: inputColor = 'WHITE' ENDCASE ENDELSE ENDIF ELSE BEGIN IF traditional THEN BEGIN CASE thisDevice OF 'PS': inputColor = 'BLACK' 'Z': inputColor = 'WHITE' ELSE: inputColor = 'WHITE' ENDCASE ENDIF ELSE BEGIN CASE thisDevice OF 'PS': inputColor = 'BLACK' 'Z': inputColor = 'BLACK' ELSE: inputColor = 'BLACK' ENDCASE ENDELSE ENDELSE ENDIF ; If we get here, the input color is defined as *something*. ; This is the crux of the problem. What does this color mean? ; If it is a byte or integer value, we assume this is an index ; into the current color table. We do the same thing with a long ; integer if the MODE is 0, or indexed color, and the value is ; between 0 and 255. If it is a string, we can return it directly. thisType = Size(inputcolor, /TNAME) TVLCT, r, g, b, /GET IF (thisType EQ 'BYTE') && (thisMode EQ 0) THEN BEGIN RETURN, inputColor ENDIF IF (thisType EQ 'BYTE') && (thisMode EQ 1) THEN BEGIN ncolors = N_Elements(inputColor) colors = LonArr(ncolors) FOR j=0L,ncolors-1 DO colors[j] = cgColor24([r[inputColor[j]], g[inputColor[j]], b[inputColor[j]]]) IF N_Elements(colors) EQ 1 THEN RETURN, colors[0] ELSE RETURN, colors ENDIF IF (thisType EQ 'INT') && (thisMode EQ 0) THEN BEGIN RETURN, inputColor ENDIF IF (thisType EQ 'INT') && (thisMode EQ 1) THEN BEGIN ncolors = N_Elements(inputColor) colors = LonArr(ncolors) ; Make sure the input color is in the range 0 to 255 index = Where((inputcolor GT 255) OR (inputcolor LT 0), count) IF count GT 0 THEN BEGIN Message, 'Improper input color. It is possible 24-bit colors (LONGs) are being used in indexed color mode to specify colors.' ENDIF FOR j=0L,ncolors-1 DO colors[j] = cgColor24([r[inputColor[j]], g[inputColor[j]], b[inputColor[j]]]) IF N_Elements(colors) EQ 1 THEN RETURN, colors[0] ELSE RETURN, colors ENDIF IF thisType EQ 'LONG' && (thisMode EQ 0) THEN BEGIN RETURN, inputColor ENDIF IF thisType EQ 'LONG' && (thisMode EQ 1) THEN BEGIN theColors = LonArr(N_Elements(inputColor)) ENDIF IF N_Elements(theColors) EQ 0 THEN theColors = StrArr(N_Elements(inputColor)) ; Fill the color return array. FOR j=0L,N_Elements(theColors)-1 DO BEGIN thisColor = inputColor[j] CASE thisType OF 'STRING': theColors[j] = StrTrim(thisColor,2) 'LONG': BEGIN IF (thisMode EQ 0) && ( (thisColor GE 0) && (thisColor LT 256) ) THEN BEGIN theColors[j] = StrTrim(thisColor, 2) ENDIF ELSE BEGIN IF (thisMode EQ 0) && ( (thisColor LT 0) || (thisColor GT 255) ) THEN BEGIN Message, 'Value of LONG integer ' + StrTrim(thisColor,2) + ' is out of indexed color range.' ENDIF ELSE BEGIN theColors[j] = thisColor ENDELSE ENDELSE END ELSE: BEGIN ; I feel like an enabler of bad programming practices. Sigh... IF (thisColor GE 0) && (thisColor LE 255) && (thisMode EQ 0) THEN BEGIN theColors[j] = StrTrim(Fix(thisColor),2) ENDIF ELSE BEGIN Message, 'Cannot determine a color from a value of ' + $ StrTrim(thisColor,2) + ' of data type ' + thisType + '.' ENDELSE END ENDCASE ENDFOR ; Return the colors after making sure to return a scalar if there is only one element. IF N_Elements(theColors) EQ 1 THEN theColors = theColors[0] RETURN, theColors END