| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 /* | |
| 6 * Copyright (C) 2010 Google Inc. All rights reserved. | |
| 7 * Copyright (C) 2012 Apple Inc. | |
| 8 * | |
| 9 * Redistribution and use in source and binary forms, with or without | |
| 10 * modification, are permitted provided that the following conditions are | |
| 11 * met: | |
| 12 * | |
| 13 * * Redistributions of source code must retain the above copyright | |
| 14 * notice, this list of conditions and the following disclaimer. | |
| 15 * * Redistributions in binary form must reproduce the above | |
| 16 * copyright notice, this list of conditions and the following disclaimer | |
| 17 * in the documentation and/or other materials provided with the | |
| 18 * distribution. | |
| 19 * * Neither the name of Google Inc. nor the names of its | |
| 20 * contributors may be used to endorse or promote products derived from | |
| 21 * this software without specific prior written permission. | |
| 22 * | |
| 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 34 */ | |
| 35 | |
| 36 #import <AppKit/AppKit.h> | |
| 37 #import <AvailabilityMacros.h> | |
| 38 #include <signal.h> | |
| 39 #include <stdio.h> | |
| 40 #include <stdlib.h> | |
| 41 | |
| 42 // This is a simple helper app that changes the color sync profile to the | |
| 43 // generic profile and back when done. This program is managed by the layout | |
| 44 // test script, so it can do the job for multiple DumpRenderTree while they are | |
| 45 // running layout tests. | |
| 46 | |
| 47 namespace { | |
| 48 | |
| 49 #if defined(MAC_OS_X_VERSION_10_7) && \ | |
| 50 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 | |
| 51 | |
| 52 CFURLRef user_color_profile_url; | |
| 53 | |
| 54 void InstallLayoutTestColorProfile() { | |
| 55 // To make sure we get consistent colors (not dependent on the chosen color | |
| 56 // space of the main display), we force the generic RGB color profile. | |
| 57 // This causes a change the user can see. | |
| 58 | |
| 59 CFUUIDRef main_display_id = | |
| 60 CGDisplayCreateUUIDFromDisplayID(CGMainDisplayID()); | |
| 61 | |
| 62 if (!user_color_profile_url) { | |
| 63 CFDictionaryRef device_info = ColorSyncDeviceCopyDeviceInfo( | |
| 64 kColorSyncDisplayDeviceClass, main_display_id); | |
| 65 | |
| 66 if (!device_info) { | |
| 67 NSLog(@"No display attached to system; not setting main display's color " | |
| 68 "profile."); | |
| 69 CFRelease(main_display_id); | |
| 70 return; | |
| 71 } | |
| 72 | |
| 73 CFDictionaryRef profile_info = (CFDictionaryRef)CFDictionaryGetValue( | |
| 74 device_info, kColorSyncCustomProfiles); | |
| 75 if (profile_info) { | |
| 76 user_color_profile_url = | |
| 77 (CFURLRef)CFDictionaryGetValue(profile_info, CFSTR("1")); | |
| 78 CFRetain(user_color_profile_url); | |
| 79 } else { | |
| 80 profile_info = (CFDictionaryRef)CFDictionaryGetValue( | |
| 81 device_info, kColorSyncFactoryProfiles); | |
| 82 CFDictionaryRef factory_profile = | |
| 83 (CFDictionaryRef)CFDictionaryGetValue(profile_info, CFSTR("1")); | |
| 84 user_color_profile_url = (CFURLRef)CFDictionaryGetValue( | |
| 85 factory_profile, kColorSyncDeviceProfileURL); | |
| 86 CFRetain(user_color_profile_url); | |
| 87 } | |
| 88 | |
| 89 CFRelease(device_info); | |
| 90 } | |
| 91 | |
| 92 ColorSyncProfileRef generic_rgb_profile = | |
| 93 ColorSyncProfileCreateWithName(kColorSyncGenericRGBProfile); | |
| 94 CFErrorRef error; | |
| 95 CFURLRef profile_url = ColorSyncProfileGetURL(generic_rgb_profile, &error); | |
| 96 if (!profile_url) { | |
| 97 NSLog(@"Failed to get URL of Generic RGB color profile! Many pixel tests " | |
| 98 "may fail as a result. Error: %@", | |
| 99 error); | |
| 100 | |
| 101 if (user_color_profile_url) { | |
| 102 CFRelease(user_color_profile_url); | |
| 103 user_color_profile_url = 0; | |
| 104 } | |
| 105 | |
| 106 CFRelease(generic_rgb_profile); | |
| 107 CFRelease(main_display_id); | |
| 108 return; | |
| 109 } | |
| 110 | |
| 111 CFMutableDictionaryRef profile_info = | |
| 112 CFDictionaryCreateMutable(kCFAllocatorDefault, | |
| 113 0, | |
| 114 &kCFTypeDictionaryKeyCallBacks, | |
| 115 &kCFTypeDictionaryValueCallBacks); | |
| 116 CFDictionarySetValue( | |
| 117 profile_info, kColorSyncDeviceDefaultProfileID, profile_url); | |
| 118 | |
| 119 if (!ColorSyncDeviceSetCustomProfiles( | |
| 120 kColorSyncDisplayDeviceClass, main_display_id, profile_info)) { | |
| 121 NSLog(@"Failed to set color profile for main display! Many pixel tests may " | |
| 122 "fail as a result."); | |
| 123 | |
| 124 if (user_color_profile_url) { | |
| 125 CFRelease(user_color_profile_url); | |
| 126 user_color_profile_url = 0; | |
| 127 } | |
| 128 } | |
| 129 | |
| 130 CFRelease(profile_info); | |
| 131 CFRelease(generic_rgb_profile); | |
| 132 CFRelease(main_display_id); | |
| 133 } | |
| 134 | |
| 135 void RestoreUserColorProfile() { | |
| 136 // This is used as a signal handler, and thus the calls into ColorSync are | |
| 137 // unsafe. | |
| 138 // But we might as well try to restore the user's color profile, we're going | |
| 139 // down anyway... | |
| 140 | |
| 141 if (!user_color_profile_url) | |
| 142 return; | |
| 143 | |
| 144 CFUUIDRef main_display_id = | |
| 145 CGDisplayCreateUUIDFromDisplayID(CGMainDisplayID()); | |
| 146 CFMutableDictionaryRef profile_info = | |
| 147 CFDictionaryCreateMutable(kCFAllocatorDefault, | |
| 148 0, | |
| 149 &kCFTypeDictionaryKeyCallBacks, | |
| 150 &kCFTypeDictionaryValueCallBacks); | |
| 151 CFDictionarySetValue( | |
| 152 profile_info, kColorSyncDeviceDefaultProfileID, user_color_profile_url); | |
| 153 ColorSyncDeviceSetCustomProfiles( | |
| 154 kColorSyncDisplayDeviceClass, main_display_id, profile_info); | |
| 155 CFRelease(main_display_id); | |
| 156 CFRelease(profile_info); | |
| 157 } | |
| 158 | |
| 159 #else // For Snow Leopard and before, use older CM* API. | |
| 160 | |
| 161 const char color_profile_path[] = | |
| 162 "/System/Library/ColorSync/Profiles/Generic RGB Profile.icc"; | |
| 163 | |
| 164 // The locType field is initialized to 0 which is the same as cmNoProfileBase. | |
| 165 CMProfileLocation initial_color_profile_location; | |
| 166 | |
| 167 void InstallLayoutTestColorProfile() { | |
| 168 // To make sure we get consistent colors (not dependent on the Main display), | |
| 169 // we force the generic rgb color profile. This cases a change the user can | |
| 170 // see. | |
| 171 const CMDeviceScope scope = {kCFPreferencesCurrentUser, | |
| 172 kCFPreferencesCurrentHost}; | |
| 173 | |
| 174 CMProfileRef profile = 0; | |
| 175 int error = | |
| 176 CMGetProfileByAVID((CMDisplayIDType)kCGDirectMainDisplay, &profile); | |
| 177 if (!error) { | |
| 178 UInt32 size = sizeof(initial_color_profile_location); | |
| 179 error = NCMGetProfileLocation(profile, &initial_color_profile_location, &siz
e); | |
| 180 CMCloseProfile(profile); | |
| 181 } | |
| 182 if (error) { | |
| 183 NSLog(@"failed to get the current color profile, pixmaps won't match. " | |
| 184 "Error: %d", | |
| 185 (int)error); | |
| 186 initial_color_profile_location.locType = cmNoProfileBase; | |
| 187 return; | |
| 188 } | |
| 189 | |
| 190 CMProfileLocation location; | |
| 191 location.locType = cmPathBasedProfile; | |
| 192 strncpy(location.u.pathLoc.path, | |
| 193 color_profile_path, | |
| 194 sizeof(location.u.pathLoc.path)); | |
| 195 error = CMSetDeviceProfile(cmDisplayDeviceClass, | |
| 196 (CMDeviceID)kCGDirectMainDisplay, | |
| 197 &scope, | |
| 198 cmDefaultProfileID, | |
| 199 &location); | |
| 200 if (error) { | |
| 201 NSLog(@"failed install the generic color profile, pixmaps won't match. " | |
| 202 "Error: %d", | |
| 203 (int)error); | |
| 204 initial_color_profile_location.locType = cmNoProfileBase; | |
| 205 } | |
| 206 } | |
| 207 | |
| 208 void RestoreUserColorProfile() { | |
| 209 // This is used as a signal handler, and thus the calls into ColorSync are | |
| 210 // unsafe. | |
| 211 // But we might as well try to restore the user's color profile, we're going | |
| 212 // down anyway... | |
| 213 if (initial_color_profile_location.locType != cmNoProfileBase) { | |
| 214 const CMDeviceScope scope = {kCFPreferencesCurrentUser, | |
| 215 kCFPreferencesCurrentHost}; | |
| 216 int error = CMSetDeviceProfile(cmDisplayDeviceClass, | |
| 217 (CMDeviceID)kCGDirectMainDisplay, | |
| 218 &scope, | |
| 219 cmDefaultProfileID, | |
| 220 &initial_color_profile_location); | |
| 221 if (error) { | |
| 222 NSLog(@"Failed to restore color profile, use System Preferences -> " | |
| 223 "Displays -> Color to reset. Error: %d", | |
| 224 (int)error); | |
| 225 } | |
| 226 initial_color_profile_location.locType = cmNoProfileBase; | |
| 227 } | |
| 228 } | |
| 229 | |
| 230 #endif | |
| 231 | |
| 232 void SimpleSignalHandler(int sig) { | |
| 233 // Try to restore the color profile and try to go down cleanly. | |
| 234 RestoreUserColorProfile(); | |
| 235 exit(128 + sig); | |
| 236 } | |
| 237 | |
| 238 } // namespace | |
| 239 | |
| 240 int main(int argc, char* argv[]) { | |
| 241 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; | |
| 242 | |
| 243 // Hooks the ways we might get told to clean up... | |
| 244 signal(SIGINT, SimpleSignalHandler); | |
| 245 signal(SIGHUP, SimpleSignalHandler); | |
| 246 signal(SIGTERM, SimpleSignalHandler); | |
| 247 | |
| 248 // Save off the current profile, and then install the layout test profile. | |
| 249 InstallLayoutTestColorProfile(); | |
| 250 | |
| 251 // Let the script know we're ready. | |
| 252 printf("ready\n"); | |
| 253 fflush(stdout); | |
| 254 | |
| 255 // Wait for any key (or signal). | |
| 256 getchar(); | |
| 257 | |
| 258 // Restore the profile. | |
| 259 RestoreUserColorProfile(); | |
| 260 | |
| 261 [pool release]; | |
| 262 return 0; | |
| 263 } | |
| OLD | NEW |