POPCGUtils.mm 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /**
  2. Copyright (c) 2014-present, Facebook, Inc.
  3. All rights reserved.
  4. This source code is licensed under the BSD-style license found in the
  5. LICENSE file in the root directory of this source tree. An additional grant
  6. of patent rights can be found in the PATENTS file in the same directory.
  7. */
  8. #import "POPCGUtils.h"
  9. #import <objc/runtime.h>
  10. void POPCGColorGetRGBAComponents(CGColorRef color, CGFloat components[])
  11. {
  12. if (color) {
  13. const CGFloat *colors = CGColorGetComponents(color);
  14. size_t count = CGColorGetNumberOfComponents(color);
  15. if (4 == count) {
  16. // RGB colorspace
  17. components[0] = colors[0];
  18. components[1] = colors[1];
  19. components[2] = colors[2];
  20. components[3] = colors[3];
  21. } else if (2 == count) {
  22. // Grey colorspace
  23. components[0] = components[1] = components[2] = colors[0];
  24. components[3] = colors[1];
  25. } else {
  26. // Use CI to convert
  27. CIColor *ciColor = [CIColor colorWithCGColor:color];
  28. components[0] = ciColor.red;
  29. components[1] = ciColor.green;
  30. components[2] = ciColor.blue;
  31. components[3] = ciColor.alpha;
  32. }
  33. } else {
  34. memset(components, 0, 4 * sizeof(components[0]));
  35. }
  36. }
  37. CGColorRef POPCGColorRGBACreate(const CGFloat components[])
  38. {
  39. #if TARGET_OS_IPHONE
  40. CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
  41. CGColorRef color = CGColorCreate(space, components);
  42. CGColorSpaceRelease(space);
  43. return color;
  44. #else
  45. return CGColorCreateGenericRGB(components[0], components[1], components[2], components[3]);
  46. #endif
  47. }
  48. CGColorRef POPCGColorWithColor(id color)
  49. {
  50. if (CFGetTypeID((__bridge CFTypeRef)color) == CGColorGetTypeID()) {
  51. return ((__bridge CGColorRef)color);
  52. }
  53. #if TARGET_OS_IPHONE
  54. else if ([color isKindOfClass:[UIColor class]]) {
  55. return [color CGColor];
  56. }
  57. #else
  58. else if ([color isKindOfClass:[NSColor class]]) {
  59. // -[NSColor CGColor] is only supported since OSX 10.8+
  60. if ([color respondsToSelector:@selector(CGColor)]) {
  61. return [color CGColor];
  62. }
  63. /*
  64. * Otherwise create a CGColorRef manually.
  65. *
  66. * The original accessor is (or would be) declared as:
  67. * @property(readonly) CGColorRef CGColor;
  68. * - (CGColorRef)CGColor NS_RETURNS_INNER_POINTER CF_RETURNS_NOT_RETAINED;
  69. *
  70. * (Please note that OSX' accessor is atomic, while iOS' isn't.)
  71. *
  72. * The access to the NSColor object must thus be synchronized
  73. * and the CGColorRef be stored as an associated object,
  74. * to return a reference which doesn't need to be released manually.
  75. */
  76. @synchronized(color) {
  77. static const void* key = &key;
  78. CGColorRef colorRef = (__bridge CGColorRef)objc_getAssociatedObject(color, key);
  79. if (!colorRef) {
  80. size_t numberOfComponents = [(NSColor *)color numberOfComponents];
  81. CGFloat components[numberOfComponents];
  82. CGColorSpaceRef colorSpace = [[(NSColor *)color colorSpace] CGColorSpace];
  83. [color getComponents:components];
  84. colorRef = CGColorCreate(colorSpace, components);
  85. objc_setAssociatedObject(color, key, (__bridge id)colorRef, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  86. CGColorRelease(colorRef);
  87. }
  88. return colorRef;
  89. }
  90. }
  91. #endif
  92. return nil;
  93. }
  94. #if TARGET_OS_IPHONE
  95. void POPUIColorGetRGBAComponents(UIColor *color, CGFloat components[])
  96. {
  97. return POPCGColorGetRGBAComponents(POPCGColorWithColor(color), components);
  98. }
  99. UIColor *POPUIColorRGBACreate(const CGFloat components[])
  100. {
  101. CGColorRef colorRef = POPCGColorRGBACreate(components);
  102. UIColor *color = [[UIColor alloc] initWithCGColor:colorRef];
  103. CGColorRelease(colorRef);
  104. return color;
  105. }
  106. #else
  107. void POPNSColorGetRGBAComponents(NSColor *color, CGFloat components[])
  108. {
  109. return POPCGColorGetRGBAComponents(POPCGColorWithColor(color), components);
  110. }
  111. NSColor *POPNSColorRGBACreate(const CGFloat components[])
  112. {
  113. CGColorRef colorRef = POPCGColorRGBACreate(components);
  114. NSColor *color = nil;
  115. if (colorRef) {
  116. if ([NSColor respondsToSelector:@selector(colorWithCGColor:)]) {
  117. color = [NSColor colorWithCGColor:colorRef];
  118. } else {
  119. color = [NSColor colorWithCIColor:[CIColor colorWithCGColor:colorRef]];
  120. }
  121. CGColorRelease(colorRef);
  122. }
  123. return color;
  124. }
  125. #endif