[cups] Test patch for ICC support added but not applied by default.
Tim Waugh
twaugh at fedoraproject.org
Tue Jan 11 15:37:37 UTC 2011
commit ba9bc8eeab8cd8bceb326ab3af8b8f6f69ecd39b
Author: Tim Waugh <twaugh at redhat.com>
Date: Thu Jan 6 16:21:12 2011 +0000
Test patch for ICC support added but not applied by default.
cups-icc.patch | 1741 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cups.spec | 6 +
2 files changed, 1747 insertions(+), 0 deletions(-)
---
diff --git a/cups-icc.patch b/cups-icc.patch
new file mode 100644
index 0000000..f6275bd
--- /dev/null
+++ b/cups-icc.patch
@@ -0,0 +1,1741 @@
+diff -up cups-1.4.6/scheduler/ipp.c.icc cups-1.4.6/scheduler/ipp.c
+--- cups-1.4.6/scheduler/ipp.c.icc 2011-01-11 15:23:38.318062917 +0000
++++ cups-1.4.6/scheduler/ipp.c 2011-01-11 15:23:38.379057153 +0000
+@@ -32,10 +32,6 @@
+ * based upon the printer state...
+ * add_queued_job_count() - Add the "queued-job-count" attribute for the
+ * specified printer or class.
+- * apple_init_profile() - Initialize a color profile.
+- * apple_register_profiles() - Register color profiles for a printer.
+- * apple_unregister_profiles() - Remove color profiles for the specified
+- * printer.
+ * apply_printer_defaults() - Apply printer default options to a job.
+ * authenticate_job() - Set job authentication info.
+ * cancel_all_jobs() - Cancel all print jobs.
+@@ -107,11 +103,9 @@
+ */
+
+ #include "cupsd.h"
+-#include <cups/ppd-private.h>
+
+ #ifdef __APPLE__
+ # include <ApplicationServices/ApplicationServices.h>
+-# include <CoreFoundation/CoreFoundation.h>
+ # ifdef HAVE_MEMBERSHIP_H
+ # include <membership.h>
+ # endif /* HAVE_MEMBERSHIP_H */
+@@ -142,14 +136,6 @@ static void add_printer(cupsd_client_t *
+ static void add_printer_state_reasons(cupsd_client_t *con,
+ cupsd_printer_t *p);
+ static void add_queued_job_count(cupsd_client_t *con, cupsd_printer_t *p);
+-#ifdef __APPLE__
+-static void apple_init_profile(ppd_file_t *ppd, cups_array_t *languages,
+- CMDeviceProfileInfo *profile, unsigned id,
+- const char *name, const char *text,
+- const char *iccfile);
+-static void apple_register_profiles(cupsd_printer_t *p);
+-static void apple_unregister_profiles(cupsd_printer_t *p);
+-#endif /* __APPLE__ */
+ static void apply_printer_defaults(cupsd_printer_t *printer,
+ cupsd_job_t *job);
+ static void authenticate_job(cupsd_client_t *con, ipp_attribute_t *uri);
+@@ -2947,17 +2933,15 @@ add_printer(cupsd_client_t *con, /* I -
+
+ cupsdSetPrinterReasons(printer, "none");
+
+-#ifdef __APPLE__
+ /*
+ * (Re)register color profiles...
+ */
+
+ if (!RunUser)
+ {
+- apple_unregister_profiles(printer);
+- apple_register_profiles(printer);
++ cupsdUnregisterColorProfiles(printer);
++ cupsdRegisterColorProfiles(printer);
+ }
+-#endif /* __APPLE__ */
+ }
+
+ /*
+@@ -3093,553 +3077,6 @@ add_queued_job_count(
+ }
+
+
+-#ifdef __APPLE__
+-/*
+- * 'apple_init_profile()' - Initialize a color profile.
+- */
+-
+-static void
+-apple_init_profile(
+- ppd_file_t *ppd, /* I - PPD file */
+- cups_array_t *languages, /* I - Languages in the PPD file */
+- CMDeviceProfileInfo *profile, /* I - Profile record */
+- unsigned id, /* I - Profile ID */
+- const char *name, /* I - Profile name */
+- const char *text, /* I - Profile UI text */
+- const char *iccfile) /* I - ICC filename */
+-{
+- char url[1024]; /* URL for profile filename */
+- CFMutableDictionaryRef dict; /* Dictionary for name */
+- char *language; /* Current language */
+- ppd_attr_t *attr; /* Profile attribute */
+- CFStringRef cflang, /* Language string */
+- cftext; /* Localized text */
+-
+-
+- /*
+- * Build the profile name dictionary...
+- */
+-
+- dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+- &kCFTypeDictionaryKeyCallBacks,
+- &kCFTypeDictionaryValueCallBacks);
+-
+- cftext = CFStringCreateWithCString(kCFAllocatorDefault, text,
+- kCFStringEncodingUTF8);
+-
+- if (cftext)
+- {
+- CFDictionarySetValue(dict, CFSTR("en"), cftext);
+- CFRelease(cftext);
+- }
+-
+- if (languages)
+- {
+- /*
+- * Find localized names for the color profiles...
+- */
+-
+- cupsArraySave(ppd->sorted_attrs);
+-
+- for (language = (char *)cupsArrayFirst(languages);
+- language;
+- language = (char *)cupsArrayNext(languages))
+- {
+- if (iccfile)
+- {
+- if ((attr = _ppdLocalizedAttr(ppd, "cupsICCProfile", name,
+- language)) == NULL)
+- attr = _ppdLocalizedAttr(ppd, "APTiogaProfile", name, language);
+- }
+- else
+- attr = _ppdLocalizedAttr(ppd, "ColorModel", name, language);
+-
+- if (attr && attr->text[0])
+- {
+- cflang = CFStringCreateWithCString(kCFAllocatorDefault, language,
+- kCFStringEncodingUTF8);
+- cftext = CFStringCreateWithCString(kCFAllocatorDefault, attr->text,
+- kCFStringEncodingUTF8);
+-
+- if (cflang && cftext)
+- CFDictionarySetValue(dict, cflang, cftext);
+-
+- if (cflang)
+- CFRelease(cflang);
+-
+- if (cftext)
+- CFRelease(cftext);
+- }
+- }
+-
+- cupsArrayRestore(ppd->sorted_attrs);
+- }
+-
+- /*
+- * Fill in the profile data...
+- */
+-
+- if (iccfile)
+- httpAssembleURI(HTTP_URI_CODING_ALL, url, sizeof(url), "file", NULL, "", 0,
+- iccfile);
+-
+- profile->dataVersion = cmDeviceProfileInfoVersion1;
+- profile->profileID = id;
+- profile->profileLoc.locType = iccfile ? cmPathBasedProfile : cmNoProfileBase;
+- profile->profileName = dict;
+-
+- if (iccfile)
+- strlcpy(profile->profileLoc.u.pathLoc.path, iccfile,
+- sizeof(profile->profileLoc.u.pathLoc.path));
+-}
+-
+-
+-/*
+- * 'apple_register_profiles()' - Register color profiles for a printer.
+- */
+-
+-static void
+-apple_register_profiles(
+- cupsd_printer_t *p) /* I - Printer */
+-{
+- int i; /* Looping var */
+- char ppdfile[1024], /* PPD filename */
+- iccfile[1024], /* ICC filename */
+- selector[PPD_MAX_NAME];
+- /* Profile selection string */
+- ppd_file_t *ppd; /* PPD file */
+- ppd_attr_t *attr, /* Profile attributes */
+- *profileid_attr,/* cupsProfileID attribute */
+- *q1_attr, /* ColorModel (or other) qualifier */
+- *q2_attr, /* MediaType (or other) qualifier */
+- *q3_attr; /* Resolution (or other) qualifier */
+- char q_keyword[PPD_MAX_NAME];
+- /* Qualifier keyword */
+- const char *q1_choice, /* ColorModel (or other) choice */
+- *q2_choice, /* MediaType (or other) choice */
+- *q3_choice; /* Resolution (or other) choice */
+- const char *profile_key; /* Profile keyword */
+- ppd_option_t *cm_option; /* Color model option */
+- ppd_choice_t *cm_choice; /* Color model choice */
+- int num_profiles; /* Number of profiles */
+- CMError error; /* Last error */
+- unsigned device_id, /* Printer device ID */
+- profile_id, /* Profile ID */
+- default_profile_id = 0;
+- /* Default profile ID */
+- CFMutableDictionaryRef device_name; /* Printer device name dictionary */
+- CFStringRef printer_name; /* Printer name string */
+- CMDeviceScope scope = /* Scope of the registration */
+- {
+- kCFPreferencesAnyUser,
+- kCFPreferencesCurrentHost
+- };
+- CMDeviceProfileArrayPtr profiles; /* Profiles */
+- CMDeviceProfileInfo *profile; /* Current profile */
+- cups_array_t *languages; /* Languages array */
+-
+-
+- /*
+- * Make sure ColorSync is available...
+- */
+-
+- if (CMRegisterColorDevice == NULL)
+- return;
+-
+- /*
+- * Try opening the PPD file for this printer...
+- */
+-
+- snprintf(ppdfile, sizeof(ppdfile), "%s/ppd/%s.ppd", ServerRoot, p->name);
+- if ((ppd = ppdOpenFile(ppdfile)) == NULL)
+- return;
+-
+- /*
+- * See if we have any profiles...
+- */
+-
+- if ((attr = ppdFindAttr(ppd, "APTiogaProfile", NULL)) != NULL)
+- profile_key = "APTiogaProfile";
+- else
+- {
+- attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
+- profile_key = "cupsICCProfile";
+- }
+-
+- for (num_profiles = 0; attr; attr = ppdFindNextAttr(ppd, profile_key, NULL))
+- if (attr->spec[0] && attr->value && attr->value[0])
+- {
+- if (attr->value[0] != '/')
+- snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir,
+- attr->value);
+- else
+- strlcpy(iccfile, attr->value, sizeof(iccfile));
+-
+- if (access(iccfile, 0))
+- continue;
+-
+- num_profiles ++;
+- }
+-
+-
+- /*
+- * If we have profiles, add them...
+- */
+-
+- if (num_profiles > 0)
+- {
+- if (profile_key[0] == 'A')
+- {
+- /*
+- * For Tioga PPDs, get the default profile using the DefaultAPTiogaProfile
+- * attribute...
+- */
+-
+- if ((attr = ppdFindAttr(ppd, "DefaultAPTiogaProfile", NULL)) != NULL &&
+- attr->value)
+- default_profile_id = atoi(attr->value);
+-
+- q1_choice = q2_choice = q3_choice = NULL;
+- }
+- else
+- {
+- /*
+- * For CUPS PPDs, figure out the default profile selector values...
+- */
+-
+- if ((attr = ppdFindAttr(ppd, "cupsICCQualifier1", NULL)) != NULL &&
+- attr->value && attr->value[0])
+- {
+- snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value);
+- q1_attr = ppdFindAttr(ppd, q_keyword, NULL);
+- }
+- else if ((q1_attr = ppdFindAttr(ppd, "DefaultColorModel", NULL)) == NULL)
+- q1_attr = ppdFindAttr(ppd, "DefaultColorSpace", NULL);
+-
+- if (q1_attr && q1_attr->value && q1_attr->value[0])
+- q1_choice = q1_attr->value;
+- else
+- q1_choice = "";
+-
+- if ((attr = ppdFindAttr(ppd, "cupsICCQualifier2", NULL)) != NULL &&
+- attr->value && attr->value[0])
+- {
+- snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value);
+- q2_attr = ppdFindAttr(ppd, q_keyword, NULL);
+- }
+- else
+- q2_attr = ppdFindAttr(ppd, "DefaultMediaType", NULL);
+-
+- if (q2_attr && q2_attr->value && q2_attr->value[0])
+- q2_choice = q2_attr->value;
+- else
+- q2_choice = NULL;
+-
+- if ((attr = ppdFindAttr(ppd, "cupsICCQualifier3", NULL)) != NULL &&
+- attr->value && attr->value[0])
+- {
+- snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value);
+- q3_attr = ppdFindAttr(ppd, q_keyword, NULL);
+- }
+- else
+- q3_attr = ppdFindAttr(ppd, "DefaultResolution", NULL);
+-
+- if (q3_attr && q3_attr->value && q3_attr->value[0])
+- q3_choice = q3_attr->value;
+- else
+- q3_choice = NULL;
+- }
+-
+- /*
+- * Build the array of profiles...
+- *
+- * Note: This calloc actually requests slightly more memory than needed.
+- */
+-
+- if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL)
+- {
+- cupsdLogMessage(CUPSD_LOG_ERROR,
+- "Unable to allocate memory for %d profiles!",
+- num_profiles);
+- ppdClose(ppd);
+- return;
+- }
+-
+- profiles->profileCount = num_profiles;
+- languages = _ppdGetLanguages(ppd);
+-
+- for (profile = profiles->profiles,
+- attr = ppdFindAttr(ppd, profile_key, NULL);
+- attr;
+- attr = ppdFindNextAttr(ppd, profile_key, NULL))
+- if (attr->spec[0] && attr->value && attr->value[0])
+- {
+- /*
+- * Add this profile...
+- */
+-
+- if (attr->value[0] != '/')
+- snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir,
+- attr->value);
+- else
+- strlcpy(iccfile, attr->value, sizeof(iccfile));
+-
+- if (access(iccfile, 0))
+- continue;
+-
+- if (profile_key[0] == 'c')
+- {
+- cupsArraySave(ppd->sorted_attrs);
+-
+- if ((profileid_attr = ppdFindAttr(ppd, "cupsProfileID",
+- attr->spec)) != NULL &&
+- profileid_attr->value && isdigit(profileid_attr->value[0] & 255))
+- profile_id = (unsigned)strtoul(profileid_attr->value, NULL, 10);
+- else
+- profile_id = _ppdHashName(attr->spec);
+-
+- cupsArrayRestore(ppd->sorted_attrs);
+- }
+- else
+- profile_id = atoi(attr->spec);
+-
+- apple_init_profile(ppd, languages, profile, profile_id, attr->spec,
+- attr->text[0] ? attr->text : attr->spec, iccfile);
+-
+- profile ++;
+-
+- /*
+- * See if this is the default profile...
+- */
+-
+- if (!default_profile_id)
+- {
+- if (q2_choice)
+- {
+- if (q3_choice)
+- {
+- snprintf(selector, sizeof(selector), "%s.%s.%s",
+- q1_choice, q2_choice, q3_choice);
+- if (!strcmp(selector, attr->spec))
+- default_profile_id = profile_id;
+- }
+-
+- if (!default_profile_id)
+- {
+- snprintf(selector, sizeof(selector), "%s.%s.", q1_choice,
+- q2_choice);
+- if (!strcmp(selector, attr->spec))
+- default_profile_id = profile_id;
+- }
+- }
+-
+- if (!default_profile_id && q3_choice)
+- {
+- snprintf(selector, sizeof(selector), "%s..%s", q1_choice,
+- q3_choice);
+- if (!strcmp(selector, attr->spec))
+- default_profile_id = profile_id;
+- }
+-
+- if (!default_profile_id)
+- {
+- snprintf(selector, sizeof(selector), "%s..", q1_choice);
+- if (!strcmp(selector, attr->spec))
+- default_profile_id = profile_id;
+- }
+- }
+- }
+-
+- _ppdFreeLanguages(languages);
+- }
+- else if ((cm_option = ppdFindOption(ppd, "ColorModel")) != NULL)
+- {
+- /*
+- * Extract profiles from ColorModel option...
+- */
+-
+- const char *profile_name; /* Name of generic profile */
+-
+-
+- num_profiles = cm_option->num_choices;
+-
+- if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL)
+- {
+- cupsdLogMessage(CUPSD_LOG_ERROR,
+- "Unable to allocate memory for %d profiles!",
+- num_profiles);
+- ppdClose(ppd);
+- return;
+- }
+-
+- profiles->profileCount = num_profiles;
+-
+- for (profile = profiles->profiles, i = cm_option->num_choices,
+- cm_choice = cm_option->choices;
+- i > 0;
+- i --, cm_choice ++, profile ++)
+- {
+- if (!strcmp(cm_choice->choice, "Gray") ||
+- !strcmp(cm_choice->choice, "Black"))
+- profile_name = "Gray";
+- else if (!strcmp(cm_choice->choice, "RGB") ||
+- !strcmp(cm_choice->choice, "CMY"))
+- profile_name = "RGB";
+- else if (!strcmp(cm_choice->choice, "CMYK") ||
+- !strcmp(cm_choice->choice, "KCMY"))
+- profile_name = "CMYK";
+- else
+- profile_name = "DeviceN";
+-
+- snprintf(selector, sizeof(selector), "%s..", profile_name);
+- profile_id = _ppdHashName(selector);
+-
+- apple_init_profile(ppd, NULL, profile, profile_id, cm_choice->choice,
+- cm_choice->text, NULL);
+-
+- if (cm_choice->marked)
+- default_profile_id = profile_id;
+- }
+- }
+- else
+- {
+- /*
+- * Use the default colorspace...
+- */
+-
+- attr = ppdFindAttr(ppd, "DefaultColorSpace", NULL);
+-
+- num_profiles = (attr && ppd->colorspace == PPD_CS_GRAY) ? 1 : 2;
+-
+- if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL)
+- {
+- cupsdLogMessage(CUPSD_LOG_ERROR,
+- "Unable to allocate memory for %d profiles!",
+- num_profiles);
+- ppdClose(ppd);
+- return;
+- }
+-
+- profiles->profileCount = num_profiles;
+-
+- apple_init_profile(ppd, NULL, profiles->profiles, _ppdHashName("Gray.."),
+- "Gray", "Gray", NULL);
+-
+- switch (ppd->colorspace)
+- {
+- case PPD_CS_RGB :
+- case PPD_CS_CMY :
+- apple_init_profile(ppd, NULL, profiles->profiles + 1,
+- _ppdHashName("RGB.."), "RGB", "RGB", NULL);
+- break;
+- case PPD_CS_RGBK :
+- case PPD_CS_CMYK :
+- apple_init_profile(ppd, NULL, profiles->profiles + 1,
+- _ppdHashName("CMYK.."), "CMYK", "CMYK", NULL);
+- break;
+-
+- case PPD_CS_GRAY :
+- if (attr)
+- break;
+-
+- case PPD_CS_N :
+- apple_init_profile(ppd, NULL, profiles->profiles + 1,
+- _ppdHashName("DeviceN.."), "DeviceN", "DeviceN",
+- NULL);
+- break;
+- }
+- }
+-
+- if (num_profiles > 0)
+- {
+- /*
+- * Make sure we have a default profile ID...
+- */
+-
+- if (!default_profile_id)
+- default_profile_id = profiles->profiles[num_profiles - 1].profileID;
+-
+- /*
+- * Get the device ID hash and pathelogical name dictionary.
+- */
+-
+- cupsdLogMessage(CUPSD_LOG_INFO, "Registering ICC color profiles for \"%s\"",
+- p->name);
+-
+- device_id = _ppdHashName(p->name);
+- device_name = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+- &kCFTypeDictionaryKeyCallBacks,
+- &kCFTypeDictionaryValueCallBacks);
+- printer_name = CFStringCreateWithCString(kCFAllocatorDefault,
+- p->name, kCFStringEncodingUTF8);
+-
+- if (device_name && printer_name)
+- {
+- CFDictionarySetValue(device_name, CFSTR("en"), printer_name);
+-
+- /*
+- * Register the device with ColorSync...
+- */
+-
+- error = CMRegisterColorDevice(cmPrinterDeviceClass, device_id,
+- device_name, &scope);
+-
+- /*
+- * Register the profiles...
+- */
+-
+- if (error == noErr)
+- error = CMSetDeviceFactoryProfiles(cmPrinterDeviceClass, device_id,
+- default_profile_id, profiles);
+- }
+- else
+- error = 1000;
+-
+- /*
+- * Clean up...
+- */
+-
+- if (error != noErr)
+- cupsdLogMessage(CUPSD_LOG_ERROR,
+- "Unable to register ICC color profiles for \"%s\" - %d",
+- p->name, (int)error);
+-
+- for (profile = profiles->profiles;
+- num_profiles > 0;
+- profile ++, num_profiles --)
+- CFRelease(profile->profileName);
+-
+- free(profiles);
+-
+- if (printer_name)
+- CFRelease(printer_name);
+-
+- if (device_name)
+- CFRelease(device_name);
+- }
+-
+- ppdClose(ppd);
+-}
+-
+-
+-/*
+- * 'apple_unregister_profiles()' - Remove color profiles for the specified
+- * printer.
+- */
+-
+-static void
+-apple_unregister_profiles(
+- cupsd_printer_t *p) /* I - Printer */
+-{
+- /*
+- * Make sure ColorSync is available...
+- */
+-
+- if (CMUnregisterColorDevice != NULL)
+- CMUnregisterColorDevice(cmPrinterDeviceClass, _ppdHashName(p->name));
+-}
+-#endif /* __APPLE__ */
+-
+ /*
+ * 'apply_printer_defaults()' - Apply printer default options to a job.
+ */
+@@ -6532,7 +5969,7 @@ delete_printer(cupsd_client_t *con, /*
+ * Unregister color profiles...
+ */
+
+- apple_unregister_profiles(printer);
++ cupsdUnregisterColorProfiles(printer);
+ #endif /* __APPLE__ */
+
+ if (dtype & CUPS_PRINTER_CLASS)
+diff -up cups-1.4.6/scheduler/printers.c.icc cups-1.4.6/scheduler/printers.c
+--- cups-1.4.6/scheduler/printers.c.icc 2011-01-11 15:23:38.364058569 +0000
++++ cups-1.4.6/scheduler/printers.c 2011-01-11 15:23:38.389056205 +0000
+@@ -40,6 +40,14 @@
+ * cupsdValidateDest() - Validate a printer/class destination.
+ * cupsdWritePrintcap() - Write a pseudo-printcap file for older
+ * applications that need it...
++ * apple_init_profile() - Initialize a color profile.
++ * dbus_create_profile() - Initialise a color profile.
++ * dbus_create_device() - Initialise a color device.
++ * cupsdRegisterColorProfiles()
++ * - Register color profiles for a printer.
++ * cupsdUnregisterColorProfiles()
++ * - Remove color profiles for the specified
++ * printer.
+ * add_printer_defaults() - Add name-default attributes to the printer
+ * attributes.
+ * add_printer_filter() - Add a MIME filter for a printer.
+@@ -64,10 +72,14 @@
+ */
+
+ #include "cupsd.h"
++#include <cups/ppd-private.h>
+ #include <cups/dir.h>
+ #ifdef HAVE_APPLICATIONSERVICES_H
+ # include <ApplicationServices/ApplicationServices.h>
+ #endif /* HAVE_APPLICATIONSERVICES_H */
++#ifdef __APPLE__
++# include <CoreFoundation/CoreFoundation.h>
++#endif /* __APPLE__ */
+ #ifdef HAVE_SYS_MOUNT_H
+ # include <sys/mount.h>
+ #endif /* HAVE_SYS_MOUNT_H */
+@@ -81,6 +93,16 @@
+ # include <sys/vfs.h>
+ #endif /* HAVE_SYS_VFS_H */
+
++#ifdef HAVE_DBUS
++# include <dbus/dbus.h>
++# ifdef HAVE_DBUS_MESSAGE_ITER_INIT_APPEND
++# define dbus_message_append_iter_init dbus_message_iter_init_append
++# define dbus_message_iter_append_string(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &(v))
++# define dbus_message_iter_append_object_path(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_OBJECT_PATH, &(v))
++# define dbus_message_iter_append_uint32(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &(v))
++# endif /* HAVE_DBUS_MESSAGE_ITER_INIT_APPEND */
++#endif /* HAVE_DBUS */
++
+
+ /*
+ * Local functions...
+@@ -102,6 +124,12 @@ static void write_irix_config(cupsd_prin
+ static void write_irix_state(cupsd_printer_t *p);
+ #endif /* __sgi */
+ static void write_xml_string(cups_file_t *fp, const char *s);
++#ifdef __APPLE__
++static void apple_init_profile(ppd_file_t *ppd, cups_array_t *languages,
++ CMDeviceProfileInfo *profile, unsigned id,
++ const char *name, const char *text,
++ const char *iccfile);
++#endif /* __APPLE__ */
+
+
+ /*
+@@ -786,6 +814,14 @@ cupsdDeletePrinter(
+ update ? "Job stopped due to printer being deleted." :
+ "Job stopped.");
+
++#ifdef HAVE_DBUS
++ /*
++ * Unregister the color profiles
++ */
++
++ cupsdUnregisterColorProfiles(p);
++#endif /* HAVE_DBUS */
++
+ /*
+ * If this printer is the next for browsing, point to the next one...
+ */
+@@ -1533,6 +1569,14 @@ cupsdRenamePrinter(
+ mimeDeleteType(MimeDatabase, p->prefiltertype);
+ p->prefiltertype = mimeAddType(MimeDatabase, "prefilter", name);
+
++#ifdef HAVE_DBUS
++ /*
++ * Unregister the color profiles
++ */
++
++ cupsdUnregisterColorProfiles(p);
++#endif /* HAVE_DBUS */
++
+ /*
+ * Rename the printer...
+ */
+@@ -2722,6 +2766,14 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)
+ write_irix_state(p);
+ #endif /* __sgi */
+
++#ifdef HAVE_DBUS
++ /*
++ * (Re-)register the color profiles
++ */
++ cupsdUnregisterColorProfiles(p);
++ cupsdRegisterColorProfiles(p);
++#endif /* HAVE_DBUS */
++
+ /*
+ * Let the browse protocols reflect the change
+ */
+@@ -5576,6 +5628,996 @@ write_xml_string(cups_file_t *fp, /* I -
+ }
+
+
++#ifdef __APPLE__
++/*
++ * 'apple_init_profile()' - Initialize a color profile.
++ */
++
++static void
++apple_init_profile(
++ ppd_file_t *ppd, /* I - PPD file */
++ cups_array_t *languages, /* I - Languages in the PPD file */
++ CMDeviceProfileInfo *profile, /* I - Profile record */
++ unsigned id, /* I - Profile ID */
++ const char *name, /* I - Profile name */
++ const char *text, /* I - Profile UI text */
++ const char *iccfile) /* I - ICC filename */
++{
++ char url[1024]; /* URL for profile filename */
++ CFMutableDictionaryRef dict; /* Dictionary for name */
++ char *language; /* Current language */
++ ppd_attr_t *attr; /* Profile attribute */
++ CFStringRef cflang, /* Language string */
++ cftext; /* Localized text */
++
++
++ /*
++ * Build the profile name dictionary...
++ */
++
++ dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
++ &kCFTypeDictionaryKeyCallBacks,
++ &kCFTypeDictionaryValueCallBacks);
++
++ cftext = CFStringCreateWithCString(kCFAllocatorDefault, text,
++ kCFStringEncodingUTF8);
++
++ if (cftext)
++ {
++ CFDictionarySetValue(dict, CFSTR("en"), cftext);
++ CFRelease(cftext);
++ }
++
++ if (languages)
++ {
++ /*
++ * Find localized names for the color profiles...
++ */
++
++ cupsArraySave(ppd->sorted_attrs);
++
++ for (language = (char *)cupsArrayFirst(languages);
++ language;
++ language = (char *)cupsArrayNext(languages))
++ {
++ if (iccfile)
++ {
++ if ((attr = _ppdLocalizedAttr(ppd, "cupsICCProfile", name,
++ language)) == NULL)
++ attr = _ppdLocalizedAttr(ppd, "APTiogaProfile", name, language);
++ }
++ else
++ attr = _ppdLocalizedAttr(ppd, "ColorModel", name, language);
++
++ if (attr && attr->text[0])
++ {
++ cflang = CFStringCreateWithCString(kCFAllocatorDefault, language,
++ kCFStringEncodingUTF8);
++ cftext = CFStringCreateWithCString(kCFAllocatorDefault, attr->text,
++ kCFStringEncodingUTF8);
++
++ if (cflang && cftext)
++ CFDictionarySetValue(dict, cflang, cftext);
++
++ if (cflang)
++ CFRelease(cflang);
++
++ if (cftext)
++ CFRelease(cftext);
++ }
++ }
++
++ cupsArrayRestore(ppd->sorted_attrs);
++ }
++
++ /*
++ * Fill in the profile data...
++ */
++
++ if (iccfile)
++ httpAssembleURI(HTTP_URI_CODING_ALL, url, sizeof(url), "file", NULL, "", 0,
++ iccfile);
++
++ profile->dataVersion = cmDeviceProfileInfoVersion1;
++ profile->profileID = id;
++ profile->profileLoc.locType = iccfile ? cmPathBasedProfile : cmNoProfileBase;
++ profile->profileName = dict;
++
++ if (iccfile)
++ strlcpy(profile->profileLoc.u.pathLoc.path, iccfile,
++ sizeof(profile->profileLoc.u.pathLoc.path));
++}
++#endif /* __APPLE__ */
++
++
++#if !defined(__APPLE__) && defined(HAVE_DBUS)
++/*
++ * 'dbus_create_profile()' - Create a color profile for a printer.
++ */
++
++static void
++dbus_create_profile (cups_array_t *profiles, /* I - Profiles array */
++ DBusConnection *con, /* I - D-Bus connection */
++ const char *printer_name, /* I - Printer name */
++ const char *qualifier, /* I - Profile qualifier */
++ const char *iccfile) /* I - ICC filename */
++{
++ DBusMessage *message; /* D-Bus message */
++ DBusMessageIter args; /* D-Bus method arguments */
++ DBusPendingCall *pending; /* D-Bus method call */
++ char *path = NULL; /* Profile path */
++ char *idstr; /* Profile ID string */
++ size_t idstrlen; /* Profile ID allocated length */
++ int options = 1; /* Options for CreateProfile */
++
++ /*
++ * Create the profile...
++ */
++
++ message = dbus_message_new_method_call("org.freedesktop.ColorManager",
++ "/org/freedesktop/ColorManager",
++ "org.freedesktop.ColorManager",
++ "CreateProfile");
++
++ dbus_message_append_iter_init(message, &args);
++ idstrlen = strlen (printer_name) + 1 + strlen (qualifier) + 1;
++ idstr = malloc (idstrlen);
++ if (!idstr)
++ goto out;
++
++ snprintf (idstr, idstrlen, "%s-%s", printer_name, qualifier);
++ dbus_message_iter_append_string(&args, idstr);
++ dbus_message_iter_append_uint32(&args, options);
++ cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling CreateProfile(%s,%d)",
++ idstr, options);
++ if (!dbus_connection_send_with_reply(con, message, &pending, -1))
++ goto out;
++
++ dbus_connection_flush(con);
++ dbus_message_unref(message);
++ dbus_pending_call_block(pending);
++ message = dbus_pending_call_steal_reply(pending);
++// dbus_pending_call_unref(pending); <-fixme
++
++ if (!message ||
++ !dbus_message_iter_init(message, &args) ||
++ dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
++ goto out;
++
++ dbus_message_iter_get_basic(&args, &path);
++ path = strdup(path);
++ cupsArrayAdd(profiles, strdup(path));
++
++ /*
++ * Set the qualifier...
++ */
++
++ dbus_message_unref(message);
++ message = dbus_message_new_method_call("org.freedesktop.ColorManager",
++ path,
++ "org.freedesktop.ColorManager.Profile",
++ "SetQualifier");
++ dbus_message_append_iter_init(message, &args);
++ dbus_message_iter_append_string(&args, qualifier);
++ cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling SetQualifier(%s)", qualifier);
++ if (!dbus_connection_send_with_reply(con, message, &pending, -1))
++ goto out;
++
++ dbus_connection_flush(con);
++ dbus_message_unref(message);
++ dbus_pending_call_block(pending);
++ message = dbus_pending_call_steal_reply(pending);
++ dbus_pending_call_unref(pending);
++
++ /*
++ * If we know the ICC file for it, set that now...
++ */
++
++ if (!iccfile)
++ goto out;
++
++ dbus_message_unref(message);
++ message = dbus_message_new_method_call("org.freedesktop.ColorManager",
++ path,
++ "org.freedesktop.ColorManager.Profile",
++ "SetFilename");
++ dbus_message_append_iter_init(message, &args);
++ dbus_message_iter_append_string(&args, iccfile);
++ cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling SetFilename(%s)", iccfile);
++ if (!dbus_connection_send_with_reply(con, message, &pending, -1))
++ goto out;
++
++ dbus_connection_flush(con);
++ dbus_message_unref(message);
++ dbus_pending_call_block(pending);
++ message = dbus_pending_call_steal_reply(pending);
++ dbus_pending_call_unref(pending);
++
++out:
++ free (path);
++ free (idstr);
++ dbus_message_unref(message);
++}
++
++
++/*
++ * 'dbus_create_device()' - Create a device and register profiles.
++ */
++
++static void
++dbus_create_device (DBusConnection *con, /* I - D-Bus connection */
++ const char *name, /* I - Printer name */
++ cups_array_t *profiles, /* I - Profiles array */
++ const char *default_profile_id) /* I - Default profile */
++{
++ DBusMessage *message; /* D-Bus message */
++ DBusMessageIter args; /* D-Bus method arguments */
++ DBusPendingCall *pending; /* D-Bus method call */
++ const char *device_path_tmp; /* Device path data */
++ char *device_path = NULL; /* Device path */
++ const char *profile_path; /* Profile path */
++ char *default_profile_path = NULL;
++ /* Default profile path */
++ size_t default_path_len;
++ /* Length of profile path */
++ int options = 1; /* Options for CreateDevice */
++
++ /*
++ * Create the device...
++ */
++ message = dbus_message_new_method_call("org.freedesktop.ColorManager",
++ "/org/freedesktop/ColorManager",
++ "org.freedesktop.ColorManager",
++ "CreateDevice");
++
++ dbus_message_append_iter_init(message, &args);
++ dbus_message_iter_append_string(&args, name);
++ dbus_message_iter_append_uint32(&args, options);
++ cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling CreateDevice(%s,%d)",
++ name, options);
++ if (!dbus_connection_send_with_reply (con, message, &pending, -1))
++ goto out;
++
++ dbus_connection_flush(con);
++ dbus_message_unref(message);
++ dbus_pending_call_block(pending);
++ message = dbus_pending_call_steal_reply(pending);
++ dbus_pending_call_unref(pending);
++
++ if (!message ||
++ !dbus_message_iter_init(message, &args) ||
++ dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
++ goto out;
++
++ /* get device path, and duplicate so we can free the method */
++ dbus_message_iter_get_basic(&args, &device_path_tmp);
++ device_path = strdup (device_path_tmp);
++ dbus_message_unref(message);
++ for (profile_path = cupsArrayFirst(profiles);
++ profile_path;
++ profile_path = cupsArrayNext(profiles))
++ {
++ message = dbus_message_new_method_call("org.freedesktop.ColorManager",
++ device_path,
++ "org.freedesktop.ColorManager.Device",
++ "AddProfile");
++
++ dbus_message_append_iter_init(message, &args);
++ dbus_message_iter_append_object_path(&args, profile_path);
++ cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling AddProfile(%s)", profile_path);
++ pending = NULL;
++ if (!dbus_connection_send_with_reply (con, message, &pending, -1))
++ goto out;
++
++ dbus_connection_flush(con);
++ dbus_message_unref(message);
++ dbus_pending_call_block(pending);
++// message = dbus_pending_call_steal_reply(pending);
++ dbus_pending_call_unref(pending);
++ }
++
++ /*
++ * Set the default profile
++ */
++ default_path_len = strlen (name) + 1 + strlen (default_profile_id) + 1;
++ default_profile_path = malloc (default_path_len);
++ if (!default_profile_path)
++ goto out;
++
++ snprintf(default_profile_path, default_path_len, "%s-%s", name,
++ default_profile_id);
++ message = dbus_message_new_method_call("org.freedesktop.ColorManager",
++ device_path,
++ "org.freedesktop.ColorManager.Device",
++ "MakeProfileDefault");
++
++ dbus_message_append_iter_init(message, &args);
++ dbus_message_iter_append_string(&args, default_profile_path);
++ cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling MakeProfileDefault(%s)",
++ default_profile_path);
++ if (!dbus_connection_send_with_reply (con, message, &pending, -1))
++ goto out;
++
++ dbus_connection_flush(con);
++ dbus_message_unref(message);
++ dbus_pending_call_block(pending);
++// message = dbus_pending_call_steal_reply(pending);
++ dbus_pending_call_unref(pending);
++
++out:
++ free(default_profile_path);
++ free(device_path);
++// dbus_message_unref(message);
++}
++
++
++/*
++ * 'dbus_delete_device_and_profiles()' - Delete previously registered
++ * color device and profiles
++ */
++
++static void
++dbus_delete_device_and_profiles(cupsd_printer_t *p) /* I - Printer */
++{
++ DBusConnection *con; /* System D-Bus connection */
++ DBusMessage *message; /* D-Bus message */
++ DBusMessageIter args, array_args; /* D-Bus method arguments */
++ DBusPendingCall *pending; /* D-Bus method call */
++ const char *device_path; /* Device path */
++ const char *options = ""; /* Options for GetProfilesForDevice */
++ cups_array_t *profile_paths; /* Profile paths array */
++ char *profile_path; /* Profile path */
++
++ con = dbus_bus_get (DBUS_BUS_SYSTEM, NULL);
++ if (!con)
++ return;
++
++ /*
++ * Get the device path
++ */
++
++ profile_paths = cupsArrayNew(NULL, NULL);
++ message = dbus_message_new_method_call("org.freedesktop.ColorManager",
++ "/org/freedesktop/ColorManager",
++ "org.freedesktop.ColorManager",
++ "FindDeviceById");
++
++ dbus_message_append_iter_init(message, &args);
++ dbus_message_iter_append_string(&args, p->name);
++ cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling FindDeviceById");
++ if (!dbus_connection_send_with_reply(con, message, &pending, -1))
++ goto out;
++
++ dbus_connection_flush(con);
++ dbus_message_unref(message);
++ dbus_pending_call_block(pending);
++ message = dbus_pending_call_steal_reply(pending);
++ dbus_pending_call_unref(pending);
++
++ if (!message ||
++ !dbus_message_iter_init(message, &args) ||
++ dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_OBJECT_PATH)
++ goto out;
++
++ dbus_message_iter_get_basic(&args, &device_path);
++ device_path = strdup(device_path);
++
++ /*
++ * Get the profiles
++ */
++
++ dbus_message_unref(message);
++ message = dbus_message_new_method_call("org.freedesktop.ColorManager",
++ "/org/freedesktop/ColorManager",
++ "org.freedesktop.ColorManager",
++ "GetProfilesForDevice");
++
++ dbus_message_append_iter_init(message, &args);
++ dbus_message_iter_append_object_path(&args, device_path);
++ dbus_message_iter_append_string(&args, options);
++ cupsdLogMessage(CUPSD_LOG_DEBUG, "Calling GetProfilesForDevice(%s,\"\")",
++ device_path);
++ if (!dbus_connection_send_with_reply(con, message, &pending, -1))
++ goto out;
++
++ dbus_connection_flush(con);
++ dbus_message_unref(message);
++ dbus_pending_call_block(pending);
++ message = dbus_pending_call_steal_reply(pending);
++ dbus_pending_call_unref(pending);
++
++ if (!message ||
++ !dbus_message_iter_init(message, &args) ||
++ dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY)
++ goto out;
++
++ dbus_message_iter_recurse(&args, &array_args);
++ do
++ {
++ if (dbus_message_iter_get_arg_type(&array_args) == DBUS_TYPE_OBJECT_PATH)
++ {
++ dbus_message_iter_get_basic(&array_args, &profile_path);
++ cupsArrayAdd(profile_paths, strdup (profile_path));
++ }
++ } while (dbus_message_iter_next(&array_args));
++
++ /*
++ * Delete each profile.
++ */
++
++
++out:
++ for (profile_path = cupsArrayFirst(profile_paths);
++ profile_path;
++ profile_path = cupsArrayNext(profile_paths))
++ free (profile_path);
++
++ cupsArrayDelete(profile_paths);
++ dbus_message_unref(message);
++ dbus_connection_unref(con);
++}
++#endif /* !defined(__APPLE__) && defined(HAVE_DBUS) */
++
++
++/*
++ * 'cupsdRegisterColorProfiles()' - Register color profiles for a printer.
++ */
++
++void
++cupsdRegisterColorProfiles(
++ cupsd_printer_t *p) /* I - Printer */
++{
++ int i; /* Looping var */
++ char ppdfile[1024], /* PPD filename */
++ iccfile[1024], /* ICC filename */
++ selector[PPD_MAX_NAME];
++ /* Profile selection string */
++ ppd_file_t *ppd; /* PPD file */
++ ppd_attr_t *attr, /* Profile attributes */
++ *q1_attr, /* ColorModel (or other) qualifier */
++ *q2_attr, /* MediaType (or other) qualifier */
++ *q3_attr; /* Resolution (or other) qualifier */
++ char q_keyword[PPD_MAX_NAME];
++ /* Qualifier keyword */
++ const char *q1_choice, /* ColorModel (or other) choice */
++ *q2_choice, /* MediaType (or other) choice */
++ *q3_choice; /* Resolution (or other) choice */
++ const char *profile_key; /* Profile keyword */
++ ppd_option_t *cm_option; /* Color model option */
++ ppd_choice_t *cm_choice; /* Color model choice */
++ int num_profiles; /* Number of profiles */
++#ifdef __APPLE__
++ ppd_attr_t *profileid_attr;/* cupsProfileID attribute */
++ unsigned profile_id, /* Profile ID */
++ default_profile_id = 0;
++ /* Default profile ID */
++ CMError error; /* Last error */
++ CFMutableDictionaryRef device_name; /* Printer device name dictionary */
++ unsigned device_id; /* Printer device ID */
++ CFStringRef printer_name; /* Printer name string */
++ CMDeviceScope scope = /* Scope of the registration */
++ {
++ kCFPreferencesAnyUser,
++ kCFPreferencesCurrentHost
++ };
++ CMDeviceProfileArrayPtr profiles; /* Profiles */
++ CMDeviceProfileInfo *profile; /* Current profile */
++ cups_array_t *languages; /* Languages array */
++#elif HAVE_DBUS
++ const char *profile_id = NULL,
++ /* Profile ID */
++ *default_profile_id = NULL;
++ /* Default profile ID */
++ DBusError error; /* Error, if any */
++ static DBusConnection *con; /* System D-Bus connection */
++ cups_array_t *profiles; /* Profile paths array */
++ char *profile_path; /* Profile path */
++#endif /* HAVE_DBUS */
++
++
++#ifdef __APPLE__
++ /*
++ * Make sure ColorSync is available...
++ */
++
++ if (CMRegisterColorDevice == NULL)
++ return;
++#elif defined(HAVE_DBUS)
++ if (con && !dbus_connection_get_is_connected(con))
++ {
++ dbus_connection_unref(con);
++ con = NULL;
++ }
++
++ if (!con)
++ {
++ dbus_error_init(&error);
++
++ con = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
++ if (!con)
++ {
++ if (dbus_error_is_set(&error))
++ cupsdLogMessage(CUPSD_LOG_DEBUG,
++ "D-Bus connection error: %s", error.message);
++
++ dbus_error_free(&error);
++ return;
++ }
++ }
++
++ profiles = cupsArrayNew (NULL, NULL);
++#else /* defined(__APPLE__) || defined(HAVE_DBUS) */
++ return;
++#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */
++
++ /*
++ * Try opening the PPD file for this printer...
++ */
++
++ snprintf(ppdfile, sizeof(ppdfile), "%s/ppd/%s.ppd", ServerRoot, p->name);
++ if ((ppd = ppdOpenFile(ppdfile)) == NULL)
++ return;
++
++ /*
++ * See if we have any profiles...
++ */
++
++ if ((attr = ppdFindAttr(ppd, "APTiogaProfile", NULL)) != NULL)
++ profile_key = "APTiogaProfile";
++ else
++ {
++ attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
++ profile_key = "cupsICCProfile";
++ }
++
++ for (num_profiles = 0; attr; attr = ppdFindNextAttr(ppd, profile_key, NULL))
++ if (attr->spec[0] && attr->value && attr->value[0])
++ {
++ if (attr->value[0] != '/')
++ snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir,
++ attr->value);
++ else
++ strlcpy(iccfile, attr->value, sizeof(iccfile));
++
++ if (access(iccfile, 0))
++ continue;
++
++ num_profiles ++;
++ }
++
++
++ /*
++ * If we have profiles, add them...
++ */
++
++ if (num_profiles > 0)
++ {
++ if (profile_key[0] == 'A')
++ {
++ /*
++ * For Tioga PPDs, get the default profile using the DefaultAPTiogaProfile
++ * attribute...
++ */
++
++ if ((attr = ppdFindAttr(ppd, "DefaultAPTiogaProfile", NULL)) != NULL &&
++ attr->value)
++ {
++#ifdef __APPLE__
++ default_profile_id = atoi(attr->value);
++#elif HAVE_DBUS
++ default_profile_id = attr->value;
++#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */
++ }
++
++ q1_choice = q2_choice = q3_choice = NULL;
++ }
++ else
++ {
++ /*
++ * For CUPS PPDs, figure out the default profile selector values...
++ */
++
++ if ((attr = ppdFindAttr(ppd, "cupsICCQualifier1", NULL)) != NULL &&
++ attr->value && attr->value[0])
++ {
++ snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value);
++ q1_attr = ppdFindAttr(ppd, q_keyword, NULL);
++ }
++ else if ((q1_attr = ppdFindAttr(ppd, "DefaultColorModel", NULL)) == NULL)
++ q1_attr = ppdFindAttr(ppd, "DefaultColorSpace", NULL);
++
++ if (q1_attr && q1_attr->value && q1_attr->value[0])
++ q1_choice = q1_attr->value;
++ else
++ q1_choice = "";
++
++ if ((attr = ppdFindAttr(ppd, "cupsICCQualifier2", NULL)) != NULL &&
++ attr->value && attr->value[0])
++ {
++ snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value);
++ q2_attr = ppdFindAttr(ppd, q_keyword, NULL);
++ }
++ else
++ q2_attr = ppdFindAttr(ppd, "DefaultMediaType", NULL);
++
++ if (q2_attr && q2_attr->value && q2_attr->value[0])
++ q2_choice = q2_attr->value;
++ else
++ q2_choice = NULL;
++
++ if ((attr = ppdFindAttr(ppd, "cupsICCQualifier3", NULL)) != NULL &&
++ attr->value && attr->value[0])
++ {
++ snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value);
++ q3_attr = ppdFindAttr(ppd, q_keyword, NULL);
++ }
++ else
++ q3_attr = ppdFindAttr(ppd, "DefaultResolution", NULL);
++
++ if (q3_attr && q3_attr->value && q3_attr->value[0])
++ q3_choice = q3_attr->value;
++ else
++ q3_choice = NULL;
++ }
++
++#ifdef __APPLE__
++ /*
++ * Build the array of profiles...
++ *
++ * Note: This calloc actually requests slightly more memory than needed.
++ */
++
++ if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL)
++ {
++ cupsdLogMessage(CUPSD_LOG_ERROR,
++ "Unable to allocate memory for %d profiles!",
++ num_profiles);
++ ppdClose(ppd);
++ return;
++ }
++
++ profiles->profileCount = num_profiles;
++ languages = _ppdGetLanguages(ppd);
++ profile = profiles->profiles;
++#endif /* __APPLE__ */
++
++ for (attr = ppdFindAttr(ppd, profile_key, NULL);
++ attr;
++ attr = ppdFindNextAttr(ppd, profile_key, NULL))
++ if (attr->spec[0] && attr->value && attr->value[0])
++ {
++ /*
++ * Add this profile...
++ */
++
++ if (attr->value[0] != '/')
++ snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir,
++ attr->value);
++ else
++ strlcpy(iccfile, attr->value, sizeof(iccfile));
++
++ if (access(iccfile, 0))
++ continue;
++
++#ifdef __APPLE__
++ if (profile_key[0] == 'c')
++ {
++ cupsArraySave(ppd->sorted_attrs);
++
++ if ((profileid_attr = ppdFindAttr(ppd, "cupsProfileID",
++ attr->spec)) != NULL &&
++ profileid_attr->value && isdigit(profileid_attr->value[0] & 255))
++ profile_id = (unsigned)strtoul(profileid_attr->value, NULL, 10);
++ else
++ profile_id = _ppdHashName(attr->spec);
++
++ cupsArrayRestore(ppd->sorted_attrs);
++ }
++ else
++ profile_id = atoi(attr->spec);
++
++ apple_init_profile(ppd, languages, profile, profile_id, attr->spec,
++ attr->text[0] ? attr->text : attr->spec, iccfile);
++ profile ++;
++#elif defined(HAVE_DBUS)
++ profile_id = attr->spec;
++ dbus_create_profile(profiles, con, p->name, attr->spec, iccfile);
++#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */
++
++ /*
++ * See if this is the default profile...
++ */
++
++ if (!default_profile_id)
++ {
++ if (q2_choice)
++ {
++ if (q3_choice)
++ {
++ snprintf(selector, sizeof(selector), "%s.%s.%s",
++ q1_choice, q2_choice, q3_choice);
++ if (!strcmp(selector, attr->spec))
++ default_profile_id = profile_id;
++ }
++
++ if (!default_profile_id)
++ {
++ snprintf(selector, sizeof(selector), "%s.%s.", q1_choice,
++ q2_choice);
++ if (!strcmp(selector, attr->spec))
++ default_profile_id = profile_id;
++ }
++ }
++
++ if (!default_profile_id && q3_choice)
++ {
++ snprintf(selector, sizeof(selector), "%s..%s", q1_choice,
++ q3_choice);
++ if (!strcmp(selector, attr->spec))
++ default_profile_id = profile_id;
++ }
++
++ if (!default_profile_id)
++ {
++ snprintf(selector, sizeof(selector), "%s..", q1_choice);
++ if (!strcmp(selector, attr->spec))
++ default_profile_id = profile_id;
++ }
++ }
++ }
++
++#ifdef __APPLE__
++ _ppdFreeLanguages(languages);
++#endif /* __APPLE__ */
++ }
++ else if ((cm_option = ppdFindOption(ppd, "ColorModel")) != NULL)
++ {
++ /*
++ * Extract profiles from ColorModel option...
++ */
++
++ const char *profile_name; /* Name of generic profile */
++
++
++ num_profiles = cm_option->num_choices;
++
++#ifdef __APPLE__
++ if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL)
++ {
++ cupsdLogMessage(CUPSD_LOG_ERROR,
++ "Unable to allocate memory for %d profiles!",
++ num_profiles);
++ ppdClose(ppd);
++ return;
++ }
++
++ profiles->profileCount = num_profiles;
++ profile = profiles->profiles;
++#endif /* __APPLE__ */
++
++ for (i = cm_option->num_choices, cm_choice = cm_option->choices;
++ i > 0;
++ i --, cm_choice ++)
++ {
++ if (!strcmp(cm_choice->choice, "Gray") ||
++ !strcmp(cm_choice->choice, "Black"))
++ profile_name = "Gray";
++ else if (!strcmp(cm_choice->choice, "RGB") ||
++ !strcmp(cm_choice->choice, "CMY"))
++ profile_name = "RGB";
++ else if (!strcmp(cm_choice->choice, "CMYK") ||
++ !strcmp(cm_choice->choice, "KCMY"))
++ profile_name = "CMYK";
++ else
++ profile_name = "DeviceN";
++
++ snprintf(selector, sizeof(selector), "%s..", profile_name);
++
++#ifdef __APPLE__
++ profile_id = _ppdHashName(selector);
++ apple_init_profile(ppd, NULL, profile, profile_id, cm_choice->choice,
++ cm_choice->text, NULL);
++ profile ++;
++#elif defined(HAVE_DBUS)
++ profile_id = selector;
++ dbus_create_profile(profiles, con, p->name, selector, NULL);
++#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */
++
++ if (cm_choice->marked)
++ default_profile_id = profile_id;
++ }
++ }
++ else
++ {
++ /*
++ * Use the default colorspace...
++ */
++
++ attr = ppdFindAttr(ppd, "DefaultColorSpace", NULL);
++
++ num_profiles = (attr && ppd->colorspace == PPD_CS_GRAY) ? 1 : 2;
++
++#ifdef __APPLE__
++ if ((profiles = calloc(num_profiles, sizeof(CMDeviceProfileArray))) == NULL)
++ {
++ cupsdLogMessage(CUPSD_LOG_ERROR,
++ "Unable to allocate memory for %d profiles!",
++ num_profiles);
++ ppdClose(ppd);
++ return;
++ }
++
++ profiles->profileCount = num_profiles;
++
++ apple_init_profile(ppd, NULL, profiles->profiles, _ppdHashName("Gray.."),
++ "Gray", "Gray", NULL);
++#elif defined(HAVE_DBUS)
++ profile_id = "Gray..";
++ dbus_create_profile(profiles, con, p->name, profile_id, NULL);
++#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */
++
++ switch (ppd->colorspace)
++ {
++ case PPD_CS_RGB :
++ case PPD_CS_CMY :
++#ifdef __APPLE__
++ apple_init_profile(ppd, NULL, profiles->profiles + 1,
++ _ppdHashName("RGB.."), "RGB", "RGB", NULL);
++#elif defined(HAVE_DBUS)
++ profile_id = "RGB..";
++ dbus_create_profile(profiles, con, p->name, profile_id, NULL);
++#endif /* HAVE_DBUS */
++ break;
++ case PPD_CS_RGBK :
++ case PPD_CS_CMYK :
++#ifdef __APPLE__
++ apple_init_profile(ppd, NULL, profiles->profiles + 1,
++ _ppdHashName("CMYK.."), "CMYK", "CMYK", NULL);
++#elif defined(HAVE_DBUS)
++ profile_id = "CMYK..";
++ dbus_create_profile(profiles, con, p->name, profile_id, NULL);
++#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */
++ break;
++
++ case PPD_CS_GRAY :
++ if (attr)
++ break;
++
++ case PPD_CS_N :
++#ifdef __APPLE__
++ apple_init_profile(ppd, NULL, profiles->profiles + 1,
++ _ppdHashName("DeviceN.."), "DeviceN", "DeviceN",
++ NULL);
++#elif defined(HAVE_DBUS)
++ profile_id = "DeviceN..";
++ dbus_create_profile(profiles, con, p->name, profile_id, NULL);
++#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */
++
++ break;
++ }
++ }
++
++ if (num_profiles > 0)
++ {
++ /*
++ * Make sure we have a default profile ID...
++ */
++
++ if (!default_profile_id)
++ {
++#ifdef __APPLE__
++ default_profile_id = profiles->profiles[num_profiles - 1].profileID;
++#elif HAVE_DBUS
++ default_profile_id = profile_id;
++#endif /* __APPLE__ */
++ }
++
++ /*
++ * Get the device ID hash and pathelogical name dictionary.
++ */
++
++ cupsdLogMessage(CUPSD_LOG_INFO, "Registering ICC color profiles for \"%s\"",
++ p->name);
++
++#ifdef __APPLE__
++ device_id = _ppdHashName(p->name);
++
++ device_name = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
++ &kCFTypeDictionaryKeyCallBacks,
++ &kCFTypeDictionaryValueCallBacks);
++ printer_name = CFStringCreateWithCString(kCFAllocatorDefault,
++ p->name, kCFStringEncodingUTF8);
++
++ if (device_name && printer_name)
++ {
++ CFDictionarySetValue(device_name, CFSTR("en"), printer_name);
++
++ /*
++ * Register the device with ColorSync...
++ */
++
++ error = CMRegisterColorDevice(cmPrinterDeviceClass, device_id,
++ device_name, &scope);
++
++ /*
++ * Register the profiles...
++ */
++
++ if (error == noErr)
++ error = CMSetDeviceFactoryProfiles(cmPrinterDeviceClass, device_id,
++ default_profile_id, profiles);
++ }
++ else
++ error = 1000;
++#elif defined(HAVE_DBUS)
++ dbus_create_device (con, p->name, profiles, default_profile_id);
++#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */
++
++ /*
++ * Clean up...
++ */
++
++#ifdef __APPLE__
++ if (error != noErr)
++ cupsdLogMessage(CUPSD_LOG_ERROR,
++ "Unable to register ICC color profiles for \"%s\" - %d",
++ p->name, (int)error);
++
++ for (profile = profiles->profiles;
++ num_profiles > 0;
++ profile ++, num_profiles --)
++ CFRelease(profile->profileName);
++
++ free(profiles);
++
++ if (printer_name)
++ CFRelease(printer_name);
++
++ if (device_name)
++ CFRelease(device_name);
++#elif defined(HAVE_DBUS)
++ for (profile_path = cupsArrayFirst(profiles);
++ profile_path;
++ profile_path = cupsArrayNext(profiles))
++ free (profile_path);
++
++ cupsArrayDelete(profiles);
++ dbus_connection_flush(con);
++
++ /*
++ * Don't unref the connection but instead keep it around for future
++ * calls (it is a local static variable). Once we disconnect from
++ * the bus all our devices and profiles will be gone.
++ */
++#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */
++ }
++
++ ppdClose(ppd);
++}
++
++
++/*
++ * 'cupsdUnregisterColorProfiles()' - Remove color profiles for the specified
++ * printer.
++ */
++
++void
++cupsdUnregisterColorProfiles(
++ cupsd_printer_t *p) /* I - Printer */
++{
++#ifdef __APPLE__
++ /*
++ * Make sure ColorSync is available...
++ */
++
++ if (CMUnregisterColorDevice != NULL)
++ CMUnregisterColorDevice(cmPrinterDeviceClass, _ppdHashName(p->name));
++#elif defined(HAVE_DBUS)
++ dbus_delete_device_and_profiles (p);
++#endif /* defined(__APPLE__) || defined(HAVE_DBUS) */
++}
++
++
+ /*
+ * End of "$Id: printers.c 9313 2010-09-22 18:35:07Z mike $".
+ */
+diff -up cups-1.4.6/scheduler/printers.h.icc cups-1.4.6/scheduler/printers.h
+--- cups-1.4.6/scheduler/printers.h.icc 2011-01-11 15:23:38.365058476 +0000
++++ cups-1.4.6/scheduler/printers.h 2011-01-11 15:23:38.389056205 +0000
+@@ -189,6 +189,8 @@ extern const char *cupsdValidateDest(con
+ cups_ptype_t *dtype,
+ cupsd_printer_t **printer);
+ extern void cupsdWritePrintcap(void);
++extern void cupsdRegisterColorProfiles(cupsd_printer_t *printer);
++extern void cupsdUnregisterColorProfiles(cupsd_printer_t *printer);
+
+
+ /*
diff --git a/cups.spec b/cups.spec
index f1affdd..72bf0f7 100644
--- a/cups.spec
+++ b/cups.spec
@@ -2,6 +2,7 @@
%global php_apiver %((echo 0; php -i 2>/dev/null | sed -n 's/^PHP API => //p') | tail -1)
%define use_alternatives 1
+%define icc 0
%define lspp 1
%define cups_serverbin %{_exec_prefix}/lib/cups
@@ -68,6 +69,7 @@ Patch38: cups-autotype-crash.patch
Patch39: cups-str3754.patch
Patch40: cups-avahi.patch
Patch41: cups-usb-buffer-size.patch
+Patch42: cups-icc.patch
Patch100: cups-lspp.patch
@@ -285,6 +287,10 @@ module.
%patch40 -p1 -b .avahi
# Use a smaller buffer when writing to USB devices (bug #617208).
%patch41 -p1 -b .usb-buffer-size
+%if %icc
+# ICC support (work in progress). Disable lspp for testing.
+%patch42 -p1 -b .icc
+%endif
%if %lspp
# LSPP support.
More information about the scm-commits
mailing list