initial import
[vuplus_webkit] / Source / WebCore / platform / graphics / mac / GraphicsContextMac.mm
1 /*
2  * Copyright (C) 2003, 2004, 2005, 2006, 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 #import "config.h"
27 #import "GraphicsContext.h"
28
29 #import "GraphicsContextPlatformPrivateCG.h"
30 #import <AppKit/AppKit.h>
31 #import <wtf/StdLibExtras.h>
32
33 #import "LocalCurrentGraphicsContext.h"
34 #import "WebCoreSystemInterface.h"
35
36 @class NSColor;
37
38 // FIXME: More of this should use CoreGraphics instead of AppKit.
39 // FIXME: More of this should move into GraphicsContextCG.cpp.
40
41 namespace WebCore {
42
43 // NSColor, NSBezierPath, and NSGraphicsContext
44 // calls in this file are all exception-safe, so we don't block
45 // exceptions for those.
46
47 static void drawFocusRingToContext(CGContextRef context, CGPathRef focusRingPath, CGColorRef color, int radius)
48 {
49     CGContextBeginPath(context);
50     CGContextAddPath(context, focusRingPath);
51     wkDrawFocusRing(context, color, radius);
52 }
53
54 void GraphicsContext::drawFocusRing(const Path& path, int width, int /*offset*/, const Color& color)
55 {
56     // FIXME: Use 'offset' for something? http://webkit.org/b/49909
57
58     if (paintingDisabled())
59         return;
60
61     int radius = (width - 1) / 2;
62     CGColorRef colorRef = color.isValid() ? cachedCGColor(color, ColorSpaceDeviceRGB) : 0;
63
64     drawFocusRingToContext(platformContext(), path.platformPath(), colorRef, radius);
65 }
66
67 void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
68 {
69     if (paintingDisabled())
70         return;
71
72     int radius = (width - 1) / 2;
73     offset += radius;
74     CGColorRef colorRef = color.isValid() ? cachedCGColor(color, ColorSpaceDeviceRGB) : 0;
75
76     RetainPtr<CGMutablePathRef> focusRingPath(AdoptCF, CGPathCreateMutable());
77     unsigned rectCount = rects.size();
78     for (unsigned i = 0; i < rectCount; i++)
79         CGPathAddRect(focusRingPath.get(), 0, CGRectInset(rects[i], -offset, -offset));
80
81     drawFocusRingToContext(platformContext(), focusRingPath.get(), colorRef, radius);
82 }
83
84
85 static NSColor* createPatternColor(NSString* name, NSColor* defaultColor, bool& usingDot)
86 {
87     NSImage *image = [NSImage imageNamed:name];
88     ASSERT(image); // if image is not available, we want to know
89     NSColor *color = (image ? [NSColor colorWithPatternImage:image] : nil);
90     if (color)
91         usingDot = true;
92     else
93         color = defaultColor;
94     return color;
95 }
96
97 // WebKit on Mac is a standard platform component, so it must use the standard platform artwork for underline.
98 void GraphicsContext::drawLineForTextChecking(const FloatPoint& point, float width, TextCheckingLineStyle style)
99 {
100     if (paintingDisabled())
101         return;
102         
103     // These are the same for misspelling or bad grammar.
104     int patternHeight = cMisspellingLineThickness;
105     float patternWidth = cMisspellingLinePatternWidth;
106
107     bool usingDot;
108     NSColor *patternColor;
109     switch (style) {
110         case TextCheckingSpellingLineStyle:
111         {
112             // Constants for spelling pattern color.
113             static bool usingDotForSpelling = false;
114             DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, spellingPatternColor, (createPatternColor(@"SpellingDot", [NSColor redColor], usingDotForSpelling)));
115             usingDot = usingDotForSpelling;
116             patternColor = spellingPatternColor.get();
117             break;
118         }
119         case TextCheckingGrammarLineStyle:
120         {
121             // Constants for grammar pattern color.
122             static bool usingDotForGrammar = false;
123             DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, grammarPatternColor, (createPatternColor(@"GrammarDot", [NSColor greenColor], usingDotForGrammar)));
124             usingDot = usingDotForGrammar;
125             patternColor = grammarPatternColor.get();
126             break;
127         }
128 #if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
129         // To support correction panel.
130         case TextCheckingReplacementLineStyle:
131         {
132             // Constants for spelling pattern color.
133             static bool usingDotForSpelling = false;
134             DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, spellingPatternColor, (createPatternColor(@"CorrectionDot", [NSColor blueColor], usingDotForSpelling)));
135             usingDot = usingDotForSpelling;
136             patternColor = spellingPatternColor.get();
137             break;
138         }
139 #endif
140         default:
141             return;
142     }
143
144     // Make sure to draw only complete dots.
145     // NOTE: Code here used to shift the underline to the left and increase the width
146     // to make sure everything gets underlined, but that results in drawing out of
147     // bounds (e.g. when at the edge of a view) and could make it appear that the
148     // space between adjacent misspelled words was underlined.
149     if (usingDot) {
150         // allow slightly more considering that the pattern ends with a transparent pixel
151         float widthMod = fmodf(width, patternWidth);
152         if (patternWidth - widthMod > cMisspellingLinePatternGapWidth)
153             width -= widthMod;
154     }
155     
156     // FIXME: This code should not use NSGraphicsContext currentContext
157     // In order to remove this requirement we will need to use CGPattern instead of NSColor
158     // FIXME: This code should not be using wkSetPatternPhaseInUserSpace, as this approach is wrong
159     // for transforms.
160
161     // Draw underline.
162     LocalCurrentGraphicsContext localContext(this);
163     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
164     CGContextRef context = (CGContextRef)[currentContext graphicsPort];
165     CGContextSaveGState(context);
166
167     [patternColor set];
168
169     wkSetPatternPhaseInUserSpace(context, point);
170
171     NSRectFillUsingOperation(NSMakeRect(point.x(), point.y(), width, patternHeight), NSCompositeSourceOver);
172     
173     CGContextRestoreGState(context);
174 }
175
176 }