2 * Copyright (C) 2006 Eric Seidel (eric@webkit.org)
3 * Copyright (C) 2008 Apple, Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "CachedPage.h"
32 #include "DocumentLoader.h"
33 #include "EditCommand.h"
34 #include "FloatRect.h"
36 #include "FrameLoader.h"
37 #include "FrameView.h"
38 #include "GraphicsContext.h"
39 #include "ImageObserver.h"
40 #include "NotImplemented.h"
42 #include "RenderView.h"
43 #include "ResourceError.h"
44 #include "SVGDocument.h"
45 #include "SVGLength.h"
46 #include "SVGRenderSupport.h"
47 #include "SVGSVGElement.h"
50 #include "SVGImageEmptyClients.h"
54 SVGImage::SVGImage(ImageObserver
* observer
)
66 m_frame
->loader()->frameDetached(); // Break both the loader and view references to the frame
69 void SVGImage::setContainerSize(const IntSize
& containerSize
)
71 if (containerSize
.width() <= 0 || containerSize
.height() <= 0)
74 if (!m_frame
|| !m_frame
->document())
76 SVGSVGElement
* rootElement
= static_cast<SVGDocument
*>(m_frame
->document())->rootElement();
80 rootElement
->setContainerSize(containerSize
);
83 bool SVGImage::usesContainerSize() const
85 if (!m_frame
|| !m_frame
->document())
87 SVGSVGElement
* rootElement
= static_cast<SVGDocument
*>(m_frame
->document())->rootElement();
91 return rootElement
->hasSetContainerSize();
94 IntSize
SVGImage::size() const
96 if (!m_frame
|| !m_frame
->document())
99 SVGSVGElement
* rootElement
= static_cast<SVGDocument
*>(m_frame
->document())->rootElement();
103 SVGLength width
= rootElement
->width();
104 SVGLength height
= rootElement
->height();
107 if (width
.unitType() == LengthTypePercentage
)
108 svgSize
.setWidth(rootElement
->relativeWidthValue());
110 svgSize
.setWidth(static_cast<int>(width
.value()));
112 if (height
.unitType() == LengthTypePercentage
)
113 svgSize
.setHeight(rootElement
->relativeHeightValue());
115 svgSize
.setHeight(static_cast<int>(height
.value()));
120 bool SVGImage::hasRelativeWidth() const
122 if (!m_frame
|| !m_frame
->document())
124 SVGSVGElement
* rootElement
= static_cast<SVGDocument
*>(m_frame
->document())->rootElement();
128 return rootElement
->width().unitType() == LengthTypePercentage
;
131 bool SVGImage::hasRelativeHeight() const
133 if (!m_frame
|| !m_frame
->document())
135 SVGSVGElement
* rootElement
= static_cast<SVGDocument
*>(m_frame
->document())->rootElement();
139 return rootElement
->height().unitType() == LengthTypePercentage
;
142 void SVGImage::draw(GraphicsContext
* context
, const FloatRect
& dstRect
, const FloatRect
& srcRect
, CompositeOperator compositeOp
)
148 context
->setCompositeOperation(compositeOp
);
149 context
->clip(enclosingIntRect(dstRect
));
150 if (compositeOp
!= CompositeSourceOver
)
151 context
->beginTransparencyLayer(1.0f
);
152 context
->translate(dstRect
.location().x(), dstRect
.location().y());
153 context
->scale(FloatSize(dstRect
.width()/srcRect
.width(), dstRect
.height()/srcRect
.height()));
155 if (m_frame
->view()->needsLayout())
156 m_frame
->view()->layout();
157 m_frame
->paint(context
, enclosingIntRect(srcRect
));
159 if (compositeOp
!= CompositeSourceOver
)
160 context
->endTransparencyLayer();
165 imageObserver()->didDraw(this);
168 NativeImagePtr
SVGImage::nativeImageForCurrentFrame()
170 // FIXME: In order to support dynamic SVGs we need to have a way to invalidate this
171 // frame cache, or better yet, not use a cache for tiled drawing at all, instead
172 // having a tiled drawing callback (hopefully non-virtual).
174 m_frameCache
.set(ImageBuffer::create(size(), false).release());
175 if (!m_frameCache
) // failed to allocate image
177 renderSubtreeToImage(m_frameCache
.get(), m_frame
->contentRenderer());
180 return m_frameCache
->cgImage();
182 return m_frameCache
->pixmap();
183 #elif PLATFORM(CAIRO)
184 return m_frameCache
->surface();
191 bool SVGImage::dataChanged(bool allDataReceived
)
193 int length
= m_data
->size();
194 if (!length
) // if this was an empty image
197 if (allDataReceived
) {
198 static ChromeClient
* dummyChromeClient
= new SVGEmptyChromeClient
;
199 static FrameLoaderClient
* dummyFrameLoaderClient
= new SVGEmptyFrameLoaderClient
;
200 static EditorClient
* dummyEditorClient
= new SVGEmptyEditorClient
;
201 static ContextMenuClient
* dummyContextMenuClient
= new SVGEmptyContextMenuClient
;
202 static DragClient
* dummyDragClient
= new SVGEmptyDragClient
;
203 static InspectorClient
* dummyInspectorClient
= new SVGEmptyInspectorClient
;
205 // FIXME: If this SVG ends up loading itself, we'll leak this Frame (and associated DOM & render trees).
206 // The Cache code does not know about CachedImages holding Frames and won't know to break the cycle.
207 m_page
.set(new Page(dummyChromeClient
, dummyContextMenuClient
, dummyEditorClient
, dummyDragClient
, dummyInspectorClient
));
208 m_page
->settings()->setJavaScriptEnabled(false);
210 m_frame
= new Frame(m_page
.get(), 0, dummyFrameLoaderClient
);
211 m_frameView
= new FrameView(m_frame
.get());
212 m_frameView
->deref(); // FIXME: FrameView starts with a refcount of 1
213 m_frame
->setView(m_frameView
.get());
215 ResourceRequest
fakeRequest(KURL(""));
216 m_frame
->loader()->load(fakeRequest
); // Make sure the DocumentLoader is created
217 m_frame
->loader()->cancelContentPolicyCheck(); // cancel any policy checks
218 m_frame
->loader()->commitProvisionalLoad(0);
219 m_frame
->loader()->setResponseMIMEType("image/svg+xml");
220 m_frame
->loader()->begin(KURL()); // create the empty document
221 m_frame
->loader()->write(m_data
->data(), m_data
->size());
222 m_frame
->loader()->end();
223 m_frameView
->setTransparent(true); // SVG Images are transparent.
230 #endif // ENABLE(SVG)