0ab837134909b2eeb0645cc690c120f1204cba55
[WebKit-https.git] / WebCore / kcanvas / device / quartz / QuartzSupport.cpp
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 #include <ApplicationServices/ApplicationServices.h>
31 #include "QuartzSupport.h"
32
33 #include "GraphicsContext.h"
34 #include "KCanvasRenderingStyle.h"
35 #include "RenderStyle.h"
36 #include "wtf/Assertions.h"
37 #include "SVGRenderStyle.h"
38
39 namespace WebCore {
40
41 CFStringRef CFStringFromCGAffineTransform(CGAffineTransform t)
42 {
43     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);
44 }
45
46 CGAffineTransform CGAffineTransformMakeMapBetweenRects(CGRect source, CGRect dest)
47 {
48     CGAffineTransform transform = CGAffineTransformMakeTranslation(dest.origin.x - source.origin.x, dest.origin.y - source.origin.y);
49     transform = CGAffineTransformScale(transform, dest.size.width/source.size.width, dest.size.height/source.size.height);
50     return transform;
51 }
52
53 void applyStrokeStyleToContext(CGContextRef context, RenderStyle* style, const RenderObject* object)
54 {
55     /* Shouldn't all these be in the stroke painter? */
56     CGContextSetLineWidth(context, KSVGPainterFactory::cssPrimitiveToLength(object, style->svgStyle()->strokeWidth(), 1.0));
57
58     CGContextSetLineCap(context, CGLineCapFromKC(style->svgStyle()->capStyle()));
59     CGContextSetLineJoin(context, CGLineJoinFromKC(style->svgStyle()->joinStyle()));
60
61     CGContextSetMiterLimit(context, style->svgStyle()->strokeMiterLimit());
62
63     const KCDashArray& dashes = KSVGPainterFactory::dashArrayFromRenderingStyle(style);
64     double dashOffset = KSVGPainterFactory::cssPrimitiveToLength(object, style->svgStyle()->strokeDashOffset(), 0.0);
65
66     CGContextSetLineDash(context, dashOffset, dashes.data(), dashes.size());
67 }
68
69 CGContextRef scratchContext()
70 {
71     static CGContextRef scratch = 0;
72     if (!scratch) {
73         CFMutableDataRef empty = CFDataCreateMutable(NULL, 0);
74         CGDataConsumerRef consumer = CGDataConsumerCreateWithCFData(empty);
75         scratch = CGPDFContextCreate(consumer, NULL, NULL);
76         CGDataConsumerRelease(consumer);
77         CFRelease(empty);
78
79         CGFloat black[4] = {0, 0, 0, 1};
80         CGContextSetFillColor(scratch, black);
81         CGContextSetStrokeColor(scratch, black);
82      }
83     return scratch;
84 }
85
86 FloatRect strokeBoundingBox(const Path& path, RenderStyle* style, const RenderObject* object)
87  {
88     // the bbox might grow if the path is stroked.
89     // and CGPathGetBoundingBox doesn't support that, so we'll have
90     // to make an alternative call...
91  
92     // FIXME: since this is mainly used to decide what to repaint,
93     // perhaps it would be sufficien to just outset the fill bbox by
94     // the stroke width - that should be way cheaper and simpler than
95     // what we do here.
96  
97     CGPathRef cgPath = path.platformPath();
98
99     CGContextRef context = scratchContext();
100     CGContextSaveGState(context);
101
102     CGContextBeginPath(context);
103     CGContextAddPath(context, cgPath);
104     applyStrokeStyleToContext(context, style, object);
105     CGContextReplacePathWithStrokedPath(context);
106     CGRect box = CGContextGetPathBoundingBox(context);
107         
108     CGContextRestoreGState(context);
109
110     return FloatRect(box);
111 }
112
113 }
114
115 #endif // SVG_SUPPORT
116