OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #ifndef CC_BASE_PYRAMID_SEQUENCE_H_ |
| 6 #define CC_BASE_PYRAMID_SEQUENCE_H_ |
| 7 |
| 8 #include <memory> |
| 9 #include <vector> |
| 10 |
| 11 #include "base/logging.h" |
| 12 #include "base/macros.h" |
| 13 #include "cc/base/cc_export.h" |
| 14 #include "cc/base/index_rect.h" |
| 15 |
| 16 namespace cc { |
| 17 |
| 18 // The pyramid sequence covers following 4 directions while iterating, where R |
| 19 // is right, T is top, L is left and B is bottom. |
| 20 // T |
| 21 // L * R |
| 22 // B |
| 23 enum class CoverageDirection : int { |
| 24 NONE = -1, |
| 25 RIGHT = 0, |
| 26 TOP, |
| 27 LEFT, |
| 28 BOTTOM, |
| 29 SIZE |
| 30 }; |
| 31 |
| 32 namespace internal { |
| 33 |
| 34 // This class provides iterating mechanism for numbers between defined bounds. |
| 35 // e.g. For interval having bounds 3 as start and 6 as end, represented as |
| 36 // [3, 6], the interval returns 3, 4, 5, 6 sequence for Iterator traversal and |
| 37 // returns 6, 5, 4, 3 for ReverseIterator traversal. |
| 38 // |
| 39 // start end |
| 40 // | | |
| 41 // V V |
| 42 // ┌───┬───┬───┬───┐ |
| 43 // │ 3 │ 4 │ 5 │ 6 │ |
| 44 // └───┴───┴───┴───┘ |
| 45 class CC_EXPORT Interval { |
| 46 public: |
| 47 class Iterator; |
| 48 class ReverseIterator; |
| 49 |
| 50 Interval() : empty_(true) {} |
| 51 Interval(int start, int end) : empty_(false), start_(start), end_(end) {} |
| 52 |
| 53 Iterator* Begin(); |
| 54 ReverseIterator* ReverseBegin(); |
| 55 |
| 56 // Return the bounds of the interval. |
| 57 int start() const { return start_; } |
| 58 int end() const { return end_; } |
| 59 |
| 60 // Returns true if interval is empty. Empty interval does not return any |
| 61 // index on traversing. |
| 62 bool IsEmpty() const { return empty_; } |
| 63 |
| 64 // Returns the distance between |start_| and |end_| which includes both |
| 65 // |start_| and |end_|. |
| 66 int GetSpan() const; |
| 67 |
| 68 // Return clamped indices for the given indices. |
| 69 int GetForwardClampedIndex(int index) const; |
| 70 int GetBackwardClampedIndex(int index) const; |
| 71 |
| 72 // Clamp this interval to the given interval. For these functions, interval |
| 73 // and other interval to which this interval is to be clammped should be in |
| 74 // the same direction, i.e. both intervals should have either |
| 75 // |start_| <= |end_| or |start_| >= |end_|. |
| 76 void ForwardClampTo(const Interval* other); |
| 77 void BackwardClampTo(const Interval* other); |
| 78 |
| 79 // Return the inflated intervals for the given |level|. |
| 80 void ForwardInflate(int level, Interval* output) const; |
| 81 void BackwardInflate(int level, Interval* output) const; |
| 82 |
| 83 // Returns true if interval contains the given index. |
| 84 bool Contains(int index) const; |
| 85 |
| 86 // For these functions, interval and other interval to which first one is to |
| 87 // be intersected should be in the same direction, i.e. both intervals should |
| 88 // have |start_| <= |end_| or |start_| >= |end_|. |
| 89 bool Intersects(const Interval* interval) const; |
| 90 void Intersect(const Interval* interval); |
| 91 |
| 92 // Iterators. |
| 93 class IteratorBase { |
| 94 public: |
| 95 operator bool() const { return within_bounds_; } |
| 96 IteratorBase& operator++(); |
| 97 int index() { return current_index_; } |
| 98 |
| 99 protected: |
| 100 explicit IteratorBase(Interval* interval); |
| 101 |
| 102 virtual bool IsWithinBounds() = 0; |
| 103 |
| 104 Interval* interval_; |
| 105 bool within_bounds_; |
| 106 int step_; |
| 107 int current_index_; |
| 108 |
| 109 private: |
| 110 DISALLOW_COPY_AND_ASSIGN(IteratorBase); |
| 111 }; |
| 112 |
| 113 class Iterator : public IteratorBase { |
| 114 private: |
| 115 explicit Iterator(Interval* interval); |
| 116 |
| 117 bool IsWithinBounds() override; |
| 118 |
| 119 friend class Interval; |
| 120 |
| 121 DISALLOW_COPY_AND_ASSIGN(Iterator); |
| 122 }; |
| 123 |
| 124 class ReverseIterator : public IteratorBase { |
| 125 private: |
| 126 explicit ReverseIterator(Interval* interval); |
| 127 |
| 128 bool IsWithinBounds() override; |
| 129 |
| 130 friend class Interval; |
| 131 |
| 132 DISALLOW_COPY_AND_ASSIGN(ReverseIterator); |
| 133 }; |
| 134 |
| 135 private: |
| 136 bool empty_; |
| 137 int start_; |
| 138 int end_; |
| 139 }; |
| 140 |
| 141 // This class provides affinity based interating mechanism for the given |
| 142 // |interval| [start, end] with functionality of inflating the |interval|. |
| 143 // The interval inflation means expanding the start and end by n steps forward |
| 144 // or backward, based on |forward_direction| argument provided. Suppose the |
| 145 // LinearSequence has interval [3, 3] i.e. start = 3 and end = 3, the interval |
| 146 // inflated by 1 step in forward direction would be [2, 4] and that of in |
| 147 // backward direction would be [4, 2]. |
| 148 // The affinity based traversing means portion of |interval| that intersects |
| 149 // with |affinity_interval| is traversed before remaining two portions of |
| 150 // |interval|. Internally the |interval| is split up into three sub-intervals |
| 151 // before traversing as |affinity_sub_interval_|, |before_sub_interval_| and |
| 152 // |after_sub_interval_|. These sub-intervals are traversed instead of directly |
| 153 // traversing |interval|. First |affinity_sub_interval_| is traversed fully, |
| 154 // then remaining two sub-intervals are traversed in alternative fashion. |
| 155 // |
| 156 // e.g. Suppose LinearSequence has interval [0, 9] and affinity interval |
| 157 // [4, 6], then the interval is splitted into three sub-intervals viz. [4, 6], |
| 158 // [3, 0], [7, 9]. |
| 159 // |
| 160 // affinity_sub_interval |
| 161 // ┌─────^─────┐ |
| 162 // ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐ |
| 163 // │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ |
| 164 // └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘ |
| 165 // └───────v───────┘ └─────v─────┘ |
| 166 // before_sub_interval after_sub_interval |
| 167 // |
| 168 // On traversal, Iterator returns the sequence as 4, 5, 6, 3, 7, 2, 8, 1, 9, 0 |
| 169 // and RerverseIterator returns the sequence as 0, 9, 1, 8, 2, 7, 3, 6, 5, 4. |
| 170 class CC_EXPORT LinearSequence { |
| 171 public: |
| 172 class Iterator; |
| 173 class ReverseIterator; |
| 174 |
| 175 // The |interval| is used for actual traversal. The |affinity_interval| is |
| 176 // used for defining affinity in the |interval|. While traversing portion of |
| 177 // |interval| which intersects |affinity_interval| is traversed before |
| 178 // remaining portions of the interval. The |inflate_limit| is used to clamp |
| 179 // the |interval|, when it is inflated to any given |level|. |
| 180 LinearSequence(bool forward_direction, |
| 181 std::unique_ptr<Interval> interval, |
| 182 std::unique_ptr<Interval> affinity_interval, |
| 183 std::unique_ptr<Interval> inflate_limit); |
| 184 ~LinearSequence(); |
| 185 |
| 186 Iterator* Begin(); |
| 187 ReverseIterator* ReverseBegin(); |
| 188 |
| 189 // This function inflates the original |interval| to the given |level|, |
| 190 // where level >= 0. |
| 191 void InflateToLevel(int level); |
| 192 |
| 193 // Iterators. |
| 194 class IteratorBase { |
| 195 public: |
| 196 ~IteratorBase(); |
| 197 |
| 198 operator bool() const { return within_bounds_; } |
| 199 IteratorBase& operator++(); |
| 200 int index() { return current_index_; } |
| 201 |
| 202 protected: |
| 203 enum class SubIntervalIteratorType : unsigned int { |
| 204 AFFINITY, |
| 205 BEFORE, |
| 206 AFTER |
| 207 }; |
| 208 |
| 209 explicit IteratorBase(LinearSequence* level_sequence); |
| 210 |
| 211 bool IsWithinBounds(); |
| 212 virtual SubIntervalIteratorType GetCurrentSubIntervalIteratorType() = 0; |
| 213 |
| 214 LinearSequence* level_sequence_; |
| 215 bool within_bounds_; |
| 216 int current_index_; |
| 217 std::unique_ptr<Interval::IteratorBase> sub_interval_iterators_[3]; |
| 218 SubIntervalIteratorType current_sub_interval_iterator_; |
| 219 |
| 220 private: |
| 221 DISALLOW_COPY_AND_ASSIGN(IteratorBase); |
| 222 }; |
| 223 |
| 224 class Iterator : public IteratorBase { |
| 225 public: |
| 226 ~Iterator(); |
| 227 |
| 228 private: |
| 229 explicit Iterator(LinearSequence* level_sequence); |
| 230 |
| 231 SubIntervalIteratorType GetCurrentSubIntervalIteratorType() override; |
| 232 |
| 233 bool before_first_; |
| 234 |
| 235 friend class LinearSequence; |
| 236 |
| 237 DISALLOW_COPY_AND_ASSIGN(Iterator); |
| 238 }; |
| 239 |
| 240 class ReverseIterator : public IteratorBase { |
| 241 public: |
| 242 ~ReverseIterator(); |
| 243 |
| 244 private: |
| 245 explicit ReverseIterator(LinearSequence* level_sequence); |
| 246 |
| 247 SubIntervalIteratorType GetCurrentSubIntervalIteratorType() override; |
| 248 |
| 249 bool after_first_; |
| 250 int before_sub_interval_span_; |
| 251 int after_sub_interval_span_; |
| 252 |
| 253 friend class LinearSequence; |
| 254 |
| 255 DISALLOW_COPY_AND_ASSIGN(ReverseIterator); |
| 256 }; |
| 257 |
| 258 private: |
| 259 void TrisectInterval(); |
| 260 |
| 261 bool forward_direction_; |
| 262 std::unique_ptr<Interval> interval_; |
| 263 std::unique_ptr<Interval> inflate_limit_; |
| 264 std::unique_ptr<Interval> affinity_interval_; |
| 265 |
| 266 std::unique_ptr<Interval> initial_interval_; |
| 267 |
| 268 // The |interval_| is split up into following sub-intervals such a way that |
| 269 // they are non-intersecting, adjacent and union of these three sub-intervals |
| 270 // is |interval_|. |
| 271 Interval affinity_sub_interval_; |
| 272 Interval before_sub_interval_; |
| 273 Interval after_sub_interval_; |
| 274 |
| 275 DISALLOW_COPY_AND_ASSIGN(LinearSequence); |
| 276 }; |
| 277 |
| 278 // This class implements the 2D sequence (x, y) which uses LinearSequence and |
| 279 // Interval to represent the co-ordinates. The linear sequence |
| 280 // |traversal_sequence| is used for traversing the actual sequence cross the |
| 281 // direction and |level_interval| is used for computing the number of levels in |
| 282 // the |traversal_sequence|. The interval in |traversal_sequence| can be |
| 283 // inflated max to the levels given by |level_interval|. |
| 284 // This class uses LevelDistance structure to represent the distance associated |
| 285 // with the level. The first level has distance 0, to represent the minimum |
| 286 // distance for the origin level, and increments by the step of |distance| |
| 287 // given in LevelDistance for every level. Suppose there are 5 levels and |
| 288 // distance is 10, then the levels would have distances as 0, 10, 20, 30, 40. |
| 289 // The distances are stored in the sorted order in vector, so that the distance |
| 290 // at front is minimum, while the distance at back is maximum. The layout of |
| 291 // the level distance vector for the example would be (0, 0), (1, 10), (2, 20), |
| 292 // (3, 30), (4, 40). |
| 293 // |
| 294 // e.g. If traversal sequence has interval [3, 4], number of levels is 3 and |
| 295 // distance is 10, then the Iterator would give following data on traversal. |
| 296 // |
| 297 // traversal_sequence level_index |
| 298 // [3, 4] 0 |
| 299 // [2, 5] 1 |
| 300 // [1, 6] 2 |
| 301 // |
| 302 // The order of iteration for ReverseIterator would be as given below. |
| 303 // |
| 304 // traversal_sequence level index |
| 305 // [1, 6] 2 |
| 306 // [2, 5] 1 |
| 307 // [3, 4] 0 |
| 308 // |
| 309 // The indices (x, y) for the iterator are as given below. |
| 310 // |
| 311 // (3, 0), (4, 0) (level 1) |
| 312 // (2, 1), (3, 1), (4, 1), (5, 1), (level 2) |
| 313 // (1, 2), (2, 2), (3, 2), (4, 2), (5, 2), (6, 2) (level 3) |
| 314 // |
| 315 // In a way the original interval in |traversal_sequence| and inflated |
| 316 // intervals form triangular geometry in co-ordinate space as given below, |
| 317 // hence the name TriangularSequence. |
| 318 // |
| 319 // x 0 1 2 3 4 5 6 |
| 320 // y ┌───┬───┬───┬───┬───┬───┬───┐ |
| 321 // 0 │ │ │ │ 3 │ 4 │ │ │ (level 1, distance 0) |
| 322 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 323 // 1 │ │ │ 2 │ 3 │ 4 │ 5 │ │ (level 2, distance 10) |
| 324 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 325 // 2 │ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ (level 3, distance 20) |
| 326 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 327 // 3 │ │ │ │ │ │ │ │ |
| 328 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 329 // 4 │ │ │ │ │ │ │ │ |
| 330 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 331 // 5 │ │ │ │ │ │ │ │ |
| 332 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 333 // 6 │ │ │ │ │ │ │ │ |
| 334 // └───┴───┴───┴───┴───┴───┴───┘ |
| 335 class CC_EXPORT TriangularSequence { |
| 336 public: |
| 337 class Iterator; |
| 338 class ReverseIterator; |
| 339 |
| 340 // The |traversal_sequence| defines the sequence for traversal and |
| 341 // |level_interval| defines the number of levels for |traversal_sequence|. |
| 342 // If |should_swap_index_representation| is false, then the indices in |
| 343 // |traversal_sequence| represent the x indices and level indices in |
| 344 // |level_interval| represent the y indices, otherwise vice-versa. The |
| 345 // |levels_to_skip| defines the number of levels which should be skipped to |
| 346 // avoid unnecessary traversing. Check PyramidSequence::PyramidSequence() for |
| 347 // more details on level skipping. The |distance| defines the length for the |
| 348 // index. |
| 349 TriangularSequence(CoverageDirection coverage_direction, |
| 350 std::unique_ptr<LinearSequence> traversal_sequence, |
| 351 std::unique_ptr<Interval> level_interval, |
| 352 bool should_swap_index_representation, |
| 353 int levels_to_skip, |
| 354 int distance); |
| 355 ~TriangularSequence(); |
| 356 |
| 357 Iterator* Begin(); |
| 358 ReverseIterator* ReverseBegin(); |
| 359 |
| 360 CoverageDirection coverage_direction() const { return coverage_direction_; } |
| 361 |
| 362 struct LevelDistance { |
| 363 LevelDistance(int interval_level, int level_index, int distance) |
| 364 : interval_level(interval_level), |
| 365 level_index(level_index), |
| 366 distance(distance) {} |
| 367 |
| 368 int interval_level; |
| 369 int level_index; |
| 370 int distance; |
| 371 }; |
| 372 |
| 373 class IteratorBase { |
| 374 public: |
| 375 IteratorBase(); |
| 376 ~IteratorBase(); |
| 377 |
| 378 operator bool() const { return !level_distances_.empty(); } |
| 379 IteratorBase& operator++(); |
| 380 LinearSequence* traversal_sequence() { |
| 381 DCHECK(*this); |
| 382 return traversal_sequence_; |
| 383 } |
| 384 int level_index() { |
| 385 DCHECK(*this); |
| 386 return current_level_index_; |
| 387 } |
| 388 |
| 389 bool is_index_representation_swapped() const { |
| 390 return should_swap_index_representation_; |
| 391 } |
| 392 |
| 393 virtual int GetNextDistance() const = 0; |
| 394 |
| 395 protected: |
| 396 explicit IteratorBase(TriangularSequence* triangular_sequence); |
| 397 |
| 398 virtual void Advance() = 0; |
| 399 virtual void UpdateCurrent() = 0; |
| 400 |
| 401 LinearSequence* traversal_sequence_; |
| 402 bool should_swap_index_representation_; |
| 403 std::vector<LevelDistance> level_distances_; |
| 404 int current_level_index_; |
| 405 |
| 406 private: |
| 407 DISALLOW_COPY_AND_ASSIGN(IteratorBase); |
| 408 }; |
| 409 |
| 410 class Iterator : public IteratorBase { |
| 411 public: |
| 412 Iterator(); |
| 413 |
| 414 // Returns next minimum distance. |
| 415 int GetNextDistance() const override; |
| 416 |
| 417 private: |
| 418 explicit Iterator(TriangularSequence* triangular_sequence); |
| 419 |
| 420 void Advance() override; |
| 421 void UpdateCurrent() override; |
| 422 |
| 423 friend class TriangularSequence; |
| 424 |
| 425 DISALLOW_COPY_AND_ASSIGN(Iterator); |
| 426 }; |
| 427 |
| 428 class ReverseIterator : public IteratorBase { |
| 429 public: |
| 430 ReverseIterator(); |
| 431 |
| 432 // Returns next maximum distance. |
| 433 int GetNextDistance() const override; |
| 434 |
| 435 private: |
| 436 explicit ReverseIterator(TriangularSequence* triangular_sequence); |
| 437 |
| 438 void Advance() override; |
| 439 void UpdateCurrent() override; |
| 440 |
| 441 friend class TriangularSequence; |
| 442 |
| 443 DISALLOW_COPY_AND_ASSIGN(ReverseIterator); |
| 444 }; |
| 445 |
| 446 typedef std::vector<std::unique_ptr<TriangularSequence>> Vector; |
| 447 typedef std::vector<TriangularSequence::IteratorBase> IteratorVector; |
| 448 |
| 449 private: |
| 450 CoverageDirection coverage_direction_; |
| 451 std::unique_ptr<LinearSequence> traversal_sequence_; |
| 452 std::unique_ptr<Interval> level_interval_; |
| 453 bool should_swap_index_representation_; |
| 454 int levels_to_skip_; |
| 455 int distance_; |
| 456 |
| 457 DISALLOW_COPY_AND_ASSIGN(TriangularSequence); |
| 458 }; |
| 459 |
| 460 // The pyramid sequence consists of 4 triangular sequences, one for each of |
| 461 // the directions considered counter-clockwise or clockwise. The ideal pyramid |
| 462 // sequence is as given below where it has all triangular sequences in 4 |
| 463 // directions. |
| 464 // |
| 465 // ┌───┬───┬───┬───┬───┬───┬───┐ |
| 466 // │ L │ T │ T │ T │ T │ T │ R │ |
| 467 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 468 // │ L │ L │ T │ T │ T │ R │ R │ |
| 469 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 470 // │ L │ L │ L │ T │ R │ R │ R │ |
| 471 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 472 // │ L │ L │ L │ * │ R │ R │ R │ |
| 473 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 474 // │ L │ L │ L │ B │ R │ R │ R │ |
| 475 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 476 // │ L │ L │ B │ B │ B │ R │ R │ |
| 477 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 478 // │ L │ B │ B │ B │ B │ B │ R │ |
| 479 // └───┴───┴───┴───┴───┴───┴───┘ |
| 480 // |
| 481 // The triangular sequences for the above pyramid sequence are shown below. |
| 482 // * represents the center. |
| 483 // |
| 484 // (T = top) |
| 485 // ┌───┬───┬───┬───┬───┐ |
| 486 // │ T │ T │ T │ T │ T │ |
| 487 // ┌───┐ └───┼───┼───┼───┼───┘ ┌───┐ |
| 488 // │ L │ │ T │ T │ T │ │ R │ |
| 489 // ├───┼───┐ └───┼───┼───┘ ┌───┼───┤ |
| 490 // │ L │ L │ │ T │ │ R │ R │ |
| 491 // ├───┼───┼───┐ └───┘ ┌───┼───┼───┤ |
| 492 // │ L │ L │ L │ │ R │ R │ R │ |
| 493 // ├───┼───┼───┤ ┌───┐ ├───┼───┼───┤ |
| 494 // (L = left) │ L │ L │ L │ │ * │ │ R │ R │ R │ (R = right) |
| 495 // ├───┼───┼───┤ └───┘ ├───┼───┼───┤ |
| 496 // │ L │ L │ L │ │ R │ R │ R │ |
| 497 // ├───┼───┼───┘ ┌───┐ └───┼───┼───┤ |
| 498 // │ L │ L │ │ B │ │ R │ R │ |
| 499 // ├───┼───┘ ┌───┼───┼───┐ └───┼───┤ |
| 500 // │ L │ │ B │ B │ B │ │ R │ |
| 501 // └───┘ ┌───┼───┼───┼───┼───┐ └───┘ |
| 502 // │ B │ B │ B │ B │ B │ |
| 503 // └───┴───┴───┴───┴───┘ |
| 504 // (B = bottom) |
| 505 // |
| 506 // This sequence iterates over all the underlined triangular sequences level by |
| 507 // level in increasing or decreasing order of distances. The increasing order of |
| 508 // distances can be iterated using Iterator, while the decreasing order of |
| 509 // distances can be iterated using ReverseIterator. The default coverage for |
| 510 // internal triangular sequences is R, T, L, B forming spiral order. |
| 511 // The iteration sequence generated by Iterator is as given below. |
| 512 // (Iteration is considered counter-clockwise.) |
| 513 // |
| 514 // x 0 1 2 3 4 5 6 |
| 515 // y ┌───┬───┬───┬───┬───┬───┬───┐ |
| 516 // 0 │ 42│ 36│ 34│ 32│ 33│ 35│ 31│ |
| 517 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 518 // 1 │ 40│ 20│ 16│ 14│ 15│ 13│ 29│ |
| 519 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 520 // 2 │ 38│ 18│ 6│ 4│ 3│ 11│ 27│ |
| 521 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 522 // 3 │ 37│ 17│ 5│ *│ 1│ 9│ 25│ |
| 523 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 524 // 4 │ 39│ 19│ 7│ 8│ 2│ 10│ 26│ |
| 525 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 526 // 5 │ 41│ 21│ 23│ 22│ 24│ 12│ 28│ |
| 527 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 528 // 6 │ 43│ 47│ 45│ 44│ 46│ 48│ 30│ |
| 529 // └───┴───┴───┴───┴───┴───┴───┘ |
| 530 // |
| 531 // The iteration sequence generated by ReverseIterator is as given below. |
| 532 // (Iteration is considered clockwise.) |
| 533 // |
| 534 // x 0 1 2 3 4 5 6 |
| 535 // y ┌───┬───┬───┬───┬───┬───┬───┐ |
| 536 // 0 │ 7│ 13│ 15│ 17│ 16│ 14│ 18│ |
| 537 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 538 // 1 │ 9│ 29│ 33│ 35│ 34│ 36│ 20│ |
| 539 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 540 // 2 │ 11│ 31│ 43│ 45│ 46│ 38│ 22│ |
| 541 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 542 // 3 │ 12│ 32│ 44│ *│ 48│ 40│ 24│ |
| 543 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 544 // 4 │ 10│ 30│ 42│ 41│ 47│ 39│ 23│ |
| 545 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 546 // 5 │ 8│ 28│ 26│ 27│ 25│ 37│ 21│ |
| 547 // ├───┼───┼───┼───┼───┼───┼───┤ |
| 548 // 6 │ 6│ 2│ 4│ 5│ 3│ 1│ 19│ |
| 549 // └───┴───┴───┴───┴───┴───┴───┘ |
| 550 class CC_EXPORT PyramidSequence { |
| 551 public: |
| 552 class Iterator; |
| 553 class ReverseIterator; |
| 554 |
| 555 // The |around_index_rect| is the index rect computed around some index rect, |
| 556 // called as center index rect. In the above example, center index rect is |
| 557 // (3, 3, 3, 3), so around index rect for it is (2, 4, 2, 4). |
| 558 // The |consider_index_rect| is used to limit the coverage and the |
| 559 // |ignore_index_rect| is used to ignore the indices from coverage. For above |
| 560 // example consider index rect is (0, 6, 0, 6) and ignore index rect is |
| 561 // (-1, -1, -1, -1). |
| 562 // The width and height specify the width and height of the single index. This |
| 563 // is used for traversing indices based on their distances from center index |
| 564 // rect. |
| 565 PyramidSequence(const IndexRect& around_index_rect, |
| 566 const IndexRect& consider_index_rect, |
| 567 const IndexRect& ignore_index_rect, |
| 568 int width, |
| 569 int height); |
| 570 ~PyramidSequence(); |
| 571 |
| 572 Iterator* Begin(); |
| 573 ReverseIterator* ReverseBegin(); |
| 574 |
| 575 class IteratorBase { |
| 576 public: |
| 577 IteratorBase(); |
| 578 ~IteratorBase(); |
| 579 |
| 580 operator bool() const; |
| 581 IteratorBase& operator++(); |
| 582 int index_x() const { return index_x_; } |
| 583 int index_y() const { return index_y_; } |
| 584 |
| 585 protected: |
| 586 explicit IteratorBase(const IndexRect& consider_index_rect, |
| 587 const IndexRect& ignore_index_rect); |
| 588 |
| 589 virtual bool IsEmpty() const = 0; |
| 590 virtual void Advance() = 0; |
| 591 virtual void UpdateCurrent() = 0; |
| 592 |
| 593 IndexRect consider_index_rect_; |
| 594 IndexRect ignore_index_rect_; |
| 595 int index_x_; |
| 596 int index_y_; |
| 597 |
| 598 TriangularSequence::IteratorBase* current_triangular_sequence_it_; |
| 599 |
| 600 private: |
| 601 DISALLOW_COPY_AND_ASSIGN(IteratorBase); |
| 602 }; |
| 603 |
| 604 class Iterator : public IteratorBase { |
| 605 public: |
| 606 Iterator(); |
| 607 ~Iterator(); |
| 608 |
| 609 private: |
| 610 explicit Iterator(PyramidSequence* pyramid_sequence); |
| 611 |
| 612 bool IsEmpty() const override; |
| 613 void Advance() override; |
| 614 void UpdateCurrent() override; |
| 615 |
| 616 TriangularSequence::IteratorBase* GetNextTriangularSequenceIterator(); |
| 617 |
| 618 LinearSequence::Iterator* current_traversal_sequence_iterator_; |
| 619 std::vector<std::unique_ptr<TriangularSequence::Iterator>> |
| 620 triangular_sequence_iterators_; |
| 621 |
| 622 friend class PyramidSequence; |
| 623 |
| 624 DISALLOW_COPY_AND_ASSIGN(Iterator); |
| 625 }; |
| 626 |
| 627 class ReverseIterator : public IteratorBase { |
| 628 public: |
| 629 ReverseIterator(); |
| 630 ~ReverseIterator(); |
| 631 |
| 632 private: |
| 633 explicit ReverseIterator(PyramidSequence* pyramid_sequence); |
| 634 |
| 635 bool IsEmpty() const override; |
| 636 void Advance() override; |
| 637 void UpdateCurrent() override; |
| 638 |
| 639 TriangularSequence::IteratorBase* |
| 640 GetNextTriangularSequenceReverseIterator(); |
| 641 |
| 642 LinearSequence::ReverseIterator* |
| 643 current_traversal_sequence_reverse_iterator_; |
| 644 std::vector<std::unique_ptr<TriangularSequence::ReverseIterator>> |
| 645 triangular_sequence_reverse_iterators_; |
| 646 |
| 647 friend class PyramidSequence; |
| 648 |
| 649 DISALLOW_COPY_AND_ASSIGN(ReverseIterator); |
| 650 }; |
| 651 |
| 652 private: |
| 653 void EmplaceAt(int position, |
| 654 std::unique_ptr<TriangularSequence> triangular_sequence); |
| 655 |
| 656 IndexRect consider_index_rect_; |
| 657 IndexRect ignore_index_rect_; |
| 658 TriangularSequence::Vector triangular_sequences_; |
| 659 |
| 660 DISALLOW_COPY_AND_ASSIGN(PyramidSequence); |
| 661 }; |
| 662 |
| 663 } // namespace internal |
| 664 |
| 665 class PyramidSequence { |
| 666 public: |
| 667 PyramidSequence(); |
| 668 PyramidSequence(const IndexRect& around_index_rect, |
| 669 const IndexRect& consider_index_rect, |
| 670 const IndexRect& ignore_index_rect, |
| 671 int width, |
| 672 int height); |
| 673 PyramidSequence(const PyramidSequence& other); |
| 674 PyramidSequence(PyramidSequence&& other); |
| 675 ~PyramidSequence(); |
| 676 |
| 677 PyramidSequence& operator=(const PyramidSequence& other); |
| 678 PyramidSequence& operator=(PyramidSequence&& other); |
| 679 |
| 680 class Iterator { |
| 681 public: |
| 682 Iterator(); |
| 683 Iterator(const Iterator& other); |
| 684 Iterator(Iterator&& other); |
| 685 ~Iterator(); |
| 686 |
| 687 Iterator& operator=(const Iterator& other); |
| 688 Iterator& operator=(Iterator&& other); |
| 689 |
| 690 operator bool() const; |
| 691 Iterator& operator++(); |
| 692 int index_x() const; |
| 693 int index_y() const; |
| 694 |
| 695 public: |
| 696 explicit Iterator(internal::PyramidSequence::Iterator* ptr); |
| 697 |
| 698 std::shared_ptr<internal::PyramidSequence::Iterator> ptr_; |
| 699 |
| 700 friend class PyramidSequence; |
| 701 }; |
| 702 |
| 703 class ReverseIterator { |
| 704 public: |
| 705 ReverseIterator(); |
| 706 ReverseIterator(const ReverseIterator& other); |
| 707 ReverseIterator(ReverseIterator&& other); |
| 708 ~ReverseIterator(); |
| 709 |
| 710 ReverseIterator& operator=(const ReverseIterator& other); |
| 711 ReverseIterator& operator=(ReverseIterator&& other); |
| 712 |
| 713 operator bool() const; |
| 714 ReverseIterator& operator++(); |
| 715 int index_x() const; |
| 716 int index_y() const; |
| 717 |
| 718 private: |
| 719 explicit ReverseIterator(internal::PyramidSequence::ReverseIterator* ptr); |
| 720 |
| 721 std::shared_ptr<internal::PyramidSequence::ReverseIterator> ptr_; |
| 722 |
| 723 friend class PyramidSequence; |
| 724 }; |
| 725 |
| 726 Iterator Begin(); |
| 727 ReverseIterator ReverseBegin(); |
| 728 |
| 729 private: |
| 730 std::shared_ptr<internal::PyramidSequence> ptr_; |
| 731 }; |
| 732 |
| 733 } // namespace cc |
| 734 |
| 735 #endif // CC_BASE_PYRAMID_SEQUENCE_H_ |
OLD | NEW |