Add animation to progress element
https://bugs.webkit.org/show_bug.cgi?id=36664
Reviewed by Antti Koivisto.
Add a timer to control the animation. The timer is started after painting
or a state change in the progress bar, to prevent animation from running
when the progress bar is not visible.
* html/HTMLProgressElement.cpp:
* platform/qt/RenderThemeQt.cpp:
* platform/qt/RenderThemeQt.h:
* rendering/RenderProgress.cpp:
* rendering/RenderProgress.h:
* rendering/RenderTheme.cpp:
* rendering/RenderTheme.h:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@56850 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 4cc3c34..8a68678 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,37 @@
+2010-03-31 Yael Aharon <yael.aharon@nokia.com>
+
+ Reviewed by Antti Koivisto.
+
+ Add animation to progress element
+ https://bugs.webkit.org/show_bug.cgi?id=36664
+
+ Add a timer to control the animation. The timer is started after painting
+ or a state change in the progress bar, to prevent animation from running
+ when the progress bar is not visible.
+
+ * html/HTMLProgressElement.cpp:
+ (WebCore::HTMLProgressElement::createRenderer):
+ * manual-tests/dom: Added.
+ * manual-tests/dom/progressbar.html: Added.
+ * platform/qt/RenderThemeQt.cpp:
+ (WebCore::RenderThemeQt::animationRepeatIntervalForProgressBar):
+ (WebCore::RenderThemeQt::animationDurationForProgressBar):
+ (WebCore::RenderThemeQt::paintProgressBar):
+ * platform/qt/RenderThemeQt.h:
+ * rendering/RenderProgress.cpp:
+ (WebCore::RenderProgress::RenderProgress):
+ (WebCore::RenderProgress::layout):
+ (WebCore::RenderProgress::updateFromElement):
+ (WebCore::RenderProgress::animationProgress):
+ (WebCore::RenderProgress::animationTimerFired):
+ (WebCore::RenderProgress::paint):
+ (WebCore::RenderProgress::updateAnimationState):
+ * rendering/RenderProgress.h:
+ * rendering/RenderTheme.cpp:
+ (WebCore::RenderTheme::animationRepeatIntervalForProgressBar):
+ (WebCore::RenderTheme::animationDurationForProgressBar):
+ * rendering/RenderTheme.h:
+
2010-03-31 Pavel Feldman <pfeldman@chromium.org>
Not reviewed. Rolling out r56829 since it broke chromium layout tests.
diff --git a/WebCore/html/HTMLProgressElement.cpp b/WebCore/html/HTMLProgressElement.cpp
index 132fcde..6fa8043 100644
--- a/WebCore/html/HTMLProgressElement.cpp
+++ b/WebCore/html/HTMLProgressElement.cpp
@@ -45,7 +45,7 @@
return adoptRef(new HTMLProgressElement(tagName, document, form));
}
-RenderObject* HTMLProgressElement::createRenderer(RenderArena* arena, RenderStyle* style)
+RenderObject* HTMLProgressElement::createRenderer(RenderArena* arena, RenderStyle*)
{
return new (arena) RenderProgress(this);
}
diff --git a/WebCore/manual-tests/dom/progressbar.html b/WebCore/manual-tests/dom/progressbar.html
new file mode 100644
index 0000000..95e64f2
--- /dev/null
+++ b/WebCore/manual-tests/dom/progressbar.html
@@ -0,0 +1,8 @@
+<html><body>
+<h1>Indeterminate progress bar</h1>
+This is an example of <progress value=7 max=10></progress> a determinate progress bar.<br>
+This is an example of <progress></progress> an indeterminate progress bar.<br>
+This is an example of <progress dir=rtl value=7 max=10></progress> a right-to-left determinate progress bar.<br>
+This is an example of <progress dir=rtl></progress> a right-to-left indeterminate progress bar.<br>
+
+</body></html>
diff --git a/WebCore/platform/qt/RenderThemeQt.cpp b/WebCore/platform/qt/RenderThemeQt.cpp
index 38c12ae..5ee372b 100644
--- a/WebCore/platform/qt/RenderThemeQt.cpp
+++ b/WebCore/platform/qt/RenderThemeQt.cpp
@@ -653,10 +653,26 @@
}
#if ENABLE(PROGRESS_TAG)
-bool RenderThemeQt::getNumberOfPixelsForProgressPosition(double position, int& progressSize) const
+double RenderThemeQt::animationRepeatIntervalForProgressBar(RenderProgress* renderProgress) const
{
- progressSize = 65536 * position;
- return false;
+ if (renderProgress->position() >= 0)
+ return 0;
+
+ // FIXME: Use hard-coded value until http://bugreports.qt.nokia.com/browse/QTBUG-9171 is fixed.
+ // Use the value from windows style which is 10 fps.
+ return 0.1;
+}
+
+double RenderThemeQt::animationDurationForProgressBar(RenderProgress* renderProgress) const
+{
+ if (renderProgress->position() >= 0)
+ return 0;
+
+ QStyleOptionProgressBarV2 option;
+ option.rect.setSize(renderProgress->size());
+ // FIXME: Until http://bugreports.qt.nokia.com/browse/QTBUG-9171 is fixed,
+ // we simulate one square animating across the progress bar.
+ return (option.rect.width() / qStyle()->pixelMetric(QStyle::PM_ProgressBarChunkWidth, &option)) * animationRepeatIntervalForProgressBar(renderProgress);
}
void RenderThemeQt::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
@@ -686,7 +702,19 @@
option.rect.moveTo(QPoint(0, 0));
option.rect.setSize(r.size());
- p.drawControl(QStyle::CE_ProgressBar, option);
+ if (option.progress < 0) {
+ // FIXME: Until http://bugreports.qt.nokia.com/browse/QTBUG-9171 is fixed,
+ // we simulate one square animating across the progress bar.
+ p.drawControl(QStyle::CE_ProgressBarGroove, option);
+ int chunkWidth = qStyle()->pixelMetric(QStyle::PM_ProgressBarChunkWidth, &option);
+ QColor color = (option.palette.highlight() == option.palette.background()) ? option.palette.color(QPalette::Active, QPalette::Highlight) : option.palette.color(QPalette::Highlight);
+ if (renderProgress->style()->direction() == RTL)
+ p.painter->fillRect(option.rect.right() - chunkWidth - renderProgress->animationProgress() * option.rect.width(), 0, chunkWidth, option.rect.height(), color);
+ else
+ p.painter->fillRect(renderProgress->animationProgress() * option.rect.width(), 0, chunkWidth, option.rect.height(), color);
+ } else
+ p.drawControl(QStyle::CE_ProgressBar, option);
+
p.painter->translate(-topLeft);
return false;
diff --git a/WebCore/platform/qt/RenderThemeQt.h b/WebCore/platform/qt/RenderThemeQt.h
index 121b078..d046914 100644
--- a/WebCore/platform/qt/RenderThemeQt.h
+++ b/WebCore/platform/qt/RenderThemeQt.h
@@ -34,6 +34,9 @@
namespace WebCore {
+#if ENABLE(PROGRESS_TAG)
+class RenderProgress;
+#endif
class RenderStyle;
class HTMLMediaElement;
class ScrollbarThemeQt;
@@ -128,10 +131,10 @@
virtual bool paintSearchFieldResultsDecoration(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
#if ENABLE(PROGRESS_TAG)
- // Helper method for optimizing the paint area of the progress bar.
- // If supported, it returns number of pixels needed to draw the progress bar up to the progress position.
- // progressSize is the value that is passed back to RenderTheme during drawing.
- virtual bool getNumberOfPixelsForProgressPosition(double position, int& progressSize) const;
+ // Returns the repeat interval of the animation for the progress bar.
+ virtual double animationRepeatIntervalForProgressBar(RenderProgress* renderProgress) const;
+ // Returns the duration of the animation for the progress bar.
+ virtual double animationDurationForProgressBar(RenderProgress* renderProgress) const;
#endif
#if ENABLE(VIDEO)
diff --git a/WebCore/rendering/RenderProgress.cpp b/WebCore/rendering/RenderProgress.cpp
index 6d92187..6ee066d 100644
--- a/WebCore/rendering/RenderProgress.cpp
+++ b/WebCore/rendering/RenderProgress.cpp
@@ -35,6 +35,11 @@
RenderProgress::RenderProgress(HTMLProgressElement* element)
: RenderBlock(element)
, m_position(-1)
+ , m_animationStartTime(0)
+ , m_animationRepeatInterval(0)
+ , m_animationDuration(0)
+ , m_animating(false)
+ , m_animationTimer(this, &RenderProgress::animationTimerFired)
{
}
@@ -49,6 +54,8 @@
m_overflow.clear();
+ updateAnimationState();
+
repainter.repaintAfterLayout();
setNeedsLayout(false);
@@ -61,8 +68,47 @@
return;
m_position = element->position();
+ updateAnimationState();
+
repaint();
}
+double RenderProgress::animationProgress()
+{
+ return m_animating ? (fmod((currentTime() - m_animationStartTime), m_animationDuration) / m_animationDuration) : 0;
+}
+
+void RenderProgress::animationTimerFired(Timer<RenderProgress>*)
+{
+ repaint();
+}
+
+void RenderProgress::paint(PaintInfo& paintInfo, int tx, int ty)
+{
+ if (paintInfo.phase == PaintPhaseBlockBackground) {
+ if (!m_animationTimer.isActive() && m_animating)
+ m_animationTimer.startOneShot(m_animationRepeatInterval);
+ }
+
+ RenderBlock::paint(paintInfo, tx, ty);
+}
+
+void RenderProgress::updateAnimationState()
+{
+ m_animationDuration = theme()->animationDurationForProgressBar(this);
+ m_animationRepeatInterval = theme()->animationRepeatIntervalForProgressBar(this);
+
+ bool animating = m_animationDuration > 0;
+ if (animating == m_animating)
+ return;
+
+ m_animating = animating;
+ if (m_animating) {
+ m_animationStartTime = currentTime();
+ m_animationTimer.startOneShot(m_animationRepeatInterval);
+ } else
+ m_animationTimer.stop();
+}
+
} // namespace WebCore
#endif
diff --git a/WebCore/rendering/RenderProgress.h b/WebCore/rendering/RenderProgress.h
index a2e823c..767ed37 100644
--- a/WebCore/rendering/RenderProgress.h
+++ b/WebCore/rendering/RenderProgress.h
@@ -32,13 +32,24 @@
public:
RenderProgress(HTMLProgressElement*);
double position() { return m_position; }
+ double animationProgress();
private:
virtual const char* renderName() const { return "RenderProgress"; }
virtual bool isProgress() const { return true; }
virtual void layout();
virtual void updateFromElement();
+ virtual void paint(PaintInfo&, int tx, int ty);
+
+ void animationTimerFired(Timer<RenderProgress>*);
+ void updateAnimationState();
+
double m_position;
+ double m_animationStartTime;
+ double m_animationRepeatInterval;
+ double m_animationDuration;
+ bool m_animating;
+ Timer<RenderProgress> m_animationTimer;
};
inline RenderProgress* toRenderProgress(RenderObject* object)
diff --git a/WebCore/rendering/RenderTheme.cpp b/WebCore/rendering/RenderTheme.cpp
index 7c284a6..1d0411a 100644
--- a/WebCore/rendering/RenderTheme.cpp
+++ b/WebCore/rendering/RenderTheme.cpp
@@ -840,10 +840,14 @@
}
#if ENABLE(PROGRESS_TAG)
-bool RenderTheme::getNumberOfPixelsForProgressPosition(double , int& progressSize) const
+double RenderTheme::animationRepeatIntervalForProgressBar(RenderProgress*) const
{
- progressSize = 0;
- return false;
+ return 0;
+}
+
+double RenderTheme::animationDurationForProgressBar(RenderProgress*) const
+{
+ return 0;
}
void RenderTheme::adjustProgressBarStyle(CSSStyleSelector*, RenderStyle*, Element*) const
diff --git a/WebCore/rendering/RenderTheme.h b/WebCore/rendering/RenderTheme.h
index fbdf910..5f65d7f 100644
--- a/WebCore/rendering/RenderTheme.h
+++ b/WebCore/rendering/RenderTheme.h
@@ -39,6 +39,9 @@
class Element;
class PopupMenu;
class RenderMenuList;
+#if ENABLE(PROGRESS_TAG)
+class RenderProgress;
+#endif
class CSSStyleSheet;
class RenderTheme : public RefCounted<RenderTheme> {
@@ -170,10 +173,10 @@
virtual bool paintCapsLockIndicator(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { return 0; };
#if ENABLE(PROGRESS_TAG)
- // Helper method for optimizing the paint area of the progress bar.
- // If supported, it returns number of pixels needed to draw the progress bar up to the progress position.
- // progressSize is the value that is passed back to RenderTheme during drawing.
- virtual bool getNumberOfPixelsForProgressPosition(double position, int& progressSize) const;
+ // Returns the repeat interval of the animation for the progress bar.
+ virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const;
+ // Returns the duration of the animation for the progress bar.
+ virtual double animationDurationForProgressBar(RenderProgress*) const;
#endif
#if ENABLE(VIDEO)