18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Portions are Copyright (C) 1998 Netscape Communications Corporation.
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Other contributors:
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *   Robert O'Callahan <roc+@cs.cmu.edu>
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *   David Baron <dbaron@fas.harvard.edu>
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *   Christian Biesinger <cbiesinger@web.de>
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *   Randall Jesup <rjesup@wgate.com>
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *   Josh Soref <timeless@mac.com>
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *   Boris Zbarsky <bzbarsky@mit.edu>
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Lesser General Public
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2.1 of the License, or (at your option) any later version.
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful,
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Lesser General Public License for more details.
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Lesser General Public
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License along with this library; if not, write to the Free Software
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Alternatively, the contents of this file may be used under the terms
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * of either the Mozilla Public License Version 1.1, found at
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (the "GPL"), in which case the provisions of the MPL or the GPL are
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * applicable instead of those above.  If you wish to allow use of your
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version of this file only under the terms of one of those two
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * licenses (the MPL or the GPL) and not to allow others to use your
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version of this file under the LGPL, indicate your decision by
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * deletingthe provisions above and replace them with the notice and
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * other provisions required by the MPL or the GPL, as the case may be.
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * If you do not delete the provisions above, a recipient may use your
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version of this file under any of the LGPL, the MPL or the GPL.
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderMarquee.h"
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FrameView.h"
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLMarqueeElement.h"
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLNames.h"
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderLayer.h"
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace std;
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectusing namespace HTMLNames;
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectRenderMarquee::RenderMarquee(RenderLayer* l)
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    : m_layer(l), m_currentLoop(0)
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_totalLoops(0)
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_timer(this, &RenderMarquee::timerFired)
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_start(0), m_end(0), m_speed(0), m_reset(false)
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_suspended(false), m_stopped(false), m_direction(MAUTO)
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
69a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochRenderMarquee::~RenderMarquee()
70a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
71a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
72a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint RenderMarquee::marqueeSpeed() const
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int result = m_layer->renderer()->style()->marqueeSpeed();
768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    Node* n = m_layer->renderer()->node();
778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (n && n->hasTagName(marqueeTag)) {
788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        HTMLMarqueeElement* marqueeElt = static_cast<HTMLMarqueeElement*>(n);
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result = max(result, marqueeElt->minimumDelay());
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result;
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectEMarqueeDirection RenderMarquee::direction() const
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: Support the CSS3 "auto" value for determining the direction of the marquee.
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // For now just map MAUTO to MBACKWARD
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    EMarqueeDirection result = m_layer->renderer()->style()->marqueeDirection();
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    TextDirection dir = m_layer->renderer()->style()->direction();
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (result == MAUTO)
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result = MBACKWARD;
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (result == MFORWARD)
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result = (dir == LTR) ? MRIGHT : MLEFT;
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (result == MBACKWARD)
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result = (dir == LTR) ? MLEFT : MRIGHT;
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Now we have the real direction.  Next we check to see if the increment is negative.
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If so, then we reverse the direction.
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Length increment = m_layer->renderer()->style()->marqueeIncrement();
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (increment.isNegative())
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result = static_cast<EMarqueeDirection>(-result);
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return result;
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool RenderMarquee::isHorizontal() const
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return direction() == MLEFT || direction() == MRIGHT;
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint RenderMarquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge)
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    RenderBox* box = m_layer->renderBox();
1148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ASSERT(box);
1158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    RenderStyle* s = box->style();
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isHorizontal()) {
117a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        bool ltr = s->isLeftToRightDirection();
1188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        int clientWidth = box->clientWidth();
1192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        int contentWidth = ltr ? box->maxXLayoutOverflow() : box->minXLayoutOverflow();
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (ltr)
1218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            contentWidth += (box->paddingRight() - box->borderLeft());
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else {
1238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            contentWidth = box->width() - contentWidth;
1248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            contentWidth += (box->paddingLeft() - box->borderRight());
1258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (dir == MRIGHT) {
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (stopAtContentEdge)
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return max(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            else
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return ltr ? contentWidth : clientWidth;
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else {
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (stopAtContentEdge)
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return min(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            else
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return ltr ? -clientWidth : -contentWidth;
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else {
1402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        int contentHeight = box->maxYLayoutOverflow() - box->borderTop() + box->paddingBottom();
1418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        int clientHeight = box->clientHeight();
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (dir == MUP) {
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (stopAtContentEdge)
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                 return min(contentHeight - clientHeight, 0);
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            else
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return -clientHeight;
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else {
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (stopAtContentEdge)
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return max(contentHeight - clientHeight, 0);
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            else
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return contentHeight;
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid RenderMarquee::start()
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
159231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_timer.isActive() || m_layer->renderer()->style()->marqueeIncrement().isZero()
160231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if ENABLE(WCSS) && ENABLE(XHTMLMP)
161231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        || (m_layer->renderer()->document()->isXHTMLMPDocument() && !m_layer->renderer()->style()->marqueeLoopCount())
162231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif
163231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block       )
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // We may end up propagating a scroll event. It is important that we suspend events until
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // the end of the function since they could delete the layer, including the marquee.
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FrameView* frameView = m_layer->renderer()->document()->view();
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (frameView)
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        frameView->pauseScheduledEvents();
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_suspended && !m_stopped) {
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isHorizontal())
174ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch            m_layer->scrollToOffset(m_start, 0);
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else
176ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch            m_layer->scrollToOffset(0, m_start);
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else {
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_suspended = false;
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_stopped = false;
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_timer.startRepeating(speed() * 0.001);
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (frameView)
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        frameView->resumeScheduledEvents();
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid RenderMarquee::suspend()
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_timer.stop();
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_suspended = true;
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid RenderMarquee::stop()
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_timer.stop();
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_stopped = true;
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid RenderMarquee::updateMarqueePosition()
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool activate = (m_totalLoops <= 0 || m_currentLoop < m_totalLoops);
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (activate) {
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        EMarqueeBehavior behavior = m_layer->renderer()->style()->marqueeBehavior();
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_start = computePosition(direction(), behavior == MALTERNATE);
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_end = computePosition(reverseDirection(), behavior == MALTERNATE || behavior == MSLIDE);
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!m_stopped)
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            start();
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid RenderMarquee::updateMarqueeStyle()
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderStyle* s = m_layer->renderer()->style();
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_direction != s->marqueeDirection() || (m_totalLoops != s->marqueeLoopCount() && m_currentLoop >= m_totalLoops))
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_currentLoop = 0; // When direction changes or our loopCount is a smaller number than our current loop, reset our loop.
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_totalLoops = s->marqueeLoopCount();
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_direction = s->marqueeDirection();
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_layer->renderer()->isHTMLMarquee()) {
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Hack for WinIE.  In WinIE, a value of 0 or lower for the loop count for SLIDE means to only do
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // one loop.
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_totalLoops <= 0 && s->marqueeBehavior() == MSLIDE)
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_totalLoops = 1;
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Hack alert: Set the white-space value to nowrap for horizontal marquees with inline children, thus ensuring
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // all the text ends up on one line by default.  Limit this hack to the <marquee> element to emulate
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // WinIE's behavior.  Someone using CSS3 can use white-space: nowrap on their own to get this effect.
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Second hack alert: Set the text-align back to auto.  WinIE completely ignores text-align on the
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // marquee element.
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // FIXME: Bring these up with the CSS WG.
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isHorizontal() && m_layer->renderer()->childrenInline()) {
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            s->setWhiteSpace(NOWRAP);
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            s->setTextAlign(TAAUTO);
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Marquee height hack!! Make sure that, if it is a horizontal marquee, the height attribute is overridden
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // if it is smaller than the font size. If it is a vertical marquee and height is not specified, we default
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // to a marquee of 200px.
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isHorizontal()) {
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (s->height().isFixed() && s->height().value() < s->fontSize())
2460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            s->setHeight(Length(s->fontSize(), Fixed));
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else if (s->height().isAuto())  //vertical marquee with no specified height
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        s->setHeight(Length(200, Fixed));
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (speed() != marqueeSpeed()) {
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_speed = marqueeSpeed();
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_timer.isActive())
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_timer.startRepeating(speed() * 0.001);
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check the loop count to see if we should now stop.
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool activate = (m_totalLoops <= 0 || m_currentLoop < m_totalLoops);
2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (activate && !m_timer.isActive())
2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_layer->renderer()->setNeedsLayout(true);
2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else if (!activate && m_timer.isActive())
2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_timer.stop();
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid RenderMarquee::timerFired(Timer<RenderMarquee>*)
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_layer->renderer()->needsLayout())
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_reset) {
2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_reset = false;
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isHorizontal())
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_layer->scrollToXOffset(m_start);
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_layer->scrollToYOffset(m_start);
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderStyle* s = m_layer->renderer()->style();
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int endPoint = m_end;
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int range = m_end - m_start;
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int newPos;
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (range == 0)
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        newPos = m_end;
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else {
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool addIncrement = direction() == MUP || direction() == MLEFT;
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool isReversed = s->marqueeBehavior() == MALTERNATE && m_currentLoop % 2;
2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (isReversed) {
2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // We're going in the reverse direction.
2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            endPoint = m_start;
2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            range = -range;
2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            addIncrement = !addIncrement;
2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool positive = range > 0;
2958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        int clientSize = (isHorizontal() ? m_layer->renderBox()->clientWidth() : m_layer->renderBox()->clientHeight());
296f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        int increment = abs(m_layer->renderer()->style()->marqueeIncrement().calcValue(clientSize));
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        int currentPos = (isHorizontal() ? m_layer->scrollXOffset() : m_layer->scrollYOffset());
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        newPos =  currentPos + (addIncrement ? increment : -increment);
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (positive)
3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            newPos = min(newPos, endPoint);
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else
3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            newPos = max(newPos, endPoint);
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (newPos == endPoint) {
3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_currentLoop++;
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (m_totalLoops > 0 && m_currentLoop >= m_totalLoops)
3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_timer.stop();
3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else if (s->marqueeBehavior() != MALTERNATE)
3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_reset = true;
3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isHorizontal())
3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_layer->scrollToXOffset(newPos);
3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else
3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_layer->scrollToYOffset(newPos);
3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
320