Semantic colors should not be transformed by color-filter
[WebKit-https.git] / Source / WebCore / platform / graphics / mac / ColorMac.mm
1 /*
2  * Copyright (C) 2003, 2004, 2005, 2006 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 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 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 #import "config.h"
27 #import "ColorMac.h"
28
29 #if USE(APPKIT)
30
31 #import "LocalCurrentGraphicsContext.h"
32 #import <wtf/BlockObjCExceptions.h>
33 #import <wtf/NeverDestroyed.h>
34 #import <wtf/RetainPtr.h>
35 #import <wtf/StdLibExtras.h>
36
37 namespace WebCore {
38
39 static bool useOldAquaFocusRingColor;
40
41 Color oldAquaFocusRingColor()
42 {
43     return 0xFF7DADD9;
44 }
45
46 void setUsesTestModeFocusRingColor(bool newValue)
47 {
48     useOldAquaFocusRingColor = newValue;
49 }
50
51 bool usesTestModeFocusRingColor()
52 {
53     return useOldAquaFocusRingColor;
54 }
55
56 static RGBA32 makeRGBAFromNSColor(NSColor *color)
57 {
58     ASSERT_ARG(color, color);
59
60     CGFloat redComponent;
61     CGFloat greenComponent;
62     CGFloat blueComponent;
63     CGFloat alpha;
64
65     BEGIN_BLOCK_OBJC_EXCEPTIONS;
66     NSColor *rgbColor = [color colorUsingColorSpace:NSColorSpace.deviceRGBColorSpace];
67     if (!rgbColor) {
68         // The color space conversion above can fail if the NSColor is in the NSPatternColorSpace.
69         // These colors are actually a repeating pattern, not just a solid color. To workaround
70         // this we simply draw a one pixel image of the color and use that pixel's color.
71         // FIXME: It might be better to use an average of the colors in the pattern instead.
72         RetainPtr<NSBitmapImageRep> offscreenRep = adoptNS([[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil pixelsWide:1 pixelsHigh:1
73             bitsPerSample:8 samplesPerPixel:4 hasAlpha:YES isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace bytesPerRow:4 bitsPerPixel:32]);
74
75         GraphicsContext bitmapContext([NSGraphicsContext graphicsContextWithBitmapImageRep:offscreenRep.get()].CGContext);
76         LocalCurrentGraphicsContext localContext(bitmapContext);
77
78         [color drawSwatchInRect:NSMakeRect(0, 0, 1, 1)];
79
80         NSUInteger pixel[4];
81         [offscreenRep getPixel:pixel atX:0 y:0];
82
83         return makeRGBA(pixel[0], pixel[1], pixel[2], pixel[3]);
84     }
85
86     [rgbColor getRed:&redComponent green:&greenComponent blue:&blueComponent alpha:&alpha];
87     END_BLOCK_OBJC_EXCEPTIONS;
88
89     static const double scaleFactor = nextafter(256.0, 0.0);
90     return makeRGBA(scaleFactor * redComponent, scaleFactor * greenComponent, scaleFactor * blueComponent, scaleFactor * alpha);
91 }
92
93 Color colorFromNSColor(NSColor *color)
94 {
95     return Color(makeRGBAFromNSColor(color));
96 }
97
98 Color semanticColorFromNSColor(NSColor *color)
99 {
100     return Color(makeRGBAFromNSColor(color), Color::Semantic);
101 }
102
103 NSColor *nsColor(const Color& color)
104 {
105     if (!color.isValid()) {
106         // Need this to avoid returning nil because cachedRGBAValues will default to 0.
107         static NeverDestroyed<NSColor *> clearColor = [[NSColor colorWithSRGBRed:0 green:0 blue:0 alpha:0] retain];
108         return clearColor;
109     }
110
111     if (Color::isBlackColor(color)) {
112         static NeverDestroyed<NSColor *> blackColor = [[NSColor colorWithSRGBRed:0 green:0 blue:0 alpha:1] retain];
113         return blackColor;
114     }
115
116     if (Color::isWhiteColor(color)) {
117         static NeverDestroyed<NSColor *> whiteColor = [[NSColor colorWithSRGBRed:1 green:1 blue:1 alpha:1] retain];
118         return whiteColor;
119     }
120
121     const int cacheSize = 32;
122     static unsigned cachedRGBAValues[cacheSize];
123     static RetainPtr<NSColor>* cachedColors = new RetainPtr<NSColor>[cacheSize];
124
125     unsigned hash = color.hash();
126     for (int i = 0; i < cacheSize; ++i) {
127         if (cachedRGBAValues[i] == hash)
128             return cachedColors[i].get();
129     }
130
131     NSColor *result = [NSColor colorWithCGColor:cachedCGColor(color)];
132
133     static int cursor;
134     cachedRGBAValues[cursor] = hash;
135     cachedColors[cursor] = result;
136     if (++cursor == cacheSize)
137         cursor = 0;
138     return result;
139 }
140
141
142 } // namespace WebCore
143
144 #endif // USE(APPKIT)