* platform/graphics/svg/mac/SVGResourceFilterPlatformDataMac.h:
[WebKit-https.git] / WebCore / platform / graphics / svg / mac / SVGResourceFilterPlatformDataMac.mm
1 /*
2  * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #if ENABLE(SVG) && ENABLE(SVG_EXPERIMENTAL_FEATURES)
28
29 #include "SVGResourceFilterPlatformDataMac.h"
30 #include <QuartzCore/CoreImage.h>
31
32 namespace WebCore {
33
34 static const char* const SVGPreviousFilterOutputName = "__previousOutput__";
35
36 SVGResourceFilterPlatformDataMac::SVGResourceFilterPlatformDataMac(SVGResourceFilter* filter)
37     : m_filterCIContext(0)
38     , m_filterCGLayer(0)
39     , m_imagesByName(AdoptNS, [[NSMutableDictionary alloc] init])
40     , m_filter(filter)
41 {
42 }
43
44 SVGResourceFilterPlatformDataMac::~SVGResourceFilterPlatformDataMac()
45 {
46     ASSERT(!m_filterCGLayer);
47     ASSERT(!m_filterCIContext);
48 }
49
50     
51 NSArray* SVGResourceFilterPlatformDataMac::getCIFilterStack(CIImage* inputImage, const FloatRect& bbox)
52 {
53     NSMutableArray* filterEffects = [NSMutableArray array];
54     
55     setImageForName(inputImage, "SourceGraphic"); // input
56     
57     for (unsigned int i = 0; i < m_filter->effects().size(); i++) {
58         CIFilter* filter = m_filter->effects()[i]->getCIFilter(bbox);
59         if (filter)
60             [filterEffects addObject:filter];
61     }
62     
63     [m_imagesByName.get() removeAllObjects]; // clean up before next time.
64     
65     return filterEffects;
66 }
67     
68 static inline CIImage* alphaImageForImage(CIImage* image)
69 {
70     CIFilter* onlyAlpha = [CIFilter filterWithName:@"CIColorMatrix"];
71     CGFloat zero[4] = {0, 0, 0, 0};
72     [onlyAlpha setDefaults];
73     [onlyAlpha setValue:image forKey:@"inputImage"];
74     [onlyAlpha setValue:[CIVector vectorWithValues:zero count:4] forKey:@"inputRVector"];
75     [onlyAlpha setValue:[CIVector vectorWithValues:zero count:4] forKey:@"inputGVector"];
76     [onlyAlpha setValue:[CIVector vectorWithValues:zero count:4] forKey:@"inputBVector"];
77     return [onlyAlpha valueForKey:@"outputImage"];
78 }
79
80 CIImage* SVGResourceFilterPlatformDataMac::imageForName(const String& name) const
81 {
82     return [m_imagesByName.get() objectForKey:name];
83 }
84
85 void SVGResourceFilterPlatformDataMac::setImageForName(CIImage* image, const String& name)
86 {
87     [m_imagesByName.get() setValue:image forKey:name];
88 }
89
90 void SVGResourceFilterPlatformDataMac::setOutputImage(const SVGFilterEffect* filterEffect, CIImage* output)
91 {
92     if (!filterEffect->result().isEmpty())
93         setImageForName(output, filterEffect->result());
94     
95     setImageForName(output, SVGPreviousFilterOutputName);
96 }
97
98 CIImage* SVGResourceFilterPlatformDataMac::inputImage(const SVGFilterEffect* filterEffect)
99 {
100     if (filterEffect->in().isEmpty()) {
101         CIImage* inImage = imageForName(SVGPreviousFilterOutputName);
102         
103         if (!inImage)
104             inImage = imageForName("SourceGraphic");
105         
106         return inImage;
107     } else if (filterEffect->in() == "SourceAlpha") {
108         CIImage* sourceAlpha = imageForName(filterEffect->in());
109         
110         if (!sourceAlpha) {
111             CIImage* sourceGraphic = imageForName("SourceGraphic");
112             
113             if (!sourceGraphic)
114                 return nil;
115             
116             sourceAlpha = alphaImageForImage(sourceGraphic);
117             setImageForName(sourceAlpha, "SourceAlpha");
118         }
119         
120         return sourceAlpha;
121     }
122     
123     return imageForName(filterEffect->in());
124 }
125     
126
127 }
128
129 #endif // #if ENABLE(SVG) && ENABLE(SVG_EXPERIMENTAL_FEATURES)