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 41namespace 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 47static 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 54void 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 67void 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 85static 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. 98void 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} 177