1// Aseprite Document Library
2// Copyright (c) 2022 Igara Studio S.A.
3// Copyright (c) 2016-2018 David Capello
4//
5// This file is released under the terms of the MIT license.
6// Read LICENSE.txt for more information.
7
8#ifndef DOC_SELECTED_FRAMES_H_INCLUDED
9#define DOC_SELECTED_FRAMES_H_INCLUDED
10#pragma once
11
12#include "doc/frame_range.h"
13
14#include <iosfwd>
15#include <vector>
16
17namespace doc {
18
19 class SelectedFrames {
20 typedef std::vector<FrameRange> Ranges;
21
22 public:
23 class const_iterator {
24 static const int kNullFrame = -2;
25 public:
26 using iterator_category = std::forward_iterator_tag;
27 using value_type = frame_t;
28 using difference_type = std::ptrdiff_t;
29 using pointer = frame_t*;
30 using reference = frame_t&;
31
32 const_iterator(const Ranges::const_iterator& it)
33 : m_it(it), m_frame(kNullFrame) {
34 }
35
36 const_iterator& operator++() {
37 if (m_frame == kNullFrame)
38 m_frame = m_it->fromFrame;
39
40 if (m_it->fromFrame <= m_it->toFrame) {
41 if (m_frame < m_it->toFrame)
42 ++m_frame;
43 else {
44 m_frame = kNullFrame;
45 ++m_it;
46 }
47 }
48 else {
49 if (m_frame > m_it->toFrame)
50 --m_frame;
51 else {
52 m_frame = kNullFrame;
53 ++m_it;
54 }
55 }
56
57 return *this;
58 }
59
60 frame_t operator*() const {
61 if (m_frame == kNullFrame)
62 m_frame = m_it->fromFrame;
63 return m_frame;
64 }
65
66 bool operator==(const const_iterator& o) const {
67 return (m_it == o.m_it && m_frame == o.m_frame);
68 }
69
70 bool operator!=(const const_iterator& it) const {
71 return !operator==(it);
72 }
73
74 private:
75 mutable Ranges::const_iterator m_it;
76 mutable frame_t m_frame;
77 };
78
79 class const_reverse_iterator {
80 public:
81 using iterator_category = std::forward_iterator_tag;
82 using value_type = frame_t;
83 using difference_type = std::ptrdiff_t;
84 using pointer = frame_t*;
85 using reference = frame_t&;
86
87 const_reverse_iterator(const Ranges::const_reverse_iterator& it)
88 : m_it(it), m_frame(-1) {
89 }
90
91 const_reverse_iterator& operator++() {
92 if (m_frame < 0)
93 m_frame = m_it->toFrame;
94
95 if (m_frame > m_it->fromFrame)
96 --m_frame;
97 else {
98 m_frame = -1;
99 ++m_it;
100 }
101
102 return *this;
103 }
104
105 frame_t operator*() const {
106 if (m_frame < 0)
107 m_frame = m_it->toFrame;
108 return m_frame;
109 }
110
111 bool operator==(const const_reverse_iterator& o) const {
112 return (m_it == o.m_it && m_frame == o.m_frame);
113 }
114
115 bool operator!=(const const_reverse_iterator& it) const {
116 return !operator==(it);
117 }
118
119 private:
120 mutable Ranges::const_reverse_iterator m_it;
121 mutable frame_t m_frame;
122 };
123
124 class Reversed {
125 public:
126 typedef const_reverse_iterator const_iterator;
127
128 const_iterator begin() const { return m_selectedFrames.rbegin(); }
129 const_iterator end() const { return m_selectedFrames.rend(); }
130
131 Reversed(const SelectedFrames& selectedFrames)
132 : m_selectedFrames(selectedFrames) {
133 }
134
135 private:
136 const SelectedFrames& m_selectedFrames;
137 };
138
139 const_iterator begin() const { return const_iterator(m_ranges.begin()); }
140 const_iterator end() const { return const_iterator(m_ranges.end()); }
141 const_reverse_iterator rbegin() const { return const_reverse_iterator(m_ranges.rbegin()); }
142 const_reverse_iterator rend() const { return const_reverse_iterator(m_ranges.rend()); }
143
144 std::size_t size() const;
145 std::size_t ranges() const { return m_ranges.size(); }
146 bool empty() const { return m_ranges.empty(); }
147
148 void clear();
149 void insert(frame_t frame);
150 void insert(frame_t fromFrame, frame_t toFrame);
151 SelectedFrames filter(frame_t fromFrame, frame_t toFrame) const;
152
153 bool contains(frame_t frame) const;
154
155 frame_t firstFrame() const { return (!m_ranges.empty() ? m_ranges.front().fromFrame: -1); }
156 frame_t lastFrame() const { return (!m_ranges.empty() ? m_ranges.back().toFrame: -1); }
157
158 void displace(frame_t frameDelta);
159 Reversed reversed() const { return Reversed(*this); }
160
161 SelectedFrames makeReverse() const;
162 SelectedFrames makePingPong() const;
163
164 bool operator==(const SelectedFrames& o) const {
165 return m_ranges == o.m_ranges;
166 }
167
168 bool operator!=(const SelectedFrames& o) const {
169 return !operator==(o);
170 }
171
172 bool write(std::ostream& os) const;
173 bool read(std::istream& is);
174
175 private:
176 Ranges m_ranges;
177 };
178
179} // namespace doc
180
181#endif // DOC_SELECTED_FRAMES_H_INCLUDED
182