diff options
Diffstat (limited to 'WebCore/rendering/SVGRenderSupport.cpp')
-rw-r--r-- | WebCore/rendering/SVGRenderSupport.cpp | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/WebCore/rendering/SVGRenderSupport.cpp b/WebCore/rendering/SVGRenderSupport.cpp new file mode 100644 index 0000000..db6e345 --- /dev/null +++ b/WebCore/rendering/SVGRenderSupport.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2007 Rob Buis <buis@kde.org> + * (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> + * (C) 2007 Eric Seidel <eric@webkit.org> + * + * 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 + * along 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 "SVGRenderSupport.h" + +#include "AffineTransform.h" +#include "ImageBuffer.h" +#include "RenderObject.h" +#include "RenderSVGContainer.h" +#include "RenderView.h" +#include "SVGResourceClipper.h" +#include "SVGResourceFilter.h" +#include "SVGResourceMasker.h" +#include "SVGStyledElement.h" +#include "SVGURIReference.h" + +namespace WebCore { + +void prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& boundingBox, SVGResourceFilter*& filter, SVGResourceFilter* rootFilter) +{ + SVGElement* svgElement = static_cast<SVGElement*>(object->element()); + ASSERT(svgElement && svgElement->document() && svgElement->isStyled()); + ASSERT(object); + + SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(svgElement); + const RenderStyle* style = object->style(); + ASSERT(style); + + const SVGRenderStyle* svgStyle = style->svgStyle(); + ASSERT(svgStyle); + + // Setup transparency layers before setting up filters! + float opacity = style->opacity(); + if (opacity < 1.0f) { + paintInfo.context->clip(enclosingIntRect(boundingBox)); + paintInfo.context->beginTransparencyLayer(opacity); + } + +#if ENABLE(SVG_FILTERS) + AtomicString filterId(SVGURIReference::getTarget(svgStyle->filter())); +#endif + + AtomicString clipperId(SVGURIReference::getTarget(svgStyle->clipPath())); + AtomicString maskerId(SVGURIReference::getTarget(svgStyle->maskElement())); + + Document* document = object->document(); + +#if ENABLE(SVG_FILTERS) + SVGResourceFilter* newFilter = getFilterById(document, filterId); + if (newFilter == rootFilter) { + // Catch <text filter="url(#foo)">Test<tspan filter="url(#foo)">123</tspan></text>. + // The filter is NOT meant to be applied twice in that case! + filter = 0; + filterId = String(); + } else + filter = newFilter; +#endif + + SVGResourceClipper* clipper = getClipperById(document, clipperId); + SVGResourceMasker* masker = getMaskerById(document, maskerId); + +#if ENABLE(SVG_FILTERS) + if (filter) { + filter->addClient(styledElement); + filter->prepareFilter(paintInfo.context, boundingBox); + } else if (!filterId.isEmpty()) + svgElement->document()->accessSVGExtensions()->addPendingResource(filterId, styledElement); +#endif + + if (clipper) { + clipper->addClient(styledElement); + clipper->applyClip(paintInfo.context, boundingBox); + } else if (!clipperId.isEmpty()) + svgElement->document()->accessSVGExtensions()->addPendingResource(clipperId, styledElement); + + if (masker) { + masker->addClient(styledElement); + masker->applyMask(paintInfo.context, boundingBox); + } else if (!maskerId.isEmpty()) + svgElement->document()->accessSVGExtensions()->addPendingResource(maskerId, styledElement); +} + +void finishRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& boundingBox, SVGResourceFilter*& filter, GraphicsContext* savedContext) +{ + ASSERT(object); + + const RenderStyle* style = object->style(); + ASSERT(style); + +#if ENABLE(SVG_FILTERS) + if (filter) { + filter->applyFilter(paintInfo.context, boundingBox); + paintInfo.context = savedContext; + } +#endif + + float opacity = style->opacity(); + if (opacity < 1.0f) + paintInfo.context->endTransparencyLayer(); +} + +void renderSubtreeToImage(ImageBuffer* image, RenderObject* item) +{ + ASSERT(item); + ASSERT(image); + ASSERT(image->context()); + RenderObject::PaintInfo info(image->context(), IntRect(), PaintPhaseForeground, 0, 0, 0); + + RenderSVGContainer* svgContainer = 0; + if (item && item->isSVGContainer()) + svgContainer = static_cast<RenderSVGContainer*>(item); + + bool drawsContents = svgContainer ? svgContainer->drawsContents() : false; + if (svgContainer && !drawsContents) + svgContainer->setDrawsContents(true); + + item->layoutIfNeeded(); + item->paint(info, 0, 0); + + if (svgContainer && !drawsContents) + svgContainer->setDrawsContents(false); +} + +void clampImageBufferSizeToViewport(RenderObject* object, IntSize& size) +{ + if (!object || !object->isRenderView()) + return; + + RenderView* view = static_cast<RenderView*>(object); + if (!view->frameView()) + return; + + int viewWidth = view->frameView()->visibleWidth(); + int viewHeight = view->frameView()->visibleHeight(); + + if (size.width() > viewWidth) + size.setWidth(viewWidth); + + if (size.height() > viewHeight) + size.setHeight(viewHeight); +} + +} // namespace WebCore + +#endif // ENABLE(SVG) |