Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_fill_interval_map.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2014 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
9
11
12
17
21
23{
24 Private::GlobalMap::iterator rowMap = m_d->map.find(interval.row);
25 if (rowMap == m_d->map.end()) {
26 rowMap = m_d->map.insert(interval.row, Private::LineIntervalMap());
27 }
28
29 rowMap->insert(interval.start, interval);
30}
31
33{
34 Private::IteratorRange range;
35 range = m_d->findFirstIntersectingInterval(*interval);
36
37 Private::LineIntervalMap::iterator it = range.beginIt;
38
39 while (interval->isValid() && it != range.endIt) {
40 bool needsIncrement = true;
41
42 if (it->start <= interval->start && it->end >= interval->start) {
43 int savedIntervalStart = interval->start;
44 interval->start = it->end + 1;
45
50 if (it->end > interval->end) {
51 KisFillInterval newInterval(interval->end + 1, it->end, it->row);
52 range.rowMapIt->insert(newInterval.start, newInterval);
53 }
54
55 it->end = savedIntervalStart - 1;
56
64 if (!it->isValid()) {
65 it = range.rowMapIt->erase(it);
66 needsIncrement = false;
67 }
68 } else if (it->start <= interval->end && it->end >= interval->end) {
69 int savedIntervalEnd = interval->end;
70 interval->end = it->start - 1;
71 it->start = savedIntervalEnd + 1;
72
77 if (!it->isValid()) {
78 it = range.rowMapIt->erase(it);
79 needsIncrement = false;
80 }
81 } else if (it->start > interval->end) {
82 break;
83 }
84
85#ifdef ENABLE_FILL_SANITY_CHECKS
86 else if (it->start > interval->start && it->end < interval->end) {
87 SANITY_ASSERT_MSG(0, "FATAL: The backward interval cannot fully reside inside the forward interval");
88 interval->invalidate();
89 it->invalidate();
90 it = range.rowMapIt->erase(it);
91 needsIncrement = false;
92 }
93
94 // The code above should have removed the invalidated backward interval,
95 // just verify that
96 KIS_SAFE_ASSERT_RECOVER((it == range.endIt || it->isValid()) &&
97 "FATAL: The backward interval cannot become "
98 "invalid during the crop action") {
99 it = range.rowMapIt->erase(it);
100 needsIncrement = false;
101 }
102#endif /* ENABLE_FILL_SANITY_CHECKS */
103
104 if (needsIncrement) {
105 it++;
106 }
107 }
108}
109
110KisFillIntervalMap::Private::IteratorRange
111KisFillIntervalMap::Private::findFirstIntersectingInterval(const KisFillInterval &interval)
112{
113 Private::GlobalMap::iterator rowMap = map.find(interval.row);
114 if (rowMap == map.end()) {
115 return IteratorRange();
116 }
117
118 LineIntervalMap::iterator it = rowMap->begin();
119 LineIntervalMap::iterator end = rowMap->end();
120
121 while(it != end) {
122 if (it->end < interval.start) {
123 ++it;
124 } else if (it->start > interval.end) {
125 it = end;
126 break;
127 } else {
128 break;
129 }
130 }
131
132 return IteratorRange(it, end, rowMap);
133}
134
136{
137 QStack<KisFillInterval> intervals;
138
139 Private::GlobalMap::const_iterator rowMapIt = m_d->map.constBegin();
140 Private::GlobalMap::const_iterator rowMapEndIt = m_d->map.constEnd();
141
142 while (rowMapIt != rowMapEndIt) {
143 Private::LineIntervalMap::const_iterator it = rowMapIt->constBegin();
144 Private::LineIntervalMap::const_iterator end = rowMapIt->constEnd();
145
146 while(it != end) {
147 KisFillInterval interval = *it;
148 interval.row += rowCorrection;
149 intervals.append(interval);
150 ++it;
151 }
152
153 ++rowMapIt;
154 }
155
156 return intervals;
157}
158
160{
161 m_d->map.clear();
162}
const QScopedPointer< Private > m_d
void insertInterval(const KisFillInterval &interval)
QStack< KisFillInterval > fetchAllIntervals(int rowCorrection=0) const
void cropInterval(KisFillInterval *interval)
bool isValid() const
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
#define SANITY_ASSERT_MSG(cond, msg)