1 /* 2 * Copyright (C) 2000 Lars Knoll (knoll (at) kde.org) 3 * Copyright (C) 2003, 2004, 2006, 2007, 2008 Apple Inc. All right reserved. 4 * Copyright (C) 2011 Google, 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 #ifndef BidiRunList_h 24 #define BidiRunList_h 25 26 #include <wtf/Noncopyable.h> 27 28 namespace WebCore { 29 30 template <class Run> 31 class BidiRunList { 32 WTF_MAKE_NONCOPYABLE(BidiRunList); 33 public: 34 BidiRunList() 35 : m_firstRun(0) 36 , m_lastRun(0) 37 , m_logicallyLastRun(0) 38 , m_runCount(0) 39 { 40 } 41 42 // FIXME: Once BidiResolver no longer owns the BidiRunList, 43 // then ~BidiRunList should call deleteRuns() automatically. 44 45 Run* firstRun() const { return m_firstRun; } 46 Run* lastRun() const { return m_lastRun; } 47 Run* logicallyLastRun() const { return m_logicallyLastRun; } 48 unsigned runCount() const { return m_runCount; } 49 50 void addRun(Run*); 51 void prependRun(Run*); 52 53 void moveRunToEnd(Run*); 54 void moveRunToBeginning(Run*); 55 56 void deleteRuns(); 57 void reverseRuns(unsigned start, unsigned end); 58 void reorderRunsFromLevels(); 59 60 void setLogicallyLastRun(Run* run) { m_logicallyLastRun = run; } 61 62 private: 63 Run* m_firstRun; 64 Run* m_lastRun; 65 Run* m_logicallyLastRun; 66 unsigned m_runCount; 67 }; 68 69 template <class Run> 70 inline void BidiRunList<Run>::addRun(Run* run) 71 { 72 if (!m_firstRun) 73 m_firstRun = run; 74 else 75 m_lastRun->m_next = run; 76 m_lastRun = run; 77 m_runCount++; 78 } 79 80 template <class Run> 81 inline void BidiRunList<Run>::prependRun(Run* run) 82 { 83 ASSERT(!run->m_next); 84 85 if (!m_lastRun) 86 m_lastRun = run; 87 else 88 run->m_next = m_firstRun; 89 m_firstRun = run; 90 m_runCount++; 91 } 92 93 template <class Run> 94 inline void BidiRunList<Run>::moveRunToEnd(Run* run) 95 { 96 ASSERT(m_firstRun); 97 ASSERT(m_lastRun); 98 ASSERT(run->m_next); 99 100 Run* current = 0; 101 Run* next = m_firstRun; 102 while (next != run) { 103 current = next; 104 next = current->next(); 105 } 106 107 if (!current) 108 m_firstRun = run->next(); 109 else 110 current->m_next = run->m_next; 111 112 run->m_next = 0; 113 m_lastRun->m_next = run; 114 m_lastRun = run; 115 } 116 117 template <class Run> 118 inline void BidiRunList<Run>::moveRunToBeginning(Run* run) 119 { 120 ASSERT(m_firstRun); 121 ASSERT(m_lastRun); 122 ASSERT(run != m_firstRun); 123 124 Run* current = m_firstRun; 125 Run* next = current->next(); 126 while (next != run) { 127 current = next; 128 next = current->next(); 129 } 130 131 current->m_next = run->m_next; 132 if (run == m_lastRun) 133 m_lastRun = current; 134 135 run->m_next = m_firstRun; 136 m_firstRun = run; 137 } 138 139 template <class Run> 140 void BidiRunList<Run>::deleteRuns() 141 { 142 if (!m_firstRun) 143 return; 144 145 Run* curr = m_firstRun; 146 while (curr) { 147 Run* s = curr->next(); 148 curr->destroy(); 149 curr = s; 150 } 151 152 m_firstRun = 0; 153 m_lastRun = 0; 154 m_runCount = 0; 155 } 156 157 template <class Run> 158 void BidiRunList<Run>::reverseRuns(unsigned start, unsigned end) 159 { 160 if (start >= end) 161 return; 162 163 ASSERT(end < m_runCount); 164 165 // Get the item before the start of the runs to reverse and put it in 166 // |beforeStart|. |curr| should point to the first run to reverse. 167 Run* curr = m_firstRun; 168 Run* beforeStart = 0; 169 unsigned i = 0; 170 while (i < start) { 171 i++; 172 beforeStart = curr; 173 curr = curr->next(); 174 } 175 176 Run* startRun = curr; 177 while (i < end) { 178 i++; 179 curr = curr->next(); 180 } 181 Run* endRun = curr; 182 Run* afterEnd = curr->next(); 183 184 i = start; 185 curr = startRun; 186 Run* newNext = afterEnd; 187 while (i <= end) { 188 // Do the reversal. 189 Run* next = curr->next(); 190 curr->m_next = newNext; 191 newNext = curr; 192 curr = next; 193 i++; 194 } 195 196 // Now hook up beforeStart and afterEnd to the startRun and endRun. 197 if (beforeStart) 198 beforeStart->m_next = endRun; 199 else 200 m_firstRun = endRun; 201 202 startRun->m_next = afterEnd; 203 if (!afterEnd) 204 m_lastRun = startRun; 205 } 206 207 } // namespace WebCore 208 209 #endif // BidiRunList 210