1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * Copyright (C) 2003, 2007, 2010 Apple Inc. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#include "config.h"
24#include "HTMLMarqueeElement.h"
25
26#include "Attribute.h"
27#include "CSSPropertyNames.h"
28#include "CSSValueKeywords.h"
29#include "HTMLNames.h"
30#include "HTMLParserIdioms.h"
31#include "RenderLayer.h"
32#include "RenderMarquee.h"
33#include <wtf/IsoMallocInlines.h>
34
35namespace WebCore {
36
37WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLMarqueeElement);
38
39using namespace HTMLNames;
40
41inline HTMLMarqueeElement::HTMLMarqueeElement(const QualifiedName& tagName, Document& document)
42 : HTMLElement(tagName, document)
43 , ActiveDOMObject(document)
44{
45 ASSERT(hasTagName(marqueeTag));
46}
47
48Ref<HTMLMarqueeElement> HTMLMarqueeElement::create(const QualifiedName& tagName, Document& document)
49{
50 auto marqueeElement = adoptRef(*new HTMLMarqueeElement(tagName, document));
51 marqueeElement->suspendIfNeeded();
52 return marqueeElement;
53}
54
55int HTMLMarqueeElement::minimumDelay() const
56{
57 if (!hasAttributeWithoutSynchronization(truespeedAttr)) {
58 // WinIE uses 60ms as the minimum delay by default.
59 return 60;
60 }
61 return 16; // Don't allow timers at < 16ms intervals to avoid CPU hogging: webkit.org/b/160609
62}
63
64bool HTMLMarqueeElement::isPresentationAttribute(const QualifiedName& name) const
65{
66 if (name == widthAttr || name == heightAttr || name == bgcolorAttr || name == vspaceAttr || name == hspaceAttr || name == scrollamountAttr || name == scrolldelayAttr || name == loopAttr || name == behaviorAttr || name == directionAttr)
67 return true;
68 return HTMLElement::isPresentationAttribute(name);
69}
70
71void HTMLMarqueeElement::collectStyleForPresentationAttribute(const QualifiedName& name, const AtomicString& value, MutableStyleProperties& style)
72{
73 if (name == widthAttr) {
74 if (!value.isEmpty())
75 addHTMLLengthToStyle(style, CSSPropertyWidth, value);
76 } else if (name == heightAttr) {
77 if (!value.isEmpty())
78 addHTMLLengthToStyle(style, CSSPropertyHeight, value);
79 } else if (name == bgcolorAttr) {
80 if (!value.isEmpty())
81 addHTMLColorToStyle(style, CSSPropertyBackgroundColor, value);
82 } else if (name == vspaceAttr) {
83 if (!value.isEmpty()) {
84 addHTMLLengthToStyle(style, CSSPropertyMarginTop, value);
85 addHTMLLengthToStyle(style, CSSPropertyMarginBottom, value);
86 }
87 } else if (name == hspaceAttr) {
88 if (!value.isEmpty()) {
89 addHTMLLengthToStyle(style, CSSPropertyMarginLeft, value);
90 addHTMLLengthToStyle(style, CSSPropertyMarginRight, value);
91 }
92 } else if (name == scrollamountAttr) {
93 if (!value.isEmpty())
94 addHTMLLengthToStyle(style, CSSPropertyWebkitMarqueeIncrement, value);
95 } else if (name == scrolldelayAttr) {
96 if (!value.isEmpty())
97 addHTMLLengthToStyle(style, CSSPropertyWebkitMarqueeSpeed, value);
98 } else if (name == loopAttr) {
99 if (!value.isEmpty()) {
100 if (value == "-1" || equalLettersIgnoringASCIICase(value, "infinite"))
101 addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitMarqueeRepetition, CSSValueInfinite);
102 else
103 addHTMLLengthToStyle(style, CSSPropertyWebkitMarqueeRepetition, value);
104 }
105 } else if (name == behaviorAttr) {
106 if (!value.isEmpty())
107 addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitMarqueeStyle, value);
108 } else if (name == directionAttr) {
109 if (!value.isEmpty())
110 addPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitMarqueeDirection, value);
111 } else
112 HTMLElement::collectStyleForPresentationAttribute(name, value, style);
113}
114
115void HTMLMarqueeElement::start()
116{
117 if (auto* renderer = renderMarquee())
118 renderer->start();
119}
120
121void HTMLMarqueeElement::stop()
122{
123 if (auto* renderer = renderMarquee())
124 renderer->stop();
125}
126
127unsigned HTMLMarqueeElement::scrollAmount() const
128{
129 return limitToOnlyHTMLNonNegative(attributeWithoutSynchronization(scrollamountAttr), RenderStyle::initialMarqueeIncrement().intValue());
130}
131
132void HTMLMarqueeElement::setScrollAmount(unsigned scrollAmount)
133{
134 setUnsignedIntegralAttribute(scrollamountAttr, limitToOnlyHTMLNonNegative(scrollAmount, RenderStyle::initialMarqueeIncrement().intValue()));
135}
136
137unsigned HTMLMarqueeElement::scrollDelay() const
138{
139 return limitToOnlyHTMLNonNegative(attributeWithoutSynchronization(scrolldelayAttr), RenderStyle::initialMarqueeSpeed());
140}
141
142void HTMLMarqueeElement::setScrollDelay(unsigned scrollDelay)
143{
144 setUnsignedIntegralAttribute(scrolldelayAttr, limitToOnlyHTMLNonNegative(scrollDelay, RenderStyle::initialMarqueeSpeed()));
145}
146
147int HTMLMarqueeElement::loop() const
148{
149 bool ok;
150 int loopValue = attributeWithoutSynchronization(loopAttr).toInt(&ok);
151 return ok && loopValue > 0 ? loopValue : -1;
152}
153
154ExceptionOr<void> HTMLMarqueeElement::setLoop(int loop)
155{
156 if (loop <= 0 && loop != -1)
157 return Exception { IndexSizeError };
158 setIntegralAttribute(loopAttr, loop);
159 return { };
160}
161
162bool HTMLMarqueeElement::canSuspendForDocumentSuspension() const
163{
164 return true;
165}
166
167void HTMLMarqueeElement::suspend(ReasonForSuspension)
168{
169 if (RenderMarquee* marqueeRenderer = renderMarquee())
170 marqueeRenderer->suspend();
171}
172
173void HTMLMarqueeElement::resume()
174{
175 if (RenderMarquee* marqueeRenderer = renderMarquee())
176 marqueeRenderer->updateMarqueePosition();
177}
178
179RenderMarquee* HTMLMarqueeElement::renderMarquee() const
180{
181 if (!renderer() || !renderer()->hasLayer())
182 return nullptr;
183 return renderBoxModelObject()->layer()->marquee();
184}
185
186} // namespace WebCore
187