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