1/* 2 * tkMacOSXColor.c -- 3 * 4 * This file maintains a database of color values for the Tk 5 * toolkit, in order to avoid round-trips to the server to 6 * map color names to pixel values. 7 * 8 * Copyright (c) 1990-1994 The Regents of the University of California. 9 * Copyright (c) 1994-1996 Sun Microsystems, Inc. 10 * Copyright 2001-2009, Apple Inc. 11 * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net> 12 * 13 * See the file "license.terms" for information on usage and redistribution 14 * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 15 * 16 * RCS: @(#) $Id$ 17 */ 18 19#include "tkMacOSXPrivate.h" 20#include "tkColor.h" 21 22struct SystemColorMapEntry { 23 const char *name; 24 ThemeBrush brush; 25 ThemeTextColor textColor; 26 ThemeBackgroundKind background; 27}; /* unsigned char pixelCode; */ 28 29/* 30 * Array of system color definitions: the array index is required to equal the 31 * color's (pixelCode - MIN_PIXELCODE), i.e. the array order needs to be kept 32 * in sync with the public pixel code values in tkMacOSXPort.h ! 33 */ 34 35#define MIN_PIXELCODE 30 36static const struct SystemColorMapEntry systemColorMap[] = { 37 { "Transparent", 0, 0, 0 }, /* 30: TRANSPARENT_PIXEL */ 38 { "Highlight", kThemeBrushPrimaryHighlightColor, 0, 0 }, /* 31: HIGHLIGHT_PIXEL */ 39 { "HighlightSecondary", kThemeBrushSecondaryHighlightColor, 0, 0 }, /* 32: HIGHLIGHT_SECONDARY_PIXEL */ 40 { "HighlightText", kThemeBrushBlack, 0, 0 }, /* 33: HIGHLIGHT_TEXT_PIXEL */ 41 { "HighlightAlternate", kThemeBrushAlternatePrimaryHighlightColor, 0, 0 }, /* 34: HIGHLIGHT_ALTERNATE_PIXEL */ 42 { "ButtonText", 0, kThemeTextColorPushButtonActive, 0 }, /* 35: CONTROL_TEXT_PIXEL */ 43 { "PrimaryHighlightColor", kThemeBrushPrimaryHighlightColor, 0, 0 }, /* 36 */ 44 { "ButtonFace", kThemeBrushButtonFaceActive, 0, 0 }, /* 37: CONTROL_BODY_PIXEL */ 45 { "SecondaryHighlightColor", kThemeBrushSecondaryHighlightColor, 0, 0 }, /* 38 */ 46 { "ButtonFrame", kThemeBrushButtonFrameActive, 0, 0 }, /* 39: CONTROL_FRAME_PIXEL */ 47 { "AlternatePrimaryHighlightColor", kThemeBrushAlternatePrimaryHighlightColor, 0, 0 }, /* 40 */ 48 { "WindowBody", kThemeBrushDocumentWindowBackground, 0, 0 }, /* 41: WINDOW_BODY_PIXEL */ 49 { "SheetBackground", kThemeBrushSheetBackground, 0, 0 }, /* 42 */ 50 { "MenuActive", kThemeBrushMenuBackgroundSelected, 0, 0 }, /* 43: MENU_ACTIVE_PIXEL */ 51 { "Black", kThemeBrushBlack, 0, 0 }, /* 44 */ 52 { "MenuActiveText", 0, kThemeTextColorMenuItemSelected, 0 }, /* 45: MENU_ACTIVE_TEXT_PIXEL */ 53 { "White", kThemeBrushWhite, 0, 0 }, /* 46 */ 54 { "Menu", kThemeBrushMenuBackground, 0, 0 }, /* 47: MENU_BACKGROUND_PIXEL */ 55 { "DialogBackgroundActive", kThemeBrushDialogBackgroundActive, 0, 0 }, /* 48 */ 56 { "MenuDisabled", 0, kThemeTextColorMenuItemDisabled, 0 }, /* 49: MENU_DISABLED_PIXEL */ 57 { "DialogBackgroundInactive", kThemeBrushDialogBackgroundInactive, 0, 0 }, /* 50 */ 58 { "MenuText", 0, kThemeTextColorMenuItemActive, 0 }, /* 51: MENU_TEXT_PIXEL */ 59 { "AppearanceColor", 0, 0, 0 }, /* 52: APPEARANCE_PIXEL */ 60 { "AlertBackgroundActive", kThemeBrushAlertBackgroundActive, 0, 0 }, /* 53 */ 61 { "AlertBackgroundInactive", kThemeBrushAlertBackgroundInactive, 0, 0 }, /* 54 */ 62 { "ModelessDialogBackgroundActive", kThemeBrushModelessDialogBackgroundActive, 0, 0 }, /* 55 */ 63 { "ModelessDialogBackgroundInactive", kThemeBrushModelessDialogBackgroundInactive, 0, 0 }, /* 56 */ 64 { "UtilityWindowBackgroundActive", kThemeBrushUtilityWindowBackgroundActive, 0, 0 }, /* 57 */ 65 { "UtilityWindowBackgroundInactive", kThemeBrushUtilityWindowBackgroundInactive, 0, 0 }, /* 58 */ 66 { "ListViewSortColumnBackground", kThemeBrushListViewSortColumnBackground, 0, 0 }, /* 59 */ 67 { "ListViewBackground", kThemeBrushListViewBackground, 0, 0 }, /* 60 */ 68 { "IconLabelBackground", kThemeBrushIconLabelBackground, 0, 0 }, /* 61 */ 69 { "ListViewSeparator", kThemeBrushListViewSeparator, 0, 0 }, /* 62 */ 70 { "ChasingArrows", kThemeBrushChasingArrows, 0, 0 }, /* 63 */ 71 { "DragHilite", kThemeBrushDragHilite, 0, 0 }, /* 64 */ 72 { "DocumentWindowBackground", kThemeBrushDocumentWindowBackground, 0, 0 }, /* 65 */ 73 { "FinderWindowBackground", kThemeBrushFinderWindowBackground, 0, 0 }, /* 66 */ 74 { "ScrollBarDelimiterActive", kThemeBrushScrollBarDelimiterActive, 0, 0 }, /* 67 */ 75 { "ScrollBarDelimiterInactive", kThemeBrushScrollBarDelimiterInactive, 0, 0 }, /* 68 */ 76 { "FocusHighlight", kThemeBrushFocusHighlight, 0, 0 }, /* 69 */ 77 { "PopupArrowActive", kThemeBrushPopupArrowActive, 0, 0 }, /* 70 */ 78 { "PopupArrowPressed", kThemeBrushPopupArrowPressed, 0, 0 }, /* 71 */ 79 { "PopupArrowInactive", kThemeBrushPopupArrowInactive, 0, 0 }, /* 72 */ 80 { "AppleGuideCoachmark", kThemeBrushAppleGuideCoachmark, 0, 0 }, /* 73 */ 81 { "IconLabelBackgroundSelected", kThemeBrushIconLabelBackgroundSelected, 0, 0 }, /* 74 */ 82 { "StaticAreaFill", kThemeBrushStaticAreaFill, 0, 0 }, /* 75 */ 83 { "ActiveAreaFill", kThemeBrushActiveAreaFill, 0, 0 }, /* 76 */ 84 { "ButtonFrameActive", kThemeBrushButtonFrameActive, 0, 0 }, /* 77 */ 85 { "ButtonFrameInactive", kThemeBrushButtonFrameInactive, 0, 0 }, /* 78 */ 86 { "ButtonFaceActive", kThemeBrushButtonFaceActive, 0, 0 }, /* 79 */ 87 { "ButtonFaceInactive", kThemeBrushButtonFaceInactive, 0, 0 }, /* 80 */ 88 { "ButtonFacePressed", kThemeBrushButtonFacePressed, 0, 0 }, /* 81 */ 89 { "ButtonActiveDarkShadow", kThemeBrushButtonActiveDarkShadow, 0, 0 }, /* 82 */ 90 { "ButtonActiveDarkHighlight", kThemeBrushButtonActiveDarkHighlight, 0, 0 }, /* 83 */ 91 { "ButtonActiveLightShadow", kThemeBrushButtonActiveLightShadow, 0, 0 }, /* 84 */ 92 { "ButtonActiveLightHighlight", kThemeBrushButtonActiveLightHighlight, 0, 0 }, /* 85 */ 93 { "ButtonInactiveDarkShadow", kThemeBrushButtonInactiveDarkShadow, 0, 0 }, /* 86 */ 94 { "ButtonInactiveDarkHighlight", kThemeBrushButtonInactiveDarkHighlight, 0, 0 }, /* 87 */ 95 { "ButtonInactiveLightShadow", kThemeBrushButtonInactiveLightShadow, 0, 0 }, /* 88 */ 96 { "ButtonInactiveLightHighlight", kThemeBrushButtonInactiveLightHighlight, 0, 0 }, /* 89 */ 97 { "ButtonPressedDarkShadow", kThemeBrushButtonPressedDarkShadow, 0, 0 }, /* 90 */ 98 { "ButtonPressedDarkHighlight", kThemeBrushButtonPressedDarkHighlight, 0, 0 }, /* 91 */ 99 { "ButtonPressedLightShadow", kThemeBrushButtonPressedLightShadow, 0, 0 }, /* 92 */ 100 { "ButtonPressedLightHighlight", kThemeBrushButtonPressedLightHighlight, 0, 0 }, /* 93 */ 101 { "BevelActiveLight", kThemeBrushBevelActiveLight, 0, 0 }, /* 94 */ 102 { "BevelActiveDark", kThemeBrushBevelActiveDark, 0, 0 }, /* 95 */ 103 { "BevelInactiveLight", kThemeBrushBevelInactiveLight, 0, 0 }, /* 96 */ 104 { "BevelInactiveDark", kThemeBrushBevelInactiveDark, 0, 0 }, /* 97 */ 105 { "NotificationWindowBackground", kThemeBrushNotificationWindowBackground, 0, 0 }, /* 98 */ 106 { "MovableModalBackground", kThemeBrushMovableModalBackground, 0, 0 }, /* 99 */ 107 { "SheetBackgroundOpaque", kThemeBrushSheetBackgroundOpaque, 0, 0 }, /* 100 */ 108 { "DrawerBackground", kThemeBrushDrawerBackground, 0, 0 }, /* 101 */ 109 { "ToolbarBackground", kThemeBrushToolbarBackground, 0, 0 }, /* 102 */ 110 { "SheetBackgroundTransparent", kThemeBrushSheetBackgroundTransparent, 0, 0 }, /* 103 */ 111 { "MenuBackground", kThemeBrushMenuBackground, 0, 0 }, /* 104 */ 112 { "Pixel", 0, 0, 0 }, /* 105: PIXEL_MAGIC */ 113 { "MenuBackgroundSelected", kThemeBrushMenuBackgroundSelected, 0, 0 }, /* 106 */ 114 { "ListViewOddRowBackground", kThemeBrushListViewOddRowBackground, 0, 0 }, /* 107 */ 115 { "ListViewEvenRowBackground", kThemeBrushListViewEvenRowBackground, 0, 0 }, /* 108 */ 116 { "ListViewColumnDivider", kThemeBrushListViewColumnDivider, 0, 0 }, /* 109 */ 117 { "BlackText", 0, kThemeTextColorBlack, 0 }, /* 110 */ 118 { "DialogActiveText", 0, kThemeTextColorDialogActive, 0 }, /* 111 */ 119 { "DialogInactiveText", 0, kThemeTextColorDialogInactive, 0 }, /* 112 */ 120 { "AlertActiveText", 0, kThemeTextColorAlertActive, 0 }, /* 113 */ 121 { "AlertInactiveText", 0, kThemeTextColorAlertInactive, 0 }, /* 114 */ 122 { "ModelessDialogActiveText", 0, kThemeTextColorModelessDialogActive, 0 }, /* 115 */ 123 { "ModelessDialogInactiveText", 0, kThemeTextColorModelessDialogInactive, 0 }, /* 116 */ 124 { "WindowHeaderActiveText", 0, kThemeTextColorWindowHeaderActive, 0 }, /* 117 */ 125 { "WindowHeaderInactiveText", 0, kThemeTextColorWindowHeaderInactive, 0 }, /* 118 */ 126 { "PlacardActiveText", 0, kThemeTextColorPlacardActive, 0 }, /* 119 */ 127 { "PlacardInactiveText", 0, kThemeTextColorPlacardInactive, 0 }, /* 120 */ 128 { "PlacardPressedText", 0, kThemeTextColorPlacardPressed, 0 }, /* 121 */ 129 { "PushButtonActiveText", 0, kThemeTextColorPushButtonActive, 0 }, /* 122 */ 130 { "PushButtonInactiveText", 0, kThemeTextColorPushButtonInactive, 0 }, /* 123 */ 131 { "PushButtonPressedText", 0, kThemeTextColorPushButtonPressed, 0 }, /* 124 */ 132 { "BevelButtonActiveText", 0, kThemeTextColorBevelButtonActive, 0 }, /* 125 */ 133 { "BevelButtonInactiveText", 0, kThemeTextColorBevelButtonInactive, 0 }, /* 126 */ 134 { "BevelButtonPressedText", 0, kThemeTextColorBevelButtonPressed, 0 }, /* 127 */ 135 { "PopupButtonActiveText", 0, kThemeTextColorPopupButtonActive, 0 }, /* 128 */ 136 { "PopupButtonInactiveText", 0, kThemeTextColorPopupButtonInactive, 0 }, /* 129 */ 137 { "PopupButtonPressedText", 0, kThemeTextColorPopupButtonPressed, 0 }, /* 130 */ 138 { "IconLabelText", 0, kThemeTextColorIconLabel, 0 }, /* 131 */ 139 { "ListViewText", 0, kThemeTextColorListView, 0 }, /* 132 */ 140 { "DocumentWindowTitleActiveText", 0, kThemeTextColorDocumentWindowTitleActive, 0 }, /* 133 */ 141 { "DocumentWindowTitleInactiveText", 0, kThemeTextColorDocumentWindowTitleInactive, 0 }, /* 134 */ 142 { "MovableModalWindowTitleActiveText", 0, kThemeTextColorMovableModalWindowTitleActive, 0 }, /* 135 */ 143 { "MovableModalWindowTitleInactiveText",0, kThemeTextColorMovableModalWindowTitleInactive, 0 }, /* 136 */ 144 { "UtilityWindowTitleActiveText", 0, kThemeTextColorUtilityWindowTitleActive, 0 }, /* 137 */ 145 { "UtilityWindowTitleInactiveText", 0, kThemeTextColorUtilityWindowTitleInactive, 0 }, /* 138 */ 146 { "PopupWindowTitleActiveText", 0, kThemeTextColorPopupWindowTitleActive, 0 }, /* 139 */ 147 { "PopupWindowTitleInactiveText", 0, kThemeTextColorPopupWindowTitleInactive, 0 }, /* 140 */ 148 { "RootMenuActiveText", 0, kThemeTextColorRootMenuActive, 0 }, /* 141 */ 149 { "RootMenuSelectedText", 0, kThemeTextColorRootMenuSelected, 0 }, /* 142 */ 150 { "RootMenuDisabledText", 0, kThemeTextColorRootMenuDisabled, 0 }, /* 143 */ 151 { "MenuItemActiveText", 0, kThemeTextColorMenuItemActive, 0 }, /* 144 */ 152 { "MenuItemSelectedText", 0, kThemeTextColorMenuItemSelected, 0 }, /* 145 */ 153 { "MenuItemDisabledText", 0, kThemeTextColorMenuItemDisabled, 0 }, /* 146 */ 154 { "PopupLabelActiveText", 0, kThemeTextColorPopupLabelActive, 0 }, /* 147 */ 155 { "PopupLabelInactiveText", 0, kThemeTextColorPopupLabelInactive, 0 }, /* 148 */ 156 { "TabFrontActiveText", 0, kThemeTextColorTabFrontActive, 0 }, /* 149 */ 157 { "TabNonFrontActiveText", 0, kThemeTextColorTabNonFrontActive, 0 }, /* 150 */ 158 { "TabNonFrontPressedText", 0, kThemeTextColorTabNonFrontPressed, 0 }, /* 151 */ 159 { "TabFrontInactiveText", 0, kThemeTextColorTabFrontInactive, 0 }, /* 152 */ 160 { "TabNonFrontInactiveText", 0, kThemeTextColorTabNonFrontInactive, 0 }, /* 153 */ 161 { "IconLabelSelectedText", 0, kThemeTextColorIconLabelSelected, 0 }, /* 154 */ 162 { "BevelButtonStickyActiveText", 0, kThemeTextColorBevelButtonStickyActive, 0 }, /* 155 */ 163 { "BevelButtonStickyInactiveText", 0, kThemeTextColorBevelButtonStickyInactive, 0 }, /* 156 */ 164 { "NotificationText", 0, kThemeTextColorNotification, 0 }, /* 157 */ 165 { "SystemDetailText", 0, kThemeTextColorSystemDetail, 0 }, /* 158 */ 166 { "WhiteText", 0, kThemeTextColorWhite, 0 }, /* 159 */ 167 { "TabPaneBackground", 0, 0, kThemeBackgroundTabPane }, /* 160 */ 168 { "PlacardBackground", 0, 0, kThemeBackgroundPlacard }, /* 161 */ 169 { "WindowHeaderBackground", 0, 0, kThemeBackgroundWindowHeader }, /* 162 */ 170 { "ListViewWindowHeaderBackground", 0, 0, kThemeBackgroundListViewWindowHeader }, /* 163 */ 171 { "SecondaryGroupBoxBackground", 0, 0, kThemeBackgroundSecondaryGroupBox }, /* 164 */ 172 { "MetalBackground", 0, 0, kThemeBackgroundMetal }, /* 165 */ 173 { NULL, 0, 0, 0 } 174}; 175#define MAX_PIXELCODE 165 176 177/* 178 *---------------------------------------------------------------------- 179 * 180 * GetThemeFromPixelCode -- 181 * 182 * When given a pixel code corresponding to a theme system color, 183 * set one of brush, textColor or background to the corresponding 184 * Appearance Mgr theme constant. 185 * 186 * Results: 187 * Returns false if not a real pixel, true otherwise. 188 * 189 * Side effects: 190 * None. 191 * 192 *---------------------------------------------------------------------- 193 */ 194 195static int 196GetThemeFromPixelCode( 197 unsigned char code, 198 ThemeBrush *brush, 199 ThemeTextColor *textColor, 200 ThemeBackgroundKind *background) 201{ 202 if (code >= MIN_PIXELCODE && code <= MAX_PIXELCODE) { 203 *brush = systemColorMap[code - MIN_PIXELCODE].brush; 204 *textColor = systemColorMap[code - MIN_PIXELCODE].textColor; 205 *background = systemColorMap[code - MIN_PIXELCODE].background; 206 } else { 207 *brush = 0; 208 *textColor = 0; 209 *background = 0; 210 } 211 if (!*brush && !*textColor && !*background && code != PIXEL_MAGIC && 212 code != TRANSPARENT_PIXEL) { 213 return false; 214 } else { 215 return true; 216 } 217} 218 219/* 220 *---------------------------------------------------------------------- 221 * 222 * GetThemeColor -- 223 * 224 * Get RGB color for a given system color or pixel value. 225 * 226 * Results: 227 * OSStatus 228 * 229 * Side effects: 230 * None. 231 * 232 *---------------------------------------------------------------------- 233 */ 234 235static OSStatus 236GetThemeColor( 237 unsigned long pixel, 238 ThemeBrush brush, 239 ThemeTextColor textColor, 240 ThemeBackgroundKind background, 241 CGColorRef *c) 242{ 243 OSStatus err = noErr; 244 245 if (brush) { 246 err = ChkErr(HIThemeBrushCreateCGColor, brush, c); 247 /*} else if (textColor) { 248 err = ChkErr(GetThemeTextColor, textColor, 32, true, c);*/ 249 } else { 250 CGFloat rgba[4] = {0, 0, 0, 1}; 251 252 switch ((pixel >> 24) & 0xff) { 253 case PIXEL_MAGIC: { 254 unsigned short red, green, blue; 255 red = (pixel >> 16) & 0xff; 256 green = (pixel >> 8) & 0xff; 257 blue = (pixel ) & 0xff; 258 red |= red << 8; 259 green |= green << 8; 260 blue |= blue << 8; 261 rgba[0] = red / 65535.0; 262 rgba[1] = green / 65535.0; 263 rgba[2] = blue / 65535.0; 264 break; 265 } 266 case TRANSPARENT_PIXEL: 267 rgba[3] = 0.0; 268 break; 269 } 270 271 *c = CGColorCreateGenericRGB(rgba[0], rgba[1], rgba[2], rgba[3]); 272 273 /*static CGColorSpaceRef deviceRGBSpace = NULL; 274 if (!deviceRGBSpace) { 275 deviceRGBSpace = CGDisplayCopyColorSpace(CGMainDisplayID()); 276 } 277 *c = CGColorCreate(deviceRGBSpace, rgba );*/ 278 } 279 return err; 280} 281 282/* 283 *---------------------------------------------------------------------- 284 * 285 * TkSetMacColor -- 286 * 287 * Creates a CGColorRef from a X style pixel value. 288 * 289 * Results: 290 * Returns false if not a real pixel, true otherwise. 291 * 292 * Side effects: 293 * The variable macColor is set to a new CGColorRef, the caller is 294 * responsible for releasing it! 295 * 296 *---------------------------------------------------------------------- 297 */ 298 299int 300TkSetMacColor( 301 unsigned long pixel, /* Pixel value to convert. */ 302 void *macColor) /* CGColorRef to modify. */ 303{ 304 CGColorRef *color = (CGColorRef*)macColor; 305 OSStatus err = -1; 306 ThemeBrush brush; 307 ThemeTextColor textColor; 308 ThemeBackgroundKind background; 309 310 if (GetThemeFromPixelCode((pixel >> 24) & 0xff, &brush, &textColor, 311 &background)) { 312 err = ChkErr(GetThemeColor, pixel, brush, textColor, background, 313 color); 314 } 315 return (err == noErr); 316} 317 318/* 319 *---------------------------------------------------------------------- 320 * 321 * TkpInitGCCache, TkpFreeGCCache, CopyCachedColor, SetCachedColor -- 322 * 323 * Maintain a per-GC cache of previously converted CGColorRefs 324 * 325 * Results: 326 * None resp. retained CGColorRef for CopyCachedColor() 327 * 328 * Side effects: 329 * None. 330 * 331 *---------------------------------------------------------------------- 332 */ 333 334void 335TkpInitGCCache( 336 GC gc) 337{ 338 bzero(TkpGetGCCache(gc), sizeof(TkpGCCache)); 339} 340 341void 342TkpFreeGCCache( 343 GC gc) 344{ 345 TkpGCCache *gcCache = TkpGetGCCache(gc); 346 347 if (gcCache->cachedForegroundColor) { 348 CFRelease(gcCache->cachedForegroundColor); 349 } 350 if (gcCache->cachedBackgroundColor) { 351 CFRelease(gcCache->cachedBackgroundColor); 352 } 353} 354 355static CGColorRef 356CopyCachedColor( 357 GC gc, 358 unsigned long pixel) 359{ 360 TkpGCCache *gcCache = TkpGetGCCache(gc); 361 CGColorRef cgColor = NULL; 362 363 if (gcCache) { 364 if (gcCache->cachedForeground == pixel) { 365 cgColor = gcCache->cachedForegroundColor; 366 } else if (gcCache->cachedBackground == pixel) { 367 cgColor = gcCache->cachedBackgroundColor; 368 } 369 if (cgColor) { 370 CFRetain(cgColor); 371 } 372 } 373 return cgColor; 374} 375 376static void 377SetCachedColor( 378 GC gc, 379 unsigned long pixel, 380 CGColorRef cgColor) 381{ 382 TkpGCCache *gcCache = TkpGetGCCache(gc); 383 384 if (gcCache && cgColor) { 385 if (gc->foreground == pixel) { 386 if (gcCache->cachedForegroundColor) { 387 CFRelease(gcCache->cachedForegroundColor); 388 } 389 gcCache->cachedForegroundColor = (CGColorRef) CFRetain(cgColor); 390 gcCache->cachedForeground = pixel; 391 } else if (gc->background == pixel) { 392 if (gcCache->cachedBackgroundColor) { 393 CFRelease(gcCache->cachedBackgroundColor); 394 } 395 gcCache->cachedBackgroundColor = (CGColorRef) CFRetain(cgColor); 396 gcCache->cachedBackground = pixel; 397 } 398 } 399} 400 401/* 402 *---------------------------------------------------------------------- 403 * 404 * TkMacOSXCreateCGColor -- 405 * 406 * Creates a CGColorRef from a X style pixel value. 407 * 408 * Results: 409 * Returns NULL if not a real pixel, CGColorRef otherwise. 410 * 411 * Side effects: 412 * None 413 * 414 *---------------------------------------------------------------------- 415 */ 416 417CGColorRef 418TkMacOSXCreateCGColor( 419 GC gc, 420 unsigned long pixel) /* Pixel value to convert. */ 421{ 422 CGColorRef cgColor = CopyCachedColor(gc, pixel); 423 424 if (!cgColor && TkSetMacColor(pixel, &cgColor)) { 425 SetCachedColor(gc, pixel, cgColor); 426 } 427 return cgColor; 428} 429 430/* 431 *---------------------------------------------------------------------- 432 * 433 * TkMacOSXGetNSColor -- 434 * 435 * Creates an autoreleased NSColor from a X style pixel value. 436 * 437 * Results: 438 * Returns nil if not a real pixel, NSColor* otherwise. 439 * 440 * Side effects: 441 * None 442 * 443 *---------------------------------------------------------------------- 444 */ 445 446NSColor* 447TkMacOSXGetNSColor( 448 GC gc, 449 unsigned long pixel) /* Pixel value to convert. */ 450{ 451 CGColorRef cgColor = TkMacOSXCreateCGColor(gc, pixel); 452 NSColor *nsColor = nil; 453 454 if (cgColor) { 455 NSColorSpace *colorSpace = [[NSColorSpace alloc] 456 initWithCGColorSpace:CGColorGetColorSpace(cgColor)]; 457 nsColor = [NSColor colorWithColorSpace:colorSpace 458 components:CGColorGetComponents(cgColor) 459 count:CGColorGetNumberOfComponents(cgColor)]; 460 [colorSpace release]; 461 CFRelease(cgColor); 462 } 463 return nsColor; 464} 465 466/* 467 *---------------------------------------------------------------------- 468 * 469 * TkMacOSXSetColorInContext -- 470 * 471 * Sets fill and stroke color in the given CG context from an X 472 * pixel value, or if the pixel code indicates a system color, 473 * sets the corresponding brush, textColor or background via 474 * HITheme APIs if available or Appearance mgr APIs. 475 * 476 * Results: 477 * None. 478 * 479 * Side effects: 480 * None. 481 * 482 *---------------------------------------------------------------------- 483 */ 484 485void 486TkMacOSXSetColorInContext( 487 GC gc, 488 unsigned long pixel, 489 CGContextRef context) 490{ 491 OSStatus err = -1; 492 CGColorRef cgColor = CopyCachedColor(gc, pixel); 493 ThemeBrush brush; 494 ThemeTextColor textColor; 495 ThemeBackgroundKind background; 496 497 if (!cgColor && GetThemeFromPixelCode((pixel >> 24) & 0xff, &brush, 498 &textColor, &background)) { 499 if (brush) { 500 err = ChkErr(HIThemeSetFill, brush, NULL, context, 501 kHIThemeOrientationNormal); 502 if (err == noErr) { 503 err = ChkErr(HIThemeSetStroke, brush, NULL, context, 504 kHIThemeOrientationNormal); 505 } 506 } else if (textColor) { 507 err = ChkErr(HIThemeSetTextFill, textColor, NULL, context, 508 kHIThemeOrientationNormal); 509 } else if (background) { 510 CGRect rect = CGContextGetClipBoundingBox(context); 511 HIThemeBackgroundDrawInfo info = { 0, kThemeStateActive, 512 background }; 513 514 err = ChkErr(HIThemeApplyBackground, &rect, &info, 515 context, kHIThemeOrientationNormal); 516 } 517 if (err == noErr) { 518 return; 519 } 520 err = ChkErr(GetThemeColor, pixel, brush, textColor, background, 521 &cgColor); 522 if (err == noErr) { 523 SetCachedColor(gc, pixel, cgColor); 524 } 525 } else if (!cgColor) { 526 TkMacOSXDbgMsg("Ignored unknown pixel value 0x%lx", pixel); 527 } 528 if (cgColor) { 529 CGContextSetFillColorWithColor(context, cgColor); 530 CGContextSetStrokeColorWithColor(context, cgColor); 531 CGColorRelease(cgColor); 532 } 533} 534 535/* 536 *---------------------------------------------------------------------- 537 * 538 * TkpGetColor -- 539 * 540 * Allocate a new TkColor for the color with the given name. 541 * 542 * Results: 543 * Returns a newly allocated TkColor, or NULL on failure. 544 * 545 * Side effects: 546 * May invalidate the colormap cache associated with tkwin upon 547 * allocating a new colormap entry. Allocates a new TkColor 548 * structure. 549 * 550 *---------------------------------------------------------------------- 551 */ 552 553TkColor * 554TkpGetColor( 555 Tk_Window tkwin, /* Window in which color will be used. */ 556 Tk_Uid name) /* Name of color to allocated (in form 557 * suitable for passing to XParseColor). */ 558{ 559 Display *display = tkwin != None ? Tk_Display(tkwin) : NULL; 560 Colormap colormap = tkwin!= None ? Tk_Colormap(tkwin) : None; 561 TkColor *tkColPtr; 562 XColor color; 563 564 /* 565 * Check to see if this is a system color. Otherwise, XParseColor 566 * will do all the work. 567 */ 568 if (strncasecmp(name, "system", 6) == 0) { 569 Tcl_Obj *strPtr = Tcl_NewStringObj(name+6, -1); 570 int idx, result; 571 572 result = Tcl_GetIndexFromObjStruct(NULL, strPtr, systemColorMap, 573 sizeof(struct SystemColorMapEntry), NULL, TCL_EXACT, &idx); 574 Tcl_DecrRefCount(strPtr); 575 if (result == TCL_OK) { 576 OSStatus err; 577 CGColorRef c; 578 unsigned char pixelCode = idx + MIN_PIXELCODE; 579 ThemeBrush brush = systemColorMap[idx].brush; 580 ThemeTextColor textColor = systemColorMap[idx].textColor; 581 ThemeBackgroundKind background = systemColorMap[idx].background; 582 583 err = ChkErr(GetThemeColor, 0, brush, textColor, background, &c); 584 if (err == noErr) { 585 const size_t n = CGColorGetNumberOfComponents(c); 586 const CGFloat *rgba = CGColorGetComponents(c); 587 588 switch (n) { 589 case 4: 590 color.red = rgba[0] * 65535.0; 591 color.green = rgba[1] * 65535.0; 592 color.blue = rgba[2] * 65535.0; 593 break; 594 case 2: 595 color.red = color.green = color.blue = rgba[0] * 65535.0; 596 break; 597 default: 598 Tcl_Panic("CGColor with %d components", n); 599 } 600 color.pixel = ((((((pixelCode << 8) 601 | ((color.red >> 8) & 0xff)) << 8) 602 | ((color.green >> 8) & 0xff)) << 8) 603 | ((color.blue >> 8) & 0xff)); 604 CGColorRelease(c); 605 goto validXColor; 606 } 607 CGColorRelease(c); 608 } 609 } 610 611 if (XParseColor(display, colormap, name, &color) == 0) { 612 return (TkColor *) NULL; 613 } 614 615validXColor: 616 tkColPtr = (TkColor *) ckalloc(sizeof(TkColor)); 617 tkColPtr->color = color; 618 619 return tkColPtr; 620} 621 622/* 623 *---------------------------------------------------------------------- 624 * 625 * TkpGetColorByValue -- 626 * 627 * Given a desired set of red-green-blue intensities for a color, 628 * locate a pixel value to use to draw that color in a given 629 * window. 630 * 631 * Results: 632 * The return value is a pointer to an TkColor structure that 633 * indicates the closest red, blue, and green intensities available 634 * to those specified in colorPtr, and also specifies a pixel 635 * value to use to draw in that color. 636 * 637 * Side effects: 638 * May invalidate the colormap cache for the specified window. 639 * Allocates a new TkColor structure. 640 * 641 *---------------------------------------------------------------------- 642 */ 643 644TkColor * 645TkpGetColorByValue( 646 Tk_Window tkwin, /* Window in which color will be used. */ 647 XColor *colorPtr) /* Red, green, and blue fields indicate 648 * desired color. */ 649{ 650 TkColor *tkColPtr = (TkColor *) ckalloc(sizeof(TkColor)); 651 652 tkColPtr->color.red = colorPtr->red; 653 tkColPtr->color.green = colorPtr->green; 654 tkColPtr->color.blue = colorPtr->blue; 655 tkColPtr->color.pixel = TkpGetPixel(&tkColPtr->color); 656 return tkColPtr; 657} 658 659/* 660 *---------------------------------------------------------------------- 661 * 662 * Stub functions -- 663 * 664 * These functions are just stubs for functions that either 665 * don't make sense on the Mac or have yet to be implemented. 666 * 667 * Results: 668 * None. 669 * 670 * Side effects: 671 * These calls do nothing - which may not be expected. 672 * 673 *---------------------------------------------------------------------- 674 */ 675 676Status 677XAllocColor( 678 Display *display, /* Display. */ 679 Colormap map, /* Not used. */ 680 XColor *colorPtr) /* XColor struct to modify. */ 681{ 682 display->request++; 683 colorPtr->pixel = TkpGetPixel(colorPtr); 684 return 1; 685} 686 687Colormap 688XCreateColormap( 689 Display *display, /* Display. */ 690 Window window, /* X window. */ 691 Visual *visual, /* Not used. */ 692 int alloc) /* Not used. */ 693{ 694 static Colormap index = 1; 695 696 /* 697 * Just return a new value each time. 698 */ 699 return index++; 700} 701 702void 703XFreeColormap( 704 Display* display, /* Display. */ 705 Colormap colormap) /* Colormap. */ 706{ 707} 708 709void 710XFreeColors( 711 Display* display, /* Display. */ 712 Colormap colormap, /* Colormap. */ 713 unsigned long* pixels, /* Array of pixels. */ 714 int npixels, /* Number of pixels. */ 715 unsigned long planes) /* Number of pixel planes. */ 716{ 717 /* 718 * The Macintosh version of Tk uses TrueColor. Nothing 719 * needs to be done to release colors as there really is 720 * no colormap in the Tk sense. 721 */ 722} 723 724/* 725 * Local Variables: 726 * mode: c 727 * c-basic-offset: 4 728 * fill-column: 79 729 * coding: utf-8 730 * End: 731 */ 732