5c7fc31d03c5d64fd3d4d10ab0c58e4c4f8296d7
[WebKit-https.git] / WebCore / svg / graphics / filters / cg / SVGFEHelpersCg.mm
1 /*
2     Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
3
4     This file is part of the KDE project
5
6     This library is free software; you can redistribute it and/or
7     modify it under the terms of the GNU Library General Public
8     License as published by the Free Software Foundation; either
9     version 2 of the License, or (at your option) any later version.
10
11     This library is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14     Library General Public License for more details.
15
16     You should have received a copy of the GNU Library General Public License
17     aint with this library; see the file COPYING.LIB.  If not, write to
18     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19     Boston, MA 02110-1301, USA.
20 */
21
22 #include "config.h"
23
24 #if ENABLE(SVG) && ENABLE(SVG_FILTERS)
25 #include "SVGFEHelpersCg.h"
26
27 #include "Color.h"
28 #include "SVGDistantLightSource.h"
29 #include "SVGLightSource.h"
30 #include "SVGPointLightSource.h"
31 #include "SVGSpotLightSource.h"
32
33 #import "WKDistantLightFilter.h"
34 #import "WKNormalMapFilter.h"
35 #import "WKPointLightFilter.h"
36 #import "WKSpotLightFilter.h"
37
38 #include <wtf/MathExtras.h>
39
40 namespace WebCore {
41
42 CIVector* getVectorForChannel(SVGChannelSelectorType channel)
43 {
44     switch (channel) {
45     case SVG_CHANNEL_UNKNOWN:
46         return nil;    
47     case SVG_CHANNEL_R:
48         return [CIVector vectorWithX:1.0f Y:0.0f Z:0.0f W:0.0f];
49     case SVG_CHANNEL_G:
50         return [CIVector vectorWithX:0.0f Y:1.0f Z:0.0f W:0.0f];
51     case SVG_CHANNEL_B:
52         return [CIVector vectorWithX:0.0f Y:0.0f Z:1.0f W:0.0f];
53     case SVG_CHANNEL_A:
54         return [CIVector vectorWithX:0.0f Y:0.0f Z:0.0f W:1.0f];
55     default:
56         return [CIVector vectorWithX:0.0f Y:0.0f Z:0.0f W:0.0f];
57     }
58 }
59
60 CIColor* ciColor(const Color& c)
61 {
62     CGColorRef colorCG = cgColor(c);
63     CIColor* colorCI = [CIColor colorWithCGColor:colorCG];
64     CGColorRelease(colorCG);
65     return colorCI;
66 }
67
68 // Lighting
69 CIFilter* getPointLightVectors(CIFilter* normals, CIVector* lightPosition, float surfaceScale)
70 {
71     CIFilter* filter;
72     BEGIN_BLOCK_OBJC_EXCEPTIONS;
73     filter = [CIFilter filterWithName:@"WKPointLight"];
74     if (!filter)
75         return nil;
76     [filter setDefaults];
77     [filter setValue:[normals valueForKey:@"outputImage"] forKey:@"inputNormalMap"];
78     [filter setValue:lightPosition forKey:@"inputLightPosition"];
79     [filter setValue:[NSNumber numberWithFloat:surfaceScale] forKey:@"inputSurfaceScale"];
80     return filter;
81     END_BLOCK_OBJC_EXCEPTIONS;
82     return nil;
83 }
84
85 CIFilter* getLightVectors(CIFilter* normals, const SVGLightSource* light, float surfaceScale)
86 {
87     [WKDistantLightFilter class];
88     [WKPointLightFilter class];
89     [WKSpotLightFilter class];
90
91     CIFilter* filter = nil;
92     BEGIN_BLOCK_OBJC_EXCEPTIONS;
93
94     switch (light->type()) {
95     case LS_DISTANT:
96     {
97         const SVGDistantLightSource* dlight = static_cast<const SVGDistantLightSource*>(light);
98
99         filter = [CIFilter filterWithName:@"WKDistantLight"];
100         if (!filter)
101             return nil;
102         [filter setDefaults];
103
104         float azimuth = dlight->azimuth();
105         float elevation = dlight->elevation();
106         azimuth = deg2rad(azimuth);
107         elevation = deg2rad(elevation);
108         float Lx = cosf(azimuth)*cosf(elevation);
109         float Ly = sinf(azimuth)*cosf(elevation);
110         float Lz = sinf(elevation);
111
112         [filter setValue:[normals valueForKey:@"outputImage"] forKey:@"inputNormalMap"];
113         [filter setValue:[CIVector vectorWithX:Lx Y:Ly Z:Lz] forKey:@"inputLightDirection"];
114         return filter;
115     }
116     case LS_POINT:
117     {
118         const SVGPointLightSource* plight = static_cast<const SVGPointLightSource*>(light);
119         return getPointLightVectors(normals, [CIVector vectorWithX:plight->position().x() Y:plight->position().y() Z:plight->position().z()], surfaceScale);
120     }
121     case LS_SPOT:
122     {
123         const SVGSpotLightSource* slight = static_cast<const SVGSpotLightSource*>(light);
124         filter = [CIFilter filterWithName:@"WKSpotLight"];
125         if (!filter)
126             return nil;
127
128         CIFilter* pointLightFilter = getPointLightVectors(normals, [CIVector vectorWithX:slight->position().x() Y:slight->position().y() Z:slight->position().z()], surfaceScale);
129         if (!pointLightFilter)
130             return nil;
131         [filter setDefaults];
132
133         [filter setValue:[pointLightFilter valueForKey:@"outputImage"] forKey:@"inputLightVectors"];
134         [filter setValue:[CIVector vectorWithX:slight->direction().x() Y:slight->direction().y() Z:slight->direction().z()] forKey:@"inputLightDirection"];
135         [filter setValue:[NSNumber numberWithFloat:slight->specularExponent()] forKey:@"inputSpecularExponent"];
136         [filter setValue:[NSNumber numberWithFloat:deg2rad(slight->limitingConeAngle())] forKey:@"inputLimitingConeAngle"];
137         return filter;
138     }
139     }
140
141     END_BLOCK_OBJC_EXCEPTIONS;
142     return nil;
143 }
144
145 CIFilter* getNormalMap(CIImage* bumpMap, float scale)
146 {
147     [WKNormalMapFilter class];
148     CIFilter* filter;
149     BEGIN_BLOCK_OBJC_EXCEPTIONS;
150     filter = [CIFilter filterWithName:@"WKNormalMap"];
151     [filter setDefaults];
152
153     [filter setValue:bumpMap forKey:@"inputImage"];
154     [filter setValue:[NSNumber numberWithFloat:scale] forKey:@"inputSurfaceScale"];
155     return filter;
156     END_BLOCK_OBJC_EXCEPTIONS;
157     return nil;
158 }
159
160 }
161
162 #endif // ENABLE(SVG) && ENABLE(SVG_FILTERS)