-#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__ */
-