cmsColNm.c revision 57f47464
1 2/* 3 * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. 4 * All Rights Reserved 5 * 6 * This file is a component of an X Window System-specific implementation 7 * of Xcms based on the TekColor Color Management System. Permission is 8 * hereby granted to use, copy, modify, sell, and otherwise distribute this 9 * software and its documentation for any purpose and without fee, provided 10 * that this copyright, permission, and disclaimer notice is reproduced in 11 * all copies of this software and in supporting documentation. TekColor 12 * is a trademark of Tektronix, Inc. 13 * 14 * Tektronix makes no representation about the suitability of this software 15 * for any purpose. It is provided "as is" and with all faults. 16 * 17 * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, 18 * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 19 * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY 20 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 21 * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF 22 * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 23 * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. 24 * 25 * NAME 26 * XcmsColNm.c 27 * 28 * DESCRIPTION 29 * Source for _XcmsLookupColorName(). 30 * 31 * 32 */ 33 34#ifdef HAVE_CONFIG_H 35#include <config.h> 36#endif 37#include "Xlibint.h" 38#include "Xcmsint.h" 39#include <X11/Xos.h> 40#include <sys/stat.h> 41#include <stdio.h> 42#include <ctype.h> 43#define XK_LATIN1 44#include <X11/keysymdef.h> 45#include "Cv.h" 46 47/* forwards/locals */ 48static Status LoadColornameDB(void); 49 50 51/* 52 * LOCAL DEFINES 53 * #define declarations local to this package. 54 */ 55#ifndef XCMSDB 56#define XCMSDB "/usr/lib/X11/Xcms.txt" 57#endif 58 59#ifndef isgraph 60# define isgraph(c) (isprint((c)) && !isspace((c))) 61#endif 62 63#ifndef XCMSDB_MAXLINELEN 64# define XCMSDB_MAXLINELEN 256 65#endif 66 67#define FORMAT_VERSION "0.1" 68#define START_TOKEN "XCMS_COLORDB_START" 69#define END_TOKEN "XCMS_COLORDB_END" 70#define DELIM_CHAR '\t' 71 72#define NOT_VISITED 0x0 73#define VISITED 0x1 74#define CYCLE 0xFFFF 75#define XcmsDbInitNone -1 76#define XcmsDbInitFailure 0 77#define XcmsDbInitSuccess 1 78 79/* 80 * LOCAL TYPEDEFS 81 */ 82typedef struct _XcmsPair { 83 const char *first; 84 const char *second; 85 int flag; 86} XcmsPair; 87 88/* 89 * LOCAL VARIABLES 90 */ 91static int XcmsColorDbState = XcmsDbInitNone; 92static int nEntries; 93static char *strings; 94static XcmsPair *pairs; 95static const char whitePtStr[] = "WhitePoint"; 96 97 98/************************************************************************ 99 * * 100 * PRIVATE ROUTINES * 101 * * 102 ************************************************************************/ 103 104/* 105 * NAME 106 * _XcmsColorSpaceOfString 107 * 108 * SYNOPSIS 109 */ 110static XcmsColorSpace * 111_XcmsColorSpaceOfString( 112 XcmsCCC ccc, 113 const char *color_string) 114/* 115 * DESCRIPTION 116 * Returns a pointer to the color space structure 117 * (XcmsColorSpace) associated with the specified color string. 118 * 119 * RETURNS 120 * Pointer to matching XcmsColorSpace structure if found; 121 * otherwise NULL. 122 * 123 * CAVEATS 124 * 125 */ 126{ 127 XcmsColorSpace **papColorSpaces; 128 int n; 129 char *pchar; 130 131 if ((pchar = strchr(color_string, ':')) == NULL) { 132 return(XcmsFailure); 133 } 134 n = (int)(pchar - color_string); 135 136 if (ccc == NULL) { 137 return(NULL); 138 } 139 140 /* 141 * First try Device-Independent color spaces 142 */ 143 papColorSpaces = _XcmsDIColorSpaces; 144 if (papColorSpaces != NULL) { 145 while (*papColorSpaces != NULL) { 146 if (strncmp((*papColorSpaces)->prefix, color_string, n) == 0 && 147 !((*papColorSpaces)->prefix)[n]) { 148 return(*papColorSpaces); 149 } 150 papColorSpaces++; 151 } 152 } 153 154 /* 155 * Next try Device-Dependent color spaces 156 */ 157 papColorSpaces = ((XcmsFunctionSet *)ccc->pPerScrnInfo->functionSet)->DDColorSpaces; 158 if (papColorSpaces != NULL) { 159 while (*papColorSpaces != NULL) { 160 if (strncmp((*papColorSpaces)->prefix, color_string, n) == 0 && 161 !((*papColorSpaces)->prefix)[n]) { 162 return(*papColorSpaces); 163 } 164 papColorSpaces++; 165 } 166 } 167 168 return(NULL); 169} 170 171 172/* 173 * NAME 174 * _XcmsParseColorString 175 * 176 * SYNOPSIS 177 */ 178static int 179_XcmsParseColorString( 180 XcmsCCC ccc, 181 const char *color_string, 182 XcmsColor *pColor) 183/* 184 * DESCRIPTION 185 * Assuming color_string contains a numerical string color 186 * specification, attempts to parse a string into an 187 * XcmsColor structure. 188 * 189 * RETURNS 190 * 0 if failed; otherwise non-zero. 191 * 192 * CAVEATS 193 * A color string containing a numerical color specification 194 * must be in ISO Latin-1 encoding! 195 */ 196{ 197 XcmsColorSpace *pColorSpace; 198 char string_buf[64]; 199 char *string_lowered; 200 int len; 201 int res; 202 203 if (ccc == NULL) { 204 return(0); 205 } 206 207 /* 208 * While copying color_string to string_lowered, convert to lowercase 209 */ 210 if ((len = strlen(color_string)) >= sizeof(string_buf)) { 211 string_lowered = (char *) Xmalloc(len+1); 212 } else { 213 string_lowered = string_buf; 214 } 215 216 _XcmsCopyISOLatin1Lowered(string_lowered, color_string); 217 218 if (*string_lowered == '#') { 219 if ((pColorSpace = _XcmsColorSpaceOfString(ccc, "rgb:")) != NULL) { 220 res = (*pColorSpace->parseString)(string_lowered, pColor); 221 if (len >= sizeof(string_buf)) Xfree(string_lowered); 222 return res; 223 } 224 } 225 226 if ((pColorSpace = _XcmsColorSpaceOfString(ccc, string_lowered)) != NULL) { 227 res = (*pColorSpace->parseString)(string_lowered, pColor); 228 if (len >= sizeof(string_buf)) Xfree(string_lowered); 229 return res; 230 } 231 232 if (len >= sizeof(string_buf)) Xfree(string_lowered); 233 return(0); 234} 235 236 237/* 238 * NAME 239 * FirstCmp - Compare color names of pair recs 240 * 241 * SYNOPSIS 242 */ 243static int 244FirstCmp(const void *p1, const void *p2) 245/* 246 * DESCRIPTION 247 * Compares the color names of XcmsColorTuples. 248 * This routine is public to allow access from qsort???. 249 * 250 * RETURNS 251 * 0 if equal; 252 * < 0 if first precedes second, 253 * > 0 if first succeeds second. 254 * 255 */ 256{ 257 return(strcmp(((XcmsPair *)p1)->first, ((XcmsPair *)p2)->first)); 258} 259 260 261 262/* 263 * NAME 264 * stringSectionSize - determine memory needed for strings 265 * 266 * SYNOPSIS 267 */ 268static void 269SetNoVisit(void) 270/* 271 * DESCRIPTION 272 * 273 * RETURNS 274 * void 275 * 276 */ 277{ 278 int i; 279 XcmsPair *pair = pairs; 280 281 for (i = 0; i < nEntries; i++, pair++) { 282 if (pair->flag != CYCLE) { 283 pair->flag = NOT_VISITED; 284 } 285 } 286} 287 288 289 290 291/* 292 * NAME 293 * field2 - extract two fields 294 * 295 * SYNOPSIS 296 */ 297static int 298field2( 299 char *pBuf, 300 char delim, /* in: field delimiter */ 301 char **p1, /* in/out: pointer to pointer to field 1 */ 302 char **p2) /* in/out: pointer to pointer to field 2 */ 303/* 304 * DESCRIPTION 305 * Extracts two fields from a "record". 306 * 307 * RETURNS 308 * XcmsSuccess if succeeded, otherwise XcmsFailure. 309 * 310 */ 311{ 312 *p1 = *p2 = NULL; 313 314 /* Find Field 1 */ 315 while (!isgraph(*pBuf)) { 316 if ((*pBuf != '\n') || (*pBuf != '\0')) { 317 return(XcmsFailure); 318 } 319 if (isspace(*pBuf) || (*pBuf == delim)) { 320 pBuf++; 321 } 322 } 323 *p1 = pBuf; 324 325 /* Find end of Field 2 */ 326 while (isprint(*pBuf) && (*pBuf != delim)) { 327 pBuf++; 328 } 329 if ((*pBuf == '\n') || (*pBuf == '\0')) { 330 return(XcmsFailure); 331 } 332 if ((*pBuf == ' ') || (*pBuf == delim)) { 333 *pBuf++ = '\0'; /* stuff end of string character */ 334 } else { 335 return(XcmsFailure); 336 } 337 338 /* Find Field 2 */ 339 while (!isgraph(*pBuf)) { 340 if ((*pBuf == '\n') || (*pBuf == '\0')) { 341 return(XcmsFailure); 342 } 343 if (isspace(*pBuf) || (*pBuf == delim)) { 344 pBuf++; 345 } 346 } 347 *p2 = pBuf; 348 349 /* Find end of Field 2 */ 350 while (isprint(*pBuf) && (*pBuf != delim)) { 351 pBuf++; 352 } 353 if (*pBuf != '\0') { 354 *pBuf = '\0'; /* stuff end of string character */ 355 } 356 357 return(XcmsSuccess); 358} 359 360 361/* 362 * NAME 363 * _XcmsLookupColorName - Lookup DB entry for a color name 364 * 365 * SYNOPSIS 366 */ 367static Status 368_XcmsLookupColorName( 369 XcmsCCC ccc, 370 const char **name, 371 XcmsColor *pColor) 372/* 373 * DESCRIPTION 374 * Searches for an entry in the Device-Independent Color Name 375 * Database for the specified string. 376 * 377 * RETURNS 378 * XcmsFailure if failed to find a matching entry in 379 * the database. 380 * XcmsSuccess if succeeded in converting color name to 381 * XcmsColor. 382 * _XCMS_NEWNAME if succeeded in converting color string (which 383 * is a color name to yet another color name. Note 384 * that the new name is passed back via 'name'. 385 */ 386 { 387 Status retval = 0; 388 char name_lowered_64[64]; 389 char *name_lowered; 390 register int i, j, left, right; 391 int len; 392 const char *tmpName; 393 XcmsPair *pair = NULL; 394 395 /* 396 * Check state of Database: 397 * XcmsDbInitNone 398 * XcmsDbInitSuccess 399 * XcmsDbInitFailure 400 */ 401 if (XcmsColorDbState == XcmsDbInitFailure) { 402 return(XcmsFailure); 403 } 404 if (XcmsColorDbState == XcmsDbInitNone) { 405 if (!LoadColornameDB()) { 406 return(XcmsFailure); 407 } 408 } 409 410 SetNoVisit(); 411 412 /* 413 * While copying name to name_lowered, convert to lowercase 414 */ 415 416 tmpName = *name; 417 418Retry: 419 if ((len = strlen(tmpName)) > 63) { 420 name_lowered = (char *) Xmalloc(len+1); 421 } else { 422 name_lowered = name_lowered_64; 423 } 424 425 _XcmsCopyISOLatin1Lowered(name_lowered, tmpName); 426 427 /* 428 * Now, remove spaces. 429 */ 430 for (i = 0, j = 0; j < len; j++) { 431 if (!isspace(name_lowered[j])) { 432 name_lowered[i++] = name_lowered[j]; 433 } 434 } 435 name_lowered[i] = '\0'; 436 437 left = 0; 438 right = nEntries - 1; 439 while (left <= right) { 440 i = (left + right) >> 1; 441 pair = &pairs[i]; 442 j = strcmp(name_lowered, pair->first); 443 if (j < 0) 444 right = i - 1; 445 else if (j > 0) 446 left = i + 1; 447 else { 448 break; 449 } 450 } 451 if (len > 63) Xfree(name_lowered); 452 453 if (left > right) { 454 if (retval == 2) { 455 if (*name != tmpName) { 456 *name = tmpName; 457 } 458 return(_XCMS_NEWNAME); 459 } 460 return(XcmsFailure); 461 } 462 463 if (pair->flag == CYCLE) { 464 return(XcmsFailure); 465 } 466 if (pair->flag == VISITED) { 467 pair->flag = CYCLE; 468 return(XcmsFailure); 469 } 470 471 if (_XcmsParseColorString(ccc, pair->second, pColor) == XcmsSuccess) { 472 /* f2 contains a numerical string specification */ 473 return(XcmsSuccess); 474 } else { 475 /* f2 does not contain a numerical string specification */ 476 tmpName = pair->second; 477 pair->flag = VISITED; 478 retval = 2; 479 goto Retry; 480 } 481} 482 483 484/* 485 * NAME 486 * RemoveSpaces 487 * 488 * SYNOPSIS 489 */ 490static int 491RemoveSpaces( 492 char *pString) 493/* 494 * DESCRIPTION 495 * Removes spaces from string. 496 * 497 * RETURNS 498 * Void 499 * 500 */ 501{ 502 int i, count = 0; 503 char *cptr; 504 505 /* REMOVE SPACES */ 506 cptr = pString; 507 for (i = strlen(pString); i; i--, cptr++) { 508 if (!isspace(*cptr)) { 509 *pString++ = *cptr; 510 count++; 511 } 512 } 513 *pString = '\0'; 514 return(count); 515} 516 517 518/* 519 * NAME 520 * stringSectionSize - determine memory needed for strings 521 * 522 * SYNOPSIS 523 */ 524static int 525stringSectionSize( 526 FILE *stream, 527 int *pNumEntries, 528 int *pSectionSize) 529/* 530 * DESCRIPTION 531 * Determines the amount of memory required to store the 532 * color name strings and also the number of strings. 533 * 534 * RETURNS 535 * XcmsSuccess if succeeded, otherwise XcmsFailure. 536 * 537 */ 538{ 539 char buf[XCMSDB_MAXLINELEN]; 540 char token[XCMSDB_MAXLINELEN]; 541 char token2[XCMSDB_MAXLINELEN]; 542 char *pBuf; 543 char *f1; 544 char *f2; 545 int i; 546 547 *pNumEntries = 0; 548 *pSectionSize = 0; 549 550 /* 551 * Advance to START_TOKEN 552 * Anything before is just considered as comments. 553 */ 554 555 while((pBuf = fgets(buf, XCMSDB_MAXLINELEN, stream)) != NULL) { 556 if ((sscanf(buf, "%s %s", token, token2)) 557 && (strcmp(token, START_TOKEN) == 0)) { 558 if (strcmp(token2, FORMAT_VERSION) != 0) { 559 /* text file not in the right format */ 560 return(XcmsFailure); 561 } 562 break; 563 } /* else it was just a blank line or comment */ 564 } 565 566 if (pBuf == NULL) { 567 return(XcmsFailure); 568 } 569 570 while((fgets(buf, XCMSDB_MAXLINELEN, stream)) != NULL) { 571 if ((sscanf(buf, "%s", token)) && (strcmp(token, END_TOKEN) == 0)) { 572 break; 573 } 574 575 if (field2(buf, DELIM_CHAR, &f1, &f2) != XcmsSuccess) { 576 return(XcmsFailure); 577 } 578 579 (*pNumEntries)++; 580 581 (*pSectionSize) += (i = strlen(f1)) + 1; 582 for (; i; i--, f1++) { 583 /* REMOVE SPACES FROM COUNT */ 584 if (isspace(*f1)) { 585 (*pSectionSize)--; 586 } 587 } 588 589 (*pSectionSize) += (i = strlen(f2)) + 1; 590 for (; i; i--, f2++) { 591 /* REMOVE SPACES FROM COUNT */ 592 if (isspace(*f2)) { 593 (*pSectionSize)--; 594 } 595 } 596 597 } 598 599 return(XcmsSuccess); 600} 601 602 603/* 604 * NAME 605 * ReadColornameDB - Read the Color Name Database 606 * 607 * SYNOPSIS 608 */ 609static Status 610ReadColornameDB( 611 FILE *stream, 612 XcmsPair *pRec, 613 char *pString) 614/* 615 * DESCRIPTION 616 * Loads the Color Name Database from a text file. 617 * 618 * RETURNS 619 * XcmsSuccess if succeeded, otherwise XcmsFailure. 620 * 621 */ 622{ 623 char buf[XCMSDB_MAXLINELEN]; 624 char token[XCMSDB_MAXLINELEN]; 625 char token2[XCMSDB_MAXLINELEN]; 626 char *f1; 627 char *f2; 628 char *pBuf; 629 630 /* 631 * Advance to START_TOKEN 632 * Anything before is just considered as comments. 633 */ 634 635 while((pBuf = fgets(buf, XCMSDB_MAXLINELEN, stream)) != NULL) { 636 if ((sscanf(buf, "%s %s", token, token2)) 637 && (strcmp(token, START_TOKEN) == 0)) { 638 if (strcmp(token2, FORMAT_VERSION) != 0) { 639 /* text file not in the right format */ 640 return(XcmsFailure); 641 } 642 break; 643 } /* else it was just a blank line or comment */ 644 } 645 646 if (pBuf == NULL) { 647 return(XcmsFailure); 648 } 649 650 /* 651 * Process lines between START_TOKEN to END_TOKEN 652 */ 653 654 while ((fgets(buf, XCMSDB_MAXLINELEN, stream)) != NULL) { 655 if ((sscanf(buf, "%s", token)) && (strcmp(token, END_TOKEN) == 0)) { 656 /* 657 * Found END_TOKEN so break out of for loop 658 */ 659 break; 660 } 661 662 /* 663 * Get pairs 664 */ 665 if (field2(buf, DELIM_CHAR, &f1, &f2) != XcmsSuccess) { 666 /* Invalid line */ 667 continue; 668 } 669 670 /* 671 * Add strings 672 */ 673 674 /* Left String */ 675 pRec->first = pString; 676 _XcmsCopyISOLatin1Lowered(pString, f1); 677 pString += (1 + RemoveSpaces(pString)); 678 pRec->second = pString; 679 /* Right String */ 680 _XcmsCopyISOLatin1Lowered(pString, f2); 681 pString += RemoveSpaces(pString) + 1; 682 pRec++; 683 684 } 685 686 return(XcmsSuccess); 687} 688 689 690/* 691 * NAME 692 * LoadColornameDB - Load the Color Name Database 693 * 694 * SYNOPSIS 695 */ 696static Status 697LoadColornameDB(void) 698/* 699 * DESCRIPTION 700 * Loads the Color Name Database from a text file. 701 * 702 * RETURNS 703 * XcmsSuccess if succeeded, otherwise XcmsFailure. 704 * 705 */ 706{ 707 int size; 708 FILE *stream; 709 const char *pathname; 710 struct stat txt; 711 int length; 712 713 /* use and name of this env var is not part of the standard */ 714 /* implementation-dependent feature */ 715 if ((pathname = getenv("XCMSDB")) == NULL) { 716 pathname = XCMSDB; 717 } 718#ifdef __UNIXOS2__ 719 pathname = __XOS2RedirRoot(pathname); 720#endif 721 722 length = strlen(pathname); 723 if ((length == 0) || (length >= (BUFSIZ - 5))){ 724 XcmsColorDbState = XcmsDbInitFailure; 725 return(XcmsFailure); 726 } 727 728 if (stat(pathname, &txt)) { 729 /* can't stat file */ 730 XcmsColorDbState = XcmsDbInitFailure; 731 return(XcmsFailure); 732 } 733 734 if ((stream = _XFopenFile (pathname, "r")) == NULL) { 735 /* can't open file */ 736 XcmsColorDbState = XcmsDbInitFailure; 737 return(XcmsFailure); 738 } 739 740 if (stringSectionSize(stream, &nEntries, &size) != XcmsSuccess || 741 nEntries == 0) { 742 (void) fclose(stream); 743 XcmsColorDbState = XcmsDbInitFailure; 744 return(XcmsFailure); 745 } 746 rewind(stream); 747 748 strings = (char *) Xmalloc(size); 749 pairs = (XcmsPair *)Xcalloc(nEntries, sizeof(XcmsPair)); 750 751 ReadColornameDB(stream, pairs, strings); 752 (void) fclose(stream); 753 754 /* 755 * sort the pair recs 756 */ 757 qsort((char *)pairs, nEntries, sizeof(XcmsPair), FirstCmp); 758 759 XcmsColorDbState = XcmsDbInitSuccess; 760 return(XcmsSuccess); 761} 762 763 764/************************************************************************ 765 * * 766 * API PRIVATE ROUTINES * 767 * * 768 ************************************************************************/ 769 770/* 771 * NAME 772 * _XcmsCopyISOLatin1Lowered 773 * 774 * SYNOPSIS 775 */ 776void 777_XcmsCopyISOLatin1Lowered( 778 char *dst, 779 const char *src) 780/* 781 * DESCRIPTION 782 * ISO Latin-1 case conversion routine 783 * Identical to XmuCopyISOLatin1Lowered() but provided here 784 * to eliminate need to link with libXmu.a. 785 * 786 * IMPLEMENTORS NOTE: 787 * This routine is also used in XcmsFormatOfPrefix. 788 * 789 * RETURNS 790 * Void 791 * 792 */ 793{ 794 register unsigned char *dest; 795 register const unsigned char *source; 796 797 for (dest = (unsigned char *)dst, source = (const unsigned char *)src; 798 *source; 799 source++, dest++) 800 { 801 if ((*source >= XK_A) && (*source <= XK_Z)) 802 *dest = *source + (XK_a - XK_A); 803 else if ((*source >= XK_Agrave) && (*source <= XK_Odiaeresis)) 804 *dest = *source + (XK_agrave - XK_Agrave); 805 else if ((*source >= XK_Ooblique) && (*source <= XK_Thorn)) 806 *dest = *source + (XK_oslash - XK_Ooblique); 807 else 808 *dest = *source; 809 } 810 *dest = '\0'; 811} 812 813 814/* 815 * NAME 816 * _XcmsResolveColorString - 817 * 818 * SYNOPSIS 819 */ 820Status 821_XcmsResolveColorString ( 822 XcmsCCC ccc, 823 const char **color_string, 824 XcmsColor *pColor_exact_return, 825 XcmsColorFormat result_format) 826/* 827 * DESCRIPTION 828 * The XcmsLookupColor function finds the color specification 829 * associated with a color name in the Device-Independent Color 830 * Name Database. 831 * RETURNS 832 * XcmsFailure if failed to convert valid color string. 833 * XcmsSuccess if succeeded in converting color string to 834 * XcmsColor. 835 * _XCMS_NEWNAME if failed to parse the string or find it in 836 * the database, or if succeeded in looking it up and 837 * found another name which is not in the database. 838 * Note that the new name is returned in color_string. 839 * 840 * This function returns both the color specification found in the 841 * database (db specification) and the color specification for the 842 * color displayable by the specified screen (screen 843 * specification). The calling routine sets the format for these 844 * returned specifications in the XcmsColor format component. 845 * If XcmsUndefinedFormat, the specification is returned in the 846 * format used to store the color in the database. 847 */ 848{ 849 XcmsColor dbWhitePt; /* whitePt associated with pColor_exact_return*/ 850 /* the screen's white point */ 851 XcmsColor *pClientWhitePt; 852 int retval; 853 const char *strptr = whitePtStr; 854 855/* 856 * 0. Check for invalid arguments. 857 */ 858 if (ccc == NULL || (*color_string)[0] == '\0' || pColor_exact_return == NULL) { 859 return(XcmsFailure); 860 } 861 862/* 863 * 1. First attempt to parse the string 864 * If successful, then convert the specification to the target format 865 * and return. 866 */ 867 if (_XcmsParseColorString(ccc, *color_string, pColor_exact_return) 868 == 1) { 869 if (result_format != XcmsUndefinedFormat 870 && pColor_exact_return->format != result_format) { 871 /* need to be converted to the target format */ 872 return(XcmsConvertColors(ccc, pColor_exact_return, 1, 873 result_format, (Bool *)NULL)); 874 } else { 875 return(XcmsSuccess); 876 } 877 } 878 879/* 880 * 2. Attempt to find it in the DI Color Name Database 881 */ 882 883 /* 884 * a. Convert String into a XcmsColor structure 885 * Attempt to extract the specification for color_string from the 886 * DI Database (pColor_exact_return). If the DI Database does not 887 * have this entry, then return failure. 888 */ 889 retval = _XcmsLookupColorName(ccc, color_string, pColor_exact_return); 890 891 if (retval != XcmsSuccess) { 892 /* color_string replaced with a color name, or not found */ 893 return(_XCMS_NEWNAME); 894 } 895 896 if (pColor_exact_return->format == XcmsUndefinedFormat) { 897 return(XcmsFailure); 898 } 899 900 /* 901 * b. If result_format not defined, then assume target format 902 * is the exact format. 903 */ 904 if (result_format == XcmsUndefinedFormat) { 905 result_format = pColor_exact_return->format; 906 } 907 908 if ((ClientWhitePointOfCCC(ccc))->format == XcmsUndefinedFormat) { 909 pClientWhitePt = ScreenWhitePointOfCCC(ccc); 910 } else { 911 pClientWhitePt = ClientWhitePointOfCCC(ccc); 912 } 913 914 /* 915 * c. Convert to the target format, making adjustments for white 916 * point differences as necessary. 917 */ 918 if (XCMS_DD_ID(pColor_exact_return->format)) { 919 /* 920 * The spec format is Device-Dependent, therefore assume the 921 * its white point is the Screen White Point. 922 */ 923 if (XCMS_DD_ID(result_format)) { 924 /* 925 * Target format is Device-Dependent 926 * Therefore, DD --> DD conversion 927 */ 928 return(_XcmsDDConvertColors(ccc, pColor_exact_return, 929 1, result_format, (Bool *) NULL)); 930 } else { 931 /* 932 * Target format is Device-Independent 933 * Therefore, DD --> DI conversion 934 */ 935 if (ccc->whitePtAdjProc && !_XcmsEqualWhitePts(ccc, 936 pClientWhitePt, ScreenWhitePointOfCCC(ccc))) { 937 return((*ccc->whitePtAdjProc)(ccc, ScreenWhitePointOfCCC(ccc), 938 pClientWhitePt, result_format, 939 pColor_exact_return, 1, (Bool *) NULL)); 940 } else { 941 if (_XcmsDDConvertColors(ccc, pColor_exact_return, 1, 942 XcmsCIEXYZFormat, (Bool *) NULL) == XcmsFailure) { 943 return(XcmsFailure); 944 } 945 return(_XcmsDIConvertColors(ccc, pColor_exact_return, 946 pClientWhitePt, 1, result_format)); 947 } 948 } 949 } else { 950 /* 951 * The spec format is Device-Independent, therefore attempt 952 * to find a database white point. 953 * 954 * If the Database does not have a white point, then assume the 955 * database white point is the same as the Screen White Point. 956 */ 957 958 if (_XcmsLookupColorName(ccc, &strptr, &dbWhitePt) != 1) { 959 memcpy((char *)&dbWhitePt, 960 (char *)&ccc->pPerScrnInfo->screenWhitePt, 961 sizeof(XcmsColor)); 962 } 963 if (XCMS_DD_ID(result_format)) { 964 /* 965 * Target format is Device-Dependent 966 * Therefore, DI --> DD conversion 967 */ 968 if (ccc->whitePtAdjProc && !_XcmsEqualWhitePts(ccc, 969 &dbWhitePt, ScreenWhitePointOfCCC(ccc))) { 970 return((*ccc->whitePtAdjProc)(ccc, &dbWhitePt, 971 ScreenWhitePointOfCCC(ccc), result_format, 972 pColor_exact_return, 1, (Bool *)NULL)); 973 } else { 974 if (pColor_exact_return->format != XcmsCIEXYZFormat) { 975 if (_XcmsDIConvertColors(ccc, pColor_exact_return, 976 &dbWhitePt, 1, XcmsCIEXYZFormat) == XcmsFailure) { 977 return(XcmsFailure); 978 } 979 } 980 return (_XcmsDDConvertColors(ccc, pColor_exact_return, 1, 981 result_format, (Bool *)NULL)); 982 } 983 } else { 984 /* 985 * Target format is Device-Independent 986 * Therefore, DI --> DI conversion 987 */ 988 if (ccc->whitePtAdjProc && !_XcmsEqualWhitePts(ccc, 989 &dbWhitePt, pClientWhitePt)) { 990 /* 991 * The calling routine wants to resolve this color 992 * in terms if it's white point (i.e. Client White Point). 993 * Therefore, apply white adjustment for the displacement 994 * between dbWhitePt to clientWhitePt. 995 */ 996 return((*ccc->whitePtAdjProc)(ccc, &dbWhitePt, 997 pClientWhitePt, result_format, 998 pColor_exact_return, 1, (Bool *)NULL)); 999 } else if (_XcmsEqualWhitePts(ccc, 1000 &dbWhitePt, pClientWhitePt)) { 1001 /* 1002 * Can use either dbWhitePt or pClientWhitePt to 1003 * convert to the result_format. 1004 */ 1005 if (pColor_exact_return->format == result_format) { 1006 return(XcmsSuccess); 1007 } else { 1008 return (_XcmsDIConvertColors(ccc, pColor_exact_return, 1009 &dbWhitePt, 1, result_format)); 1010 } 1011 } else { 1012 /* 1013 * Need to convert to a white point independent color 1014 * space (let's choose CIEXYZ) then convert to the 1015 * target color space. Why? Lets assume that 1016 * pColor_exact_return->format and result format 1017 * are white point dependent format (e.g., CIELUV, CIELAB, 1018 * TekHVC ... same or any combination). If so, we'll 1019 * need to convert the color with dbWhitePt to an absolute 1020 * spec (i.e. non-white point dependent) then convert that 1021 * absolute value with clientWhitePt to the result_format. 1022 */ 1023 if (pColor_exact_return->format != XcmsCIEXYZFormat) { 1024 if (_XcmsDIConvertColors(ccc, pColor_exact_return, 1025 &dbWhitePt, 1, XcmsCIEXYZFormat) == XcmsFailure) { 1026 return(XcmsFailure); 1027 } 1028 } 1029 if (result_format == XcmsCIEXYZFormat) { 1030 return(XcmsSuccess); 1031 } else { 1032 return(_XcmsDIConvertColors(ccc, pColor_exact_return, 1033 pClientWhitePt, 1, result_format)); 1034 } 1035 } 1036 } 1037 } 1038} 1039