Home | History | Annotate | Download | only in mac
      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 #ifdef BUILDING_ON_TIGER
     50     CGContextBeginTransparencyLayer(context, 0);
     51 #endif
     52     CGContextBeginPath(context);
     53     CGContextAddPath(context, focusRingPath);
     54     wkDrawFocusRing(context, color, radius);
     55 #ifdef BUILDING_ON_TIGER
     56     CGContextEndTransparencyLayer(context);
     57 #endif
     58 }
     59 
     60 void GraphicsContext::drawFocusRing(const Path& path, int width, int /*offset*/, const Color& color)
     61 {
     62     // FIXME: Use 'offset' for something? http://webkit.org/b/49909
     63 
     64     if (paintingDisabled())
     65         return;
     66 
     67     int radius = (width - 1) / 2;
     68     CGColorRef colorRef = color.isValid() ? cachedCGColor(color, ColorSpaceDeviceRGB) : 0;
     69 
     70     drawFocusRingToContext(platformContext(), path.platformPath(), colorRef, radius);
     71 }
     72 
     73 void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
     74 {
     75     if (paintingDisabled())
     76         return;
     77 
     78     int radius = (width - 1) / 2;
     79     offset += radius;
     80     CGColorRef colorRef = color.isValid() ? cachedCGColor(color, ColorSpaceDeviceRGB) : 0;
     81 
     82     RetainPtr<CGMutablePathRef> focusRingPath(AdoptCF, CGPathCreateMutable());
     83     unsigned rectCount = rects.size();
     84     for (unsigned i = 0; i < rectCount; i++)
     85         CGPathAddRect(focusRingPath.get(), 0, CGRectInset(rects[i], -offset, -offset));
     86 
     87     drawFocusRingToContext(platformContext(), focusRingPath.get(), colorRef, radius);
     88 }
     89 
     90 #ifdef BUILDING_ON_TIGER // Post-Tiger's setPlatformCompositeOperation() is defined in GraphicsContextCG.cpp.
     91 void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op)
     92 {
     93     if (paintingDisabled())
     94         return;
     95     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
     96     [[NSGraphicsContext graphicsContextWithGraphicsPort:platformContext() flipped:YES]
     97         setCompositingOperation:(NSCompositingOperation)op];
     98     [pool drain];
     99 }
    100 #endif
    101 
    102 static NSColor* createPatternColor(NSString* name, NSColor* defaultColor, bool& usingDot)
    103 {
    104     NSImage *image = [NSImage imageNamed:name];
    105     ASSERT(image); // if image is not available, we want to know
    106     NSColor *color = (image ? [NSColor colorWithPatternImage:image] : nil);
    107     if (color)
    108         usingDot = true;
    109     else
    110         color = defaultColor;
    111     return color;
    112 }
    113 
    114 // WebKit on Mac is a standard platform component, so it must use the standard platform artwork for underline.
    115 void GraphicsContext::drawLineForTextChecking(const FloatPoint& point, float width, TextCheckingLineStyle style)
    116 {
    117     if (paintingDisabled())
    118         return;
    119 
    120     // These are the same for misspelling or bad grammar.
    121     int patternHeight = cMisspellingLineThickness;
    122     float patternWidth = cMisspellingLinePatternWidth;
    123 
    124     bool usingDot;
    125     NSColor *patternColor;
    126     switch (style) {
    127         case TextCheckingSpellingLineStyle:
    128         {
    129             // Constants for spelling pattern color.
    130             static bool usingDotForSpelling = false;
    131             DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, spellingPatternColor, (createPatternColor(@"SpellingDot", [NSColor redColor], usingDotForSpelling)));
    132             usingDot = usingDotForSpelling;
    133             patternColor = spellingPatternColor.get();
    134             break;
    135         }
    136         case TextCheckingGrammarLineStyle:
    137         {
    138             // Constants for grammar pattern color.
    139             static bool usingDotForGrammar = false;
    140             DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, grammarPatternColor, (createPatternColor(@"GrammarDot", [NSColor greenColor], usingDotForGrammar)));
    141             usingDot = usingDotForGrammar;
    142             patternColor = grammarPatternColor.get();
    143             break;
    144         }
    145 #if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
    146         // To support correction panel.
    147         case TextCheckingReplacementLineStyle:
    148         {
    149             // Constants for spelling pattern color.
    150             static bool usingDotForSpelling = false;
    151             DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, spellingPatternColor, (createPatternColor(@"CorrectionDot", [NSColor blueColor], usingDotForSpelling)));
    152             usingDot = usingDotForSpelling;
    153             patternColor = spellingPatternColor.get();
    154             break;
    155         }
    156 #endif
    157         default:
    158             return;
    159     }
    160 
    161     // Make sure to draw only complete dots.
    162     // NOTE: Code here used to shift the underline to the left and increase the width
    163     // to make sure everything gets underlined, but that results in drawing out of
    164     // bounds (e.g. when at the edge of a view) and could make it appear that the
    165     // space between adjacent misspelled words was underlined.
    166     if (usingDot) {
    167         // allow slightly more considering that the pattern ends with a transparent pixel
    168         float widthMod = fmodf(width, patternWidth);
    169         if (patternWidth - widthMod > cMisspellingLinePatternGapWidth)
    170             width -= widthMod;
    171     }
    172 
    173     // FIXME: This code should not use NSGraphicsContext currentContext
    174     // In order to remove this requirement we will need to use CGPattern instead of NSColor
    175     // FIXME: This code should not be using wkSetPatternPhaseInUserSpace, as this approach is wrong
    176     // for transforms.
    177 
    178     // Draw underline.
    179     LocalCurrentGraphicsContext localContext(this);
    180     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
    181     CGContextRef context = (CGContextRef)[currentContext graphicsPort];
    182     CGContextSaveGState(context);
    183 
    184     [patternColor set];
    185 
    186     wkSetPatternPhaseInUserSpace(context, point);
    187 
    188     NSRectFillUsingOperation(NSMakeRect(point.x(), point.y(), width, patternHeight), NSCompositeSourceOver);
    189 
    190     CGContextRestoreGState(context);
    191 }
    192 
    193 }
    194