blob: a83ffe7c291bd927be3f84726428ba12c4c28785 [file] [log] [blame]
Tom Sepez26b8a5b2015-01-27 12:42:36 -08001// Copyright 2015 PDFium 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
Dan Sinclair85c8e7f2016-11-21 13:50:32 -05005#include <memory>
6
Dan Sinclairbcd1e702017-08-31 13:19:18 -04007#include "core/fxcrt/fx_memory.h"
Lei Zhangb4e7f302015-11-06 15:52:32 -08008#include "public/fpdf_text.h"
9#include "public/fpdfview.h"
Wei Li091f7a02015-11-09 12:09:55 -080010#include "testing/embedder_test.h"
Tom Sepez26b8a5b2015-01-27 12:42:36 -080011#include "testing/gtest/include/gtest/gtest.h"
Dan Sinclair61046b92016-02-18 14:48:48 -050012#include "testing/test_support.h"
Tom Sepez26b8a5b2015-01-27 12:42:36 -080013
Tom Sepez526f6d52015-01-28 15:49:13 -080014namespace {
15
Lei Zhang0f2ea022016-01-11 12:01:23 -080016bool check_unsigned_shorts(const char* expected,
17 const unsigned short* actual,
18 size_t length) {
Tom Sepez526f6d52015-01-28 15:49:13 -080019 if (length > strlen(expected) + 1) {
20 return false;
21 }
22 for (size_t i = 0; i < length; ++i) {
23 if (actual[i] != static_cast<unsigned short>(expected[i])) {
24 return false;
25 }
26 }
27 return true;
28}
29
30} // namespace
31
Nico Weber9d8ec5a2015-08-04 13:00:21 -070032class FPDFTextEmbeddertest : public EmbedderTest {};
Tom Sepez26b8a5b2015-01-27 12:42:36 -080033
Tom Sepez526f6d52015-01-28 15:49:13 -080034TEST_F(FPDFTextEmbeddertest, Text) {
Wei Li091f7a02015-11-09 12:09:55 -080035 EXPECT_TRUE(OpenDocument("hello_world.pdf"));
Tom Sepezda8189e2015-01-30 14:41:50 -080036 FPDF_PAGE page = LoadPage(0);
thestig4997b222016-06-07 10:46:22 -070037 EXPECT_TRUE(page);
Tom Sepez526f6d52015-01-28 15:49:13 -080038
39 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
thestig4997b222016-06-07 10:46:22 -070040 EXPECT_TRUE(textpage);
Tom Sepez526f6d52015-01-28 15:49:13 -080041
Lei Zhangd27acae2015-05-15 15:36:02 -070042 static const char expected[] = "Hello, world!\r\nGoodbye, world!";
Tom Sepez526f6d52015-01-28 15:49:13 -080043 unsigned short fixed_buffer[128];
44 memset(fixed_buffer, 0xbd, sizeof(fixed_buffer));
45
Ryan Harrisonc5ac0572017-08-31 16:37:48 -040046 // Check that unreasonable inputs are handled gracefully
47 EXPECT_EQ(0, FPDFText_GetText(textpage, 0, 128, nullptr));
48 EXPECT_EQ(0, FPDFText_GetText(textpage, -1, 128, fixed_buffer));
49 EXPECT_EQ(0, FPDFText_GetText(textpage, 0, 0, fixed_buffer));
50 EXPECT_EQ(0, FPDFText_GetText(textpage, 0, -1, fixed_buffer));
51
Tom Sepez526f6d52015-01-28 15:49:13 -080052 // Check includes the terminating NUL that is provided.
Lei Zhanga0f67242015-08-17 15:39:30 -070053 int num_chars = FPDFText_GetText(textpage, 0, 128, fixed_buffer);
54 ASSERT_GE(num_chars, 0);
Oliver Chang35e68a52015-12-09 12:44:33 -080055 EXPECT_EQ(sizeof(expected), static_cast<size_t>(num_chars));
56 EXPECT_TRUE(check_unsigned_shorts(expected, fixed_buffer, sizeof(expected)));
Tom Sepez526f6d52015-01-28 15:49:13 -080057
58 // Count does not include the terminating NUL in the string literal.
Wei Li05d53f02016-03-29 16:42:53 -070059 EXPECT_EQ(sizeof(expected) - 1,
60 static_cast<size_t>(FPDFText_CountChars(textpage)));
Tom Sepez526f6d52015-01-28 15:49:13 -080061 for (size_t i = 0; i < sizeof(expected) - 1; ++i) {
Lei Zhanga0f67242015-08-17 15:39:30 -070062 EXPECT_EQ(static_cast<unsigned int>(expected[i]),
63 FPDFText_GetUnicode(textpage, i))
64 << " at " << i;
Tom Sepez526f6d52015-01-28 15:49:13 -080065 }
66
67 EXPECT_EQ(12.0, FPDFText_GetFontSize(textpage, 0));
68 EXPECT_EQ(16.0, FPDFText_GetFontSize(textpage, 15));
69
70 double left = 0.0;
71 double right = 0.0;
72 double bottom = 0.0;
73 double top = 0.0;
74 FPDFText_GetCharBox(textpage, 4, &left, &right, &bottom, &top);
75 EXPECT_NEAR(41.071, left, 0.001);
76 EXPECT_NEAR(46.243, right, 0.001);
77 EXPECT_NEAR(49.844, bottom, 0.001);
78 EXPECT_NEAR(55.520, top, 0.001);
79
Andrew Weintraubd3002342017-08-11 11:36:51 -040080 double x = 0.0;
81 double y = 0.0;
82 EXPECT_TRUE(FPDFText_GetCharOrigin(textpage, 4, &x, &y));
83 EXPECT_NEAR(40.664, x, 0.001);
84 EXPECT_NEAR(50.000, y, 0.001);
85
Nico Weber9d8ec5a2015-08-04 13:00:21 -070086 EXPECT_EQ(4, FPDFText_GetCharIndexAtPos(textpage, 42.0, 50.0, 1.0, 1.0));
87 EXPECT_EQ(-1, FPDFText_GetCharIndexAtPos(textpage, 0.0, 0.0, 1.0, 1.0));
88 EXPECT_EQ(-1, FPDFText_GetCharIndexAtPos(textpage, 199.0, 199.0, 1.0, 1.0));
Tom Sepez526f6d52015-01-28 15:49:13 -080089
90 // Test out of range indicies.
Nico Weber9d8ec5a2015-08-04 13:00:21 -070091 EXPECT_EQ(-1,
92 FPDFText_GetCharIndexAtPos(textpage, 42.0, 10000000.0, 1.0, 1.0));
93 EXPECT_EQ(-1, FPDFText_GetCharIndexAtPos(textpage, -1.0, 50.0, 1.0, 1.0));
Tom Sepez526f6d52015-01-28 15:49:13 -080094
95 // Count does not include the terminating NUL in the string literal.
96 EXPECT_EQ(2, FPDFText_CountRects(textpage, 0, sizeof(expected) - 1));
97
98 left = 0.0;
99 right = 0.0;
100 bottom = 0.0;
101 top = 0.0;
102 FPDFText_GetRect(textpage, 1, &left, &top, &right, &bottom);
103 EXPECT_NEAR(20.847, left, 0.001);
104 EXPECT_NEAR(135.167, right, 0.001);
105 EXPECT_NEAR(96.655, bottom, 0.001);
106 EXPECT_NEAR(116.000, top, 0.001);
107
108 // Test out of range indicies set outputs to (0.0, 0.0, 0.0, 0.0).
109 left = -1.0;
110 right = -1.0;
111 bottom = -1.0;
112 top = -1.0;
113 FPDFText_GetRect(textpage, -1, &left, &top, &right, &bottom);
114 EXPECT_EQ(0.0, left);
115 EXPECT_EQ(0.0, right);
116 EXPECT_EQ(0.0, bottom);
117 EXPECT_EQ(0.0, top);
118
119 left = -2.0;
120 right = -2.0;
121 bottom = -2.0;
122 top = -2.0;
123 FPDFText_GetRect(textpage, 2, &left, &top, &right, &bottom);
124 EXPECT_EQ(0.0, left);
125 EXPECT_EQ(0.0, right);
126 EXPECT_EQ(0.0, bottom);
127 EXPECT_EQ(0.0, top);
128
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700129 EXPECT_EQ(9, FPDFText_GetBoundedText(textpage, 41.0, 56.0, 82.0, 48.0, 0, 0));
Tom Sepez526f6d52015-01-28 15:49:13 -0800130
131 // Extract starting at character 4 as above.
132 memset(fixed_buffer, 0xbd, sizeof(fixed_buffer));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700133 EXPECT_EQ(1, FPDFText_GetBoundedText(textpage, 41.0, 56.0, 82.0, 48.0,
134 fixed_buffer, 1));
Tom Sepez526f6d52015-01-28 15:49:13 -0800135 EXPECT_TRUE(check_unsigned_shorts(expected + 4, fixed_buffer, 1));
136 EXPECT_EQ(0xbdbd, fixed_buffer[1]);
137
138 memset(fixed_buffer, 0xbd, sizeof(fixed_buffer));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700139 EXPECT_EQ(9, FPDFText_GetBoundedText(textpage, 41.0, 56.0, 82.0, 48.0,
140 fixed_buffer, 9));
Tom Sepez526f6d52015-01-28 15:49:13 -0800141 EXPECT_TRUE(check_unsigned_shorts(expected + 4, fixed_buffer, 9));
142 EXPECT_EQ(0xbdbd, fixed_buffer[9]);
143
144 memset(fixed_buffer, 0xbd, sizeof(fixed_buffer));
Oliver Chang35e68a52015-12-09 12:44:33 -0800145 EXPECT_EQ(10, FPDFText_GetBoundedText(textpage, 41.0, 56.0, 82.0, 48.0,
146 fixed_buffer, 128));
Tom Sepez526f6d52015-01-28 15:49:13 -0800147 EXPECT_TRUE(check_unsigned_shorts(expected + 4, fixed_buffer, 9));
Oliver Chang35e68a52015-12-09 12:44:33 -0800148 EXPECT_EQ(0u, fixed_buffer[9]);
149 EXPECT_EQ(0xbdbd, fixed_buffer[10]);
Tom Sepez526f6d52015-01-28 15:49:13 -0800150
151 FPDFText_ClosePage(textpage);
Lei Zhangd27acae2015-05-15 15:36:02 -0700152 UnloadPage(page);
Tom Sepez526f6d52015-01-28 15:49:13 -0800153}
154
155TEST_F(FPDFTextEmbeddertest, TextSearch) {
Wei Li091f7a02015-11-09 12:09:55 -0800156 EXPECT_TRUE(OpenDocument("hello_world.pdf"));
Tom Sepezda8189e2015-01-30 14:41:50 -0800157 FPDF_PAGE page = LoadPage(0);
thestig4997b222016-06-07 10:46:22 -0700158 EXPECT_TRUE(page);
Tom Sepez526f6d52015-01-28 15:49:13 -0800159
160 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
thestig4997b222016-06-07 10:46:22 -0700161 EXPECT_TRUE(textpage);
Tom Sepez526f6d52015-01-28 15:49:13 -0800162
Tom Sepez0aa35312016-01-06 10:16:32 -0800163 std::unique_ptr<unsigned short, pdfium::FreeDeleter> nope =
164 GetFPDFWideString(L"nope");
165 std::unique_ptr<unsigned short, pdfium::FreeDeleter> world =
166 GetFPDFWideString(L"world");
167 std::unique_ptr<unsigned short, pdfium::FreeDeleter> world_caps =
168 GetFPDFWideString(L"WORLD");
169 std::unique_ptr<unsigned short, pdfium::FreeDeleter> world_substr =
170 GetFPDFWideString(L"orld");
Tom Sepez526f6d52015-01-28 15:49:13 -0800171
172 // No occurences of "nope" in test page.
Tom Sepez0aa35312016-01-06 10:16:32 -0800173 FPDF_SCHHANDLE search = FPDFText_FindStart(textpage, nope.get(), 0, 0);
thestig4997b222016-06-07 10:46:22 -0700174 EXPECT_TRUE(search);
Tom Sepez526f6d52015-01-28 15:49:13 -0800175 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search));
176 EXPECT_EQ(0, FPDFText_GetSchCount(search));
177
178 // Advancing finds nothing.
179 EXPECT_FALSE(FPDFText_FindNext(search));
180 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search));
181 EXPECT_EQ(0, FPDFText_GetSchCount(search));
182
183 // Retreating finds nothing.
184 EXPECT_FALSE(FPDFText_FindPrev(search));
185 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search));
186 EXPECT_EQ(0, FPDFText_GetSchCount(search));
187 FPDFText_FindClose(search);
188
189 // Two occurences of "world" in test page.
Tom Sepez0aa35312016-01-06 10:16:32 -0800190 search = FPDFText_FindStart(textpage, world.get(), 0, 2);
thestig4997b222016-06-07 10:46:22 -0700191 EXPECT_TRUE(search);
Tom Sepez526f6d52015-01-28 15:49:13 -0800192
193 // Remains not found until advanced.
194 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search));
195 EXPECT_EQ(0, FPDFText_GetSchCount(search));
196
197 // First occurence of "world" in this test page.
198 EXPECT_TRUE(FPDFText_FindNext(search));
199 EXPECT_EQ(7, FPDFText_GetSchResultIndex(search));
200 EXPECT_EQ(5, FPDFText_GetSchCount(search));
201
202 // Last occurence of "world" in this test page.
203 EXPECT_TRUE(FPDFText_FindNext(search));
204 EXPECT_EQ(24, FPDFText_GetSchResultIndex(search));
205 EXPECT_EQ(5, FPDFText_GetSchCount(search));
206
207 // Found position unchanged when fails to advance.
208 EXPECT_FALSE(FPDFText_FindNext(search));
209 EXPECT_EQ(24, FPDFText_GetSchResultIndex(search));
210 EXPECT_EQ(5, FPDFText_GetSchCount(search));
211
212 // Back to first occurence.
213 EXPECT_TRUE(FPDFText_FindPrev(search));
214 EXPECT_EQ(7, FPDFText_GetSchResultIndex(search));
215 EXPECT_EQ(5, FPDFText_GetSchCount(search));
216
217 // Found position unchanged when fails to retreat.
218 EXPECT_FALSE(FPDFText_FindPrev(search));
219 EXPECT_EQ(7, FPDFText_GetSchResultIndex(search));
220 EXPECT_EQ(5, FPDFText_GetSchCount(search));
221 FPDFText_FindClose(search);
222
223 // Exact search unaffected by case sensitiity and whole word flags.
Tom Sepez0aa35312016-01-06 10:16:32 -0800224 search = FPDFText_FindStart(textpage, world.get(),
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700225 FPDF_MATCHCASE | FPDF_MATCHWHOLEWORD, 0);
thestig4997b222016-06-07 10:46:22 -0700226 EXPECT_TRUE(search);
Tom Sepez526f6d52015-01-28 15:49:13 -0800227 EXPECT_TRUE(FPDFText_FindNext(search));
228 EXPECT_EQ(7, FPDFText_GetSchResultIndex(search));
229 EXPECT_EQ(5, FPDFText_GetSchCount(search));
230 FPDFText_FindClose(search);
231
232 // Default is case-insensitive, so matching agaist caps works.
Tom Sepez0aa35312016-01-06 10:16:32 -0800233 search = FPDFText_FindStart(textpage, world_caps.get(), 0, 0);
thestig4997b222016-06-07 10:46:22 -0700234 EXPECT_TRUE(search);
Tom Sepez526f6d52015-01-28 15:49:13 -0800235 EXPECT_TRUE(FPDFText_FindNext(search));
236 EXPECT_EQ(7, FPDFText_GetSchResultIndex(search));
237 EXPECT_EQ(5, FPDFText_GetSchCount(search));
238 FPDFText_FindClose(search);
239
240 // But can be made case sensitive, in which case this fails.
Tom Sepez0aa35312016-01-06 10:16:32 -0800241 search = FPDFText_FindStart(textpage, world_caps.get(), FPDF_MATCHCASE, 0);
Tom Sepez526f6d52015-01-28 15:49:13 -0800242 EXPECT_FALSE(FPDFText_FindNext(search));
243 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search));
244 EXPECT_EQ(0, FPDFText_GetSchCount(search));
245 FPDFText_FindClose(search);
246
247 // Default is match anywhere within word, so matching substirng works.
Tom Sepez0aa35312016-01-06 10:16:32 -0800248 search = FPDFText_FindStart(textpage, world_substr.get(), 0, 0);
Tom Sepez526f6d52015-01-28 15:49:13 -0800249 EXPECT_TRUE(FPDFText_FindNext(search));
250 EXPECT_EQ(8, FPDFText_GetSchResultIndex(search));
251 EXPECT_EQ(4, FPDFText_GetSchCount(search));
252 FPDFText_FindClose(search);
253
254 // But can be made to mach word boundaries, in which case this fails.
Tom Sepez0aa35312016-01-06 10:16:32 -0800255 search =
256 FPDFText_FindStart(textpage, world_substr.get(), FPDF_MATCHWHOLEWORD, 0);
Tom Sepez526f6d52015-01-28 15:49:13 -0800257 EXPECT_FALSE(FPDFText_FindNext(search));
258 // TODO(tsepez): investigate strange index/count values in this state.
259 FPDFText_FindClose(search);
260
261 FPDFText_ClosePage(textpage);
Lei Zhangd27acae2015-05-15 15:36:02 -0700262 UnloadPage(page);
Tom Sepez526f6d52015-01-28 15:49:13 -0800263}
264
Tom Sepez26b8a5b2015-01-27 12:42:36 -0800265// Test that the page has characters despite a bad stream length.
266TEST_F(FPDFTextEmbeddertest, StreamLengthPastEndOfFile) {
Wei Li091f7a02015-11-09 12:09:55 -0800267 EXPECT_TRUE(OpenDocument("bug_57.pdf"));
Tom Sepezda8189e2015-01-30 14:41:50 -0800268 FPDF_PAGE page = LoadPage(0);
thestig4997b222016-06-07 10:46:22 -0700269 EXPECT_TRUE(page);
Tom Sepez526f6d52015-01-28 15:49:13 -0800270
Tom Sepez26b8a5b2015-01-27 12:42:36 -0800271 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
thestig4997b222016-06-07 10:46:22 -0700272 EXPECT_TRUE(textpage);
Tom Sepez26b8a5b2015-01-27 12:42:36 -0800273 EXPECT_EQ(13, FPDFText_CountChars(textpage));
Tom Sepez526f6d52015-01-28 15:49:13 -0800274
275 FPDFText_ClosePage(textpage);
Lei Zhangd27acae2015-05-15 15:36:02 -0700276 UnloadPage(page);
Tom Sepez526f6d52015-01-28 15:49:13 -0800277}
278
279TEST_F(FPDFTextEmbeddertest, WebLinks) {
Wei Li091f7a02015-11-09 12:09:55 -0800280 EXPECT_TRUE(OpenDocument("weblinks.pdf"));
Tom Sepezda8189e2015-01-30 14:41:50 -0800281 FPDF_PAGE page = LoadPage(0);
thestig4997b222016-06-07 10:46:22 -0700282 EXPECT_TRUE(page);
Tom Sepez526f6d52015-01-28 15:49:13 -0800283
284 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
thestig4997b222016-06-07 10:46:22 -0700285 EXPECT_TRUE(textpage);
Tom Sepez526f6d52015-01-28 15:49:13 -0800286
287 FPDF_PAGELINK pagelink = FPDFLink_LoadWebLinks(textpage);
thestig4997b222016-06-07 10:46:22 -0700288 EXPECT_TRUE(pagelink);
Tom Sepez526f6d52015-01-28 15:49:13 -0800289
290 // Page contains two HTTP-style URLs.
291 EXPECT_EQ(2, FPDFLink_CountWebLinks(pagelink));
292
Oliver Chang35e68a52015-12-09 12:44:33 -0800293 // Only a terminating NUL required for bogus links.
294 EXPECT_EQ(1, FPDFLink_GetURL(pagelink, 2, nullptr, 0));
295 EXPECT_EQ(1, FPDFLink_GetURL(pagelink, 1400, nullptr, 0));
296 EXPECT_EQ(1, FPDFLink_GetURL(pagelink, -1, nullptr, 0));
Tom Sepez526f6d52015-01-28 15:49:13 -0800297
298 // Query the number of characters required for each link (incl NUL).
Oliver Chang35e68a52015-12-09 12:44:33 -0800299 EXPECT_EQ(25, FPDFLink_GetURL(pagelink, 0, nullptr, 0));
300 EXPECT_EQ(26, FPDFLink_GetURL(pagelink, 1, nullptr, 0));
Tom Sepez526f6d52015-01-28 15:49:13 -0800301
Lei Zhangd27acae2015-05-15 15:36:02 -0700302 static const char expected_url[] = "http://example.com?q=foo";
Wei Li05d53f02016-03-29 16:42:53 -0700303 static const size_t expected_len = sizeof(expected_url);
Tom Sepez526f6d52015-01-28 15:49:13 -0800304 unsigned short fixed_buffer[128];
305
306 // Retrieve a link with too small a buffer. Buffer will not be
307 // NUL-terminated, but must not be modified past indicated length,
308 // so pre-fill with a pattern to check write bounds.
309 memset(fixed_buffer, 0xbd, sizeof(fixed_buffer));
310 EXPECT_EQ(1, FPDFLink_GetURL(pagelink, 0, fixed_buffer, 1));
311 EXPECT_TRUE(check_unsigned_shorts(expected_url, fixed_buffer, 1));
312 EXPECT_EQ(0xbdbd, fixed_buffer[1]);
313
314 // Check buffer that doesn't have space for a terminating NUL.
315 memset(fixed_buffer, 0xbd, sizeof(fixed_buffer));
Wei Li05d53f02016-03-29 16:42:53 -0700316 EXPECT_EQ(static_cast<int>(expected_len - 1),
317 FPDFLink_GetURL(pagelink, 0, fixed_buffer, expected_len - 1));
318 EXPECT_TRUE(
319 check_unsigned_shorts(expected_url, fixed_buffer, expected_len - 1));
320 EXPECT_EQ(0xbdbd, fixed_buffer[expected_len - 1]);
Tom Sepez526f6d52015-01-28 15:49:13 -0800321
322 // Retreive link with exactly-sized buffer.
323 memset(fixed_buffer, 0xbd, sizeof(fixed_buffer));
Wei Li05d53f02016-03-29 16:42:53 -0700324 EXPECT_EQ(static_cast<int>(expected_len),
325 FPDFLink_GetURL(pagelink, 0, fixed_buffer, expected_len));
326 EXPECT_TRUE(check_unsigned_shorts(expected_url, fixed_buffer, expected_len));
327 EXPECT_EQ(0u, fixed_buffer[expected_len - 1]);
328 EXPECT_EQ(0xbdbd, fixed_buffer[expected_len]);
Tom Sepez526f6d52015-01-28 15:49:13 -0800329
330 // Retreive link with ample-sized-buffer.
331 memset(fixed_buffer, 0xbd, sizeof(fixed_buffer));
Wei Li05d53f02016-03-29 16:42:53 -0700332 EXPECT_EQ(static_cast<int>(expected_len),
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700333 FPDFLink_GetURL(pagelink, 0, fixed_buffer, 128));
Wei Li05d53f02016-03-29 16:42:53 -0700334 EXPECT_TRUE(check_unsigned_shorts(expected_url, fixed_buffer, expected_len));
335 EXPECT_EQ(0u, fixed_buffer[expected_len - 1]);
336 EXPECT_EQ(0xbdbd, fixed_buffer[expected_len]);
Tom Sepez526f6d52015-01-28 15:49:13 -0800337
338 // Each link rendered in a single rect in this test page.
339 EXPECT_EQ(1, FPDFLink_CountRects(pagelink, 0));
340 EXPECT_EQ(1, FPDFLink_CountRects(pagelink, 1));
341
342 // Each link rendered in a single rect in this test page.
343 EXPECT_EQ(0, FPDFLink_CountRects(pagelink, -1));
344 EXPECT_EQ(0, FPDFLink_CountRects(pagelink, 2));
345 EXPECT_EQ(0, FPDFLink_CountRects(pagelink, 10000));
346
347 // Check boundary of valid link index with valid rect index.
348 double left = 0.0;
349 double right = 0.0;
350 double top = 0.0;
351 double bottom = 0.0;
352 FPDFLink_GetRect(pagelink, 0, 0, &left, &top, &right, &bottom);
353 EXPECT_NEAR(50.791, left, 0.001);
354 EXPECT_NEAR(187.963, right, 0.001);
355 EXPECT_NEAR(97.624, bottom, 0.001);
356 EXPECT_NEAR(108.736, top, 0.001);
357
358 // Check that valid link with invalid rect index leaves parameters unchanged.
359 left = -1.0;
360 right = -1.0;
361 top = -1.0;
362 bottom = -1.0;
363 FPDFLink_GetRect(pagelink, 0, 1, &left, &top, &right, &bottom);
364 EXPECT_EQ(-1.0, left);
365 EXPECT_EQ(-1.0, right);
366 EXPECT_EQ(-1.0, bottom);
367 EXPECT_EQ(-1.0, top);
368
369 // Check that invalid link index leaves parameters unchanged.
370 left = -2.0;
371 right = -2.0;
372 top = -2.0;
373 bottom = -2.0;
374 FPDFLink_GetRect(pagelink, -1, 0, &left, &top, &right, &bottom);
375 EXPECT_EQ(-2.0, left);
376 EXPECT_EQ(-2.0, right);
377 EXPECT_EQ(-2.0, bottom);
378 EXPECT_EQ(-2.0, top);
379
380 FPDFLink_CloseWebLinks(pagelink);
381 FPDFText_ClosePage(textpage);
Lei Zhangd27acae2015-05-15 15:36:02 -0700382 UnloadPage(page);
Tom Sepez26b8a5b2015-01-27 12:42:36 -0800383}
Lei Zhang0f2ea022016-01-11 12:01:23 -0800384
Wei Li76309072017-03-16 17:31:03 -0700385TEST_F(FPDFTextEmbeddertest, WebLinksAcrossLines) {
386 EXPECT_TRUE(OpenDocument("weblinks_across_lines.pdf"));
387 FPDF_PAGE page = LoadPage(0);
388 EXPECT_TRUE(page);
389
390 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
391 EXPECT_TRUE(textpage);
392
393 FPDF_PAGELINK pagelink = FPDFLink_LoadWebLinks(textpage);
394 EXPECT_TRUE(pagelink);
395
396 static const char* const kExpectedUrls[] = {
Wei Li6c8ed642017-05-19 22:17:38 -0700397 "http://example.com", // from "http://www.example.com?\r\nfoo"
Wei Li76309072017-03-16 17:31:03 -0700398 "http://example.com/", // from "http://www.example.com/\r\nfoo"
399 "http://example.com/test-foo", // from "http://example.com/test-\r\nfoo"
400 "http://abc.com/test-foo", // from "http://abc.com/test-\r\n\r\nfoo"
401 // Next two links from "http://www.example.com/\r\nhttp://www.abc.com/"
402 "http://example.com/", "http://www.abc.com",
403 };
404 static const int kNumLinks = static_cast<int>(FX_ArraySize(kExpectedUrls));
405
406 EXPECT_EQ(kNumLinks, FPDFLink_CountWebLinks(pagelink));
407
408 unsigned short fixed_buffer[128];
409 for (int i = 0; i < kNumLinks; i++) {
410 const size_t expected_len = strlen(kExpectedUrls[i]) + 1;
411 memset(fixed_buffer, 0, FX_ArraySize(fixed_buffer));
412 EXPECT_EQ(static_cast<int>(expected_len),
413 FPDFLink_GetURL(pagelink, i, nullptr, 0));
414 EXPECT_EQ(
415 static_cast<int>(expected_len),
416 FPDFLink_GetURL(pagelink, i, fixed_buffer, FX_ArraySize(fixed_buffer)));
417 EXPECT_TRUE(
418 check_unsigned_shorts(kExpectedUrls[i], fixed_buffer, expected_len));
419 }
420
421 FPDFLink_CloseWebLinks(pagelink);
422 FPDFText_ClosePage(textpage);
423 UnloadPage(page);
424}
425
426TEST_F(FPDFTextEmbeddertest, WebLinksAcrossLinesBug) {
427 EXPECT_TRUE(OpenDocument("bug_650.pdf"));
428 FPDF_PAGE page = LoadPage(0);
429 EXPECT_TRUE(page);
430
431 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
432 EXPECT_TRUE(textpage);
433
434 FPDF_PAGELINK pagelink = FPDFLink_LoadWebLinks(textpage);
435 EXPECT_TRUE(pagelink);
436
437 EXPECT_EQ(2, FPDFLink_CountWebLinks(pagelink));
438 unsigned short fixed_buffer[128] = {0};
439 static const char kExpectedUrl[] =
440 "http://tutorial45.com/learn-autocad-basics-day-166/";
441 static const int kUrlSize = static_cast<int>(sizeof(kExpectedUrl));
442
443 EXPECT_EQ(kUrlSize, FPDFLink_GetURL(pagelink, 1, nullptr, 0));
444 EXPECT_EQ(kUrlSize, FPDFLink_GetURL(pagelink, 1, fixed_buffer,
445 FX_ArraySize(fixed_buffer)));
446 EXPECT_TRUE(check_unsigned_shorts(kExpectedUrl, fixed_buffer, kUrlSize));
447
448 FPDFLink_CloseWebLinks(pagelink);
449 FPDFText_ClosePage(textpage);
450 UnloadPage(page);
451}
452
Lei Zhang0f2ea022016-01-11 12:01:23 -0800453TEST_F(FPDFTextEmbeddertest, GetFontSize) {
454 EXPECT_TRUE(OpenDocument("hello_world.pdf"));
455 FPDF_PAGE page = LoadPage(0);
thestig4997b222016-06-07 10:46:22 -0700456 EXPECT_TRUE(page);
Lei Zhang0f2ea022016-01-11 12:01:23 -0800457
458 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
thestig4997b222016-06-07 10:46:22 -0700459 EXPECT_TRUE(textpage);
Lei Zhang0f2ea022016-01-11 12:01:23 -0800460
461 const double kExpectedFontsSizes[] = {12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
462 12, 12, 12, 1, 1, 16, 16, 16, 16, 16,
463 16, 16, 16, 16, 16, 16, 16, 16, 16, 16};
464
465 int count = FPDFText_CountChars(textpage);
Wei Li05d53f02016-03-29 16:42:53 -0700466 ASSERT_EQ(FX_ArraySize(kExpectedFontsSizes), static_cast<size_t>(count));
Lei Zhang0f2ea022016-01-11 12:01:23 -0800467 for (int i = 0; i < count; ++i)
468 EXPECT_EQ(kExpectedFontsSizes[i], FPDFText_GetFontSize(textpage, i)) << i;
469
470 FPDFText_ClosePage(textpage);
471 UnloadPage(page);
472}
npm84be3a32016-09-15 13:27:21 -0700473
474TEST_F(FPDFTextEmbeddertest, ToUnicode) {
475 EXPECT_TRUE(OpenDocument("bug_583.pdf"));
476 FPDF_PAGE page = LoadPage(0);
477 EXPECT_TRUE(page);
478
479 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
480 EXPECT_TRUE(textpage);
481
482 ASSERT_EQ(1, FPDFText_CountChars(textpage));
483 EXPECT_EQ(static_cast<unsigned int>(0), FPDFText_GetUnicode(textpage, 0));
484
485 FPDFText_ClosePage(textpage);
486 UnloadPage(page);
487}