1 /*
2 * Copyright (C) 2007, 2008 Rob Buis <buis@kde.org>
3 * (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
4 * (C) 2007 Eric Seidel <eric@webkit.org>
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 * along 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
23 #include "config.h"
24
25 #if ENABLE(SVG)
26 #include "SVGRenderSupport.h"
27
28 #include "TransformationMatrix.h"
29 #include "ImageBuffer.h"
30 #include "RenderObject.h"
31 #include "RenderSVGContainer.h"
32 #include "RenderView.h"
33 #include "SVGResourceClipper.h"
34 #include "SVGResourceFilter.h"
35 #include "SVGResourceMasker.h"
36 #include "SVGStyledElement.h"
37 #include "SVGURIReference.h"
38 #include <wtf/UnusedParam.h>
39
40 namespace WebCore {
41
prepareToRenderSVGContent(RenderObject * object,RenderObject::PaintInfo & paintInfo,const FloatRect & boundingBox,SVGResourceFilter * & filter,SVGResourceFilter * rootFilter)42 void prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& boundingBox, SVGResourceFilter*& filter, SVGResourceFilter* rootFilter)
43 {
44 #if !ENABLE(SVG_FILTERS)
45 UNUSED_PARAM(filter);
46 UNUSED_PARAM(rootFilter);
47 #endif
48
49 SVGElement* svgElement = static_cast<SVGElement*>(object->element());
50 ASSERT(svgElement && svgElement->document() && svgElement->isStyled());
51 ASSERT(object);
52
53 SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement);
54 const RenderStyle* style = object->style();
55 ASSERT(style);
56
57 const SVGRenderStyle* svgStyle = style->svgStyle();
58 ASSERT(svgStyle);
59
60 // Setup transparency layers before setting up filters!
61 float opacity = style->opacity();
62 if (opacity < 1.0f) {
63 paintInfo.context->clip(enclosingIntRect(boundingBox));
64 paintInfo.context->beginTransparencyLayer(opacity);
65 }
66
67 #if ENABLE(SVG_FILTERS)
68 AtomicString filterId(svgStyle->filter());
69 #endif
70
71 AtomicString clipperId(svgStyle->clipPath());
72 AtomicString maskerId(svgStyle->maskElement());
73
74 Document* document = object->document();
75
76 #if ENABLE(SVG_FILTERS)
77 SVGResourceFilter* newFilter = getFilterById(document, filterId);
78 if (newFilter == rootFilter) {
79 // Catch <text filter="url(#foo)">Test<tspan filter="url(#foo)">123</tspan></text>.
80 // The filter is NOT meant to be applied twice in that case!
81 filter = 0;
82 filterId = String();
83 } else
84 filter = newFilter;
85 #endif
86
87 SVGResourceClipper* clipper = getClipperById(document, clipperId);
88 SVGResourceMasker* masker = getMaskerById(document, maskerId);
89
90 #if ENABLE(SVG_FILTERS)
91 if (filter) {
92 filter->addClient(styledElement);
93 filter->prepareFilter(paintInfo.context, boundingBox);
94 } else if (!filterId.isEmpty())
95 svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement);
96 #endif
97
98 if (clipper) {
99 clipper->addClient(styledElement);
100 clipper->applyClip(paintInfo.context, boundingBox);
101 } else if (!clipperId.isEmpty())
102 svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement);
103
104 if (masker) {
105 masker->addClient(styledElement);
106 masker->applyMask(paintInfo.context, boundingBox);
107 } else if (!maskerId.isEmpty())
108 svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement);
109 }
110
finishRenderSVGContent(RenderObject * object,RenderObject::PaintInfo & paintInfo,const FloatRect & boundingBox,SVGResourceFilter * & filter,GraphicsContext * savedContext)111 void finishRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& boundingBox, SVGResourceFilter*& filter, GraphicsContext* savedContext)
112 {
113 #if !ENABLE(SVG_FILTERS)
114 UNUSED_PARAM(boundingBox);
115 UNUSED_PARAM(filter);
116 UNUSED_PARAM(savedContext);
117 #endif
118
119 ASSERT(object);
120
121 const RenderStyle* style = object->style();
122 ASSERT(style);
123
124 #if ENABLE(SVG_FILTERS)
125 if (filter) {
126 filter->applyFilter(paintInfo.context, boundingBox);
127 paintInfo.context = savedContext;
128 }
129 #endif
130
131 float opacity = style->opacity();
132 if (opacity < 1.0f)
133 paintInfo.context->endTransparencyLayer();
134 }
135
renderSubtreeToImage(ImageBuffer * image,RenderObject * item)136 void renderSubtreeToImage(ImageBuffer* image, RenderObject* item)
137 {
138 ASSERT(item);
139 ASSERT(image);
140 ASSERT(image->context());
141 RenderObject::PaintInfo info(image->context(), IntRect(), PaintPhaseForeground, 0, 0, 0);
142
143 RenderSVGContainer* svgContainer = 0;
144 if (item && item->isSVGContainer())
145 svgContainer = static_cast<RenderSVGContainer*>(item);
146
147 bool drawsContents = svgContainer ? svgContainer->drawsContents() : false;
148 if (svgContainer && !drawsContents)
149 svgContainer->setDrawsContents(true);
150
151 item->layoutIfNeeded();
152 item->paint(info, 0, 0);
153
154 if (svgContainer && !drawsContents)
155 svgContainer->setDrawsContents(false);
156 }
157
clampImageBufferSizeToViewport(RenderObject * object,IntSize & size)158 void clampImageBufferSizeToViewport(RenderObject* object, IntSize& size)
159 {
160 if (!object || !object->isRenderView())
161 return;
162
163 RenderView* view = static_cast<RenderView*>(object);
164 if (!view->frameView())
165 return;
166
167 int viewWidth = view->frameView()->visibleWidth();
168 int viewHeight = view->frameView()->visibleHeight();
169
170 if (size.width() > viewWidth)
171 size.setWidth(viewWidth);
172
173 if (size.height() > viewHeight)
174 size.setHeight(viewHeight);
175 }
176
177 } // namespace WebCore
178
179 #endif // ENABLE(SVG)
180