1 /* 2 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "Color.h" 28 29 #if USE(CG) 30 31 #include "GraphicsContextCG.h" 32 #include <wtf/Assertions.h> 33 #include <wtf/RetainPtr.h> 34 #include <ApplicationServices/ApplicationServices.h> 35 36 namespace WebCore { 37 38 Color::Color(CGColorRef color) 39 { 40 if (!color) { 41 m_color = 0; 42 m_valid = false; 43 return; 44 } 45 46 size_t numComponents = CGColorGetNumberOfComponents(color); 47 const CGFloat* components = CGColorGetComponents(color); 48 49 float r = 0; 50 float g = 0; 51 float b = 0; 52 float a = 0; 53 54 switch (numComponents) { 55 case 2: 56 r = g = b = components[0]; 57 a = components[1]; 58 break; 59 case 4: 60 r = components[0]; 61 g = components[1]; 62 b = components[2]; 63 a = components[3]; 64 break; 65 default: 66 ASSERT_NOT_REACHED(); 67 } 68 69 m_color = makeRGBA(r * 255, g * 255, b * 255, a * 255); 70 m_valid = true; 71 } 72 73 static inline CGColorSpaceRef cachedCGColorSpace(ColorSpace colorSpace) 74 { 75 switch (colorSpace) { 76 case ColorSpaceDeviceRGB: 77 return deviceRGBColorSpaceRef(); 78 case ColorSpaceSRGB: 79 return sRGBColorSpaceRef(); 80 case ColorSpaceLinearRGB: 81 return linearRGBColorSpaceRef(); 82 } 83 ASSERT_NOT_REACHED(); 84 return deviceRGBColorSpaceRef(); 85 } 86 87 static CGColorRef leakCGColor(const Color& color, ColorSpace colorSpace) 88 { 89 CGFloat components[4]; 90 color.getRGBA(components[0], components[1], components[2], components[3]); 91 return CGColorCreate(cachedCGColorSpace(colorSpace), components); 92 } 93 94 template<ColorSpace colorSpace> static CGColorRef cachedCGColor(const Color& color) 95 { 96 switch (color.rgb()) { 97 case Color::transparent: { 98 static CGColorRef transparentCGColor = leakCGColor(color, colorSpace); 99 return transparentCGColor; 100 } 101 case Color::black: { 102 static CGColorRef blackCGColor = leakCGColor(color, colorSpace); 103 return blackCGColor; 104 } 105 case Color::white: { 106 static CGColorRef whiteCGColor = leakCGColor(color, colorSpace); 107 return whiteCGColor; 108 } 109 } 110 111 ASSERT(color.rgb()); 112 113 const size_t cacheSize = 32; 114 static RGBA32 cachedRGBAValues[cacheSize]; 115 static RetainPtr<CGColorRef>* cachedCGColors = new RetainPtr<CGColorRef>[cacheSize]; 116 117 for (size_t i = 0; i < cacheSize; ++i) { 118 if (cachedRGBAValues[i] == color.rgb()) 119 return cachedCGColors[i].get(); 120 } 121 122 CGColorRef newCGColor = leakCGColor(color, colorSpace); 123 124 static size_t cursor; 125 cachedRGBAValues[cursor] = color.rgb(); 126 cachedCGColors[cursor].adoptCF(newCGColor); 127 if (++cursor == cacheSize) 128 cursor = 0; 129 130 return newCGColor; 131 } 132 133 CGColorRef cachedCGColor(const Color& color, ColorSpace colorSpace) 134 { 135 switch (colorSpace) { 136 case ColorSpaceDeviceRGB: 137 return cachedCGColor<ColorSpaceDeviceRGB>(color); 138 case ColorSpaceSRGB: 139 return cachedCGColor<ColorSpaceSRGB>(color); 140 case ColorSpaceLinearRGB: 141 return cachedCGColor<ColorSpaceLinearRGB>(color); 142 } 143 ASSERT_NOT_REACHED(); 144 return cachedCGColor(color, ColorSpaceDeviceRGB); 145 } 146 147 } 148 149 #endif // USE(CG) 150