fa7811ccd0037b038816956aac97f96591c05e69
[WebKit-https.git] / WebCore / kcanvas / device / quartz / KCanvasPathQuartz.mm
1 /*
2  * Copyright (C) 2005 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 #include "config.h"
27 #ifdef SVG_SUPPORT
28 #include "KCanvasPathQuartz.h"
29 #include "QuartzSupport.h"
30
31 namespace WebCore {
32
33 KCanvasPathQuartz::KCanvasPathQuartz()
34 {
35     m_cgPath = CGPathCreateMutable();
36 }
37
38 KCanvasPathQuartz::~KCanvasPathQuartz()
39 {
40     CGPathRelease(m_cgPath);
41 }
42
43 bool KCanvasPathQuartz::isEmpty() const
44 {
45     return CGPathIsEmpty(m_cgPath);
46 }
47
48 void KCanvasPathQuartz::moveTo(float x, float y)
49 {
50     CGPathMoveToPoint(m_cgPath, 0, x, y);
51 }
52
53 void KCanvasPathQuartz::lineTo(float x, float y)
54 {
55     CGPathAddLineToPoint(m_cgPath, 0, x, y);
56 }
57
58 void KCanvasPathQuartz::curveTo(float x1, float y1, float x2, float y2, float x3, float y3)
59 {
60     CGPathAddCurveToPoint(m_cgPath, 0, x1, y1, x2, y2, x3, y3);
61 }
62
63 void KCanvasPathQuartz::closeSubpath()
64 {
65     CGPathCloseSubpath(m_cgPath);
66 }
67
68 FloatRect KCanvasPathQuartz::boundingBox()
69 {
70     return CGPathGetBoundingBox(m_cgPath);
71 }
72
73 CGContextRef scratchContext()
74 {
75     static CGContextRef scratch = 0;
76     if (!scratch) {
77         CFMutableDataRef empty = CFDataCreateMutable(NULL, 0);
78         CGDataConsumerRef consumer = CGDataConsumerCreateWithCFData(empty);
79         scratch = CGPDFContextCreate(consumer, NULL, NULL);
80         CGDataConsumerRelease(consumer);
81         CFRelease(empty);
82
83         CGFloat black[4] = {0, 0, 0, 1};
84         CGContextSetFillColor(scratch, black);
85         CGContextSetStrokeColor(scratch, black);
86     }
87     return scratch;
88 }
89
90 FloatRect KCanvasPathQuartz::strokeBoundingBox(const KRenderingStrokePainter& strokePainter)
91 {
92     // the bbox might grow if the path is stroked.
93     // and CGPathGetBoundingBox doesn't support that, so we'll have
94     // to make an alternative call...
95
96     // FIXME: since this is mainly used to decide what to repaint,
97     // perhaps it would be sufficien to just outset the fill bbox by
98     // the stroke width - that should be way cheaper and simpler than
99     // what we do here.
100
101     CGContextRef context = scratchContext();
102     CGContextSaveGState(context);
103
104     CGContextBeginPath(context);
105     CGContextAddPath(context, m_cgPath);
106     applyStrokeStyleToContext(context, strokePainter);
107     CGContextReplacePathWithStrokedPath(context);
108     CGRect box = CGContextGetPathBoundingBox(context);
109         
110     CGContextRestoreGState(context);
111
112     return FloatRect(box);
113 }
114
115 static bool pathContainsPoint(CGMutablePathRef cgPath, const FloatPoint& point, CGPathDrawingMode drawMode)
116 {
117    CGContextRef context = scratchContext();
118    CGContextSaveGState(context);
119    
120    CGContextBeginPath(context);
121    CGContextAddPath(context, cgPath);
122    bool hitSuccess = CGContextPathContainsPoint(context, point, drawMode);
123
124    CGContextRestoreGState(context);
125
126    return hitSuccess;
127 }
128
129 bool KCanvasPathQuartz::containsPoint(const FloatPoint& point, KCWindRule fillRule)
130 {
131     return pathContainsPoint(m_cgPath, point, fillRule == RULE_EVENODD ? kCGPathEOFill : kCGPathFill);
132 }
133
134 bool KCanvasPathQuartz::strokeContainsPoint(const FloatPoint& point)
135 {
136     return pathContainsPoint(m_cgPath, point, kCGPathStroke);
137 }
138
139 }
140
141 #endif // SVG_SUPPORT
142