860e4ef102c6bfcf3d44be823ad00861d7aa43ab
[WebKit-https.git] / WebCore / kcanvas / device / quartz / QuartzSupport.mm
1 /*
2  * Copyright (C) 2005 Apple Computer, Inc.  All rights reserved.
3  *               2006 Rob Buis <buis@kde.org>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27
28 #include "config.h"
29 #ifdef SVG_SUPPORT
30 #import "QuartzSupport.h"
31
32 #import "GraphicsContext.h"
33 #import "KCanvasResourcesQuartz.h"
34 #import "KRenderingFillPainter.h"
35 #import "KRenderingStrokePainter.h"
36 #import "KCanvasRenderingStyle.h"
37 #import "wtf/Assertions.h"
38
39 #import <QuartzCore/CoreImage.h>
40
41 #import "SVGRenderStyle.h"
42
43 namespace WebCore {
44
45 CFStringRef CFStringFromCGAffineTransform(CGAffineTransform t)
46 {
47     return CFStringCreateWithFormat(0, 0, CFSTR("a: %f b: %f c: %f d: %f tx: %f ty: %f"), t.a, t.b, t.c, t.d, t.tx, t.ty);
48 }
49
50 CGAffineTransform CGAffineTransformMakeMapBetweenRects(CGRect source, CGRect dest)
51 {
52     CGAffineTransform transform = CGAffineTransformMakeTranslation(dest.origin.x - source.origin.x, dest.origin.y - source.origin.y);
53     transform = CGAffineTransformScale(transform, dest.size.width/source.size.width, dest.size.height/source.size.height);
54     return transform;
55 }
56
57 void applyStrokeStyleToContext(CGContextRef context, const KRenderingStrokePainter& strokePainter)
58 {
59
60     /* Shouldn't all these be in the stroke painter? */
61     CGContextSetLineWidth(context, strokePainter.strokeWidth());
62
63     KCCapStyle capStyle = strokePainter.strokeCapStyle();
64     CGContextSetLineCap(context, CGLineCapFromKC(capStyle));
65
66     KCJoinStyle joinStyle = strokePainter.strokeJoinStyle();
67     CGContextSetLineJoin(context, CGLineJoinFromKC(joinStyle));
68
69     CGContextSetMiterLimit(context, strokePainter.strokeMiterLimit());
70
71     KCDashArray dashes = strokePainter.dashArray();
72     if (dashes.count()) {
73         size_t dashCount = dashes.count();
74         CGFloat *lengths = (CGFloat *)malloc(dashCount * sizeof(CGFloat));
75         for (unsigned x = 0; x < dashCount; x++)
76             lengths[x] = dashes[x];
77         CGContextSetLineDash(context, strokePainter.dashOffset(), lengths, dashes.count());
78         free(lengths);
79     }
80 }
81
82 void applyStrokeStyleToContext(CGContextRef context, RenderStyle* renderStyle, const RenderObject* renderObject)
83 {
84     KRenderingStrokePainter strokePainter = KSVGPainterFactory::strokePainter(renderStyle, renderObject);
85     applyStrokeStyleToContext(context, strokePainter);
86 }
87
88 CGContextRef scratchContext()
89 {
90     static CGContextRef scratch = 0;
91     if (!scratch) {
92         CFMutableDataRef empty = CFDataCreateMutable(NULL, 0);
93         CGDataConsumerRef consumer = CGDataConsumerCreateWithCFData(empty);
94         scratch = CGPDFContextCreate(consumer, NULL, NULL);
95         CGDataConsumerRelease(consumer);
96         CFRelease(empty);
97
98         CGFloat black[4] = {0, 0, 0, 1};
99         CGContextSetFillColor(scratch, black);
100         CGContextSetStrokeColor(scratch, black);
101      }
102     return scratch;
103 }
104
105 FloatRect strokeBoundingBox(const Path& path, const KRenderingStrokePainter& strokePainter)
106  {
107     // the bbox might grow if the path is stroked.
108     // and CGPathGetBoundingBox doesn't support that, so we'll have
109     // to make an alternative call...
110  
111     // FIXME: since this is mainly used to decide what to repaint,
112     // perhaps it would be sufficien to just outset the fill bbox by
113     // the stroke width - that should be way cheaper and simpler than
114     // what we do here.
115  
116     CGPathRef cgPath = path.platformPath();
117
118     CGContextRef context = scratchContext();
119     CGContextSaveGState(context);
120
121     CGContextBeginPath(context);
122     CGContextAddPath(context, cgPath);
123     applyStrokeStyleToContext(context, strokePainter);
124     CGContextReplacePathWithStrokedPath(context);
125     CGRect box = CGContextGetPathBoundingBox(context);
126         
127     CGContextRestoreGState(context);
128
129     return FloatRect(box);
130 }
131
132 bool pathContainsPoint(CGMutablePathRef cgPath, const FloatPoint& point, CGPathDrawingMode drawMode)
133 {
134    CGContextRef context = scratchContext();
135    CGContextSaveGState(context);
136    
137    CGContextBeginPath(context);
138    CGContextAddPath(context, cgPath);
139    bool hitSuccess = CGContextPathContainsPoint(context, point, drawMode);
140
141    CGContextRestoreGState(context);
142
143    return hitSuccess;
144 }
145
146 }
147
148 #endif // SVG_SUPPORT
149