1/*****************************************************************************\ 2 Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 This file is licensed under the Snes9x License. 4 For further information, consult the LICENSE file in the root directory. 5\*****************************************************************************/ 6 7/*********************************************************************************** 8 SNES9X for Mac OS (c) Copyright John Stiles 9 10 Snes9x for Mac OS X 11 12 (c) Copyright 2001 - 2011 zones 13 (c) Copyright 2002 - 2005 107 14 (c) Copyright 2002 PB1400c 15 (c) Copyright 2004 Alexander and Sander 16 (c) Copyright 2004 - 2005 Steven Seeger 17 (c) Copyright 2005 Ryan Vogt 18 ***********************************************************************************/ 19 20 21#import "port.h" 22 23#import <Foundation/Foundation.h> 24#import <QuartzCore/QuartzCore.h> 25#import <OpenGL/OpenGL.h> 26 27#import "mac-prefix.h" 28#import "mac-dialog.h" 29#import "mac-os.h" 30#import "mac-coreimage.h" 31 32enum 33{ 34 kCITypeNone = 0, 35 kCITypeBoolean = 1000, 36 kCITypeScalar, 37 kCITypeColor 38}; 39 40#define mCoreImageFilter 501 41#define FIXEDRANGE 0x10000 42#define kCommandFilterMenuBase 0x41000000 43#define kCommandCheckBoxBase 0x49000000 44#define kCommandSliderBase 0x51000000 45#define kCommandColorButtonBase 0x59000000 46#define kCIFilterNamePrefKey CFSTR("CoreImageFilterName") 47 48#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 49#define truncEnd 0 50#endif 51 52typedef struct { 53 char name[256]; 54 char displayName[256]; 55 int type; 56 union { 57 struct { 58 bool8 cur; 59 } b; 60 61 struct { 62 float max, min, cur; 63 } s; 64 65 struct { 66 float r, g, b, a; 67 } c; 68 } u; 69} FilterParam; 70 71static NSMutableArray *ciFilterNameList = NULL; 72static NSMutableArray *ciFilterLocalizedNameList = NULL; 73static NSArray *ciFilterInputKeys = NULL; 74static CIFilter *ciFilter = NULL; 75static CIContext *ciContext = NULL; 76static FilterParam *ciFilterParam = NULL; 77static CFStringRef ciFilterName = NULL; 78static HIViewRef ciFilterUIPane = NULL; 79static MenuRef ciFilterMenu = NULL; 80static CGColorSpaceRef cgColor = NULL; 81static MPSemaphoreID cisem = NULL; 82static bool8 ciFilterHasInputCenter = false; 83static bool8 ciFilterHasInputImage = false; 84static int ciFilterInputKeysCount = 0; 85 86static void LoadFilterPrefs (void); 87static void SaveFilterPrefs (void); 88static void FilterParamToFilter (void); 89static void FilterToFilterParam (void); 90static void BuildCoreImageFilterListAndMenu (void); 91static void ReleaseCoreImageFilterListAndMenu (void); 92static void ReplaceFilterUI (WindowRef); 93static void FilterUIAddSubviews (WindowRef, HIViewRef); 94static void FilterUISetValues (HIViewRef); 95static bool8 IsCoreImageFilterSupported (CIFilter *); 96static pascal OSStatus CoreImageFilterEventHandler (EventHandlerCallRef, EventRef, void *); 97 98 99void InitCoreImage (void) 100{ 101 OSStatus err; 102 NSAutoreleasePool *pool; 103 104 pool = [[NSAutoreleasePool alloc] init]; 105 106 ciFilterName = (CFStringRef) CFPreferencesCopyAppValue(kCIFilterNamePrefKey, kCFPreferencesCurrentApplication); 107 if (!ciFilterName) 108 ciFilterName = CFStringCreateCopy(kCFAllocatorDefault, CFSTR("CIGammaAdjust")); 109 110 BuildCoreImageFilterListAndMenu(); 111 112 err = MPCreateBinarySemaphore(&cisem); 113 114 [pool release]; 115} 116 117void DeinitCoreImage (void) 118{ 119 OSStatus err; 120 NSAutoreleasePool *pool; 121 122 pool = [[NSAutoreleasePool alloc] init]; 123 124 err = MPDeleteSemaphore(cisem); 125 126 ReleaseCoreImageFilterListAndMenu(); 127 128 CFPreferencesSetAppValue(kCIFilterNamePrefKey, ciFilterName, kCFPreferencesCurrentApplication); 129 130 CFRelease(ciFilterName); 131 132 [pool release]; 133} 134 135void InitCoreImageFilter (void) 136{ 137 NSAutoreleasePool *pool; 138 139 pool = [[NSAutoreleasePool alloc] init]; 140 141 ciFilter = [[CIFilter filterWithName: (NSString *) ciFilterName] retain]; 142 [ciFilter setDefaults]; 143 144 ciFilterInputKeys = [[ciFilter inputKeys] retain]; 145 ciFilterInputKeysCount = [ciFilterInputKeys count]; 146 147 ciFilterParam = new FilterParam [ciFilterInputKeysCount]; 148 memset(ciFilterParam, 0, sizeof(FilterParam) * ciFilterInputKeysCount); 149 150 ciFilterHasInputCenter = false; 151 ciFilterHasInputImage = false; 152 153 LoadFilterPrefs(); 154 155 [pool release]; 156} 157 158void DeinitCoreImageFilter (void) 159{ 160 NSAutoreleasePool *pool; 161 162 pool = [[NSAutoreleasePool alloc] init]; 163 164 SaveFilterPrefs(); 165 166 ciFilterHasInputCenter = false; 167 ciFilterHasInputImage = false; 168 169 delete [] ciFilterParam; 170 171 [ciFilterInputKeys release]; 172 ciFilterInputKeysCount = 0; 173 174 [ciFilter release]; 175 176 [pool release]; 177} 178 179static void LoadFilterPrefs (void) 180{ 181 CFDataRef data; 182 int n = sizeof(FilterParam) * ciFilterInputKeysCount; 183 184 data = (CFDataRef) CFPreferencesCopyAppValue(ciFilterName, kCFPreferencesCurrentApplication); 185 if (data) 186 { 187 if (CFDataGetLength(data) == n) 188 { 189 CFDataGetBytes(data, CFRangeMake(0, n), (UInt8 *) ciFilterParam); 190 FilterParamToFilter(); 191 } 192 193 CFRelease(data); 194 } 195 196 FilterToFilterParam(); 197} 198 199static void SaveFilterPrefs (void) 200{ 201 CFDataRef data; 202 int n = sizeof(FilterParam) * ciFilterInputKeysCount; 203 204 data = CFDataCreate(kCFAllocatorDefault, (UInt8 *) ciFilterParam, n); 205 if (data) 206 { 207 CFPreferencesSetAppValue(ciFilterName, data, kCFPreferencesCurrentApplication); 208 CFRelease(data); 209 } 210} 211 212static void FilterParamToFilter (void) 213{ 214 NSString *key; 215 NSNumber *num; 216 CIColor *color; 217 218 for (int i = 0; i < ciFilterInputKeysCount; i++) 219 { 220 key = [NSString stringWithUTF8String: ciFilterParam[i].name]; 221 if (key) 222 { 223 switch (ciFilterParam[i].type) 224 { 225 case kCITypeBoolean: 226 num = [NSNumber numberWithBool: ciFilterParam[i].u.b.cur]; 227 [ciFilter setValue: num forKey: key]; 228 break; 229 230 case kCITypeScalar: 231 num = [NSNumber numberWithFloat: ciFilterParam[i].u.s.cur]; 232 [ciFilter setValue: num forKey: key]; 233 break; 234 235 case kCITypeColor: 236 color = [CIColor colorWithRed: ciFilterParam[i].u.c.r green: ciFilterParam[i].u.c.g 237 blue: ciFilterParam[i].u.c.b alpha: ciFilterParam[i].u.c.a]; 238 [ciFilter setValue: color forKey: key]; 239 break; 240 241 default: 242 break; 243 } 244 } 245 } 246} 247 248static void FilterToFilterParam (void) 249{ 250 NSDictionary *attr; 251 NSString *key, *label, *className, *typeName; 252 NSNumber *num; 253 CIColor *color; 254 id param; 255 256 attr = [ciFilter attributes]; 257 ciFilterHasInputCenter = false; 258 ciFilterHasInputImage = false; 259 260 for (int i = 0; i < ciFilterInputKeysCount; i++) 261 { 262 key = [ciFilterInputKeys objectAtIndex: i]; 263 param = [attr objectForKey: key]; 264 265 strncpy(ciFilterParam[i].name, [key UTF8String], sizeof(ciFilterParam[i].name)); 266 ciFilterParam[i].displayName[0] = 0; 267 268 if ([param isKindOfClass: [NSDictionary class]]) 269 { 270 label = [(NSDictionary *) param objectForKey: kCIAttributeDisplayName]; 271 if (!label) 272 label = [NSString stringWithString: key]; 273 strncpy(ciFilterParam[i].displayName, [label UTF8String], sizeof(ciFilterParam[i].displayName)); 274 275 className = [(NSDictionary *) param objectForKey: kCIAttributeClass]; 276 277 if ([className isEqualToString: @"NSNumber"]) 278 { 279 typeName = [(NSDictionary *) param objectForKey: kCIAttributeType]; 280 281 if ([typeName isEqualToString: kCIAttributeTypeBoolean]) 282 { 283 ciFilterParam[i].type = kCITypeBoolean; 284 285 num = [ciFilter valueForKey: key]; 286 ciFilterParam[i].u.b.cur = [num boolValue]; 287 } 288 else 289 { 290 ciFilterParam[i].type = kCITypeScalar; 291 292 num = [ciFilter valueForKey: key]; 293 ciFilterParam[i].u.s.cur = [num floatValue]; 294 295 num = [(NSDictionary *) param objectForKey: kCIAttributeSliderMax]; 296 if (!num) 297 num = [(NSDictionary *) param objectForKey: kCIAttributeMax]; 298 ciFilterParam[i].u.s.max = [num floatValue]; 299 300 num = [(NSDictionary *) param objectForKey: kCIAttributeSliderMin]; 301 if (!num) 302 num = [(NSDictionary *) param objectForKey: kCIAttributeMin]; 303 ciFilterParam[i].u.s.min = [num floatValue]; 304 } 305 } 306 else 307 if ([className isEqualToString: @"CIColor"]) 308 { 309 ciFilterParam[i].type = kCITypeColor; 310 311 color = [ciFilter valueForKey: key]; 312 ciFilterParam[i].u.c.r = [color red]; 313 ciFilterParam[i].u.c.g = [color green]; 314 ciFilterParam[i].u.c.b = [color blue]; 315 ciFilterParam[i].u.c.a = [color alpha]; 316 } 317 else 318 { 319 ciFilterParam[i].type = kCITypeNone; 320 321 if ([className isEqualToString: @"CIVector"] && [key isEqualToString: @"inputCenter"]) 322 ciFilterHasInputCenter = true; 323 324 if ([className isEqualToString: @"CIImage" ] && [key isEqualToString: @"inputImage" ]) 325 ciFilterHasInputImage = true; 326 } 327 } 328 } 329} 330 331static void BuildCoreImageFilterListAndMenu (void) 332{ 333 NSArray *categories, *filterNames; 334 OSStatus err; 335 336 categories = [NSArray arrayWithObject: kCICategoryStillImage]; 337 filterNames = [CIFilter filterNamesInCategories: categories]; 338 339 ciFilterNameList = [[NSMutableArray alloc] initWithCapacity: 1]; 340 ciFilterLocalizedNameList = [[NSMutableArray alloc] initWithCapacity: 1]; 341 err = CreateNewMenu(mCoreImageFilter, 0, &ciFilterMenu); 342 343 int n = [filterNames count], m = 0; 344 for (int i = 0; i < n; i++) 345 { 346 CIFilter *filter; 347 NSString *name, *localName; 348 349 name = [filterNames objectAtIndex: i]; 350 filter = [CIFilter filterWithName: name]; 351 352 if (IsCoreImageFilterSupported(filter)) 353 { 354 [ciFilterNameList addObject: name]; 355 356 localName = [CIFilter localizedNameForFilterName: name]; 357 if (!localName) 358 localName = [NSString stringWithString: name]; 359 360 [ciFilterLocalizedNameList addObject: localName]; 361 362 err = AppendMenuItemTextWithCFString(ciFilterMenu, (CFStringRef) localName, 0, kCommandFilterMenuBase + m, NULL); 363 m++; 364 } 365 } 366} 367 368static void ReleaseCoreImageFilterListAndMenu (void) 369{ 370 CFRelease(ciFilterMenu); 371 [ciFilterLocalizedNameList release]; 372 [ciFilterNameList release]; 373} 374 375static bool8 IsCoreImageFilterSupported (CIFilter *filter) 376{ 377 NSDictionary *attr; 378 NSArray *inputKeys; 379 NSString *key, *className; 380 id param; 381 bool8 result = true, hasInputImage = false; 382 383 attr = [filter attributes]; 384 inputKeys = [filter inputKeys]; 385 386 int n = [inputKeys count]; 387 for (int i = 0; i < n; i++) 388 { 389 key = [inputKeys objectAtIndex: i]; 390 param = [attr objectForKey: key]; 391 392 if ([param isKindOfClass: [NSDictionary class]]) 393 { 394 className = [(NSDictionary *) param objectForKey: kCIAttributeClass]; 395 396 if ([className isEqualToString: @"CIImage"]) 397 { 398 if (![key isEqualToString: @"inputImage"]) 399 result = false; 400 else 401 hasInputImage = true; 402 } 403 else 404 if ([className isEqualToString: @"CIVector"]) 405 { 406 if (![key isEqualToString: @"inputCenter"]) 407 result = false; 408 } 409 else 410 if (![className isEqualToString: @"NSNumber"] && ![className isEqualToString: @"CIColor"]) 411 result = false; 412 } 413 } 414 415 if (hasInputImage == false) 416 result = false; 417 418 return (result); 419} 420 421void ConfigureCoreImageFilter (void) 422{ 423 NSAutoreleasePool *pool; 424 OSStatus err; 425 IBNibRef nibRef; 426 427 pool = [[NSAutoreleasePool alloc] init]; 428 429 err = CreateNibReference(kMacS9XCFString, &nibRef); 430 if (err == noErr) 431 { 432 WindowRef window; 433 434 err = CreateWindowFromNib(nibRef, CFSTR("CIFilter"), &window); 435 if (err == noErr) 436 { 437 EventHandlerRef eref; 438 EventHandlerUPP eUPP; 439 EventTypeSpec event[] = { { kEventClassWindow, kEventWindowClose }, 440 { kEventClassCommand, kEventCommandProcess }, 441 { kEventClassCommand, kEventCommandUpdateStatus } }; 442 HIViewRef ctl, root; 443 HIViewID cid; 444 Rect rct; 445 int value; 446 447 ciFilterUIPane = NULL; 448 449 FilterToFilterParam(); 450 451 root = HIViewGetRoot(window); 452 453 SetHIViewID(&cid, 'FILT', 0); 454 rct.left = 74; 455 rct.top = 20; 456 rct.right = 74 + 279; 457 rct.bottom = 20 + 20; 458 err = CreatePopupButtonControl(window, &rct, NULL, -12345, false, 0, 0, 0, &ctl); 459 HIViewSetID(ctl, cid); 460 int n = CountMenuItems(ciFilterMenu); 461 SetControlPopupMenuHandle(ctl, ciFilterMenu); 462 HIViewSetMaximum(ctl, n); 463 value = [ciFilterNameList indexOfObject: (NSString *) ciFilterName]; 464 HIViewSetValue(ctl, value + 1); 465 466 ReplaceFilterUI(window); 467 468 eUPP = NewEventHandlerUPP(CoreImageFilterEventHandler); 469 err = InstallWindowEventHandler(window, eUPP, GetEventTypeCount(event), event, (void *) window, &eref); 470 471 MoveWindowPosition(window, kWindowCoreImageFilter, false); 472 ShowWindow(window); 473 err = RunAppModalLoopForWindow(window); 474 HideWindow(window); 475 SaveWindowPosition(window, kWindowCoreImageFilter); 476 477 err = RemoveEventHandler(eref); 478 DisposeEventHandlerUPP(eUPP); 479 480 FilterParamToFilter(); 481 482 CFRelease(window); 483 } 484 485 DisposeNibReference(nibRef); 486 } 487 488 [pool release]; 489} 490 491static void ReplaceFilterUI (WindowRef window) 492{ 493 OSStatus err; 494 HIRect frame; 495 Rect bounds, rct; 496 497 if (ciFilterUIPane) 498 { 499 HIViewSetVisible(ciFilterUIPane, false); 500 DisposeControl(ciFilterUIPane); 501 ciFilterUIPane = NULL; 502 } 503 504 GetWindowBounds(window, kWindowStructureRgn, &bounds); 505 506 rct.left = 15; 507 rct.right = bounds.right - bounds.left - 15; 508 rct.top = 81; 509 rct.bottom = rct.top + 40; 510 err = CreateUserPaneControl(window, &rct, kControlSupportsEmbedding, &ciFilterUIPane); 511 HIViewSetVisible(ciFilterUIPane, false); 512 FilterUIAddSubviews(window, ciFilterUIPane); 513 514 HIViewGetFrame(ciFilterUIPane, &frame); 515 bounds.bottom = bounds.top + (short) (frame.origin.y + frame.size.height + 30); 516 517 err = TransitionWindow(window, kWindowSlideTransitionEffect, kWindowResizeTransitionAction, &bounds); 518 HIViewSetVisible(ciFilterUIPane, true); 519} 520 521static void FilterUIAddSubviews (WindowRef window, HIViewRef parent) 522{ 523 OSStatus err; 524 CFMutableStringRef label; 525 CFStringRef str; 526 HIViewRef ctl; 527 HIViewID cid; 528 HIRect bounds, frame; 529 Rect rct; 530 SInt32 value; 531 532 HIViewGetFrame(parent, &bounds); 533 rct.left = 0; 534 rct.top = 0; 535 rct.right = 200; 536 rct.bottom = 20; 537 538 int m = 0; 539 for (int i = 0; i < ciFilterInputKeysCount; i++) 540 { 541 str = CFStringCreateWithCString(kCFAllocatorDefault, ciFilterParam[i].displayName, kCFStringEncodingUTF8); 542 if (!str) 543 str = CFStringCreateCopy(kCFAllocatorDefault, CFSTR("Parameter")); 544 label = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, str); 545 CFRelease(str); 546 547 switch (ciFilterParam[i].type) 548 { 549 case kCITypeBoolean: 550 { 551 err = CreateCheckBoxControl(window, &rct, label, ciFilterParam[i].u.b.cur, true, &ctl); 552 SetHIViewID(&cid, kCommandCheckBoxBase + i, i); 553 HIViewSetID(ctl, cid); 554 HIViewSetCommandID(ctl, cid.signature); 555 err = HIViewAddSubview(parent, ctl); 556 frame.origin.x = 5.0f; 557 frame.origin.y = (float) (m * 28); 558 frame.size.width = bounds.size.width - 10.0f; 559 frame.size.height = 20.0f; 560 err = HIViewSetFrame(ctl, &frame); 561 m++; 562 563 break; 564 } 565 566 case kCITypeScalar: 567 { 568 CFStringAppend(label, CFSTR(" :")); 569 err = CreateStaticTextControl(window, &rct, label, NULL, &ctl); 570 SetStaticTextTrunc(ctl, truncEnd, true); 571 err = HIViewAddSubview(parent, ctl); 572 frame.origin.x = 5.0f; 573 frame.origin.y = (float) (m * 28); 574 frame.size.width = 120.0f; 575 frame.size.height = 20.0f; 576 err = HIViewSetFrame(ctl, &frame); 577 578 value = (SInt32) ((ciFilterParam[i].u.s.cur - ciFilterParam[i].u.s.min) / (ciFilterParam[i].u.s.max - ciFilterParam[i].u.s.min) * (float) FIXEDRANGE); 579 err = CreateSliderControl(window, &rct, value, 0, FIXEDRANGE, kControlSliderDoesNotPoint, 0, false, NULL, &ctl); 580 SetHIViewID(&cid, kCommandSliderBase + i, i); 581 HIViewSetID(ctl, cid); 582 HIViewSetCommandID(ctl, cid.signature); 583 err = HIViewAddSubview(parent, ctl); 584 frame.origin.x = 135.0f; 585 frame.origin.y = (float) (m * 28) - 1.0f; 586 frame.size.width = bounds.size.width - 140.0f; 587 frame.size.height = 20.0f; 588 err = HIViewSetFrame(ctl, &frame); 589 m++; 590 591 break; 592 } 593 594 case kCITypeColor: 595 { 596 CFStringAppend(label, CFSTR("...")); 597 err = CreatePushButtonControl(window, &rct, label, &ctl); 598 SetHIViewID(&cid, kCommandColorButtonBase + i, i); 599 HIViewSetID(ctl, cid); 600 HIViewSetCommandID(ctl, cid.signature); 601 err = HIViewAddSubview(parent, ctl); 602 frame.origin.x = bounds.size.width - 180.0f; 603 frame.origin.y = (float) (m * 28); 604 frame.size.width = 175.0f; 605 frame.size.height = 20.0f; 606 err = HIViewSetFrame(ctl, &frame); 607 m++; 608 609 break; 610 } 611 612 default: 613 break; 614 } 615 616 CFRelease(label); 617 } 618 619 if (m) 620 { 621 str = CFCopyLocalizedString(CFSTR("ResetCIFilter"), "Reset"); 622 err = CreatePushButtonControl(window, &rct, str, &ctl); 623 SetHIViewID(&cid, 'rSET', 0); 624 HIViewSetID(ctl, cid); 625 HIViewSetCommandID(ctl, cid.signature); 626 err = HIViewAddSubview(parent, ctl); 627 frame.origin.x = bounds.size.width - 180.0f; 628 frame.origin.y = (float) (m * 28 + 12); 629 frame.size.width = 175.0f; 630 frame.size.height = 20.0f; 631 err = HIViewSetFrame(ctl, &frame); 632 CFRelease(str); 633 bounds.size.height = frame.origin.y + 32.0f; 634 } 635 else 636 bounds.size.height = 4.0f; 637 638 err = HIViewSetFrame(parent, &bounds); 639} 640 641static void FilterUISetValues (HIViewRef parent) 642{ 643 HIViewRef ctl; 644 HIViewID cid; 645 SInt32 value; 646 647 for (int i = 0; i < ciFilterInputKeysCount; i++) 648 { 649 switch (ciFilterParam[i].type) 650 { 651 case kCITypeBoolean: 652 SetHIViewID(&cid, kCommandCheckBoxBase + i, i); 653 HIViewFindByID(parent, cid, &ctl); 654 HIViewSetValue(ctl, ciFilterParam[i].u.b.cur); 655 break; 656 657 case kCITypeScalar: 658 value = (SInt32) ((ciFilterParam[i].u.s.cur - ciFilterParam[i].u.s.min) / (ciFilterParam[i].u.s.max - ciFilterParam[i].u.s.min) * (float) FIXEDRANGE); 659 SetHIViewID(&cid, kCommandSliderBase + i, i); 660 HIViewFindByID(parent, cid, &ctl); 661 HIViewSetValue(ctl, value); 662 break; 663 664 default: 665 break; 666 } 667 } 668} 669 670static pascal OSStatus CoreImageFilterEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) 671{ 672 OSStatus err, result = eventNotHandledErr; 673 WindowRef window = (WindowRef) inUserData; 674 675 switch (GetEventClass(inEvent)) 676 { 677 case kEventClassWindow: 678 switch (GetEventKind(inEvent)) 679 { 680 case kEventWindowClose: 681 QuitAppModalLoopForWindow(window); 682 result = noErr; 683 } 684 685 break; 686 687 case kEventClassCommand: 688 switch (GetEventKind(inEvent)) 689 { 690 HICommandExtended tHICommand; 691 692 case kEventCommandUpdateStatus: 693 err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommandExtended), NULL, &tHICommand); 694 if (err == noErr && tHICommand.commandID == 'clos') 695 { 696 UpdateMenuCommandStatus(true); 697 result = noErr; 698 } 699 700 break; 701 702 case kEventCommandProcess: 703 err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommandExtended), NULL, &tHICommand); 704 if (err == noErr) 705 { 706 err = MPWaitOnSemaphore(cisem, kDurationForever); 707 708 if (tHICommand.commandID == 'rSET') 709 { 710 [ciFilter setDefaults]; 711 FilterToFilterParam(); 712 FilterUISetValues(ciFilterUIPane); 713 714 result = noErr; 715 } 716 else 717 { 718 unsigned long i = tHICommand.commandID & 0x00FFFFFF; 719 720 switch (tHICommand.commandID & 0xFF000000) 721 { 722 case kCommandFilterMenuBase: 723 DeinitCoreImageFilter(); 724 725 CFRelease(ciFilterName); 726 ciFilterName = CFStringCreateCopy(kCFAllocatorDefault, (CFStringRef) [ciFilterNameList objectAtIndex: i]); 727 728 InitCoreImageFilter(); 729 730 ReplaceFilterUI(window); 731 732 break; 733 734 case kCommandCheckBoxBase: 735 ciFilterParam[i].u.b.cur = !(ciFilterParam[i].u.b.cur); 736 FilterParamToFilter(); 737 result = noErr; 738 739 break; 740 741 case kCommandSliderBase: 742 SInt32 value; 743 744 value = HIViewGetValue(tHICommand.source.control); 745 ciFilterParam[i].u.s.cur = ciFilterParam[i].u.s.min + (ciFilterParam[i].u.s.max - ciFilterParam[i].u.s.min) * (float) value / (float) FIXEDRANGE; 746 FilterParamToFilter(); 747 result = noErr; 748 749 break; 750 751 case kCommandColorButtonBase: 752 NColorPickerInfo info; 753 754 memset(&info, 0, sizeof(NColorPickerInfo)); 755 info.placeWhere = kCenterOnMainScreen; 756 info.flags = kColorPickerDialogIsMoveable | kColorPickerDialogIsModal; 757 info.theColor.color.rgb.red = (int) (65535.0 * ciFilterParam[i].u.c.r); 758 info.theColor.color.rgb.green = (int) (65535.0 * ciFilterParam[i].u.c.g); 759 info.theColor.color.rgb.blue = (int) (65535.0 * ciFilterParam[i].u.c.b); 760 761 err = NPickColor(&info); 762 763 if ((err == noErr) && info.newColorChosen) 764 { 765 ciFilterParam[i].u.c.r = (float) info.theColor.color.rgb.red / 65535.0f; 766 ciFilterParam[i].u.c.g = (float) info.theColor.color.rgb.green / 65535.0f; 767 ciFilterParam[i].u.c.b = (float) info.theColor.color.rgb.blue / 65535.0f; 768 } 769 770 FilterParamToFilter(); 771 result = noErr; 772 773 break; 774 } 775 } 776 777 err = MPSignalSemaphore(cisem); 778 } 779 } 780 } 781 782 return (result); 783} 784 785void InitCoreImageContext (CGLContextObj cglctx, CGLPixelFormatObj cglpix) 786{ 787 NSAutoreleasePool *pool; 788 789 pool = [[NSAutoreleasePool alloc] init]; 790 791 FilterToFilterParam(); 792 793 cgColor = CGColorSpaceCreateDeviceRGB(); 794 795#ifdef MAC_LEOPARD_TIGER_PANTHER_SUPPORT 796 ciContext = [[CIContext contextWithCGLContext: cglctx pixelFormat: cglpix options: NULL] retain]; 797#else 798 ciContext = [[CIContext contextWithCGLContext: cglctx pixelFormat: cglpix colorSpace: cgColor options: NULL] retain]; 799#endif 800 801 [pool release]; 802} 803 804void DeinitCoreImageContext (void) 805{ 806 NSAutoreleasePool *pool; 807 808 pool = [[NSAutoreleasePool alloc] init]; 809 810 [ciContext release]; 811 CGColorSpaceRelease(cgColor); 812 813 [pool release]; 814} 815 816void DrawWithCoreImageFilter (CGRect src, CGImageRef img) 817{ 818 OSStatus err; 819 NSAutoreleasePool *pool; 820 821 pool = [[NSAutoreleasePool alloc] init]; 822 823 err = MPWaitOnSemaphore(cisem, kDurationForever); 824 825 if (ciFilterHasInputImage) 826 { 827 CIImage *image; 828 829 image = [CIImage imageWithCGImage: img]; 830 [ciFilter setValue: image forKey: @"inputImage" ]; 831 } 832 833 if (ciFilterHasInputCenter) 834 { 835 CIVector *vector; 836 837 vector = [CIVector vectorWithX: (src.origin.x + src.size.width / 2) Y: (src.origin.y + src.size.height / 2)]; 838 [ciFilter setValue: vector forKey: @"inputCenter"]; 839 } 840 841 [ciContext drawImage: [ciFilter valueForKey: @"outputImage"] atPoint: CGPointZero fromRect: src]; 842 843 err = MPSignalSemaphore(cisem); 844 845 [pool release]; 846} 847