2 * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
3 * 2006 Rob Buis <buis@kde.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
30 #import "QuartzSupport.h"
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"
39 #import <QuartzCore/CoreImage.h>
41 #import "SVGRenderStyle.h"
45 CFStringRef CFStringFromCGAffineTransform(CGAffineTransform t)
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);
50 CGAffineTransform CGAffineTransformMakeMapBetweenRects(CGRect source, CGRect dest)
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);
57 void applyStrokeStyleToContext(CGContextRef context, const KRenderingStrokePainter& strokePainter)
60 /* Shouldn't all these be in the stroke painter? */
61 CGContextSetLineWidth(context, strokePainter.strokeWidth());
63 KCCapStyle capStyle = strokePainter.strokeCapStyle();
64 CGContextSetLineCap(context, CGLineCapFromKC(capStyle));
66 KCJoinStyle joinStyle = strokePainter.strokeJoinStyle();
67 CGContextSetLineJoin(context, CGLineJoinFromKC(joinStyle));
69 CGContextSetMiterLimit(context, strokePainter.strokeMiterLimit());
71 KCDashArray dashes = strokePainter.dashArray();
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());
82 void applyStrokeStyleToContext(CGContextRef context, RenderStyle* renderStyle, const RenderObject* renderObject)
84 KRenderingStrokePainter strokePainter = KSVGPainterFactory::strokePainter(renderStyle, renderObject);
85 applyStrokeStyleToContext(context, strokePainter);
88 CGContextRef scratchContext()
90 static CGContextRef scratch = 0;
92 CFMutableDataRef empty = CFDataCreateMutable(NULL, 0);
93 CGDataConsumerRef consumer = CGDataConsumerCreateWithCFData(empty);
94 scratch = CGPDFContextCreate(consumer, NULL, NULL);
95 CGDataConsumerRelease(consumer);
98 CGFloat black[4] = {0, 0, 0, 1};
99 CGContextSetFillColor(scratch, black);
100 CGContextSetStrokeColor(scratch, black);
105 FloatRect strokeBoundingBox(const Path& path, const KRenderingStrokePainter& strokePainter)
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...
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
116 CGPathRef cgPath = path.platformPath();
118 CGContextRef context = scratchContext();
119 CGContextSaveGState(context);
121 CGContextBeginPath(context);
122 CGContextAddPath(context, cgPath);
123 applyStrokeStyleToContext(context, strokePainter);
124 CGContextReplacePathWithStrokedPath(context);
125 CGRect box = CGContextGetPathBoundingBox(context);
127 CGContextRestoreGState(context);
129 return FloatRect(box);
134 #endif // SVG_SUPPORT