diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:30:52 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:30:52 -0800 |
commit | 8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2 (patch) | |
tree | 11425ea0b299d6fb89c6d3618a22d97d5bf68d0f /WebCore/svg/graphics/cg | |
parent | 648161bb0edfc3d43db63caed5cc5213bc6cb78f (diff) | |
download | external_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.cpp | 100 | ||||
-rw-r--r-- | WebCore/svg/graphics/cg/CgSupport.h | 50 | ||||
-rw-r--r-- | WebCore/svg/graphics/cg/RenderPathCg.cpp | 79 | ||||
-rw-r--r-- | WebCore/svg/graphics/cg/SVGPaintServerCg.cpp | 89 | ||||
-rw-r--r-- | WebCore/svg/graphics/cg/SVGPaintServerGradientCg.cpp | 336 | ||||
-rw-r--r-- | WebCore/svg/graphics/cg/SVGPaintServerPatternCg.cpp | 130 | ||||
-rw-r--r-- | WebCore/svg/graphics/cg/SVGPaintServerSolidCg.cpp | 77 | ||||
-rw-r--r-- | WebCore/svg/graphics/cg/SVGResourceClipperCg.cpp | 82 | ||||
-rw-r--r-- | WebCore/svg/graphics/cg/SVGResourceFilterCg.cpp | 53 | ||||
-rw-r--r-- | WebCore/svg/graphics/cg/SVGResourceFilterCg.mm | 145 | ||||
-rw-r--r-- | WebCore/svg/graphics/cg/SVGResourceMaskerCg.cpp | 42 | ||||
-rw-r--r-- | WebCore/svg/graphics/cg/SVGResourceMaskerCg.mm | 129 |
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) |