Home | History | Annotate | Download | only in mac
      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 
     40 namespace 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 
     46 static 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 
     59 void 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 
     78 void 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.
     98 void 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 
    109 static 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.
    122 void 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