mirror of
https://github.com/Stichting-MINIX-Research-Foundation/xsrc.git
synced 2025-09-12 06:07:40 -04:00
1031 lines
23 KiB
C
1031 lines
23 KiB
C
/* $Xorg: cmsColNm.c,v 1.3 2000/08/17 19:45:09 cpqbld Exp $ */
|
||
|
||
/*
|
||
* Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
|
||
* All Rights Reserved
|
||
*
|
||
* This file is a component of an X Window System-specific implementation
|
||
* of Xcms based on the TekColor Color Management System. Permission is
|
||
* hereby granted to use, copy, modify, sell, and otherwise distribute this
|
||
* software and its documentation for any purpose and without fee, provided
|
||
* that this copyright, permission, and disclaimer notice is reproduced in
|
||
* all copies of this software and in supporting documentation. TekColor
|
||
* is a trademark of Tektronix, Inc.
|
||
*
|
||
* Tektronix makes no representation about the suitability of this software
|
||
* for any purpose. It is provided "as is" and with all faults.
|
||
*
|
||
* TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
|
||
* INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||
* PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
|
||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||
* RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
|
||
* CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||
* CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
|
||
*
|
||
* NAME
|
||
* XcmsColNm.c
|
||
*
|
||
* DESCRIPTION
|
||
* Source for _XcmsLookupColorName().
|
||
*
|
||
*
|
||
*/
|
||
/* $XFree86: xc/lib/X11/cmsColNm.c,v 3.12 2003/11/17 22:20:11 dawes Exp $ */
|
||
|
||
#include "Xlibint.h"
|
||
#include "Xcmsint.h"
|
||
#include <X11/Xos.h>
|
||
#include <sys/stat.h>
|
||
#include <stdio.h>
|
||
#include <ctype.h>
|
||
#define XK_LATIN1
|
||
#include <X11/keysymdef.h>
|
||
#include "Cv.h"
|
||
|
||
/* forwards/locals */
|
||
static Status LoadColornameDB(void);
|
||
|
||
|
||
/*
|
||
* LOCAL DEFINES
|
||
* #define declarations local to this package.
|
||
*/
|
||
#ifndef XCMSDB
|
||
#define XCMSDB "/usr/lib/X11/Xcms.txt"
|
||
#endif
|
||
|
||
#ifndef isgraph
|
||
# define isgraph(c) (isprint((c)) && !isspace((c)))
|
||
#endif
|
||
|
||
#ifndef XCMSDB_MAXLINELEN
|
||
# define XCMSDB_MAXLINELEN 256
|
||
#endif
|
||
|
||
#define FORMAT_VERSION "0.1"
|
||
#define START_TOKEN "XCMS_COLORDB_START"
|
||
#define END_TOKEN "XCMS_COLORDB_END"
|
||
#define DELIM_CHAR '\t'
|
||
|
||
#define NOT_VISITED 0x0
|
||
#define VISITED 0x1
|
||
#define CYCLE 0xFFFF
|
||
#define XcmsDbInitNone -1
|
||
#define XcmsDbInitFailure 0
|
||
#define XcmsDbInitSuccess 1
|
||
|
||
/*
|
||
* LOCAL TYPEDEFS
|
||
*/
|
||
typedef struct _XcmsPair {
|
||
const char *first;
|
||
const char *second;
|
||
int flag;
|
||
} XcmsPair;
|
||
|
||
/*
|
||
* LOCAL VARIABLES
|
||
*/
|
||
static int XcmsColorDbState = XcmsDbInitNone;
|
||
static int nEntries;
|
||
static char *strings;
|
||
static XcmsPair *pairs;
|
||
static const char whitePtStr[] = "WhitePoint";
|
||
|
||
|
||
/************************************************************************
|
||
* *
|
||
* PRIVATE ROUTINES *
|
||
* *
|
||
************************************************************************/
|
||
|
||
/*
|
||
* NAME
|
||
* _XcmsColorSpaceOfString
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static XcmsColorSpace *
|
||
_XcmsColorSpaceOfString(
|
||
XcmsCCC ccc,
|
||
const char *color_string)
|
||
/*
|
||
* DESCRIPTION
|
||
* Returns a pointer to the color space structure
|
||
* (XcmsColorSpace) associated with the specified color string.
|
||
*
|
||
* RETURNS
|
||
* Pointer to matching XcmsColorSpace structure if found;
|
||
* otherwise NULL.
|
||
*
|
||
* CAVEATS
|
||
*
|
||
*/
|
||
{
|
||
XcmsColorSpace **papColorSpaces;
|
||
int n;
|
||
char *pchar;
|
||
|
||
if ((pchar = strchr(color_string, ':')) == NULL) {
|
||
return(XcmsFailure);
|
||
}
|
||
n = (int)(pchar - color_string);
|
||
|
||
if (ccc == NULL) {
|
||
return(NULL);
|
||
}
|
||
|
||
/*
|
||
* First try Device-Independent color spaces
|
||
*/
|
||
papColorSpaces = _XcmsDIColorSpaces;
|
||
if (papColorSpaces != NULL) {
|
||
while (*papColorSpaces != NULL) {
|
||
if (strncmp((*papColorSpaces)->prefix, color_string, n) == 0 &&
|
||
!((*papColorSpaces)->prefix)[n]) {
|
||
return(*papColorSpaces);
|
||
}
|
||
papColorSpaces++;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Next try Device-Dependent color spaces
|
||
*/
|
||
papColorSpaces = ((XcmsFunctionSet *)ccc->pPerScrnInfo->functionSet)->DDColorSpaces;
|
||
if (papColorSpaces != NULL) {
|
||
while (*papColorSpaces != NULL) {
|
||
if (strncmp((*papColorSpaces)->prefix, color_string, n) == 0 &&
|
||
!((*papColorSpaces)->prefix)[n]) {
|
||
return(*papColorSpaces);
|
||
}
|
||
papColorSpaces++;
|
||
}
|
||
}
|
||
|
||
return(NULL);
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* _XcmsParseColorString
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static int
|
||
_XcmsParseColorString(
|
||
XcmsCCC ccc,
|
||
const char *color_string,
|
||
XcmsColor *pColor)
|
||
/*
|
||
* DESCRIPTION
|
||
* Assuming color_string contains a numerical string color
|
||
* specification, attempts to parse a string into an
|
||
* XcmsColor structure.
|
||
*
|
||
* RETURNS
|
||
* 0 if failed; otherwise non-zero.
|
||
*
|
||
* CAVEATS
|
||
* A color string containing a numerical color specification
|
||
* must be in ISO Latin-1 encoding!
|
||
*/
|
||
{
|
||
XcmsColorSpace *pColorSpace;
|
||
char string_buf[64];
|
||
char *string_lowered;
|
||
int len;
|
||
int res;
|
||
|
||
if (ccc == NULL) {
|
||
return(0);
|
||
}
|
||
|
||
/*
|
||
* While copying color_string to string_lowered, convert to lowercase
|
||
*/
|
||
if ((len = strlen(color_string)) >= sizeof(string_buf)) {
|
||
string_lowered = (char *) Xmalloc(len+1);
|
||
} else {
|
||
string_lowered = string_buf;
|
||
}
|
||
|
||
_XcmsCopyISOLatin1Lowered(string_lowered, color_string);
|
||
|
||
if (*string_lowered == '#') {
|
||
if ((pColorSpace = _XcmsColorSpaceOfString(ccc, "rgb:")) != NULL) {
|
||
res = (*pColorSpace->parseString)(string_lowered, pColor);
|
||
if (len >= sizeof(string_buf)) Xfree(string_lowered);
|
||
return res;
|
||
}
|
||
}
|
||
|
||
if ((pColorSpace = _XcmsColorSpaceOfString(ccc, string_lowered)) != NULL) {
|
||
res = (*pColorSpace->parseString)(string_lowered, pColor);
|
||
if (len >= sizeof(string_buf)) Xfree(string_lowered);
|
||
return res;
|
||
}
|
||
|
||
if (len >= sizeof(string_buf)) Xfree(string_lowered);
|
||
return(0);
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* FirstCmp - Compare color names of pair recs
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static int
|
||
FirstCmp(const void *p1, const void *p2)
|
||
/*
|
||
* DESCRIPTION
|
||
* Compares the color names of XcmsColorTuples.
|
||
* This routine is public to allow access from qsort???.
|
||
*
|
||
* RETURNS
|
||
* 0 if equal;
|
||
* < 0 if first precedes second,
|
||
* > 0 if first succeeds second.
|
||
*
|
||
*/
|
||
{
|
||
return(strcmp(((XcmsPair *)p1)->first, ((XcmsPair *)p2)->first));
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* stringSectionSize - determine memory needed for strings
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static void
|
||
SetNoVisit(void)
|
||
/*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*
|
||
*/
|
||
{
|
||
int i;
|
||
XcmsPair *pair = pairs;
|
||
|
||
for (i = 0; i < nEntries; i++, pair++) {
|
||
if (pair->flag != CYCLE) {
|
||
pair->flag = NOT_VISITED;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* field2 - extract two fields
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static int
|
||
field2(
|
||
char *pBuf,
|
||
char delim, /* in: field delimiter */
|
||
char **p1, /* in/out: pointer to pointer to field 1 */
|
||
char **p2) /* in/out: pointer to pointer to field 2 */
|
||
/*
|
||
* DESCRIPTION
|
||
* Extracts two fields from a "record".
|
||
*
|
||
* RETURNS
|
||
* XcmsSuccess if succeeded, otherwise XcmsFailure.
|
||
*
|
||
*/
|
||
{
|
||
*p1 = *p2 = NULL;
|
||
|
||
/* Find Field 1 */
|
||
while (!isgraph(*pBuf)) {
|
||
if ((*pBuf != '\n') || (*pBuf != '\0')) {
|
||
return(XcmsFailure);
|
||
}
|
||
if (isspace(*pBuf) || (*pBuf == delim)) {
|
||
pBuf++;
|
||
}
|
||
}
|
||
*p1 = pBuf;
|
||
|
||
/* Find end of Field 2 */
|
||
while (isprint(*pBuf) && (*pBuf != delim)) {
|
||
pBuf++;
|
||
}
|
||
if ((*pBuf == '\n') || (*pBuf == '\0')) {
|
||
return(XcmsFailure);
|
||
}
|
||
if ((*pBuf == ' ') || (*pBuf == delim)) {
|
||
*pBuf++ = '\0'; /* stuff end of string character */
|
||
} else {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
/* Find Field 2 */
|
||
while (!isgraph(*pBuf)) {
|
||
if ((*pBuf == '\n') || (*pBuf == '\0')) {
|
||
return(XcmsFailure);
|
||
}
|
||
if (isspace(*pBuf) || (*pBuf == delim)) {
|
||
pBuf++;
|
||
}
|
||
}
|
||
*p2 = pBuf;
|
||
|
||
/* Find end of Field 2 */
|
||
while (isprint(*pBuf) && (*pBuf != delim)) {
|
||
pBuf++;
|
||
}
|
||
if (*pBuf != '\0') {
|
||
*pBuf = '\0'; /* stuff end of string character */
|
||
}
|
||
|
||
return(XcmsSuccess);
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* _XcmsLookupColorName - Lookup DB entry for a color name
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static Status
|
||
_XcmsLookupColorName(
|
||
XcmsCCC ccc,
|
||
const char **name,
|
||
XcmsColor *pColor)
|
||
/*
|
||
* DESCRIPTION
|
||
* Searches for an entry in the Device-Independent Color Name
|
||
* Database for the specified string.
|
||
*
|
||
* RETURNS
|
||
* XcmsFailure if failed to find a matching entry in
|
||
* the database.
|
||
* XcmsSuccess if succeeded in converting color name to
|
||
* XcmsColor.
|
||
* _XCMS_NEWNAME if succeeded in converting color string (which
|
||
* is a color name to yet another color name. Note
|
||
* that the new name is passed back via 'name'.
|
||
*/
|
||
{
|
||
Status retval = 0;
|
||
char name_lowered_64[64];
|
||
char *name_lowered;
|
||
register int i, j, left, right;
|
||
int len;
|
||
const char *tmpName;
|
||
XcmsPair *pair = NULL;
|
||
|
||
/*
|
||
* Check state of Database:
|
||
* XcmsDbInitNone
|
||
* XcmsDbInitSuccess
|
||
* XcmsDbInitFailure
|
||
*/
|
||
if (XcmsColorDbState == XcmsDbInitFailure) {
|
||
return(XcmsFailure);
|
||
}
|
||
if (XcmsColorDbState == XcmsDbInitNone) {
|
||
if (!LoadColornameDB()) {
|
||
return(XcmsFailure);
|
||
}
|
||
}
|
||
|
||
SetNoVisit();
|
||
|
||
/*
|
||
* While copying name to name_lowered, convert to lowercase
|
||
*/
|
||
|
||
tmpName = *name;
|
||
|
||
Retry:
|
||
if ((len = strlen(tmpName)) > 63) {
|
||
name_lowered = (char *) Xmalloc(len+1);
|
||
} else {
|
||
name_lowered = name_lowered_64;
|
||
}
|
||
|
||
_XcmsCopyISOLatin1Lowered(name_lowered, tmpName);
|
||
|
||
/*
|
||
* Now, remove spaces.
|
||
*/
|
||
for (i = 0, j = 0; j < len; j++) {
|
||
if (!isspace(name_lowered[j])) {
|
||
name_lowered[i++] = name_lowered[j];
|
||
}
|
||
}
|
||
name_lowered[i] = '\0';
|
||
|
||
left = 0;
|
||
right = nEntries - 1;
|
||
while (left <= right) {
|
||
i = (left + right) >> 1;
|
||
pair = &pairs[i];
|
||
j = strcmp(name_lowered, pair->first);
|
||
if (j < 0)
|
||
right = i - 1;
|
||
else if (j > 0)
|
||
left = i + 1;
|
||
else {
|
||
break;
|
||
}
|
||
}
|
||
if (len > 63) Xfree(name_lowered);
|
||
|
||
if (left > right) {
|
||
if (retval == 2) {
|
||
if (*name != tmpName) {
|
||
*name = tmpName;
|
||
}
|
||
return(_XCMS_NEWNAME);
|
||
}
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
if (pair->flag == CYCLE) {
|
||
return(XcmsFailure);
|
||
}
|
||
if (pair->flag == VISITED) {
|
||
pair->flag = CYCLE;
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
if (_XcmsParseColorString(ccc, pair->second, pColor) == XcmsSuccess) {
|
||
/* f2 contains a numerical string specification */
|
||
return(XcmsSuccess);
|
||
} else {
|
||
/* f2 does not contain a numerical string specification */
|
||
tmpName = pair->second;
|
||
pair->flag = VISITED;
|
||
retval = 2;
|
||
goto Retry;
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* RemoveSpaces
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static int
|
||
RemoveSpaces(
|
||
char *pString)
|
||
/*
|
||
* DESCRIPTION
|
||
* Removes spaces from string.
|
||
*
|
||
* RETURNS
|
||
* Void
|
||
*
|
||
*/
|
||
{
|
||
int i, count = 0;
|
||
char *cptr;
|
||
|
||
/* REMOVE SPACES */
|
||
cptr = pString;
|
||
for (i = strlen(pString); i; i--, cptr++) {
|
||
if (!isspace(*cptr)) {
|
||
*pString++ = *cptr;
|
||
count++;
|
||
}
|
||
}
|
||
*pString = '\0';
|
||
return(count);
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* stringSectionSize - determine memory needed for strings
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static int
|
||
stringSectionSize(
|
||
FILE *stream,
|
||
int *pNumEntries,
|
||
int *pSectionSize)
|
||
/*
|
||
* DESCRIPTION
|
||
* Determines the amount of memory required to store the
|
||
* color name strings and also the number of strings.
|
||
*
|
||
* RETURNS
|
||
* XcmsSuccess if succeeded, otherwise XcmsFailure.
|
||
*
|
||
*/
|
||
{
|
||
char buf[XCMSDB_MAXLINELEN];
|
||
char token[XCMSDB_MAXLINELEN];
|
||
char token2[XCMSDB_MAXLINELEN];
|
||
char *pBuf;
|
||
char *f1;
|
||
char *f2;
|
||
int i;
|
||
|
||
*pNumEntries = 0;
|
||
*pSectionSize = 0;
|
||
|
||
/*
|
||
* Advance to START_TOKEN
|
||
* Anything before is just considered as comments.
|
||
*/
|
||
|
||
while((pBuf = fgets(buf, XCMSDB_MAXLINELEN, stream)) != NULL) {
|
||
if ((sscanf(buf, "%s %s", token, token2))
|
||
&& (strcmp(token, START_TOKEN) == 0)) {
|
||
if (strcmp(token2, FORMAT_VERSION) != 0) {
|
||
/* text file not in the right format */
|
||
return(XcmsFailure);
|
||
}
|
||
break;
|
||
} /* else it was just a blank line or comment */
|
||
}
|
||
|
||
if (pBuf == NULL) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
while((pBuf = fgets(buf, XCMSDB_MAXLINELEN, stream)) != NULL) {
|
||
if ((sscanf(buf, "%s", token)) && (strcmp(token, END_TOKEN) == 0)) {
|
||
break;
|
||
}
|
||
|
||
if (field2(buf, DELIM_CHAR, &f1, &f2) != XcmsSuccess) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
(*pNumEntries)++;
|
||
|
||
(*pSectionSize) += (i = strlen(f1)) + 1;
|
||
for (; i; i--, f1++) {
|
||
/* REMOVE SPACES FROM COUNT */
|
||
if (isspace(*f1)) {
|
||
(*pSectionSize)--;
|
||
}
|
||
}
|
||
|
||
(*pSectionSize) += (i = strlen(f2)) + 1;
|
||
for (; i; i--, f2++) {
|
||
/* REMOVE SPACES FROM COUNT */
|
||
if (isspace(*f2)) {
|
||
(*pSectionSize)--;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
return(XcmsSuccess);
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* ReadColornameDB - Read the Color Name Database
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static Status
|
||
ReadColornameDB(
|
||
FILE *stream,
|
||
XcmsPair *pRec,
|
||
char *pString)
|
||
/*
|
||
* DESCRIPTION
|
||
* Loads the Color Name Database from a text file.
|
||
*
|
||
* RETURNS
|
||
* XcmsSuccess if succeeded, otherwise XcmsFailure.
|
||
*
|
||
*/
|
||
{
|
||
char buf[XCMSDB_MAXLINELEN];
|
||
char token[XCMSDB_MAXLINELEN];
|
||
char token2[XCMSDB_MAXLINELEN];
|
||
char *f1;
|
||
char *f2;
|
||
char *pBuf;
|
||
|
||
/*
|
||
* Advance to START_TOKEN
|
||
* Anything before is just considered as comments.
|
||
*/
|
||
|
||
while((pBuf = fgets(buf, XCMSDB_MAXLINELEN, stream)) != NULL) {
|
||
if ((sscanf(buf, "%s %s", token, token2))
|
||
&& (strcmp(token, START_TOKEN) == 0)) {
|
||
if (strcmp(token2, FORMAT_VERSION) != 0) {
|
||
/* text file not in the right format */
|
||
return(XcmsFailure);
|
||
}
|
||
break;
|
||
} /* else it was just a blank line or comment */
|
||
}
|
||
|
||
if (pBuf == NULL) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
/*
|
||
* Process lines between START_TOKEN to END_TOKEN
|
||
*/
|
||
|
||
while ((pBuf = fgets(buf, XCMSDB_MAXLINELEN, stream)) != NULL) {
|
||
if ((sscanf(buf, "%s", token)) && (strcmp(token, END_TOKEN) == 0)) {
|
||
/*
|
||
* Found END_TOKEN so break out of for loop
|
||
*/
|
||
break;
|
||
}
|
||
|
||
/*
|
||
* Get pairs
|
||
*/
|
||
if (field2(buf, DELIM_CHAR, &f1, &f2) != XcmsSuccess) {
|
||
/* Invalid line */
|
||
continue;
|
||
}
|
||
|
||
/*
|
||
* Add strings
|
||
*/
|
||
|
||
/* Left String */
|
||
pRec->first = pString;
|
||
_XcmsCopyISOLatin1Lowered(pString, f1);
|
||
pString += (1 + RemoveSpaces(pString));
|
||
pRec->second = pString;
|
||
/* Right String */
|
||
_XcmsCopyISOLatin1Lowered(pString, f2);
|
||
pString += RemoveSpaces(pString) + 1;
|
||
pRec++;
|
||
|
||
}
|
||
|
||
return(XcmsSuccess);
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* LoadColornameDB - Load the Color Name Database
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static Status
|
||
LoadColornameDB(void)
|
||
/*
|
||
* DESCRIPTION
|
||
* Loads the Color Name Database from a text file.
|
||
*
|
||
* RETURNS
|
||
* XcmsSuccess if succeeded, otherwise XcmsFailure.
|
||
*
|
||
*/
|
||
{
|
||
int size;
|
||
FILE *stream;
|
||
char *pathname;
|
||
struct stat txt;
|
||
int length;
|
||
|
||
/* use and name of this env var is not part of the standard */
|
||
/* implementation-dependent feature */
|
||
if ((pathname = getenv("XCMSDB")) == NULL) {
|
||
pathname = XCMSDB;
|
||
}
|
||
#ifdef __UNIXOS2__
|
||
pathname = __XOS2RedirRoot(pathname);
|
||
#endif
|
||
|
||
length = strlen(pathname);
|
||
if ((length == 0) || (length >= (BUFSIZ - 5))){
|
||
XcmsColorDbState = XcmsDbInitFailure;
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
if (stat(pathname, &txt)) {
|
||
/* can't stat file */
|
||
XcmsColorDbState = XcmsDbInitFailure;
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
if ((stream = _XFopenFile (pathname, "r")) == NULL) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
stringSectionSize(stream, &nEntries, &size);
|
||
rewind(stream);
|
||
|
||
strings = (char *) Xmalloc(size);
|
||
pairs = (XcmsPair *)Xcalloc(nEntries, sizeof(XcmsPair));
|
||
|
||
ReadColornameDB(stream, pairs, strings);
|
||
(void) fclose(stream);
|
||
|
||
/*
|
||
* sort the pair recs
|
||
*/
|
||
qsort((char *)pairs, nEntries, sizeof(XcmsPair), FirstCmp);
|
||
|
||
XcmsColorDbState = XcmsDbInitSuccess;
|
||
return(XcmsSuccess);
|
||
}
|
||
|
||
|
||
/************************************************************************
|
||
* *
|
||
* API PRIVATE ROUTINES *
|
||
* *
|
||
************************************************************************/
|
||
|
||
/*
|
||
* NAME
|
||
* _XcmsCopyISOLatin1Lowered
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
void
|
||
_XcmsCopyISOLatin1Lowered(
|
||
char *dst,
|
||
const char *src)
|
||
/*
|
||
* DESCRIPTION
|
||
* ISO Latin-1 case conversion routine
|
||
* Identical to XmuCopyISOLatin1Lowered() but provided here
|
||
* to eliminate need to link with libXmu.a.
|
||
*
|
||
* IMPLEMENTORS NOTE:
|
||
* This routine is also used in XcmsFormatOfPrefix.
|
||
*
|
||
* RETURNS
|
||
* Void
|
||
*
|
||
*/
|
||
{
|
||
register unsigned char *dest;
|
||
register const unsigned char *source;
|
||
|
||
for (dest = (unsigned char *)dst, source = (const unsigned char *)src;
|
||
*source;
|
||
source++, dest++)
|
||
{
|
||
if ((*source >= XK_A) && (*source <= XK_Z))
|
||
*dest = *source + (XK_a - XK_A);
|
||
else if ((*source >= XK_Agrave) && (*source <= XK_Odiaeresis))
|
||
*dest = *source + (XK_agrave - XK_Agrave);
|
||
else if ((*source >= XK_Ooblique) && (*source <= XK_Thorn))
|
||
*dest = *source + (XK_oslash - XK_Ooblique);
|
||
else
|
||
*dest = *source;
|
||
}
|
||
*dest = '\0';
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* _XcmsResolveColorString -
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
Status
|
||
_XcmsResolveColorString (
|
||
XcmsCCC ccc,
|
||
const char **color_string,
|
||
XcmsColor *pColor_exact_return,
|
||
XcmsColorFormat result_format)
|
||
/*
|
||
* DESCRIPTION
|
||
* The XcmsLookupColor function finds the color specification
|
||
* associated with a color name in the Device-Independent Color
|
||
* Name Database.
|
||
* RETURNS
|
||
* XcmsFailure if failed to convert valid color string.
|
||
* XcmsSuccess if succeeded in converting color string to
|
||
* XcmsColor.
|
||
* _XCMS_NEWNAME if failed to parse the string or find it in
|
||
* the database, or if succeeded in looking it up and
|
||
* found another name which is not in the database.
|
||
* Note that the new name is returned in color_string.
|
||
*
|
||
* This function returns both the color specification found in the
|
||
* database (db specification) and the color specification for the
|
||
* color displayable by the specified screen (screen
|
||
* specification). The calling routine sets the format for these
|
||
* returned specifications in the XcmsColor format component.
|
||
* If XcmsUndefinedFormat, the specification is returned in the
|
||
* format used to store the color in the database.
|
||
*/
|
||
{
|
||
XcmsColor dbWhitePt; /* whitePt associated with pColor_exact_return*/
|
||
/* the screen's white point */
|
||
XcmsColor *pClientWhitePt;
|
||
int retval;
|
||
const char *strptr = whitePtStr;
|
||
|
||
/*
|
||
* 0. Check for invalid arguments.
|
||
*/
|
||
if (ccc == NULL || (*color_string)[0] == '\0' || pColor_exact_return == NULL) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
/*
|
||
* 1. First attempt to parse the string
|
||
* If successful, then convert the specification to the target format
|
||
* and return.
|
||
*/
|
||
if (_XcmsParseColorString(ccc, *color_string, pColor_exact_return)
|
||
== 1) {
|
||
if (result_format != XcmsUndefinedFormat
|
||
&& pColor_exact_return->format != result_format) {
|
||
/* need to be converted to the target format */
|
||
return(XcmsConvertColors(ccc, pColor_exact_return, 1,
|
||
result_format, (Bool *)NULL));
|
||
} else {
|
||
return(XcmsSuccess);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* 2. Attempt to find it in the DI Color Name Database
|
||
*/
|
||
|
||
/*
|
||
* a. Convert String into a XcmsColor structure
|
||
* Attempt to extract the specification for color_string from the
|
||
* DI Database (pColor_exact_return). If the DI Database does not
|
||
* have this entry, then return failure.
|
||
*/
|
||
retval = _XcmsLookupColorName(ccc, color_string, pColor_exact_return);
|
||
|
||
if (retval != XcmsSuccess) {
|
||
/* color_string replaced with a color name, or not found */
|
||
return(_XCMS_NEWNAME);
|
||
}
|
||
|
||
if (pColor_exact_return->format == XcmsUndefinedFormat) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
/*
|
||
* b. If result_format not defined, then assume target format
|
||
* is the exact format.
|
||
*/
|
||
if (result_format == XcmsUndefinedFormat) {
|
||
result_format = pColor_exact_return->format;
|
||
}
|
||
|
||
if ((ClientWhitePointOfCCC(ccc))->format == XcmsUndefinedFormat) {
|
||
pClientWhitePt = ScreenWhitePointOfCCC(ccc);
|
||
} else {
|
||
pClientWhitePt = ClientWhitePointOfCCC(ccc);
|
||
}
|
||
|
||
/*
|
||
* c. Convert to the target format, making adjustments for white
|
||
* point differences as necessary.
|
||
*/
|
||
if (XCMS_DD_ID(pColor_exact_return->format)) {
|
||
/*
|
||
* The spec format is Device-Dependent, therefore assume the
|
||
* its white point is the Screen White Point.
|
||
*/
|
||
if (XCMS_DD_ID(result_format)) {
|
||
/*
|
||
* Target format is Device-Dependent
|
||
* Therefore, DD --> DD conversion
|
||
*/
|
||
return(_XcmsDDConvertColors(ccc, pColor_exact_return,
|
||
1, result_format, (Bool *) NULL));
|
||
} else {
|
||
/*
|
||
* Target format is Device-Independent
|
||
* Therefore, DD --> DI conversion
|
||
*/
|
||
if (ccc->whitePtAdjProc && !_XcmsEqualWhitePts(ccc,
|
||
pClientWhitePt, ScreenWhitePointOfCCC(ccc))) {
|
||
return((*ccc->whitePtAdjProc)(ccc, ScreenWhitePointOfCCC(ccc),
|
||
pClientWhitePt, result_format,
|
||
pColor_exact_return, 1, (Bool *) NULL));
|
||
} else {
|
||
if (_XcmsDDConvertColors(ccc, pColor_exact_return, 1,
|
||
XcmsCIEXYZFormat, (Bool *) NULL) == XcmsFailure) {
|
||
return(XcmsFailure);
|
||
}
|
||
return(_XcmsDIConvertColors(ccc, pColor_exact_return,
|
||
pClientWhitePt, 1, result_format));
|
||
}
|
||
}
|
||
} else {
|
||
/*
|
||
* The spec format is Device-Independent, therefore attempt
|
||
* to find a database white point.
|
||
*
|
||
* If the Database does not have a white point, then assume the
|
||
* database white point is the same as the Screen White Point.
|
||
*/
|
||
|
||
if (_XcmsLookupColorName(ccc, &strptr, &dbWhitePt) != 1) {
|
||
memcpy((char *)&dbWhitePt,
|
||
(char *)&ccc->pPerScrnInfo->screenWhitePt,
|
||
sizeof(XcmsColor));
|
||
}
|
||
if (XCMS_DD_ID(result_format)) {
|
||
/*
|
||
* Target format is Device-Dependent
|
||
* Therefore, DI --> DD conversion
|
||
*/
|
||
if (ccc->whitePtAdjProc && !_XcmsEqualWhitePts(ccc,
|
||
&dbWhitePt, ScreenWhitePointOfCCC(ccc))) {
|
||
return((*ccc->whitePtAdjProc)(ccc, &dbWhitePt,
|
||
ScreenWhitePointOfCCC(ccc), result_format,
|
||
pColor_exact_return, 1, (Bool *)NULL));
|
||
} else {
|
||
if (pColor_exact_return->format != XcmsCIEXYZFormat) {
|
||
if (_XcmsDIConvertColors(ccc, pColor_exact_return,
|
||
&dbWhitePt, 1, XcmsCIEXYZFormat) == XcmsFailure) {
|
||
return(XcmsFailure);
|
||
}
|
||
}
|
||
return (_XcmsDDConvertColors(ccc, pColor_exact_return, 1,
|
||
result_format, (Bool *)NULL));
|
||
}
|
||
} else {
|
||
/*
|
||
* Target format is Device-Independent
|
||
* Therefore, DI --> DI conversion
|
||
*/
|
||
if (ccc->whitePtAdjProc && !_XcmsEqualWhitePts(ccc,
|
||
&dbWhitePt, pClientWhitePt)) {
|
||
/*
|
||
* The calling routine wants to resolve this color
|
||
* in terms if it's white point (i.e. Client White Point).
|
||
* Therefore, apply white adjustment for the displacement
|
||
* between dbWhitePt to clientWhitePt.
|
||
*/
|
||
return((*ccc->whitePtAdjProc)(ccc, &dbWhitePt,
|
||
pClientWhitePt, result_format,
|
||
pColor_exact_return, 1, (Bool *)NULL));
|
||
} else if (_XcmsEqualWhitePts(ccc,
|
||
&dbWhitePt, pClientWhitePt)) {
|
||
/*
|
||
* Can use either dbWhitePt or pClientWhitePt to
|
||
* convert to the result_format.
|
||
*/
|
||
if (pColor_exact_return->format == result_format) {
|
||
return(XcmsSuccess);
|
||
} else {
|
||
return (_XcmsDIConvertColors(ccc, pColor_exact_return,
|
||
&dbWhitePt, 1, result_format));
|
||
}
|
||
} else {
|
||
/*
|
||
* Need to convert to a white point independent color
|
||
* space (let's choose CIEXYZ) then convert to the
|
||
* target color space. Why? Lets assume that
|
||
* pColor_exact_return->format and result format
|
||
* are white point dependent format (e.g., CIELUV, CIELAB,
|
||
* TekHVC ... same or any combination). If so, we'll
|
||
* need to convert the color with dbWhitePt to an absolute
|
||
* spec (i.e. non-white point dependent) then convert that
|
||
* absolute value with clientWhitePt to the result_format.
|
||
*/
|
||
if (pColor_exact_return->format != XcmsCIEXYZFormat) {
|
||
if (_XcmsDIConvertColors(ccc, pColor_exact_return,
|
||
&dbWhitePt, 1, XcmsCIEXYZFormat) == XcmsFailure) {
|
||
return(XcmsFailure);
|
||
}
|
||
}
|
||
if (result_format == XcmsCIEXYZFormat) {
|
||
return(XcmsSuccess);
|
||
} else {
|
||
return(_XcmsDIConvertColors(ccc, pColor_exact_return,
|
||
pClientWhitePt, 1, result_format));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|