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