/webview/native/Source/WebCore/platform/text/BidiRunList.h
C++ Header | 253 lines | 182 code | 42 blank | 29 comment | 27 complexity | 41d1e4a9fffc5355b520a0b6cd9cc2a0 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, GPL-2.0, LGPL-2.0
- /*
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2003, 2004, 2006, 2007, 2008 Apple Inc. All right reserved.
- * Copyright (C) 2011 Google, Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
- #ifndef BidiRunList_h
- #define BidiRunList_h
- #include <wtf/Noncopyable.h>
- namespace WebCore {
- template <class Run>
- class BidiRunList {
- WTF_MAKE_NONCOPYABLE(BidiRunList);
- public:
- BidiRunList()
- : m_firstRun(0)
- , m_lastRun(0)
- , m_logicallyLastRun(0)
- , m_runCount(0)
- {
- }
- // FIXME: Once BidiResolver no longer owns the BidiRunList,
- // then ~BidiRunList should call deleteRuns() automatically.
- Run* firstRun() const { return m_firstRun; }
- Run* lastRun() const { return m_lastRun; }
- Run* logicallyLastRun() const { return m_logicallyLastRun; }
- unsigned runCount() const { return m_runCount; }
- void addRun(Run*);
- void prependRun(Run*);
- void moveRunToEnd(Run*);
- void moveRunToBeginning(Run*);
- void deleteRuns();
- void reverseRuns(unsigned start, unsigned end);
- void reorderRunsFromLevels();
- void setLogicallyLastRun(Run* run) { m_logicallyLastRun = run; }
- void replaceRunWithRuns(Run* toReplace, BidiRunList<Run>& newRuns);
- private:
- void clearWithoutDestroyingRuns();
- Run* m_firstRun;
- Run* m_lastRun;
- Run* m_logicallyLastRun;
- unsigned m_runCount;
- };
- template <class Run>
- inline void BidiRunList<Run>::addRun(Run* run)
- {
- if (!m_firstRun)
- m_firstRun = run;
- else
- m_lastRun->m_next = run;
- m_lastRun = run;
- m_runCount++;
- }
- template <class Run>
- inline void BidiRunList<Run>::prependRun(Run* run)
- {
- ASSERT(!run->m_next);
- if (!m_lastRun)
- m_lastRun = run;
- else
- run->m_next = m_firstRun;
- m_firstRun = run;
- m_runCount++;
- }
- template <class Run>
- inline void BidiRunList<Run>::moveRunToEnd(Run* run)
- {
- ASSERT(m_firstRun);
- ASSERT(m_lastRun);
- ASSERT(run->m_next);
- Run* current = 0;
- Run* next = m_firstRun;
- while (next != run) {
- current = next;
- next = current->next();
- }
- if (!current)
- m_firstRun = run->next();
- else
- current->m_next = run->m_next;
- run->m_next = 0;
- m_lastRun->m_next = run;
- m_lastRun = run;
- }
- template <class Run>
- inline void BidiRunList<Run>::moveRunToBeginning(Run* run)
- {
- ASSERT(m_firstRun);
- ASSERT(m_lastRun);
- ASSERT(run != m_firstRun);
- Run* current = m_firstRun;
- Run* next = current->next();
- while (next != run) {
- current = next;
- next = current->next();
- }
- current->m_next = run->m_next;
- if (run == m_lastRun)
- m_lastRun = current;
- run->m_next = m_firstRun;
- m_firstRun = run;
- }
- template <class Run>
- void BidiRunList<Run>::replaceRunWithRuns(Run* toReplace, BidiRunList<Run>& newRuns)
- {
- ASSERT(newRuns.runCount());
- ASSERT(m_firstRun);
- ASSERT(toReplace);
- if (m_firstRun == toReplace)
- m_firstRun = newRuns.firstRun();
- else {
- // Find the run just before "toReplace" in the list of runs.
- Run* previousRun = m_firstRun;
- while (previousRun->next() != toReplace)
- previousRun = previousRun->next();
- ASSERT(previousRun);
- previousRun->setNext(newRuns.firstRun());
- }
- newRuns.lastRun()->setNext(toReplace->next());
- // Fix up any of other pointers which may now be stale.
- if (m_lastRun == toReplace)
- m_lastRun = newRuns.lastRun();
- if (m_logicallyLastRun == toReplace)
- m_logicallyLastRun = newRuns.logicallyLastRun();
- m_runCount += newRuns.runCount() - 1; // We added the new runs and removed toReplace.
- toReplace->destroy();
- newRuns.clearWithoutDestroyingRuns();
- }
- template <class Run>
- void BidiRunList<Run>::clearWithoutDestroyingRuns()
- {
- m_firstRun = 0;
- m_lastRun = 0;
- m_logicallyLastRun = 0;
- m_runCount = 0;
- }
- template <class Run>
- void BidiRunList<Run>::deleteRuns()
- {
- if (!m_firstRun)
- return;
- Run* curr = m_firstRun;
- while (curr) {
- Run* s = curr->next();
- curr->destroy();
- curr = s;
- }
- m_firstRun = 0;
- m_lastRun = 0;
- m_runCount = 0;
- }
- template <class Run>
- void BidiRunList<Run>::reverseRuns(unsigned start, unsigned end)
- {
- if (start >= end)
- return;
- ASSERT(end < m_runCount);
- // Get the item before the start of the runs to reverse and put it in
- // |beforeStart|. |curr| should point to the first run to reverse.
- Run* curr = m_firstRun;
- Run* beforeStart = 0;
- unsigned i = 0;
- while (i < start) {
- i++;
- beforeStart = curr;
- curr = curr->next();
- }
- Run* startRun = curr;
- while (i < end) {
- i++;
- curr = curr->next();
- }
- Run* endRun = curr;
- Run* afterEnd = curr->next();
- i = start;
- curr = startRun;
- Run* newNext = afterEnd;
- while (i <= end) {
- // Do the reversal.
- Run* next = curr->next();
- curr->m_next = newNext;
- newNext = curr;
- curr = next;
- i++;
- }
- // Now hook up beforeStart and afterEnd to the startRun and endRun.
- if (beforeStart)
- beforeStart->m_next = endRun;
- else
- m_firstRun = endRun;
- startRun->m_next = afterEnd;
- if (!afterEnd)
- m_lastRun = startRun;
- }
- } // namespace WebCore
- #endif // BidiRunList