• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KHTML

SVGImage.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Eric Seidel (eric@webkit.org)
00003  * Copyright (C) 2008 Apple, Inc. All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  *
00014  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
00015  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00016  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00017  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
00018  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00019  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00020  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00021  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00022  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00023  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00024  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00025  */
00026 
00027 #include "config.h"
00028 #if ENABLE(SVG)
00029 #include "SVGImage.h"
00030 
00031 #include "CachedPage.h"
00032 #include "DocumentLoader.h"
00033 #include "EditCommand.h"
00034 #include "FloatRect.h"
00035 #include "Frame.h"
00036 #include "FrameLoader.h"
00037 #include "FrameView.h"
00038 #include "GraphicsContext.h"
00039 #include "ImageObserver.h"
00040 #include "NotImplemented.h"
00041 #include "Page.h"
00042 #include "RenderView.h"
00043 #include "ResourceError.h"
00044 #include "SVGDocument.h"
00045 #include "SVGLength.h"
00046 #include "SVGRenderSupport.h"
00047 #include "SVGSVGElement.h"
00048 #include "Settings.h"
00049 
00050 #include "SVGImageEmptyClients.h"
00051 
00052 namespace WebCore {
00053 
00054 SVGImage::SVGImage(ImageObserver* observer)
00055     : Image(observer)
00056     , m_document(0)
00057     , m_page(0)
00058     , m_frame(0)
00059     , m_frameView(0)
00060 {
00061 }
00062 
00063 SVGImage::~SVGImage()
00064 {
00065     if (m_frame)
00066         m_frame->loader()->frameDetached(); // Break both the loader and view references to the frame
00067 }
00068 
00069 void SVGImage::setContainerSize(const IntSize& containerSize)
00070 {
00071     if (containerSize.width() <= 0 || containerSize.height() <= 0)
00072         return;
00073 
00074     if (!m_frame || !m_frame->document())
00075         return;
00076     SVGSVGElement* rootElement = static_cast<SVGDocument*>(m_frame->document())->rootElement();
00077     if (!rootElement)
00078         return;
00079 
00080     rootElement->setContainerSize(containerSize);
00081 }
00082 
00083 bool SVGImage::usesContainerSize() const
00084 {
00085     if (!m_frame || !m_frame->document())
00086         return false;
00087     SVGSVGElement* rootElement = static_cast<SVGDocument*>(m_frame->document())->rootElement();
00088     if (!rootElement)
00089         return false;
00090 
00091     return rootElement->hasSetContainerSize();
00092 }
00093 
00094 IntSize SVGImage::size() const
00095 {
00096     if (!m_frame || !m_frame->document())
00097         return IntSize();
00098     
00099     SVGSVGElement* rootElement = static_cast<SVGDocument*>(m_frame->document())->rootElement();
00100     if (!rootElement)
00101         return IntSize();
00102     
00103     SVGLength width = rootElement->width();
00104     SVGLength height = rootElement->height();
00105     
00106     IntSize svgSize;
00107     if (width.unitType() == LengthTypePercentage) 
00108         svgSize.setWidth(rootElement->relativeWidthValue());
00109     else
00110         svgSize.setWidth(static_cast<int>(width.value()));
00111 
00112     if (height.unitType() == LengthTypePercentage) 
00113         svgSize.setHeight(rootElement->relativeHeightValue());
00114     else
00115         svgSize.setHeight(static_cast<int>(height.value()));
00116 
00117     return svgSize;
00118 }
00119 
00120 bool SVGImage::hasRelativeWidth() const
00121 {
00122     if (!m_frame || !m_frame->document())
00123         return false;
00124     SVGSVGElement* rootElement = static_cast<SVGDocument*>(m_frame->document())->rootElement();
00125     if (!rootElement)
00126         return false;
00127 
00128     return rootElement->width().unitType() == LengthTypePercentage;
00129 }
00130 
00131 bool SVGImage::hasRelativeHeight() const
00132 {
00133     if (!m_frame || !m_frame->document())
00134         return false;
00135     SVGSVGElement* rootElement = static_cast<SVGDocument*>(m_frame->document())->rootElement();
00136     if (!rootElement)
00137         return false;
00138 
00139     return rootElement->height().unitType() == LengthTypePercentage;
00140 }
00141 
00142 void SVGImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator compositeOp)
00143 {
00144     if (!m_frame)
00145         return;
00146     
00147     context->save();
00148     context->setCompositeOperation(compositeOp);
00149     context->clip(enclosingIntRect(dstRect));
00150     if (compositeOp != CompositeSourceOver)
00151         context->beginTransparencyLayer(1.0f);
00152     context->translate(dstRect.location().x(), dstRect.location().y());
00153     context->scale(FloatSize(dstRect.width()/srcRect.width(), dstRect.height()/srcRect.height()));
00154     
00155     if (m_frame->view()->needsLayout())
00156         m_frame->view()->layout();
00157     m_frame->paint(context, enclosingIntRect(srcRect));
00158 
00159     if (compositeOp != CompositeSourceOver)
00160         context->endTransparencyLayer();
00161 
00162     context->restore();
00163 
00164     if (imageObserver())
00165         imageObserver()->didDraw(this);
00166 }
00167 
00168 NativeImagePtr SVGImage::nativeImageForCurrentFrame()
00169 {
00170     // FIXME: In order to support dynamic SVGs we need to have a way to invalidate this
00171     // frame cache, or better yet, not use a cache for tiled drawing at all, instead
00172     // having a tiled drawing callback (hopefully non-virtual).
00173     if (!m_frameCache) {
00174         m_frameCache.set(ImageBuffer::create(size(), false).release());
00175         if (!m_frameCache) // failed to allocate image
00176             return 0;
00177         renderSubtreeToImage(m_frameCache.get(), m_frame->contentRenderer());
00178     }
00179 #if PLATFORM(CG)
00180     return m_frameCache->cgImage();
00181 #elif PLATFORM(QT)
00182     return m_frameCache->pixmap();
00183 #elif PLATFORM(CAIRO)
00184     return m_frameCache->surface();
00185 #else
00186     notImplemented();
00187     return 0;
00188 #endif
00189 }
00190 
00191 bool SVGImage::dataChanged(bool allDataReceived)
00192 {
00193     int length = m_data->size();
00194     if (!length) // if this was an empty image
00195         return true;
00196     
00197     if (allDataReceived) {
00198         static ChromeClient* dummyChromeClient = new SVGEmptyChromeClient;
00199         static FrameLoaderClient* dummyFrameLoaderClient =  new SVGEmptyFrameLoaderClient;
00200         static EditorClient* dummyEditorClient = new SVGEmptyEditorClient;
00201         static ContextMenuClient* dummyContextMenuClient = new SVGEmptyContextMenuClient;
00202         static DragClient* dummyDragClient = new SVGEmptyDragClient;
00203         static InspectorClient* dummyInspectorClient = new SVGEmptyInspectorClient;
00204 
00205         // FIXME: If this SVG ends up loading itself, we'll leak this Frame (and associated DOM & render trees).
00206         // The Cache code does not know about CachedImages holding Frames and won't know to break the cycle.
00207         m_page.set(new Page(dummyChromeClient, dummyContextMenuClient, dummyEditorClient, dummyDragClient, dummyInspectorClient));
00208         m_page->settings()->setJavaScriptEnabled(false);
00209 
00210         m_frame = new Frame(m_page.get(), 0, dummyFrameLoaderClient);
00211         m_frameView = new FrameView(m_frame.get());
00212         m_frameView->deref(); // FIXME: FrameView starts with a refcount of 1
00213         m_frame->setView(m_frameView.get());
00214         m_frame->init();
00215         ResourceRequest fakeRequest(KURL(""));
00216         m_frame->loader()->load(fakeRequest); // Make sure the DocumentLoader is created
00217         m_frame->loader()->cancelContentPolicyCheck(); // cancel any policy checks
00218         m_frame->loader()->commitProvisionalLoad(0);
00219         m_frame->loader()->setResponseMIMEType("image/svg+xml");
00220         m_frame->loader()->begin(KURL()); // create the empty document
00221         m_frame->loader()->write(m_data->data(), m_data->size());
00222         m_frame->loader()->end();
00223         m_frameView->setTransparent(true); // SVG Images are transparent.
00224     }
00225     return m_frameView;
00226 }
00227 
00228 }
00229 
00230 #endif // ENABLE(SVG)

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal