OLD | NEW |
---|---|
1 // Copyright 2015 PDFium Authors. All rights reserved. | 1 // Copyright 2015 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <algorithm> | 5 #include <algorithm> |
6 #include <memory> | 6 #include <memory> |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "public/fpdfview.h" | 10 #include "public/fpdfview.h" |
(...skipping 27 matching lines...) Expand all Loading... | |
38 bool IsOpened() const { return !!file_contents_; } | 38 bool IsOpened() const { return !!file_contents_; } |
39 | 39 |
40 FPDF_FILEACCESS* file_access() { return &file_access_; } | 40 FPDF_FILEACCESS* file_access() { return &file_access_; } |
41 FX_DOWNLOADHINTS* hints() { return this; } | 41 FX_DOWNLOADHINTS* hints() { return this; } |
42 FX_FILEAVAIL* file_avail() { return this; } | 42 FX_FILEAVAIL* file_avail() { return this; } |
43 | 43 |
44 const std::vector<std::pair<size_t, size_t>>& requested_segments() const { | 44 const std::vector<std::pair<size_t, size_t>>& requested_segments() const { |
45 return requested_segments_; | 45 return requested_segments_; |
46 } | 46 } |
47 | 47 |
48 void ClearRequestedSegments() { requested_segments_.clear(); } | 48 size_t max_requested_bound() const { return max_requested_bound_; } |
49 | |
50 void ClearRequestedSegments() { | |
51 requested_segments_.clear(); | |
52 max_requested_bound_ = 0; | |
53 } | |
49 | 54 |
50 bool is_new_data_available() const { return is_new_data_available_; } | 55 bool is_new_data_available() const { return is_new_data_available_; } |
51 void set_is_new_data_available(bool is_new_data_available) { | 56 void set_is_new_data_available(bool is_new_data_available) { |
52 is_new_data_available_ = is_new_data_available; | 57 is_new_data_available_ = is_new_data_available; |
53 } | 58 } |
54 | 59 |
60 size_t max_already_available_bound() const { | |
61 return available_ranges_.empty() ? 0 : available_ranges_.rbegin()->second; | |
62 } | |
63 | |
55 private: | 64 private: |
56 void SetDataAvailable(size_t start, size_t size) { | 65 void SetDataAvailable(size_t start, size_t size) { |
57 if (size == 0) | 66 if (size == 0) |
58 return; | 67 return; |
59 const auto range = std::make_pair(start, start + size); | 68 const auto range = std::make_pair(start, start + size); |
60 if (available_ranges_.empty()) { | 69 if (available_ranges_.empty()) { |
61 available_ranges_.insert(range); | 70 available_ranges_.insert(range); |
62 return; | 71 return; |
63 } | 72 } |
64 auto start_it = available_ranges_.upper_bound(range); | 73 auto start_it = available_ranges_.upper_bound(range); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
102 std::min(static_cast<unsigned long>(file_length_), pos + size); | 111 std::min(static_cast<unsigned long>(file_length_), pos + size); |
103 if (end <= pos) | 112 if (end <= pos) |
104 return 0; | 113 return 0; |
105 memcpy(pBuf, file_contents_.get() + pos, end - pos); | 114 memcpy(pBuf, file_contents_.get() + pos, end - pos); |
106 SetDataAvailable(pos, end - pos); | 115 SetDataAvailable(pos, end - pos); |
107 return static_cast<int>(end - pos); | 116 return static_cast<int>(end - pos); |
108 } | 117 } |
109 | 118 |
110 void AddSegmentImpl(size_t offset, size_t size) { | 119 void AddSegmentImpl(size_t offset, size_t size) { |
111 requested_segments_.push_back(std::make_pair(offset, size)); | 120 requested_segments_.push_back(std::make_pair(offset, size)); |
121 max_requested_bound_ = std::max(max_requested_bound_, offset + size); | |
112 } | 122 } |
113 | 123 |
114 bool IsDataAvailImpl(size_t offset, size_t size) { | 124 bool IsDataAvailImpl(size_t offset, size_t size) { |
115 if (offset + size > file_length_) | 125 if (offset + size > file_length_) |
116 return false; | 126 return false; |
117 if (is_new_data_available_) { | 127 if (is_new_data_available_) { |
118 SetDataAvailable(offset, size); | 128 SetDataAvailable(offset, size); |
119 return true; | 129 return true; |
120 } | 130 } |
121 return CheckDataAlreadyAvailable(offset, size); | 131 return CheckDataAlreadyAvailable(offset, size); |
(...skipping 14 matching lines...) Expand all Loading... | |
136 size_t offset, | 146 size_t offset, |
137 size_t size) { | 147 size_t size) { |
138 return static_cast<TestAsyncLoader*>(pThis)->IsDataAvailImpl(offset, size); | 148 return static_cast<TestAsyncLoader*>(pThis)->IsDataAvailImpl(offset, size); |
139 } | 149 } |
140 | 150 |
141 FPDF_FILEACCESS file_access_; | 151 FPDF_FILEACCESS file_access_; |
142 | 152 |
143 std::unique_ptr<char, pdfium::FreeDeleter> file_contents_; | 153 std::unique_ptr<char, pdfium::FreeDeleter> file_contents_; |
144 size_t file_length_; | 154 size_t file_length_; |
145 std::vector<std::pair<size_t, size_t>> requested_segments_; | 155 std::vector<std::pair<size_t, size_t>> requested_segments_; |
156 size_t max_requested_bound_ = 0; | |
146 bool is_new_data_available_ = true; | 157 bool is_new_data_available_ = true; |
147 | 158 |
148 using Range = std::pair<size_t, size_t>; | 159 using Range = std::pair<size_t, size_t>; |
149 struct range_compare { | 160 struct range_compare { |
150 bool operator()(const Range& lval, const Range& rval) const { | 161 bool operator()(const Range& lval, const Range& rval) const { |
151 return lval.first < rval.first; | 162 return lval.first < rval.first; |
152 } | 163 } |
153 }; | 164 }; |
154 using RangesContainer = std::set<Range, range_compare>; | 165 using RangesContainer = std::set<Range, range_compare>; |
155 RangesContainer available_ranges_; | 166 RangesContainer available_ranges_; |
(...skipping 22 matching lines...) Expand all Loading... | |
178 document_ = FPDFAvail_GetDocument(avail_, nullptr); | 189 document_ = FPDFAvail_GetDocument(avail_, nullptr); |
179 ASSERT_TRUE(document_); | 190 ASSERT_TRUE(document_); |
180 ASSERT_EQ(PDF_DATA_AVAIL, FPDFAvail_IsPageAvail(avail_, 1, loader.hints())); | 191 ASSERT_EQ(PDF_DATA_AVAIL, FPDFAvail_IsPageAvail(avail_, 1, loader.hints())); |
181 | 192 |
182 // No new data available, to prevent load "Pages" node. | 193 // No new data available, to prevent load "Pages" node. |
183 loader.set_is_new_data_available(false); | 194 loader.set_is_new_data_available(false); |
184 FPDF_PAGE page = LoadPage(1); | 195 FPDF_PAGE page = LoadPage(1); |
185 EXPECT_TRUE(page); | 196 EXPECT_TRUE(page); |
186 UnloadPage(page); | 197 UnloadPage(page); |
187 } | 198 } |
199 | |
200 TEST_F(FPDFDataAvailEmbeddertest, | |
201 DoNotLoadMainCrossRefForFirstPageIfLinearized) { | |
202 TestAsyncLoader loader("feature_linearized_loading.pdf"); | |
203 avail_ = FPDFAvail_Create(loader.file_avail(), loader.file_access()); | |
204 ASSERT_EQ(PDF_DATA_AVAIL, FPDFAvail_IsDocAvail(avail_, loader.hints())); | |
205 document_ = FPDFAvail_GetDocument(avail_, nullptr); | |
206 ASSERT_TRUE(document_); | |
207 const int first_page_num = FPDFAvail_GetFirstPageNum(document_); | |
Lei Zhang
2016/11/09 08:51:12
Might as well check the result since we have it?
snake
2016/11/09 12:41:49
We always should have it. For this test is not mat
| |
208 | |
209 // The main cross ref table should not be processed. | |
210 // (It is always at file end) | |
211 EXPECT_GT(loader.file_access()->m_FileLen, | |
212 loader.max_already_available_bound()); | |
213 | |
214 // No new data available, to took the download request. | |
Lei Zhang
2016/11/09 08:51:12
"to took the download request" doesn't parse.
snake
2016/11/09 12:41:49
Done.
| |
215 loader.set_is_new_data_available(false); | |
216 FPDFAvail_IsPageAvail(avail_, first_page_num, loader.hints()); | |
Lei Zhang
2016/11/09 08:51:12
Do you care about the return value?
snake
2016/11/09 12:41:49
No. For first call this is not matter. (Currently
| |
217 | |
218 // The main cross ref table should not be requested. | |
219 // (It is always at file end) | |
220 EXPECT_GT(loader.file_access()->m_FileLen, loader.max_requested_bound()); | |
221 | |
222 // Allow parse page. | |
223 loader.set_is_new_data_available(true); | |
224 ASSERT_EQ(PDF_DATA_AVAIL, | |
225 FPDFAvail_IsPageAvail(avail_, first_page_num, loader.hints())); | |
226 | |
227 // The main cross ref table should not be processed. | |
228 // (It is always at file end) | |
229 EXPECT_GT(loader.file_access()->m_FileLen, | |
230 loader.max_already_available_bound()); | |
231 | |
232 // Prevent loading data, while page loading. | |
233 loader.set_is_new_data_available(false); | |
234 FPDF_PAGE page = LoadPage(first_page_num); | |
235 EXPECT_TRUE(page); | |
236 UnloadPage(page); | |
237 } | |
OLD | NEW |