#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "Xlibint.h"
#include "Xcmsint.h"
#include "Cv.h"
#define DD_FORMAT 0x01
#define DI_FORMAT 0x02
#define MIX_FORMAT 0x04
#ifndef MAX
# define MAX(x,y) ((x) > (y) ? (x) : (y))
#endif
static int
EqualCIEXYZ(
XcmsColor *p1, XcmsColor *p2)
{
if (p1->format != XcmsCIEXYZFormat || p2->format != XcmsCIEXYZFormat) {
return(0);
}
if ((p1->spec.CIEXYZ.X != p2->spec.CIEXYZ.X)
|| (p1->spec.CIEXYZ.Y != p2->spec.CIEXYZ.Y)
|| (p1->spec.CIEXYZ.Z != p2->spec.CIEXYZ.Z)) {
return(0);
}
return(1);
}
static XcmsColorSpace *
ColorSpaceOfID(
XcmsCCC ccc,
XcmsColorFormat id)
{
XcmsColorSpace **papColorSpaces;
if (ccc == NULL) {
return(NULL);
}
papColorSpaces = _XcmsDIColorSpaces;
if (papColorSpaces != NULL) {
while (*papColorSpaces != NULL) {
if ((*papColorSpaces)->id == id) {
return(*papColorSpaces);
}
papColorSpaces++;
}
}
papColorSpaces = ((XcmsFunctionSet *)ccc->pPerScrnInfo->functionSet)->DDColorSpaces;
if (papColorSpaces != NULL) {
while (*papColorSpaces != NULL) {
if ((*papColorSpaces)->id == id) {
return(*papColorSpaces);
}
papColorSpaces++;
}
}
return(NULL);
}
static int
ValidDIColorSpaceID(
XcmsColorFormat id)
{
XcmsColorSpace **papRec;
papRec = _XcmsDIColorSpaces;
if (papRec != NULL) {
while (*papRec != NULL) {
if ((*papRec)->id == id) {
return(1);
}
papRec++;
}
}
return(0);
}
static int
ValidDDColorSpaceID(
XcmsCCC ccc,
XcmsColorFormat id)
{
XcmsColorSpace **papRec;
if (ccc->pPerScrnInfo->state != XcmsInitNone) {
papRec = ((XcmsFunctionSet *)ccc->pPerScrnInfo->functionSet)->DDColorSpaces;
while (*papRec != NULL) {
if ((*papRec)->id == id) {
return(1);
}
papRec++;
}
}
return(0);
}
static Status
ConvertMixedColors(
XcmsCCC ccc,
XcmsColor *pColors_in_out,
XcmsColor *pWhitePt,
unsigned int nColors,
XcmsColorFormat targetFormat,
unsigned char format_flag)
{
XcmsColor *pColor, *pColors_start;
XcmsColorFormat format;
Status retval_tmp;
Status retval = XcmsSuccess;
unsigned int iColors;
unsigned int nBatch;
iColors = 0;
while (iColors < nColors) {
pColor = pColors_start = pColors_in_out + iColors;
format = pColors_start->format;
nBatch = 0;
while (iColors < nColors && pColor->format == format) {
pColor++;
nBatch++;
iColors++;
}
if (format != targetFormat) {
if (XCMS_DI_ID(format) && (format_flag & DI_FORMAT) &&
XCMS_DI_ID(targetFormat)) {
retval_tmp = _XcmsDIConvertColors(ccc, pColors_start, pWhitePt,
nBatch, targetFormat);
} else if (XCMS_DD_ID(format) && (format_flag & DD_FORMAT) &&
(targetFormat == XcmsCIEXYZFormat)) {
if ((ccc->whitePtAdjProc != NULL) && !_XcmsEqualWhitePts(ccc,
pWhitePt, ScreenWhitePointOfCCC(ccc))) {
retval_tmp = (*ccc->whitePtAdjProc)(ccc,
ScreenWhitePointOfCCC(ccc), pWhitePt,
XcmsCIEXYZFormat, pColors_start, nBatch,
(Bool *)NULL);
} else {
retval_tmp = _XcmsDDConvertColors(ccc, pColors_start,
nBatch, XcmsCIEXYZFormat, (Bool *)NULL);
}
} else if (XCMS_DD_ID(format) && (format_flag & DD_FORMAT) &&
XCMS_DD_ID(targetFormat)) {
retval_tmp = _XcmsDDConvertColors(ccc, pColors_start, nBatch,
targetFormat, (Bool *)NULL);
} else {
return(XcmsFailure);
}
if (retval_tmp == XcmsFailure) {
return(XcmsFailure);
}
retval = MAX(retval, retval_tmp);
}
}
return(retval);
}
int
_XcmsEqualWhitePts(XcmsCCC ccc, XcmsColor *pWhitePt1, XcmsColor *pWhitePt2)
{
XcmsColor tmp1, tmp2;
memcpy((char *)&tmp1, (char *)pWhitePt1, sizeof(XcmsColor));
memcpy((char *)&tmp2, (char *)pWhitePt2, sizeof(XcmsColor));
if (tmp1.format != XcmsCIEXYZFormat) {
if (_XcmsDIConvertColors(ccc, &tmp1, (XcmsColor *) NULL, 1,
XcmsCIEXYZFormat)==0) {
return(0);
}
}
if (tmp2.format != XcmsCIEXYZFormat) {
if (_XcmsDIConvertColors(ccc, &tmp2, (XcmsColor *) NULL, 1,
XcmsCIEXYZFormat)==0) {
return(0);
}
}
return (EqualCIEXYZ(&tmp1, &tmp2));
}
Status
_XcmsDIConvertColors(
XcmsCCC ccc,
XcmsColor *pColors_in_out,
XcmsColor *pWhitePt,
unsigned int nColors,
XcmsColorFormat newFormat)
{
XcmsColorSpace *pFrom, *pTo;
XcmsDIConversionProc *src_to_CIEXYZ, *src_from_CIEXYZ;
XcmsDIConversionProc *dest_to_CIEXYZ, *dest_from_CIEXYZ;
XcmsDIConversionProc *to_CIEXYZ_stop, *from_CIEXYZ_start;
XcmsDIConversionProc *tmp;
if (pColors_in_out == NULL ||
!ValidDIColorSpaceID(pColors_in_out->format) ||
!ValidDIColorSpaceID(newFormat)) {
return(XcmsFailure);
}
if ((pFrom = ColorSpaceOfID(ccc, pColors_in_out->format))
== NULL) {
return(XcmsFailure);
}
if ((pTo = ColorSpaceOfID(ccc, newFormat)) == NULL) {
return(XcmsFailure);
}
src_to_CIEXYZ = pFrom->to_CIEXYZ;
src_from_CIEXYZ = pFrom->from_CIEXYZ;
dest_to_CIEXYZ = pTo->to_CIEXYZ;
dest_from_CIEXYZ = pTo->from_CIEXYZ;
if (pTo->inverse_flag && pFrom->inverse_flag) {
for (to_CIEXYZ_stop = src_to_CIEXYZ; *to_CIEXYZ_stop; to_CIEXYZ_stop++){
for (tmp = dest_to_CIEXYZ; *tmp; tmp++) {
if (*to_CIEXYZ_stop == *tmp) {
goto Continue;
}
}
}
Continue:
while (src_to_CIEXYZ != to_CIEXYZ_stop) {
if ((*src_to_CIEXYZ++)(ccc, pWhitePt, pColors_in_out,
nColors) == XcmsFailure) {
return(XcmsFailure);
}
}
from_CIEXYZ_start = dest_from_CIEXYZ;
tmp = src_from_CIEXYZ;
while ((*from_CIEXYZ_start == *tmp) && (*from_CIEXYZ_start != NULL)) {
from_CIEXYZ_start++;
tmp++;
}
} else {
while (*src_to_CIEXYZ) {
if ((*src_to_CIEXYZ++)(ccc, pWhitePt, pColors_in_out,
nColors) == XcmsFailure) {
return(XcmsFailure);
}
}
from_CIEXYZ_start = dest_from_CIEXYZ;
}
while (*from_CIEXYZ_start) {
if ((*from_CIEXYZ_start++)(ccc, pWhitePt, pColors_in_out,
nColors) == XcmsFailure) {
return(XcmsFailure);
}
}
return(XcmsSuccess);
}
Status
_XcmsDDConvertColors(
XcmsCCC ccc,
XcmsColor *pColors_in_out,
unsigned int nColors,
XcmsColorFormat newFormat,
Bool *pCompressed)
{
XcmsColorSpace *pFrom, *pTo;
XcmsDDConversionProc *src_to_CIEXYZ, *src_from_CIEXYZ;
XcmsDDConversionProc *dest_to_CIEXYZ, *dest_from_CIEXYZ;
XcmsDDConversionProc *from_CIEXYZ_start, *to_CIEXYZ_stop;
XcmsDDConversionProc *tmp;
int retval;
int hasCompressed = 0;
if (ccc == NULL || pColors_in_out == NULL) {
return(XcmsFailure);
}
if (nColors == 0 || pColors_in_out->format == newFormat) {
return(XcmsSuccess);
}
if (((XcmsFunctionSet *)ccc->pPerScrnInfo->functionSet) == NULL) {
return(XcmsFailure);
}
if ( !( ValidDDColorSpaceID(ccc, pColors_in_out->format)
||
(pColors_in_out->format == XcmsCIEXYZFormat))
||
!(ValidDDColorSpaceID(ccc, newFormat)
||
newFormat == XcmsCIEXYZFormat)) {
return(XcmsFailure);
}
if ((pFrom = ColorSpaceOfID(ccc, pColors_in_out->format)) == NULL){
return(XcmsFailure);
}
if ((pTo = ColorSpaceOfID(ccc, newFormat)) == NULL) {
return(XcmsFailure);
}
src_to_CIEXYZ = (XcmsDDConversionProc *)pFrom->to_CIEXYZ;
src_from_CIEXYZ = (XcmsDDConversionProc *)pFrom->from_CIEXYZ;
dest_to_CIEXYZ = (XcmsDDConversionProc *)pTo->to_CIEXYZ;
dest_from_CIEXYZ = (XcmsDDConversionProc *)pTo->from_CIEXYZ;
if (pTo->inverse_flag && pFrom->inverse_flag) {
for (to_CIEXYZ_stop = src_to_CIEXYZ; *to_CIEXYZ_stop; to_CIEXYZ_stop++){
for (tmp = dest_to_CIEXYZ; *tmp; tmp++) {
if (*to_CIEXYZ_stop == *tmp) {
goto Continue;
}
}
}
Continue:
while (src_to_CIEXYZ != to_CIEXYZ_stop) {
retval = (*src_to_CIEXYZ++)(ccc, pColors_in_out, nColors,
pCompressed);
if (retval == XcmsFailure) {
return(XcmsFailure);
}
hasCompressed |= (retval == XcmsSuccessWithCompression);
}
from_CIEXYZ_start = dest_from_CIEXYZ;
tmp = src_from_CIEXYZ;
while ((*from_CIEXYZ_start == *tmp) && (*from_CIEXYZ_start != NULL)) {
from_CIEXYZ_start++;
tmp++;
}
} else {
while (*src_to_CIEXYZ) {
retval = (*src_to_CIEXYZ++)(ccc, pColors_in_out, nColors,
pCompressed);
if (retval == XcmsFailure) {
return(XcmsFailure);
}
hasCompressed |= (retval == XcmsSuccessWithCompression);
}
from_CIEXYZ_start = dest_from_CIEXYZ;
}
while (*from_CIEXYZ_start) {
retval = (*from_CIEXYZ_start++)(ccc, pColors_in_out, nColors,
pCompressed);
if (retval == XcmsFailure) {
return(XcmsFailure);
}
hasCompressed |= (retval == XcmsSuccessWithCompression);
}
return(hasCompressed ? XcmsSuccessWithCompression : XcmsSuccess);
}
Status
XcmsConvertColors(
XcmsCCC ccc,
XcmsColor *pColors_in_out,
unsigned int nColors,
XcmsColorFormat targetFormat,
Bool *pCompressed)
{
XcmsColor clientWhitePt;
XcmsColor Color1;
XcmsColor *pColors_tmp;
int callWhiteAdjustProc = 0;
XcmsColorFormat format;
Status retval;
unsigned char contents_flag = 0x00;
unsigned int iColors;
if (ccc == NULL || pColors_in_out == NULL ||
!(ValidDIColorSpaceID(targetFormat) ||
ValidDDColorSpaceID(ccc, targetFormat))) {
return(XcmsFailure);
}
format = pColors_in_out->format;
for (pColors_tmp = pColors_in_out, iColors = nColors; iColors; pColors_tmp++, iColors--) {
if (!(ValidDIColorSpaceID(pColors_tmp->format) ||
ValidDDColorSpaceID(ccc, pColors_tmp->format))) {
return(XcmsFailure);
}
if (XCMS_DI_ID(pColors_tmp->format)) {
contents_flag |= DI_FORMAT;
} else {
contents_flag |= DD_FORMAT;
}
if (pColors_tmp->format != format) {
contents_flag |= MIX_FORMAT;
}
}
if ((contents_flag & DI_FORMAT) || XCMS_DI_ID(targetFormat)) {
memcpy((char *)&clientWhitePt, (char *)&ccc->clientWhitePt,
sizeof(XcmsColor));
if (clientWhitePt.format == XcmsUndefinedFormat) {
memcpy((char *)&clientWhitePt,
(char *)&ccc->pPerScrnInfo->screenWhitePt,
sizeof(XcmsColor));
} else if ((ccc->whitePtAdjProc != NULL) && !_XcmsEqualWhitePts(ccc,
&clientWhitePt, ScreenWhitePointOfCCC(ccc))) {
callWhiteAdjustProc = 1;
}
}
if (nColors > 1) {
pColors_tmp = (XcmsColor *) Xmalloc(nColors * sizeof(XcmsColor));
} else {
pColors_tmp = &Color1;
}
memcpy((char *)pColors_tmp, (char *)pColors_in_out,
nColors * sizeof(XcmsColor));
if (pCompressed) {
bzero((char *)pCompressed, nColors * sizeof(Bool));
}
if (contents_flag == DD_FORMAT || contents_flag == DI_FORMAT) {
if (XCMS_DI_ID(format) && XCMS_DI_ID(targetFormat)) {
retval = _XcmsDIConvertColors(ccc, pColors_tmp,
&clientWhitePt, nColors, targetFormat);
} else if (XCMS_DD_ID(format) && XCMS_DD_ID(targetFormat)) {
retval = _XcmsDDConvertColors(ccc, pColors_tmp, nColors,
targetFormat, (Bool *)NULL);
} else {
if (XCMS_DI_ID(format)) {
if (callWhiteAdjustProc) {
retval = (*ccc->whitePtAdjProc)(ccc, &clientWhitePt,
ScreenWhitePointOfCCC(ccc), targetFormat,
pColors_tmp, nColors, pCompressed);
} else {
if (_XcmsDIConvertColors(ccc, pColors_tmp,
&clientWhitePt, nColors, XcmsCIEXYZFormat)
== XcmsFailure) {
goto Failure;
}
retval = _XcmsDDConvertColors(ccc, pColors_tmp, nColors,
targetFormat, pCompressed);
}
} else {
if (callWhiteAdjustProc) {
retval = (*ccc->whitePtAdjProc)(ccc,
ScreenWhitePointOfCCC(ccc), &clientWhitePt,
targetFormat, pColors_tmp, nColors, pCompressed);
} else {
if (_XcmsDDConvertColors(ccc, pColors_tmp, nColors,
XcmsCIEXYZFormat, (Bool *)NULL) == XcmsFailure) {
goto Failure;
}
retval = _XcmsDIConvertColors(ccc, pColors_tmp,
&clientWhitePt, nColors, targetFormat);
}
}
}
} else {
if ((contents_flag == (DI_FORMAT | MIX_FORMAT)) &&
XCMS_DI_ID(targetFormat)) {
retval = ConvertMixedColors(ccc, pColors_tmp, &clientWhitePt,
nColors, targetFormat, (unsigned char)DI_FORMAT);
} else if ((contents_flag == (DD_FORMAT | MIX_FORMAT)) &&
XCMS_DD_ID(targetFormat)) {
retval = ConvertMixedColors(ccc, pColors_tmp,
(XcmsColor *)NULL, nColors, targetFormat,
(unsigned char)DD_FORMAT);
} else if (XCMS_DI_ID(targetFormat)) {
retval = ConvertMixedColors(ccc, pColors_tmp, &clientWhitePt,
nColors, XcmsCIEXYZFormat, (unsigned char)DD_FORMAT);
retval = ConvertMixedColors(ccc, pColors_tmp, &clientWhitePt,
nColors, targetFormat, (unsigned char)DI_FORMAT);
} else {
if ((retval = ConvertMixedColors(ccc, pColors_tmp, &clientWhitePt,
nColors, XcmsCIEXYZFormat,
(unsigned char)(DI_FORMAT | DD_FORMAT))) == XcmsFailure) {
goto Failure;
}
if (callWhiteAdjustProc) {
retval = (*ccc->whitePtAdjProc)(ccc,
&clientWhitePt, ScreenWhitePointOfCCC(ccc),
targetFormat, pColors_tmp, nColors, pCompressed);
} else {
retval = _XcmsDDConvertColors(ccc, pColors_tmp, nColors,
targetFormat, pCompressed);
}
}
}
if (retval != XcmsFailure) {
memcpy((char *)pColors_in_out, (char *)pColors_tmp,
nColors * sizeof(XcmsColor));
}
if (nColors > 1) {
Xfree((char *)pColors_tmp);
}
return(retval);
Failure:
if (nColors > 1) {
Xfree((char *)pColors_tmp);
}
return(XcmsFailure);
}
XcmsColorFormat
_XcmsRegFormatOfPrefix(
_Xconst char *prefix)
{
XcmsRegColorSpaceEntry *pEntry = _XcmsRegColorSpaces;
while (pEntry->prefix != NULL) {
if (strcmp(prefix, pEntry->prefix) == 0) {
return(pEntry->id);
}
pEntry++;
}
return(XcmsUndefinedFormat);
}