/*
* Copyright (C) 2007, 2008 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 "TransformationMatrix.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"
#include <wtf/UnusedParam.h>
namespace WebCore {
void prepareToRenderSVGContent(RenderObject* object, RenderObject::PaintInfo& paintInfo, const FloatRect& boundingBox, SVGResourceFilter*& filter, SVGResourceFilter* rootFilter)
{
#if !ENABLE(SVG_FILTERS)
UNUSED_PARAM(filter);
UNUSED_PARAM(rootFilter);
#endif
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(svgStyle->filter());
#endif
AtomicString clipperId(svgStyle->clipPath());
AtomicString maskerId(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)
{
#if !ENABLE(SVG_FILTERS)
UNUSED_PARAM(boundingBox);
UNUSED_PARAM(filter);
UNUSED_PARAM(savedContext);
#endif
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)