WebCore:
[WebKit-https.git] / WebCore / platform / graphics / mac / GraphicsContextMac.mm
1 /*
2  * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, 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 "../cg/GraphicsContextPlatformPrivate.h"
30
31 #import "WebCoreSystemInterface.h"
32
33 // FIXME: More of this should use CoreGraphics instead of AppKit.
34 // FIXME: More of this should move into GraphicsContextCG.cpp.
35
36 namespace WebCore {
37
38 // NSColor, NSBezierPath, and NSGraphicsContext
39 // calls in this file are all exception-safe, so we don't block
40 // exceptions for those.
41
42 void GraphicsContext::drawFocusRing(const Color& color)
43 {
44     if (paintingDisabled())
45         return;
46
47     int radius = (focusRingWidth() - 1) / 2;
48     int offset = radius + focusRingOffset();
49     CGColorRef colorRef = color.isValid() ? cgColor(color) : 0;
50
51     CGMutablePathRef focusRingPath = CGPathCreateMutable();
52     const Vector<IntRect>& rects = focusRingRects();
53     unsigned rectCount = rects.size();
54     for (unsigned i = 0; i < rectCount; i++)
55         CGPathAddRect(focusRingPath, 0, CGRectInset(rects[i], -offset, -offset));
56
57     CGContextRef context = platformContext();
58 #ifdef BUILDING_ON_TIGER
59     CGContextBeginTransparencyLayer(context, NULL);
60 #endif
61     CGContextBeginPath(context);
62     CGContextAddPath(context, focusRingPath);
63     wkDrawFocusRing(context, colorRef, radius);
64 #ifdef BUILDING_ON_TIGER
65     CGContextEndTransparencyLayer(context);
66 #endif
67     CGColorRelease(colorRef);
68
69     CGPathRelease(focusRingPath);
70 }
71
72 void GraphicsContext::setCompositeOperation(CompositeOperator op)
73 {
74     if (paintingDisabled())
75         return;
76     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
77     [[NSGraphicsContext graphicsContextWithGraphicsPort:platformContext() flipped:YES]
78         setCompositingOperation:(NSCompositingOperation)op];
79     [pool drain];
80 }
81
82 void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point, int width, bool grammar)
83 {
84     if (paintingDisabled())
85         return;
86         
87     // Constants for spelling pattern color
88     static RetainPtr<NSColor> spellingPatternColor = nil;
89     static bool usingDotForSpelling = false;
90
91     // Constants for grammar pattern color
92     static RetainPtr<NSColor> grammarPatternColor = nil;
93     static bool usingDotForGrammar = false;
94     
95     // These are the same for misspelling or bad grammar
96     int patternHeight = cMisspellingLineThickness;
97     int patternWidth = cMisspellingLinePatternWidth;
98  
99     // Initialize pattern color if needed
100     if (!grammar && !spellingPatternColor) {
101         NSImage *image = [NSImage imageNamed:@"SpellingDot"];
102         ASSERT(image); // if image is not available, we want to know
103         NSColor *color = (image ? [NSColor colorWithPatternImage:image] : nil);
104         if (color)
105             usingDotForSpelling = true;
106         else
107             color = [NSColor redColor];
108         spellingPatternColor = color;
109     }
110     
111     if (grammar && !grammarPatternColor) {
112         NSImage *image = [NSImage imageNamed:@"GrammarDot"];
113         ASSERT(image); // if image is not available, we want to know
114         NSColor *color = (image ? [NSColor colorWithPatternImage:image] : nil);
115         if (color)
116             usingDotForGrammar = true;
117         else
118             color = [NSColor greenColor];
119         grammarPatternColor = color;
120     }
121     
122     bool usingDot;
123     NSColor *patternColor;
124     if (grammar) {
125         usingDot = usingDotForGrammar;
126         patternColor = grammarPatternColor.get();
127     } else {
128         usingDot = usingDotForSpelling;
129         patternColor = spellingPatternColor.get();
130     }
131
132     // Make sure to draw only complete dots.
133     // NOTE: Code here used to shift the underline to the left and increase the width
134     // to make sure everything gets underlined, but that results in drawing out of
135     // bounds (e.g. when at the edge of a view) and could make it appear that the
136     // space between adjacent misspelled words was underlined.
137     if (usingDot) {
138         // allow slightly more considering that the pattern ends with a transparent pixel
139         int widthMod = width % patternWidth;
140         if (patternWidth - widthMod > cMisspellingLinePatternGapWidth)
141             width -= widthMod;
142     }
143     
144     // FIXME: This code should not use NSGraphicsContext currentContext
145     // In order to remove this requirement we will need to use CGPattern instead of NSColor
146     // FIXME: This code should not be using wkSetPatternPhaseInUserSpace, as this approach is wrong
147     // for transforms.
148
149     // Draw underline
150     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
151     CGContextRef context = (CGContextRef)[currentContext graphicsPort];
152     CGContextSaveGState(context);
153
154     [patternColor set];
155
156     wkSetPatternPhaseInUserSpace(context, point);
157
158     NSRectFillUsingOperation(NSMakeRect(point.x(), point.y(), width, patternHeight), NSCompositeSourceOver);
159     
160     CGContextRestoreGState(context);
161 }
162
163 }