summaryrefslogtreecommitdiffstats
path: root/WebCore/svg/graphics/cg
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:30:52 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:30:52 -0800
commit8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2 (patch)
tree11425ea0b299d6fb89c6d3618a22d97d5bf68d0f /WebCore/svg/graphics/cg
parent648161bb0edfc3d43db63caed5cc5213bc6cb78f (diff)
downloadexternal_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.zip
external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.tar.gz
external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'WebCore/svg/graphics/cg')
-rw-r--r--WebCore/svg/graphics/cg/CgSupport.cpp100
-rw-r--r--WebCore/svg/graphics/cg/CgSupport.h50
-rw-r--r--WebCore/svg/graphics/cg/RenderPathCg.cpp79
-rw-r--r--WebCore/svg/graphics/cg/SVGPaintServerCg.cpp89
-rw-r--r--WebCore/svg/graphics/cg/SVGPaintServerGradientCg.cpp336
-rw-r--r--WebCore/svg/graphics/cg/SVGPaintServerPatternCg.cpp130
-rw-r--r--WebCore/svg/graphics/cg/SVGPaintServerSolidCg.cpp77
-rw-r--r--WebCore/svg/graphics/cg/SVGResourceClipperCg.cpp82
-rw-r--r--WebCore/svg/graphics/cg/SVGResourceFilterCg.cpp53
-rw-r--r--WebCore/svg/graphics/cg/SVGResourceFilterCg.mm145
-rw-r--r--WebCore/svg/graphics/cg/SVGResourceMaskerCg.cpp42
-rw-r--r--WebCore/svg/graphics/cg/SVGResourceMaskerCg.mm129
12 files changed, 1312 insertions, 0 deletions
diff --git a/WebCore/svg/graphics/cg/CgSupport.cpp b/WebCore/svg/graphics/cg/CgSupport.cpp
new file mode 100644
index 0000000..f9bfb4c
--- /dev/null
+++ b/WebCore/svg/graphics/cg/CgSupport.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
+ * 2006 Rob Buis <buis@kde.org>
+ * 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "CgSupport.h"
+
+#include <ApplicationServices/ApplicationServices.h>
+#include "FloatConversion.h"
+#include "GraphicsContext.h"
+#include "RenderStyle.h"
+#include "SVGPaintServer.h"
+#include "SVGRenderStyle.h"
+#include <wtf/Assertions.h>
+
+namespace WebCore {
+
+CGContextRef scratchContext()
+{
+ static CGContextRef scratch = 0;
+ if (!scratch) {
+ CFMutableDataRef empty = CFDataCreateMutable(NULL, 0);
+ CGDataConsumerRef consumer = CGDataConsumerCreateWithCFData(empty);
+ scratch = CGPDFContextCreate(consumer, NULL, NULL);
+ CGDataConsumerRelease(consumer);
+ CFRelease(empty);
+
+ CGFloat black[4] = {0, 0, 0, 1};
+ CGContextSetFillColor(scratch, black);
+ CGContextSetStrokeColor(scratch, black);
+ }
+ return scratch;
+}
+
+FloatRect strokeBoundingBox(const Path& path, RenderStyle* style, const RenderObject* object)
+ {
+ // the bbox might grow if the path is stroked.
+ // and CGPathGetBoundingBox doesn't support that, so we'll have
+ // to make an alternative call...
+
+ // FIXME: since this is mainly used to decide what to repaint,
+ // perhaps it would be sufficient to just outset the fill bbox by
+ // the stroke width - that should be way cheaper and simpler than
+ // what we do here.
+
+ CGPathRef cgPath = path.platformPath();
+
+ CGContextRef context = scratchContext();
+ CGContextSaveGState(context);
+
+ CGContextBeginPath(context);
+ CGContextAddPath(context, cgPath);
+
+ GraphicsContext gc(context);
+ applyStrokeStyleToContext(&gc, style, object);
+
+ CGContextReplacePathWithStrokedPath(context);
+ if (CGContextIsPathEmpty(context)) {
+ // CGContextReplacePathWithStrokedPath seems to fail to create a path sometimes, this is not well understood.
+ // returning here prevents CG from logging to the console from CGContextGetPathBoundingBox
+ CGContextRestoreGState(context);
+ return FloatRect();
+ }
+
+ CGRect box = CGContextGetPathBoundingBox(context);
+ CGContextRestoreGState(context);
+
+ return FloatRect(box);
+}
+
+}
+
+#endif // ENABLE(SVG)
+
diff --git a/WebCore/svg/graphics/cg/CgSupport.h b/WebCore/svg/graphics/cg/CgSupport.h
new file mode 100644
index 0000000..de6e4b3
--- /dev/null
+++ b/WebCore/svg/graphics/cg/CgSupport.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CgSupport_h
+#define CgSupport_h
+
+#if ENABLE(SVG)
+
+#include <ApplicationServices/ApplicationServices.h>
+#include "GraphicsTypes.h"
+
+namespace WebCore {
+
+typedef struct CGPath *CGMutablePathRef;
+
+class Path;
+class FloatRect;
+class RenderStyle;
+class RenderObject;
+class GraphicsContext;
+
+CGContextRef scratchContext();
+FloatRect strokeBoundingBox(const Path& path, RenderStyle*, const RenderObject*);
+
+}
+
+#endif // ENABLE(SVG)
+#endif // !CgSupport_h
diff --git a/WebCore/svg/graphics/cg/RenderPathCg.cpp b/WebCore/svg/graphics/cg/RenderPathCg.cpp
new file mode 100644
index 0000000..eb8e482
--- /dev/null
+++ b/WebCore/svg/graphics/cg/RenderPathCg.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
+ * (C) 2006 Alexander Kellett <lypanov@kde.org>
+ * 2006 Rob Buis <buis@kde.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "RenderPath.h"
+
+#include <ApplicationServices/ApplicationServices.h>
+#include "CgSupport.h"
+#include "GraphicsContext.h"
+#include "SVGPaintServer.h"
+#include "SVGRenderStyle.h"
+#include "SVGStyledElement.h"
+#include <wtf/Assertions.h>
+
+namespace WebCore {
+
+FloatRect RenderPath::strokeBBox() const
+{
+ if (style()->svgStyle()->hasStroke())
+ return strokeBoundingBox(path(), style(), this);
+
+ return path().boundingRect();
+}
+
+
+bool RenderPath::strokeContains(const FloatPoint& point, bool requiresStroke) const
+{
+ if (path().isEmpty())
+ return false;
+
+ if (requiresStroke && !SVGPaintServer::strokePaintServer(style(), this))
+ return false;
+
+ CGMutablePathRef cgPath = path().platformPath();
+
+ CGContextRef context = scratchContext();
+ CGContextSaveGState(context);
+
+ CGContextBeginPath(context);
+ CGContextAddPath(context, cgPath);
+
+ GraphicsContext gc(context);
+ applyStrokeStyleToContext(&gc, style(), this);
+
+ bool hitSuccess = CGContextPathContainsPoint(context, point, kCGPathStroke);
+ CGContextRestoreGState(context);
+
+ return hitSuccess;
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/svg/graphics/cg/SVGPaintServerCg.cpp b/WebCore/svg/graphics/cg/SVGPaintServerCg.cpp
new file mode 100644
index 0000000..35eb239
--- /dev/null
+++ b/WebCore/svg/graphics/cg/SVGPaintServerCg.cpp
@@ -0,0 +1,89 @@
+/*
+ Copyright (C) 2006 Nikolas Zimmermann <wildfox@kde.org>
+
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ aint with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "SVGPaintServer.h"
+
+#include "GraphicsContext.h"
+#include "RenderObject.h"
+
+namespace WebCore {
+
+void SVGPaintServer::draw(GraphicsContext*& context, const RenderObject* path, SVGPaintTargetType type) const
+{
+ if (!setup(context, path, type))
+ return;
+
+ renderPath(context, path, type);
+ teardown(context, path, type);
+}
+
+void SVGPaintServer::teardown(GraphicsContext*&, const RenderObject*, SVGPaintTargetType, bool isPaintingText) const
+{
+ // no-op
+}
+
+void SVGPaintServer::renderPath(GraphicsContext*& context, const RenderObject* path, SVGPaintTargetType type) const
+{
+ RenderStyle* style = path ? path->style() : 0;
+ CGContextRef contextRef = context->platformContext();
+
+ if ((type & ApplyToFillTargetType) && (!style || style->svgStyle()->hasFill()))
+ fillPath(contextRef, path);
+
+ if ((type & ApplyToStrokeTargetType) && (!style || style->svgStyle()->hasStroke()))
+ strokePath(contextRef, path);
+}
+
+void SVGPaintServer::strokePath(CGContextRef context, const RenderObject*) const
+{
+ CGContextStrokePath(context);
+}
+
+void SVGPaintServer::clipToStrokePath(CGContextRef context, const RenderObject*) const
+{
+ CGContextReplacePathWithStrokedPath(context);
+ CGContextClip(context);
+}
+
+void SVGPaintServer::fillPath(CGContextRef context, const RenderObject* path) const
+{
+ if (!path || path->style()->svgStyle()->fillRule() == RULE_EVENODD)
+ CGContextEOFillPath(context);
+ else
+ CGContextFillPath(context);
+}
+
+void SVGPaintServer::clipToFillPath(CGContextRef context, const RenderObject* path) const
+{
+ if (!path || path->style()->svgStyle()->fillRule() == RULE_EVENODD)
+ CGContextEOClip(context);
+ else
+ CGContextClip(context);
+}
+
+} // namespace WebCore
+
+#endif
+
+// vim:ts=4:noet
diff --git a/WebCore/svg/graphics/cg/SVGPaintServerGradientCg.cpp b/WebCore/svg/graphics/cg/SVGPaintServerGradientCg.cpp
new file mode 100644
index 0000000..bfa5017
--- /dev/null
+++ b/WebCore/svg/graphics/cg/SVGPaintServerGradientCg.cpp
@@ -0,0 +1,336 @@
+/*
+ Copyright (C) 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
+
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ aint with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "SVGPaintServerGradient.h"
+
+#include "FloatConversion.h"
+#include "GraphicsContext.h"
+#include "ImageBuffer.h"
+#include "RenderObject.h"
+#include "SVGGradientElement.h"
+#include "SVGPaintServerLinearGradient.h"
+#include "SVGPaintServerRadialGradient.h"
+#include "SVGRenderSupport.h"
+
+#include <wtf/MathExtras.h>
+
+using namespace std;
+
+namespace WebCore {
+
+static void releaseCachedStops(void* info)
+{
+ static_cast<SVGPaintServerGradient::SharedStopCache*>(info)->deref();
+}
+
+static void cgGradientCallback(void* info, const CGFloat* inValues, CGFloat* outColor)
+{
+ SVGPaintServerGradient::SharedStopCache* stopsCache = static_cast<SVGPaintServerGradient::SharedStopCache*>(info);
+
+ SVGPaintServerGradient::QuartzGradientStop* stops = stopsCache->m_stops.data();
+
+ int stopsCount = stopsCache->m_stops.size();
+
+ CGFloat inValue = inValues[0];
+
+ if (!stopsCount) {
+ outColor[0] = 0;
+ outColor[1] = 0;
+ outColor[2] = 0;
+ outColor[3] = 0;
+ return;
+ } else if (stopsCount == 1) {
+ memcpy(outColor, stops[0].colorArray, 4 * sizeof(CGFloat));
+ return;
+ }
+
+ if (!(inValue > stops[0].offset))
+ memcpy(outColor, stops[0].colorArray, 4 * sizeof(CGFloat));
+ else if (!(inValue < stops[stopsCount - 1].offset))
+ memcpy(outColor, stops[stopsCount - 1].colorArray, 4 * sizeof(CGFloat));
+ else {
+ int nextStopIndex = 0;
+ while ((nextStopIndex < stopsCount) && (stops[nextStopIndex].offset < inValue))
+ nextStopIndex++;
+
+ CGFloat* nextColorArray = stops[nextStopIndex].colorArray;
+ CGFloat* previousColorArray = stops[nextStopIndex - 1].colorArray;
+ CGFloat diffFromPrevious = inValue - stops[nextStopIndex - 1].offset;
+ CGFloat percent = diffFromPrevious * stops[nextStopIndex].previousDeltaInverse;
+
+ outColor[0] = ((1.0f - percent) * previousColorArray[0] + percent * nextColorArray[0]);
+ outColor[1] = ((1.0f - percent) * previousColorArray[1] + percent * nextColorArray[1]);
+ outColor[2] = ((1.0f - percent) * previousColorArray[2] + percent * nextColorArray[2]);
+ outColor[3] = ((1.0f - percent) * previousColorArray[3] + percent * nextColorArray[3]);
+ }
+ // FIXME: have to handle the spreadMethod()s here SPREADMETHOD_REPEAT, etc.
+}
+
+static CGShadingRef CGShadingRefForLinearGradient(const SVGPaintServerLinearGradient* server)
+{
+ CGPoint start = CGPoint(server->gradientStart());
+ CGPoint end = CGPoint(server->gradientEnd());
+
+ CGFunctionCallbacks callbacks = {0, cgGradientCallback, releaseCachedStops};
+ CGFloat domainLimits[2] = {0, 1};
+ CGFloat rangeLimits[8] = {0, 1, 0, 1, 0, 1, 0, 1};
+ server->m_stopsCache->ref();
+ CGFunctionRef shadingFunction = CGFunctionCreate(server->m_stopsCache.get(), 1, domainLimits, 4, rangeLimits, &callbacks);
+
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ CGShadingRef shading = CGShadingCreateAxial(colorSpace, start, end, shadingFunction, true, true);
+ CGColorSpaceRelease(colorSpace);
+ CGFunctionRelease(shadingFunction);
+ return shading;
+}
+
+static CGShadingRef CGShadingRefForRadialGradient(const SVGPaintServerRadialGradient* server)
+{
+ CGPoint center = CGPoint(server->gradientCenter());
+ CGPoint focus = CGPoint(server->gradientFocal());
+ double radius = server->gradientRadius();
+
+ double fdx = focus.x - center.x;
+ double fdy = focus.y - center.y;
+
+ // Spec: If (fx, fy) lies outside the circle defined by (cx, cy) and r, set (fx, fy)
+ // to the point of intersection of the line through (fx, fy) and the circle.
+ if (sqrt(fdx * fdx + fdy * fdy) > radius) {
+ double angle = atan2(focus.y * 100.0, focus.x * 100.0);
+ focus.x = narrowPrecisionToCGFloat(cos(angle) * radius);
+ focus.y = narrowPrecisionToCGFloat(sin(angle) * radius);
+ }
+
+ CGFunctionCallbacks callbacks = {0, cgGradientCallback, releaseCachedStops};
+ CGFloat domainLimits[2] = {0, 1};
+ CGFloat rangeLimits[8] = {0, 1, 0, 1, 0, 1, 0, 1};
+ server->m_stopsCache->ref();
+ CGFunctionRef shadingFunction = CGFunctionCreate(server->m_stopsCache.get(), 1, domainLimits, 4, rangeLimits, &callbacks);
+
+ CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+ CGShadingRef shading = CGShadingCreateRadial(colorSpace, focus, 0, center, narrowPrecisionToCGFloat(radius), shadingFunction, true, true);
+ CGColorSpaceRelease(colorSpace);
+ CGFunctionRelease(shadingFunction);
+ return shading;
+}
+
+void SVGPaintServerGradient::updateQuartzGradientStopsCache(const Vector<SVGGradientStop>& stops)
+{
+ m_stopsCache = SharedStopCache::create();
+ Vector<QuartzGradientStop>& stopsCache = m_stopsCache->m_stops;
+ stopsCache.resize(stops.size());
+ CGFloat previousOffset = 0.0f;
+ for (unsigned i = 0; i < stops.size(); ++i) {
+ CGFloat currOffset = min(max(stops[i].first, previousOffset), static_cast<CGFloat>(1.0));
+ stopsCache[i].offset = currOffset;
+ stopsCache[i].previousDeltaInverse = 1.0f / (currOffset - previousOffset);
+ previousOffset = currOffset;
+ CGFloat* ca = stopsCache[i].colorArray;
+ stops[i].second.getRGBA(ca[0], ca[1], ca[2], ca[3]);
+ }
+}
+
+void SVGPaintServerGradient::updateQuartzGradientCache(const SVGPaintServerGradient* server)
+{
+ // cache our own copy of the stops for faster access.
+ // this is legacy code, probably could be reworked.
+ if (!m_stopsCache)
+ updateQuartzGradientStopsCache(gradientStops());
+
+ CGShadingRelease(m_shadingCache);
+
+ if (type() == RadialGradientPaintServer) {
+ const SVGPaintServerRadialGradient* radial = static_cast<const SVGPaintServerRadialGradient*>(server);
+ m_shadingCache = CGShadingRefForRadialGradient(radial);
+ } else if (type() == LinearGradientPaintServer) {
+ const SVGPaintServerLinearGradient* linear = static_cast<const SVGPaintServerLinearGradient*>(server);
+ m_shadingCache = CGShadingRefForLinearGradient(linear);
+ }
+}
+
+// Helper function for text painting
+static inline const RenderObject* findTextRootObject(const RenderObject* start)
+{
+ while (start && !start->isSVGText())
+ start = start->parent();
+
+ ASSERT(start);
+ ASSERT(start->isSVGText());
+
+ return start;
+}
+
+void SVGPaintServerGradient::teardown(GraphicsContext*& context, const RenderObject* object, SVGPaintTargetType type, bool isPaintingText) const
+{
+ CGShadingRef shading = m_shadingCache;
+ CGContextRef contextRef = context->platformContext();
+ ASSERT(contextRef);
+
+ // As renderPath() is not used when painting text, special logic needed here.
+ if (isPaintingText) {
+ if (m_savedContext) {
+ FloatRect maskBBox = const_cast<RenderObject*>(findTextRootObject(object))->relativeBBox(false);
+
+ // Fixup transformations to be able to clip to mask
+ AffineTransform transform = object->absoluteTransform();
+ FloatRect textBoundary = transform.mapRect(maskBBox);
+
+ IntSize maskSize(lroundf(textBoundary.width()), lroundf(textBoundary.height()));
+ clampImageBufferSizeToViewport(object->document()->renderer(), maskSize);
+
+ if (maskSize.width() < static_cast<int>(textBoundary.width()))
+ textBoundary.setWidth(maskSize.width());
+
+ if (maskSize.height() < static_cast<int>(textBoundary.height()))
+ textBoundary.setHeight(maskSize.height());
+
+ // Clip current context to mask image (gradient)
+ m_savedContext->concatCTM(transform.inverse());
+ m_savedContext->clipToImageBuffer(textBoundary, m_imageBuffer);
+ m_savedContext->concatCTM(transform);
+
+ handleBoundingBoxModeAndGradientTransformation(m_savedContext, maskBBox);
+
+ // Restore on-screen drawing context, after we got the image of the gradient
+ delete m_imageBuffer;
+
+ context = m_savedContext;
+ contextRef = context->platformContext();
+
+ m_savedContext = 0;
+ m_imageBuffer = 0;
+ }
+ }
+
+ CGContextDrawShading(contextRef, shading);
+ context->restore();
+}
+
+void SVGPaintServerGradient::renderPath(GraphicsContext*& context, const RenderObject* path, SVGPaintTargetType type) const
+{
+ RenderStyle* style = path->style();
+ CGContextRef contextRef = context->platformContext();
+ ASSERT(contextRef);
+
+ bool isFilled = (type & ApplyToFillTargetType) && style->svgStyle()->hasFill();
+
+ // Compute destination object bounding box
+ FloatRect objectBBox;
+ if (boundingBoxMode()) {
+ FloatRect bbox = path->relativeBBox(false);
+ if (bbox.width() > 0 && bbox.height() > 0)
+ objectBBox = bbox;
+ }
+
+ if (isFilled)
+ clipToFillPath(contextRef, path);
+ else
+ clipToStrokePath(contextRef, path);
+
+ handleBoundingBoxModeAndGradientTransformation(context, objectBBox);
+}
+
+void SVGPaintServerGradient::handleBoundingBoxModeAndGradientTransformation(GraphicsContext* context, const FloatRect& targetRect) const
+{
+ if (boundingBoxMode()) {
+ // Choose default gradient bounding box
+ FloatRect gradientBBox(0.0f, 0.0f, 1.0f, 1.0f);
+
+ // Generate a transform to map between both bounding boxes
+ context->concatCTM(makeMapBetweenRects(gradientBBox, targetRect));
+ }
+
+ // Apply the gradient's own transform
+ context->concatCTM(gradientTransform());
+}
+
+bool SVGPaintServerGradient::setup(GraphicsContext*& context, const RenderObject* object, SVGPaintTargetType type, bool isPaintingText) const
+{
+ m_ownerElement->buildGradient();
+
+ // We need a hook to call this when the gradient gets updated, before drawn.
+ if (!m_shadingCache)
+ const_cast<SVGPaintServerGradient*>(this)->updateQuartzGradientCache(this);
+
+ CGContextRef contextRef = context->platformContext();
+ ASSERT(contextRef);
+
+ RenderStyle* style = object->style();
+
+ bool isFilled = (type & ApplyToFillTargetType) && style->svgStyle()->hasFill();
+ bool isStroked = (type & ApplyToStrokeTargetType) && style->svgStyle()->hasStroke();
+
+ ASSERT(isFilled && !isStroked || !isFilled && isStroked);
+
+ context->save();
+ CGContextSetAlpha(contextRef, isFilled ? style->svgStyle()->fillOpacity() : style->svgStyle()->strokeOpacity());
+
+ if (isPaintingText) {
+ FloatRect maskBBox = const_cast<RenderObject*>(findTextRootObject(object))->relativeBBox(false);
+ IntRect maskRect = enclosingIntRect(object->absoluteTransform().mapRect(maskBBox));
+
+ IntSize maskSize(maskRect.width(), maskRect.height());
+ clampImageBufferSizeToViewport(object->document()->renderer(), maskSize);
+
+ auto_ptr<ImageBuffer> maskImage = ImageBuffer::create(maskSize, false);
+
+ if (!maskImage.get()) {
+ context->restore();
+ return false;
+ }
+
+ GraphicsContext* maskImageContext = maskImage->context();
+ maskImageContext->save();
+
+ maskImageContext->setTextDrawingMode(isFilled ? cTextFill : cTextStroke);
+ maskImageContext->translate(-maskRect.x(), -maskRect.y());
+ maskImageContext->concatCTM(object->absoluteTransform());
+
+ m_imageBuffer = maskImage.release();
+ m_savedContext = context;
+
+ context = maskImageContext;
+ contextRef = context->platformContext();
+ }
+
+ if (isStroked)
+ applyStrokeStyleToContext(context, style, object);
+
+ return true;
+}
+
+void SVGPaintServerGradient::invalidate()
+{
+ SVGPaintServer::invalidate();
+
+ // Invalidate caches
+ CGShadingRelease(m_shadingCache);
+
+ m_stopsCache = 0;
+ m_shadingCache = 0;
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/svg/graphics/cg/SVGPaintServerPatternCg.cpp b/WebCore/svg/graphics/cg/SVGPaintServerPatternCg.cpp
new file mode 100644
index 0000000..416d5fe
--- /dev/null
+++ b/WebCore/svg/graphics/cg/SVGPaintServerPatternCg.cpp
@@ -0,0 +1,130 @@
+/*
+ Copyright (C) 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ aint with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "SVGPaintServerPattern.h"
+
+#include "CgSupport.h"
+#include "GraphicsContext.h"
+#include "ImageBuffer.h"
+#include "RenderObject.h"
+#include "SVGPatternElement.h"
+
+namespace WebCore {
+
+static void patternCallback(void* info, CGContextRef context)
+{
+ ImageBuffer* patternImage = reinterpret_cast<ImageBuffer*>(info);
+ CGContextSaveGState(context);
+ CGContextTranslateCTM(context, 0, patternImage->size().height());
+ CGContextScaleCTM(context, 1.0f, -1.0f);
+ CGContextDrawImage(context, CGRect(FloatRect(FloatPoint(), patternImage->size())), patternImage->image()->getCGImageRef());
+ CGContextRestoreGState(context);
+}
+
+bool SVGPaintServerPattern::setup(GraphicsContext*& context, const RenderObject* object, SVGPaintTargetType type, bool isPaintingText) const
+{
+ CGContextRef contextRef = context->platformContext();
+
+ // Build pattern tile, passing destination object bounding box
+ FloatRect targetRect;
+ if (isPaintingText) {
+ IntRect textBoundary = const_cast<RenderObject*>(object)->absoluteBoundingBoxRect();
+ targetRect = object->absoluteTransform().inverse().mapRect(textBoundary);
+ } else
+ targetRect = object->relativeBBox(false);
+
+ m_ownerElement->buildPattern(targetRect);
+
+ if (!tile())
+ return false;
+
+ context->save();
+
+ // Respect local pattern transformation
+ context->concatCTM(patternTransform());
+
+ // Apply pattern space transformation
+ context->translate(patternBoundaries().x(), patternBoundaries().y());
+
+ // Crude hack to support overflow="visible".
+ // When the patternBoundaries() size is smaller than the actual tile() size, we run into a problem:
+ // Our tile contains content which is larger than the pattern cell size. We just draw the pattern
+ // "out of" cell boundaries, to draw the overflown content, instead of clipping it away. The uppermost
+ // cell doesn't include the overflown content of the cell right above it though -> that's why we're moving
+ // down the phase by a very small amount, so we're sure the "cell right above"'s overflown content gets drawn.
+ CGContextSetPatternPhase(contextRef, CGSizeMake(0.0f, -0.01f));
+
+ RenderStyle* style = object->style();
+ CGContextSetAlpha(contextRef, style->opacity());
+
+ CGPatternCallbacks callbacks = {0, patternCallback, 0};
+
+ ASSERT(!m_pattern);
+ m_pattern = CGPatternCreate(tile(),
+ CGRect(FloatRect(FloatPoint(), tile()->size())),
+ CGContextGetCTM(contextRef),
+ patternBoundaries().width(),
+ patternBoundaries().height(),
+ kCGPatternTilingConstantSpacing,
+ true, // has color
+ &callbacks);
+
+ if (!m_patternSpace)
+ m_patternSpace = CGColorSpaceCreatePattern(0);
+
+ if ((type & ApplyToFillTargetType) && style->svgStyle()->hasFill()) {
+ CGFloat alpha = style->svgStyle()->fillOpacity();
+ CGContextSetFillColorSpace(contextRef, m_patternSpace);
+ CGContextSetFillPattern(contextRef, m_pattern, &alpha);
+
+ if (isPaintingText)
+ context->setTextDrawingMode(cTextFill);
+ }
+
+ if ((type & ApplyToStrokeTargetType) && style->svgStyle()->hasStroke()) {
+ CGFloat alpha = style->svgStyle()->strokeOpacity();
+ CGContextSetStrokeColorSpace(contextRef, m_patternSpace);
+ CGContextSetStrokePattern(contextRef, m_pattern, &alpha);
+ applyStrokeStyleToContext(context, style, object);
+
+ if (isPaintingText)
+ context->setTextDrawingMode(cTextStroke);
+ }
+
+ return true;
+}
+
+void SVGPaintServerPattern::teardown(GraphicsContext*& context, const RenderObject*, SVGPaintTargetType, bool) const
+{
+ CGPatternRelease(m_pattern);
+ m_pattern = 0;
+
+ context->restore();
+}
+
+} // namespace WebCore
+
+#endif
+
+// vim:ts=4:noet
diff --git a/WebCore/svg/graphics/cg/SVGPaintServerSolidCg.cpp b/WebCore/svg/graphics/cg/SVGPaintServerSolidCg.cpp
new file mode 100644
index 0000000..bd2a56f
--- /dev/null
+++ b/WebCore/svg/graphics/cg/SVGPaintServerSolidCg.cpp
@@ -0,0 +1,77 @@
+/*
+ Copyright (C) 2006 Nikolas Zimmermann <wildfox@kde.org>
+
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ aint with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "SVGPaintServerSolid.h"
+
+#include "Color.h"
+#include "CgSupport.h"
+#include "GraphicsContext.h"
+#include "RenderObject.h"
+
+namespace WebCore {
+
+bool SVGPaintServerSolid::setup(GraphicsContext*& context, const RenderObject* object, SVGPaintTargetType type, bool isPaintingText) const
+{
+ // FIXME: This function does not use any CG-specific calls, however it's not yet
+ // cross platform, because CG handles fill rule different from other graphics
+ // platforms. CG makes you use two separate fill calls, other platforms set
+ // the fill rule state on the context and then call a generic "fillPath"
+
+ RenderStyle* style = object ? object->style() : 0;
+
+ if ((type & ApplyToFillTargetType) && (!style || style->svgStyle()->hasFill())) {
+ RGBA32 rgba = color().rgb();
+ ASSERT(!color().hasAlpha());
+ if (style)
+ rgba = colorWithOverrideAlpha(rgba, style->svgStyle()->fillOpacity());
+
+ context->setFillColor(rgba);
+
+ if (isPaintingText)
+ context->setTextDrawingMode(cTextFill);
+ }
+
+ if ((type & ApplyToStrokeTargetType) && (!style || style->svgStyle()->hasStroke())) {
+ RGBA32 rgba = color().rgb();
+ ASSERT(!color().hasAlpha());
+ if (style)
+ rgba = colorWithOverrideAlpha(rgba, style->svgStyle()->strokeOpacity());
+
+ context->setStrokeColor(rgba);
+
+ if (style)
+ applyStrokeStyleToContext(context, style, object);
+
+ if (isPaintingText)
+ context->setTextDrawingMode(cTextStroke);
+ }
+
+ return true;
+}
+
+} // namespace WebCore
+
+#endif
+
+// vim:ts=4:noet
diff --git a/WebCore/svg/graphics/cg/SVGResourceClipperCg.cpp b/WebCore/svg/graphics/cg/SVGResourceClipperCg.cpp
new file mode 100644
index 0000000..b04a0dc
--- /dev/null
+++ b/WebCore/svg/graphics/cg/SVGResourceClipperCg.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
+ * 2005 Alexander Kellett <lypanov@kde.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "SVGResourceClipper.h"
+
+#include "AffineTransform.h"
+#include "GraphicsContext.h"
+
+#include <ApplicationServices/ApplicationServices.h>
+
+namespace WebCore {
+
+void SVGResourceClipper::applyClip(GraphicsContext* context, const FloatRect& boundingBox) const
+{
+ if (m_clipData.clipData().size() < 1)
+ return;
+
+ bool heterogenousClipRules = false;
+ WindRule clipRule = m_clipData.clipData()[0].windRule;
+
+ context->beginPath();
+
+ AffineTransform bboxTransform = makeMapBetweenRects(FloatRect(0.0f, 0.0f, 1.0f, 1.0f), boundingBox);
+
+ for (unsigned x = 0; x < m_clipData.clipData().size(); x++) {
+ ClipData data = m_clipData.clipData()[x];
+ if (data.windRule != clipRule)
+ heterogenousClipRules = true;
+
+ Path clipPath = data.path;
+
+ if (data.bboxUnits)
+ clipPath.transform(bboxTransform);
+
+ context->addPath(clipPath);
+ }
+
+ CGContextRef cgContext = context->platformContext();
+ if (m_clipData.clipData().size()) {
+ // FIXME!
+ // We don't currently allow for heterogenous clip rules.
+ // we would have to detect such, draw to a mask, and then clip
+ // to that mask
+ if (!CGContextIsPathEmpty(cgContext)) {
+ if (clipRule == RULE_EVENODD)
+ CGContextEOClip(cgContext);
+ else
+ CGContextClip(cgContext);
+ }
+ }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/svg/graphics/cg/SVGResourceFilterCg.cpp b/WebCore/svg/graphics/cg/SVGResourceFilterCg.cpp
new file mode 100644
index 0000000..ecfcdd8
--- /dev/null
+++ b/WebCore/svg/graphics/cg/SVGResourceFilterCg.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Dave MacLachlan (dmaclach@mac.com)
+ * 2006 Rob Buis <buis@kde.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+#if ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#include "NotImplemented.h"
+#include "SVGResourceFilter.h"
+
+namespace WebCore {
+
+SVGResourceFilterPlatformData* SVGResourceFilter::createPlatformData()
+{
+ return 0;
+}
+
+void SVGResourceFilter::prepareFilter(GraphicsContext*&, const FloatRect&)
+{
+ notImplemented();
+}
+
+void SVGResourceFilter::applyFilter(GraphicsContext*&, const FloatRect&)
+{
+ notImplemented();
+}
+
+}
+
+#endif // ENABLE(SVG) && ENABLE(SVG_FILTERS)
diff --git a/WebCore/svg/graphics/cg/SVGResourceFilterCg.mm b/WebCore/svg/graphics/cg/SVGResourceFilterCg.mm
new file mode 100644
index 0000000..f3dc819
--- /dev/null
+++ b/WebCore/svg/graphics/cg/SVGResourceFilterCg.mm
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2005 Apple Computer, Inc. All rights reserved.
+ * (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG) && ENABLE(SVG_FILTERS)
+#include "SVGResourceFilter.h"
+
+#include "AffineTransform.h"
+#include "FoundationExtras.h"
+#include "GraphicsContext.h"
+
+#include "SVGResourceFilterPlatformDataMac.h"
+
+#include <QuartzCore/CoreImage.h>
+
+// Setting to a value > 0 allows to dump the output image as JPEG.
+#define DEBUG_OUTPUT_IMAGE 0
+
+namespace WebCore {
+
+SVGResourceFilterPlatformData* SVGResourceFilter::createPlatformData()
+{
+ return new SVGResourceFilterPlatformDataMac(this);
+}
+
+void SVGResourceFilter::prepareFilter(GraphicsContext*& context, const FloatRect& bbox)
+{
+ if (bbox.isEmpty() || m_effects.isEmpty())
+ return;
+
+ SVGResourceFilterPlatformDataMac* platform = static_cast<SVGResourceFilterPlatformDataMac*>(platformData());
+
+ CGContextRef cgContext = context->platformContext();
+
+ // Use of CGBegin/EndTransparencyLayer around this call causes over release
+ // of cgContext due to it being created on an autorelease pool, and released
+ // after CGEndTransparencyLayer. Create local pool to fix.
+ // <http://bugs.webkit.org/show_bug.cgi?id=8425>
+ // <http://bugs.webkit.org/show_bug.cgi?id=6947>
+ // <rdar://problem/4647735>
+ NSAutoreleasePool* filterContextPool = [[NSAutoreleasePool alloc] init];
+ platform->m_filterCIContext = HardRetain([CIContext contextWithCGContext:cgContext options:nil]);
+ [filterContextPool drain];
+
+ FloatRect filterRect = filterBBoxForItemBBox(bbox);
+
+ // TODO: Ensure the size is not greater than the nearest <svg> size and/or the window size.
+ // This is also needed for masking & gradients-on-stroke-of-text. File a bug on this.
+ float width = filterRect.width();
+ float height = filterRect.height();
+
+ platform->m_filterCGLayer = [platform->m_filterCIContext createCGLayerWithSize:CGSizeMake(width, height) info:NULL];
+
+ context = new GraphicsContext(CGLayerGetContext(platform->m_filterCGLayer));
+ context->save();
+
+ context->translate(-filterRect.x(), -filterRect.y());
+}
+
+#ifndef NDEBUG
+// Extremly helpful debugging utilities for any paint server / resource that creates
+// internal image buffers (ie. gradients on text, masks, filters...)
+void dumpCIOutputImage(CIImage* outputImage, NSString* fileName)
+{
+ CGSize extentSize = [outputImage extent].size;
+ NSImage* image = [[[NSImage alloc] initWithSize:NSMakeSize(extentSize.width, extentSize.height)] autorelease];
+ [image addRepresentation:[NSCIImageRep imageRepWithCIImage:outputImage]];
+
+ NSData* imageData = [image TIFFRepresentation];
+ NSBitmapImageRep* imageRep = [NSBitmapImageRep imageRepWithData:imageData];
+ imageData = [imageRep representationUsingType:NSJPEGFileType properties:nil];
+
+ [imageData writeToFile:fileName atomically:YES];
+}
+
+void dumpCGOutputImage(CGImage* outputImage, NSString* fileName)
+{
+ if (CIImage* ciOutputImage = [CIImage imageWithCGImage:outputImage])
+ dumpCIOutputImage(ciOutputImage, fileName);
+}
+#endif
+
+void SVGResourceFilter::applyFilter(GraphicsContext*& context, const FloatRect& bbox)
+{
+ if (bbox.isEmpty() || m_effects.isEmpty())
+ return;
+
+ SVGResourceFilterPlatformDataMac* platform = static_cast<SVGResourceFilterPlatformDataMac*>(platformData());
+
+ // actually apply the filter effects
+ CIImage* inputImage = [CIImage imageWithCGLayer:platform->m_filterCGLayer];
+ NSArray* filterStack = platform->getCIFilterStack(inputImage, bbox);
+ if ([filterStack count]) {
+ CIImage* outputImage = [[filterStack lastObject] valueForKey:@"outputImage"];
+
+ if (outputImage) {
+#if DEBUG_OUTPUT_IMAGE > 0
+ dumpOutputImage(outputImage);
+#endif
+
+ FloatRect filterRect = filterBBoxForItemBBox(bbox);
+ FloatPoint destOrigin = filterRect.location();
+ filterRect.setLocation(FloatPoint(0.0f, 0.0f));
+
+ [platform->m_filterCIContext drawImage:outputImage atPoint:CGPoint(destOrigin) fromRect:filterRect];
+ }
+ }
+
+ CGLayerRelease(platform->m_filterCGLayer);
+ platform->m_filterCGLayer = 0;
+
+ HardRelease(platform->m_filterCIContext);
+ platform->m_filterCIContext = 0;
+
+ delete context;
+ context = 0;
+}
+
+}
+
+#endif // ENABLE(SVG) ENABLE(SVG_FILTERS)
diff --git a/WebCore/svg/graphics/cg/SVGResourceMaskerCg.cpp b/WebCore/svg/graphics/cg/SVGResourceMaskerCg.cpp
new file mode 100644
index 0000000..4d2100b
--- /dev/null
+++ b/WebCore/svg/graphics/cg/SVGResourceMaskerCg.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2007 Apple Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "SVGResourceMasker.h"
+#include "NotImplemented.h"
+
+namespace WebCore {
+
+void SVGResourceMasker::applyMask(GraphicsContext*, const FloatRect&)
+{
+ notImplemented();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
diff --git a/WebCore/svg/graphics/cg/SVGResourceMaskerCg.mm b/WebCore/svg/graphics/cg/SVGResourceMaskerCg.mm
new file mode 100644
index 0000000..f867f9c
--- /dev/null
+++ b/WebCore/svg/graphics/cg/SVGResourceMaskerCg.mm
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2005, 2006 Alexander Kellett <lypanov@kde.org>
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#import "SVGResourceMasker.h"
+
+#import "BlockExceptions.h"
+#import "CgSupport.h"
+#import "GraphicsContext.h"
+#import "ImageBuffer.h"
+#import "SVGMaskElement.h"
+#import "SVGRenderSupport.h"
+#import "SVGRenderStyle.h"
+#import "SVGResourceFilter.h"
+#import <QuartzCore/CIFilter.h>
+#import <QuartzCore/CoreImage.h>
+
+using namespace std;
+
+namespace WebCore {
+
+static CIImage* applyLuminanceToAlphaFilter(CIImage* inputImage)
+{
+ CIFilter* luminanceToAlpha = [CIFilter filterWithName:@"CIColorMatrix"];
+ [luminanceToAlpha setDefaults];
+ CGFloat alpha[4] = {0.2125f, 0.7154f, 0.0721f, 0.0f};
+ CGFloat zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ [luminanceToAlpha setValue:inputImage forKey:@"inputImage"];
+ [luminanceToAlpha setValue:[CIVector vectorWithValues:zero count:4] forKey:@"inputRVector"];
+ [luminanceToAlpha setValue:[CIVector vectorWithValues:zero count:4] forKey:@"inputGVector"];
+ [luminanceToAlpha setValue:[CIVector vectorWithValues:zero count:4] forKey:@"inputBVector"];
+ [luminanceToAlpha setValue:[CIVector vectorWithValues:alpha count:4] forKey:@"inputAVector"];
+ [luminanceToAlpha setValue:[CIVector vectorWithValues:zero count:4] forKey:@"inputBiasVector"];
+ return [luminanceToAlpha valueForKey:@"outputImage"];
+}
+
+static CIImage* applyExpandAlphatoGrayscaleFilter(CIImage* inputImage)
+{
+ CIFilter* alphaToGrayscale = [CIFilter filterWithName:@"CIColorMatrix"];
+ CGFloat zero[4] = {0, 0, 0, 0};
+ [alphaToGrayscale setDefaults];
+ [alphaToGrayscale setValue:inputImage forKey:@"inputImage"];
+ [alphaToGrayscale setValue:[CIVector vectorWithValues:zero count:4] forKey:@"inputRVector"];
+ [alphaToGrayscale setValue:[CIVector vectorWithValues:zero count:4] forKey:@"inputGVector"];
+ [alphaToGrayscale setValue:[CIVector vectorWithValues:zero count:4] forKey:@"inputBVector"];
+ [alphaToGrayscale setValue:[CIVector vectorWithX:0.0f Y:0.0f Z:0.0f W:1.0f] forKey:@"inputAVector"];
+ [alphaToGrayscale setValue:[CIVector vectorWithX:1.0f Y:1.0f Z:1.0f W:0.0f] forKey:@"inputBiasVector"];
+ return [alphaToGrayscale valueForKey:@"outputImage"];
+}
+
+static CIImage* transformImageIntoGrayscaleMask(CIImage* inputImage)
+{
+ CIFilter* blackBackground = [CIFilter filterWithName:@"CIConstantColorGenerator"];
+ [blackBackground setValue:[CIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:1.0f] forKey:@"inputColor"];
+
+ CIFilter* layerOverBlack = [CIFilter filterWithName:@"CISourceOverCompositing"];
+ [layerOverBlack setValue:[blackBackground valueForKey:@"outputImage"] forKey:@"inputBackgroundImage"];
+ [layerOverBlack setValue:inputImage forKey:@"inputImage"];
+
+ CIImage* luminanceAlpha = applyLuminanceToAlphaFilter([layerOverBlack valueForKey:@"outputImage"]);
+ CIImage* luminanceAsGrayscale = applyExpandAlphatoGrayscaleFilter(luminanceAlpha);
+ CIImage* alphaAsGrayscale = applyExpandAlphatoGrayscaleFilter(inputImage);
+
+ CIFilter* multipliedGrayscale = [CIFilter filterWithName:@"CIMultiplyCompositing"];
+ [multipliedGrayscale setValue:luminanceAsGrayscale forKey:@"inputBackgroundImage"];
+ [multipliedGrayscale setValue:alphaAsGrayscale forKey:@"inputImage"];
+ return [multipliedGrayscale valueForKey:@"outputImage"];
+}
+
+void SVGResourceMasker::applyMask(GraphicsContext* context, const FloatRect& boundingBox)
+{
+ if (!m_mask)
+ m_mask.set(m_ownerElement->drawMaskerContent(boundingBox, m_maskRect).release());
+
+ if (!m_mask)
+ return;
+
+ IntSize maskSize(static_cast<int>(m_maskRect.width()), static_cast<int>(m_maskRect.height()));
+ clampImageBufferSizeToViewport(m_ownerElement->document()->renderer(), maskSize);
+
+ // Create new graphics context in gray scale mode for image rendering
+ auto_ptr<ImageBuffer> grayScaleImage(ImageBuffer::create(maskSize, true));
+ if (!grayScaleImage.get())
+ return;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ CGContextRef grayScaleContext = grayScaleImage->context()->platformContext();
+ CIContext* ciGrayscaleContext = [CIContext contextWithCGContext:grayScaleContext options:nil];
+
+ // Transform colorized mask to gray scale
+ CIImage* colorMask = [CIImage imageWithCGImage:m_mask->image()->getCGImageRef()];
+ if (!colorMask)
+ return;
+
+ CIImage* grayScaleMask = transformImageIntoGrayscaleMask(colorMask);
+ [ciGrayscaleContext drawImage:grayScaleMask atPoint:CGPointZero fromRect:CGRectMake(0, 0, maskSize.width(), maskSize.height())];
+
+ CGContextClipToMask(context->platformContext(), m_maskRect, grayScaleImage->image()->getCGImageRef());
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)