Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: pdf/range_set.cc

Issue 2349753003: Improve linearized pdf load/show time. (Closed)
Patch Set: Fix heap use after free. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 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 #include "pdf/range_set.h"
6
7 #include <algorithm>
8 #include <list>
9 #include <sstream>
10
11 namespace chrome_pdf {
12
13 namespace {
14
15 gfx::Range FixDirection(const gfx::Range& range) {
16 if (!range.IsValid() || !range.is_reversed())
17 return range;
18 return gfx::Range(range.end() + 1, range.start() + 1);
19 }
20
21 } // namespace
22
23 RangeSet::RangeSet() {}
24
25 RangeSet::RangeSet(const gfx::Range& range) {
26 Union(range);
27 }
28
29 RangeSet::RangeSet(const RangeSet& range_set) : ranges_(range_set.ranges_) {
30 }
31
32 RangeSet::RangeSet(RangeSet&& range_set)
33 : ranges_(std::move(range_set.ranges_)) {
34 }
35
36 RangeSet& RangeSet::operator=(const RangeSet& other) {
37 ranges_ = other.ranges_;
38 return *this;
39 }
40
41 RangeSet::~RangeSet() {}
42
43 bool RangeSet::operator==(const RangeSet& other) const {
44 return other.ranges_ == ranges_;
45 }
46
47 bool RangeSet::operator!=(const RangeSet& other) const {
48 return other.ranges_ != ranges_;
49 }
50
51 void RangeSet::Union(const gfx::Range& range) {
52 if (range.is_empty())
53 return;
54 gfx::Range fixed_range = FixDirection(range);
55 if (IsEmpty()) {
56 ranges_.insert(fixed_range);
57 return;
58 }
59
60 auto start = ranges_.upper_bound(fixed_range);
61 if (start != ranges_.begin())
62 --start; // start now points to the key equal or lower than offset.
63 if (start->end() < fixed_range.start())
64 ++start; // start element is entirely before current range, skip it.
65
66 auto end = ranges_.upper_bound(gfx::Range(fixed_range.end()));
67 if (start == end) { // No ranges to merge.
68 ranges_.insert(fixed_range);
69 return;
70 }
71
72 --end;
73
74 int new_start = std::min<size_t>(start->start(), fixed_range.start());
75 int new_end = std::max(end->end(), fixed_range.end());
76
77 ranges_.erase(start, ++end);
78 ranges_.insert(gfx::Range(new_start, new_end));
79 }
80
81 void RangeSet::Union(const RangeSet& range_set) {
82 if (&range_set == this)
83 return;
84 for (const auto& it : range_set.ranges()) {
85 Union(it);
86 }
87 }
88
89 bool RangeSet::Contains(uint32_t point) const {
90 return Contains(gfx::Range(point, point + 1));
91 }
92
93 bool RangeSet::Contains(const gfx::Range& range) const {
94 if (range.is_empty())
95 return false;
96 const gfx::Range fixed_range = FixDirection(range);
97 auto it = ranges().upper_bound(fixed_range);
98 if (it == ranges().begin())
99 return false; // No ranges includes range.start().
100
101 --it; // Now it starts equal or before range.start().
102 return it->end() >= fixed_range.end();
103 }
104
105 bool RangeSet::Contains(const RangeSet& range_set) const {
106 for (const auto& it : range_set.ranges()) {
107 if (!Contains(it))
108 return false;
109 }
110 return true;
111 }
112
113 bool RangeSet::Intersects(const gfx::Range& range) const {
114 if (IsEmpty() || range.is_empty())
115 return false;
116 const gfx::Range fixed_range = FixDirection(range);
117 auto start = ranges_.upper_bound(fixed_range);
118 if (start != ranges_.begin())
119 --start; // start now points to the key equal or lower than
120 // range.start().
121 if (start->end() < range.start())
122 ++start; // start element is entirely before current range, skip it.
123 auto end = ranges_.upper_bound(gfx::Range(fixed_range.end()));
124 for (auto it = start; it != end; ++it) {
125 if (fixed_range.end() > it->start() && fixed_range.start() < it->end())
126 return true;
127 }
128 return false;
129 }
130
131 bool RangeSet::Intersects(const RangeSet& range_set) const {
132 for (const auto& it : range_set.ranges()) {
133 if (Intersects(it))
134 return true;
135 }
136 return false;
137 }
138
139 void RangeSet::Intersect(const gfx::Range& range) {
140 Intersect(RangeSet(range));
141 }
142
143 void RangeSet::Intersect(const RangeSet& range_set) {
144 if (IsEmpty())
145 return;
146 RangesContainer new_ranges;
147 for (const auto& range : range_set.ranges()) {
148 auto start = ranges_.upper_bound(range);
149 if (start != ranges_.begin())
150 --start; // start now points to the key equal or lower than
151 // range.start().
152 if (start->end() < range.start())
153 ++start; // start element is entirely before current range, skip it.
154 auto end = ranges_.upper_bound(gfx::Range(range.end()));
155 if (start == end) { // No data in the current range available.
156 continue;
157 }
158 for (auto it = start; it != end; ++it) {
159 const gfx::Range new_range = range.Intersect(*it);
160 if (!new_range.is_empty()) {
161 new_ranges.insert(new_range);
162 }
163 }
164 }
165 new_ranges.swap(ranges_);
166 }
167
168 void RangeSet::Subtract(const gfx::Range& range) {
169 if (range.is_empty() || IsEmpty())
170 return;
171 const gfx::Range fixed_range = FixDirection(range);
172 auto start = ranges_.upper_bound(fixed_range);
173 if (start != ranges_.begin())
174 --start; // start now points to the key equal or lower than
175 // range.start().
176 if (start->end() < fixed_range.start())
177 ++start; // start element is entirely before current range, skip it.
178 auto end = ranges_.upper_bound(gfx::Range(fixed_range.end()));
179 if (start == end) { // No data in the current range available.
180 return;
181 }
182 std::list<gfx::Range> new_ranges;
183 for (auto it = start; it != end; ++it) {
184 const gfx::Range left(it->start(),
185 std::min(it->end(), fixed_range.start()));
186 const gfx::Range right(std::max(it->start(), fixed_range.end()), it->end());
187 if (!left.is_empty() && !left.is_reversed()) {
188 new_ranges.push_back(left);
189 }
190 if (!right.is_empty() && !right.is_reversed() && right != left) {
191 new_ranges.push_back(right);
192 }
193 }
194 ranges_.erase(start, end);
195 for (const auto& it : new_ranges) {
196 ranges_.insert(it);
197 }
198 }
199
200 void RangeSet::Subtract(const RangeSet& range_set) {
201 if (&range_set == this) {
202 ranges_.clear();
203 return;
204 }
205 for (const auto& range : range_set.ranges()) {
206 Subtract(range);
207 }
208 }
209
210 void RangeSet::Xor(const gfx::Range& range) {
211 Xor(RangeSet(range));
212 }
213
214 void RangeSet::Xor(const RangeSet& range_set) {
215 RangeSet tmp = *this;
216 tmp.Intersect(range_set);
217 Union(range_set);
218 Subtract(tmp);
219 }
220
221 bool RangeSet::IsEmpty() const {
222 return ranges().empty();
223 }
224
225 void RangeSet::Clear() {
226 ranges_.clear();
227 }
228
229 gfx::Range RangeSet::First() const {
230 return *ranges().begin();
231 }
232
233 gfx::Range RangeSet::Last() const {
234 return *ranges().rbegin();
235 }
236
237 std::string RangeSet::ToString() const {
238 std::stringstream ss;
239 ss << "{";
240 for (const auto& it : ranges()) {
241 ss << "[" << it.start() << "," << it.end() << ")";
242 }
243 ss << "}";
244 return ss.str();
245 }
246
247 } // namespace chrome_pdf
248
249 std::ostream& operator<<(std::ostream& os,
250 const chrome_pdf::RangeSet& range_set) {
251 return (os << range_set.ToString());
252 }
OLDNEW
« pdf/document_loader.cc ('K') | « pdf/range_set.h ('k') | pdf/range_set_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698