2007-06-13 Alp Toker <alp.toker@collabora.co.uk>
[WebKit-https.git] / WebCore / platform / graphics / svg / cairo / SVGPaintServerGradientCairo.cpp
1 /*
2  * Copyright (C) 2007 Alp Toker <alp.toker@collabora.co.uk>
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
28 #if ENABLE(SVG)
29 #include "SVGPaintServerGradient.h"
30 #include "SVGPaintServerLinearGradient.h"
31 #include "SVGPaintServerRadialGradient.h"
32
33 #include "GraphicsContext.h"
34 #include "RenderObject.h"
35 #include "RenderPath.h"
36 #include "RenderStyle.h"
37 #include "SVGGradientElement.h"
38
39 namespace WebCore {
40
41 bool SVGPaintServerGradient::setup(GraphicsContext*& context, const RenderObject* object, SVGPaintTargetType type, bool isPaintingText) const
42 {
43     m_ownerElement->buildGradient();
44
45     cairo_t* cr = context->platformContext();
46     cairo_pattern_t* pattern;
47
48     cairo_matrix_t matrix;
49     cairo_matrix_init_identity (&matrix);
50     const cairo_matrix_t gradient_matrix = gradientTransform();
51
52     // TODO: revise this code, it is known not to work in many cases
53     if (this->type() == LinearGradientPaintServer) {
54         const SVGPaintServerLinearGradient* linear = static_cast<const SVGPaintServerLinearGradient*>(this);
55
56         if (boundingBoxMode()) {
57             // TODO: use RenderPathCairo's strokeBBox?
58             double x1, y1, x2, y2;
59             cairo_fill_extents(cr, &x1, &y1, &x2, &y2);
60             cairo_matrix_translate(&matrix, x1, y1);
61             cairo_matrix_scale(&matrix, x2 - x1, y2 - y1);
62             cairo_matrix_multiply(&matrix, &matrix, &gradient_matrix);
63             cairo_matrix_invert(&matrix);
64         }
65
66         double x0, x1, y0, y1;
67         x0 = linear->gradientStart().x();
68         y0 = linear->gradientStart().y();
69         x1 = linear->gradientEnd().x();
70         y1 = linear->gradientEnd().y();
71         pattern = cairo_pattern_create_linear(x0, y0, x1, y1);
72
73     } else if (this->type() == RadialGradientPaintServer) {
74         const SVGPaintServerRadialGradient* radial = static_cast<const SVGPaintServerRadialGradient*>(this);
75         // TODO: pattern = cairo_pattern_create_radial();
76         return false;
77     } else {
78         return false;
79     }
80
81     cairo_pattern_set_filter(pattern, CAIRO_FILTER_BILINEAR);
82
83     switch (spreadMethod()) {
84         case SPREADMETHOD_PAD:
85             cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
86             break;
87         case SPREADMETHOD_REFLECT:
88             cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REFLECT);
89             break;
90         case SPREADMETHOD_REPEAT:
91             cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
92             break;
93         default:
94             cairo_pattern_set_extend(pattern, CAIRO_EXTEND_NONE);
95             break;
96     }
97
98     cairo_pattern_set_matrix(pattern, &matrix);
99
100     const Vector<SVGGradientStop>& stops = gradientStops();
101
102     for (unsigned i = 0; i < stops.size(); ++i) {
103         float offset = stops[i].first;
104         Color color = stops[i].second;
105
106         cairo_pattern_add_color_stop_rgba(pattern, offset, color.red(), color.green(), color.blue(), color.alpha());
107     }
108
109     cairo_set_source(cr, pattern);
110     cairo_pattern_destroy(pattern);
111
112     return true;
113 }
114
115 } // namespace WebCore
116
117 #endif