1 /*
2 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27
28 #if ENABLE(VIDEO)
29 #include "HTMLVideoElement.h"
30
31 #include "CSSHelper.h"
32 #include "CSSPropertyNames.h"
33 #include "Document.h"
34 #include "HTMLImageLoader.h"
35 #include "HTMLNames.h"
36 #include "MappedAttribute.h"
37 #include "RenderImage.h"
38 #include "RenderVideo.h"
39
40 namespace WebCore {
41
42 using namespace HTMLNames;
43
HTMLVideoElement(const QualifiedName & tagName,Document * doc)44 HTMLVideoElement::HTMLVideoElement(const QualifiedName& tagName, Document* doc)
45 : HTMLMediaElement(tagName, doc)
46 , m_shouldShowPosterImage(false)
47 {
48 ASSERT(hasTagName(videoTag));
49 }
50
rendererIsNeeded(RenderStyle * style)51 bool HTMLVideoElement::rendererIsNeeded(RenderStyle* style)
52 {
53 return HTMLElement::rendererIsNeeded(style);
54 }
55
56 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
createRenderer(RenderArena * arena,RenderStyle *)57 RenderObject* HTMLVideoElement::createRenderer(RenderArena* arena, RenderStyle*)
58 {
59 if (m_shouldShowPosterImage)
60 return new (arena) RenderImage(this);
61 return new (arena) RenderVideo(this);
62 }
63 #endif
64
attach()65 void HTMLVideoElement::attach()
66 {
67 HTMLMediaElement::attach();
68
69 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
70 if (m_shouldShowPosterImage) {
71 if (!m_imageLoader)
72 m_imageLoader.set(new HTMLImageLoader(this));
73 m_imageLoader->updateFromElement();
74 if (renderer() && renderer()->isImage()) {
75 RenderImage* imageRenderer = toRenderImage(renderer());
76 imageRenderer->setCachedImage(m_imageLoader->image());
77 }
78 }
79 #endif
80 }
81
detach()82 void HTMLVideoElement::detach()
83 {
84 HTMLMediaElement::detach();
85
86 if (!m_shouldShowPosterImage)
87 if (m_imageLoader)
88 m_imageLoader.clear();
89 }
90
parseMappedAttribute(MappedAttribute * attr)91 void HTMLVideoElement::parseMappedAttribute(MappedAttribute* attr)
92 {
93 const QualifiedName& attrName = attr->name();
94
95 if (attrName == posterAttr) {
96 updatePosterImage();
97 if (m_shouldShowPosterImage) {
98 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
99 if (!m_imageLoader)
100 m_imageLoader.set(new HTMLImageLoader(this));
101 m_imageLoader->updateFromElementIgnoringPreviousError();
102 #else
103 if (m_player)
104 m_player->setPoster(poster());
105 #endif
106 }
107 } else if (attrName == widthAttr)
108 addCSSLength(attr, CSSPropertyWidth, attr->value());
109 else if (attrName == heightAttr)
110 addCSSLength(attr, CSSPropertyHeight, attr->value());
111 else
112 HTMLMediaElement::parseMappedAttribute(attr);
113 }
114
videoWidth() const115 unsigned HTMLVideoElement::videoWidth() const
116 {
117 if (!m_player)
118 return 0;
119 return m_player->naturalSize().width();
120 }
121
videoHeight() const122 unsigned HTMLVideoElement::videoHeight() const
123 {
124 if (!m_player)
125 return 0;
126 return m_player->naturalSize().height();
127 }
128
width() const129 unsigned HTMLVideoElement::width() const
130 {
131 bool ok;
132 unsigned w = getAttribute(widthAttr).string().toUInt(&ok);
133 return ok ? w : 0;
134 }
135
setWidth(unsigned value)136 void HTMLVideoElement::setWidth(unsigned value)
137 {
138 setAttribute(widthAttr, String::number(value));
139 }
140
height() const141 unsigned HTMLVideoElement::height() const
142 {
143 bool ok;
144 unsigned h = getAttribute(heightAttr).string().toUInt(&ok);
145 return ok ? h : 0;
146 }
147
setHeight(unsigned value)148 void HTMLVideoElement::setHeight(unsigned value)
149 {
150 setAttribute(heightAttr, String::number(value));
151 }
152
poster() const153 KURL HTMLVideoElement::poster() const
154 {
155 return document()->completeURL(getAttribute(posterAttr));
156 }
157
setPoster(const String & value)158 void HTMLVideoElement::setPoster(const String& value)
159 {
160 setAttribute(posterAttr, value);
161 }
162
isURLAttribute(Attribute * attr) const163 bool HTMLVideoElement::isURLAttribute(Attribute* attr) const
164 {
165 return attr->name() == posterAttr;
166 }
167
imageSourceAttributeName() const168 const QualifiedName& HTMLVideoElement::imageSourceAttributeName() const
169 {
170 return posterAttr;
171 }
172
updatePosterImage()173 void HTMLVideoElement::updatePosterImage()
174 {
175 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
176 bool oldShouldShowPosterImage = m_shouldShowPosterImage;
177 #endif
178
179 m_shouldShowPosterImage = !poster().isEmpty() && readyState() < HAVE_CURRENT_DATA;
180
181 #if !ENABLE(PLUGIN_PROXY_FOR_VIDEO)
182 if (attached() && oldShouldShowPosterImage != m_shouldShowPosterImage) {
183 detach();
184 attach();
185 }
186 #endif
187 }
188
paint(GraphicsContext * context,const IntRect & destRect)189 void HTMLVideoElement::paint(GraphicsContext* context, const IntRect& destRect)
190 {
191 // FIXME: We should also be able to paint the poster image.
192
193 MediaPlayer* player = HTMLMediaElement::player();
194 if (!player)
195 return;
196
197 player->setVisible(true); // Make player visible or it won't draw.
198 player->paint(context, destRect);
199 }
200
paintCurrentFrameInContext(GraphicsContext * context,const IntRect & destRect)201 void HTMLVideoElement::paintCurrentFrameInContext(GraphicsContext* context, const IntRect& destRect)
202 {
203 // FIXME: We should also be able to paint the poster image.
204
205 MediaPlayer* player = HTMLMediaElement::player();
206 if (!player)
207 return;
208
209 player->setVisible(true); // Make player visible or it won't draw.
210 player->paintCurrentFrameInContext(context, destRect);
211 }
212
213 }
214 #endif
215