Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
fpdf_text_embeddertest.cpp
Go to the documentation of this file.
1// Copyright 2015 The PDFium Authors
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 <algorithm>
6#include <utility>
7#include <vector>
8
9#include "build/build_config.h"
10#include "core/fxge/fx_font.h"
11#include "public/cpp/fpdf_scopers.h"
12#include "public/fpdf_doc.h"
13#include "public/fpdf_text.h"
14#include "public/fpdf_transformpage.h"
15#include "public/fpdfview.h"
16#include "testing/embedder_test.h"
17#include "testing/fx_string_testhelpers.h"
18#include "testing/gtest/include/gtest/gtest.h"
19
20namespace {
21
22constexpr char kHelloGoodbyeText[] = "Hello, world!\r\nGoodbye, world!";
23constexpr int kHelloGoodbyeTextSize = std::size(kHelloGoodbyeText);
24
25bool check_unsigned_shorts(const char* expected,
26 const unsigned short* actual,
27 size_t length) {
28 if (length > strlen(expected) + 1)
29 return false;
30
31 for (size_t i = 0; i < length; ++i) {
32 if (actual[i] != static_cast<unsigned short>(expected[i]))
33 return false;
34 }
35 return true;
36}
37
38} // namespace
39
41
43 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
44 FPDF_PAGE page = LoadPage(0);
45 ASSERT_TRUE(page);
46
47 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
48 ASSERT_TRUE(textpage);
49
50 unsigned short buffer[128];
51 memset(buffer, 0xbd, sizeof(buffer));
52
53 // Check that edge cases are handled gracefully
54 EXPECT_EQ(0, FPDFText_GetText(textpage, 0, 128, nullptr));
55 EXPECT_EQ(0, FPDFText_GetText(textpage, -1, 128, buffer));
56 EXPECT_EQ(0, FPDFText_GetText(textpage, 0, -1, buffer));
57 EXPECT_EQ(1, FPDFText_GetText(textpage, 0, 0, buffer));
58 EXPECT_EQ(0, buffer[0]);
59
60 // Keep going and check the next case.
61 memset(buffer, 0xbd, sizeof(buffer));
62 EXPECT_EQ(2, FPDFText_GetText(textpage, 0, 1, buffer));
63 EXPECT_EQ(kHelloGoodbyeText[0], buffer[0]);
64 EXPECT_EQ(0, buffer[1]);
65
66 // Check includes the terminating NUL that is provided.
67 int num_chars = FPDFText_GetText(textpage, 0, 128, buffer);
68 ASSERT_EQ(kHelloGoodbyeTextSize, num_chars);
69 EXPECT_TRUE(
70 check_unsigned_shorts(kHelloGoodbyeText, buffer, kHelloGoodbyeTextSize));
71
72 // Count does not include the terminating NUL in the string literal.
73 EXPECT_EQ(kHelloGoodbyeTextSize - 1, FPDFText_CountChars(textpage));
74 for (size_t i = 0; i < kHelloGoodbyeTextSize - 1; ++i) {
75 EXPECT_EQ(static_cast<unsigned int>(kHelloGoodbyeText[i]),
76 FPDFText_GetUnicode(textpage, i))
77 << " at " << i;
78 }
79
80 // Extracting using a buffer that will be completely filled. Small buffer is
81 // 12 elements long, since it will need 2 locations per displayed character in
82 // the expected string, plus 2 more for the terminating character.
83 static const char kSmallExpected[] = "Hello";
84 unsigned short small_buffer[12];
85 memset(buffer, 0xbd, sizeof(buffer));
86 EXPECT_EQ(6, FPDFText_GetText(textpage, 0, 5, small_buffer));
87 EXPECT_TRUE(check_unsigned_shorts(kSmallExpected, small_buffer,
88 sizeof(kSmallExpected)));
89
90 EXPECT_EQ(12.0, FPDFText_GetFontSize(textpage, 0));
91 EXPECT_EQ(16.0, FPDFText_GetFontSize(textpage, 15));
92
93 double left = 1.0;
94 double right = 2.0;
95 double bottom = 3.0;
96 double top = 4.0;
97 EXPECT_FALSE(FPDFText_GetCharBox(nullptr, 4, &left, &right, &bottom, &top));
98 EXPECT_DOUBLE_EQ(1.0, left);
99 EXPECT_DOUBLE_EQ(2.0, right);
100 EXPECT_DOUBLE_EQ(3.0, bottom);
101 EXPECT_DOUBLE_EQ(4.0, top);
102 EXPECT_FALSE(FPDFText_GetCharBox(textpage, -1, &left, &right, &bottom, &top));
103 EXPECT_DOUBLE_EQ(1.0, left);
104 EXPECT_DOUBLE_EQ(2.0, right);
105 EXPECT_DOUBLE_EQ(3.0, bottom);
106 EXPECT_DOUBLE_EQ(4.0, top);
107 EXPECT_FALSE(FPDFText_GetCharBox(textpage, 55, &left, &right, &bottom, &top));
108 EXPECT_DOUBLE_EQ(1.0, left);
109 EXPECT_DOUBLE_EQ(2.0, right);
110 EXPECT_DOUBLE_EQ(3.0, bottom);
111 EXPECT_DOUBLE_EQ(4.0, top);
112 EXPECT_FALSE(
113 FPDFText_GetCharBox(textpage, 4, nullptr, &right, &bottom, &top));
114 EXPECT_FALSE(FPDFText_GetCharBox(textpage, 4, &left, nullptr, &bottom, &top));
115 EXPECT_FALSE(FPDFText_GetCharBox(textpage, 4, &left, &right, nullptr, &top));
116 EXPECT_FALSE(
117 FPDFText_GetCharBox(textpage, 4, &left, &right, &bottom, nullptr));
118 EXPECT_FALSE(
119 FPDFText_GetCharBox(textpage, 4, nullptr, nullptr, nullptr, nullptr));
120
121 EXPECT_TRUE(FPDFText_GetCharBox(textpage, 4, &left, &right, &bottom, &top));
122 EXPECT_NEAR(41.120, left, 0.001);
123 EXPECT_NEAR(46.208, right, 0.001);
124 EXPECT_NEAR(49.892, bottom, 0.001);
125 EXPECT_NEAR(55.652, top, 0.001);
126
127 FS_RECTF rect = {4.0f, 1.0f, 3.0f, 2.0f};
128 EXPECT_FALSE(FPDFText_GetLooseCharBox(nullptr, 4, &rect));
129 EXPECT_FLOAT_EQ(4.0f, rect.left);
130 EXPECT_FLOAT_EQ(3.0f, rect.right);
131 EXPECT_FLOAT_EQ(2.0f, rect.bottom);
132 EXPECT_FLOAT_EQ(1.0f, rect.top);
133 EXPECT_FALSE(FPDFText_GetLooseCharBox(textpage, -1, &rect));
134 EXPECT_FLOAT_EQ(4.0f, rect.left);
135 EXPECT_FLOAT_EQ(3.0f, rect.right);
136 EXPECT_FLOAT_EQ(2.0f, rect.bottom);
137 EXPECT_FLOAT_EQ(1.0f, rect.top);
138 EXPECT_FALSE(FPDFText_GetLooseCharBox(textpage, 55, &rect));
139 EXPECT_FLOAT_EQ(4.0f, rect.left);
140 EXPECT_FLOAT_EQ(3.0f, rect.right);
141 EXPECT_FLOAT_EQ(2.0f, rect.bottom);
142 EXPECT_FLOAT_EQ(1.0f, rect.top);
143 EXPECT_FALSE(FPDFText_GetLooseCharBox(textpage, 4, nullptr));
144
145 EXPECT_TRUE(FPDFText_GetLooseCharBox(textpage, 4, &rect));
146 EXPECT_FLOAT_EQ(40.664001f, rect.left);
147 EXPECT_FLOAT_EQ(46.664001f, rect.right);
148 EXPECT_FLOAT_EQ(47.667271f, rect.bottom);
149 EXPECT_FLOAT_EQ(59.667271f, rect.top);
150
151 double x = 0.0;
152 double y = 0.0;
153 EXPECT_TRUE(FPDFText_GetCharOrigin(textpage, 4, &x, &y));
154 EXPECT_NEAR(40.664, x, 0.001);
155 EXPECT_NEAR(50.000, y, 0.001);
156
157 EXPECT_EQ(4, FPDFText_GetCharIndexAtPos(textpage, 42.0, 50.0, 1.0, 1.0));
158 EXPECT_EQ(-1, FPDFText_GetCharIndexAtPos(textpage, 0.0, 0.0, 1.0, 1.0));
159 EXPECT_EQ(-1, FPDFText_GetCharIndexAtPos(textpage, 199.0, 199.0, 1.0, 1.0));
160
161 // Test out of range indicies.
162 EXPECT_EQ(-1,
163 FPDFText_GetCharIndexAtPos(textpage, 42.0, 10000000.0, 1.0, 1.0));
164 EXPECT_EQ(-1, FPDFText_GetCharIndexAtPos(textpage, -1.0, 50.0, 1.0, 1.0));
165
166 // Count does not include the terminating NUL in the string literal.
167 EXPECT_EQ(2, FPDFText_CountRects(textpage, 0, kHelloGoodbyeTextSize - 1));
168
169 left = 0.0;
170 right = 0.0;
171 bottom = 0.0;
172 top = 0.0;
173 EXPECT_TRUE(FPDFText_GetRect(textpage, 1, &left, &top, &right, &bottom));
174 EXPECT_NEAR(20.800, left, 0.001);
175 EXPECT_NEAR(135.040, right, 0.001);
176 EXPECT_NEAR(96.688, bottom, 0.001);
177 EXPECT_NEAR(111.600, top, 0.001);
178
179 // Test out of range indicies set outputs to (0.0, 0.0, 0.0, 0.0).
180 left = -1.0;
181 right = -1.0;
182 bottom = -1.0;
183 top = -1.0;
184 EXPECT_FALSE(FPDFText_GetRect(textpage, -1, &left, &top, &right, &bottom));
185 EXPECT_EQ(0.0, left);
186 EXPECT_EQ(0.0, right);
187 EXPECT_EQ(0.0, bottom);
188 EXPECT_EQ(0.0, top);
189
190 left = -2.0;
191 right = -2.0;
192 bottom = -2.0;
193 top = -2.0;
194 EXPECT_FALSE(FPDFText_GetRect(textpage, 2, &left, &top, &right, &bottom));
195 EXPECT_EQ(0.0, left);
196 EXPECT_EQ(0.0, right);
197 EXPECT_EQ(0.0, bottom);
198 EXPECT_EQ(0.0, top);
199
200 EXPECT_EQ(
201 9, FPDFText_GetBoundedText(textpage, 41.0, 56.0, 82.0, 48.0, nullptr, 0));
202
203 // Extract starting at character 4 as above.
204 memset(buffer, 0xbd, sizeof(buffer));
205 EXPECT_EQ(
206 1, FPDFText_GetBoundedText(textpage, 41.0, 56.0, 82.0, 48.0, buffer, 1));
207 EXPECT_TRUE(check_unsigned_shorts(kHelloGoodbyeText + 4, buffer, 1));
208 EXPECT_EQ(0xbdbd, buffer[1]);
209
210 memset(buffer, 0xbd, sizeof(buffer));
211 EXPECT_EQ(
212 9, FPDFText_GetBoundedText(textpage, 41.0, 56.0, 82.0, 48.0, buffer, 9));
213 EXPECT_TRUE(check_unsigned_shorts(kHelloGoodbyeText + 4, buffer, 8));
214 EXPECT_EQ(0xbdbd, buffer[9]);
215
216 memset(buffer, 0xbd, sizeof(buffer));
217 EXPECT_EQ(10, FPDFText_GetBoundedText(textpage, 41.0, 56.0, 82.0, 48.0,
218 buffer, 128));
219 EXPECT_TRUE(check_unsigned_shorts(kHelloGoodbyeText + 4, buffer, 9));
220 EXPECT_EQ(0u, buffer[9]);
221 EXPECT_EQ(0xbdbd, buffer[10]);
222
223 FPDFText_ClosePage(textpage);
224 UnloadPage(page);
225}
226
228 ASSERT_TRUE(OpenDocument("vertical_text.pdf"));
229 FPDF_PAGE page = LoadPage(0);
230 ASSERT_TRUE(page);
231
232 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
233 ASSERT_TRUE(textpage);
234
235 EXPECT_EQ(12.0, FPDFText_GetFontSize(textpage, 0));
236
237 double x = 0.0;
238 double y = 0.0;
239 EXPECT_TRUE(FPDFText_GetCharOrigin(textpage, 1, &x, &y));
240 EXPECT_NEAR(6.664, x, 0.001);
241 EXPECT_NEAR(171.508, y, 0.001);
242
243 EXPECT_TRUE(FPDFText_GetCharOrigin(textpage, 2, &x, &y));
244 EXPECT_NEAR(8.668, x, 0.001);
245 EXPECT_NEAR(160.492, y, 0.001);
246
247 FS_RECTF rect;
248 EXPECT_TRUE(FPDFText_GetLooseCharBox(textpage, 1, &rect));
249 EXPECT_NEAR(4, rect.left, 0.001);
250 EXPECT_NEAR(16, rect.right, 0.001);
251 EXPECT_NEAR(178.984, rect.bottom, 0.001);
252 EXPECT_NEAR(170.308, rect.top, 0.001);
253
254 EXPECT_TRUE(FPDFText_GetLooseCharBox(textpage, 2, &rect));
255 EXPECT_NEAR(4, rect.left, 0.001);
256 EXPECT_NEAR(16, rect.right, 0.001);
257 EXPECT_NEAR(170.308, rect.bottom, 0.001);
258 EXPECT_NEAR(159.292, rect.top, 0.001);
259
260 FPDFText_ClosePage(textpage);
261 UnloadPage(page);
262}
263
265 ASSERT_TRUE(OpenDocument("hebrew_mirrored.pdf"));
266 FPDF_PAGE page = LoadPage(0);
267 ASSERT_TRUE(page);
268
269 {
270 ScopedFPDFTextPage textpage(FPDFText_LoadPage(page));
271 ASSERT_TRUE(textpage);
272
273 constexpr int kCharCount = 10;
274 ASSERT_EQ(kCharCount, FPDFText_CountChars(textpage.get()));
275
276 unsigned short buffer[kCharCount + 1];
277 memset(buffer, 0x42, sizeof(buffer));
278 EXPECT_EQ(kCharCount + 1,
279 FPDFText_GetText(textpage.get(), 0, kCharCount, buffer));
280 EXPECT_EQ(0x05d1, buffer[0]);
281 EXPECT_EQ(0x05e0, buffer[1]);
282 EXPECT_EQ(0x05d9, buffer[2]);
283 EXPECT_EQ(0x05de, buffer[3]);
284 EXPECT_EQ(0x05d9, buffer[4]);
285 EXPECT_EQ(0x05df, buffer[5]);
286 EXPECT_EQ(0x000d, buffer[6]);
287 EXPECT_EQ(0x000a, buffer[7]);
288 EXPECT_EQ(0x05df, buffer[8]);
289 EXPECT_EQ(0x05d1, buffer[9]);
290 }
291
292 UnloadPage(page);
293}
294
296 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
297 FPDF_PAGE page = LoadPage(0);
298 ASSERT_TRUE(page);
299
300 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
301 ASSERT_TRUE(textpage);
302
303 ScopedFPDFWideString nope = GetFPDFWideString(L"nope");
304 ScopedFPDFWideString world = GetFPDFWideString(L"world");
305 ScopedFPDFWideString world_caps = GetFPDFWideString(L"WORLD");
306 ScopedFPDFWideString world_substr = GetFPDFWideString(L"orld");
307
308 {
309 // No occurrences of "nope" in test page.
310 ScopedFPDFTextFind search(FPDFText_FindStart(textpage, nope.get(), 0, 0));
311 EXPECT_TRUE(search);
312 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search.get()));
313 EXPECT_EQ(0, FPDFText_GetSchCount(search.get()));
314
315 // Advancing finds nothing.
316 EXPECT_FALSE(FPDFText_FindNext(search.get()));
317 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search.get()));
318 EXPECT_EQ(0, FPDFText_GetSchCount(search.get()));
319
320 // Retreating finds nothing.
321 EXPECT_FALSE(FPDFText_FindPrev(search.get()));
322 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search.get()));
323 EXPECT_EQ(0, FPDFText_GetSchCount(search.get()));
324 }
325
326 {
327 // Two occurrences of "world" in test page.
328 ScopedFPDFTextFind search(FPDFText_FindStart(textpage, world.get(), 0, 2));
329 EXPECT_TRUE(search);
330
331 // Remains not found until advanced.
332 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search.get()));
333 EXPECT_EQ(0, FPDFText_GetSchCount(search.get()));
334
335 // First occurrence of "world" in this test page.
336 EXPECT_TRUE(FPDFText_FindNext(search.get()));
337 EXPECT_EQ(7, FPDFText_GetSchResultIndex(search.get()));
338 EXPECT_EQ(5, FPDFText_GetSchCount(search.get()));
339
340 // Last occurrence of "world" in this test page.
341 EXPECT_TRUE(FPDFText_FindNext(search.get()));
342 EXPECT_EQ(24, FPDFText_GetSchResultIndex(search.get()));
343 EXPECT_EQ(5, FPDFText_GetSchCount(search.get()));
344
345 // Found position unchanged when fails to advance.
346 EXPECT_FALSE(FPDFText_FindNext(search.get()));
347 EXPECT_EQ(24, FPDFText_GetSchResultIndex(search.get()));
348 EXPECT_EQ(5, FPDFText_GetSchCount(search.get()));
349
350 // Back to first occurrence.
351 EXPECT_TRUE(FPDFText_FindPrev(search.get()));
352 EXPECT_EQ(7, FPDFText_GetSchResultIndex(search.get()));
353 EXPECT_EQ(5, FPDFText_GetSchCount(search.get()));
354
355 // Found position unchanged when fails to retreat.
356 EXPECT_FALSE(FPDFText_FindPrev(search.get()));
357 EXPECT_EQ(7, FPDFText_GetSchResultIndex(search.get()));
358 EXPECT_EQ(5, FPDFText_GetSchCount(search.get()));
359 }
360
361 {
362 // Exact search unaffected by case sensitiity and whole word flags.
363 ScopedFPDFTextFind search(FPDFText_FindStart(
364 textpage, world.get(), FPDF_MATCHCASE | FPDF_MATCHWHOLEWORD, 0));
365 EXPECT_TRUE(search);
366 EXPECT_TRUE(FPDFText_FindNext(search.get()));
367 EXPECT_EQ(7, FPDFText_GetSchResultIndex(search.get()));
368 EXPECT_EQ(5, FPDFText_GetSchCount(search.get()));
369 }
370
371 {
372 // Default is case-insensitive, so matching agaist caps works.
373 ScopedFPDFTextFind search(
374 FPDFText_FindStart(textpage, world_caps.get(), 0, 0));
375 EXPECT_TRUE(search);
376 EXPECT_TRUE(FPDFText_FindNext(search.get()));
377 EXPECT_EQ(7, FPDFText_GetSchResultIndex(search.get()));
378 EXPECT_EQ(5, FPDFText_GetSchCount(search.get()));
379 }
380
381 {
382 // But can be made case sensitive, in which case this fails.
383 ScopedFPDFTextFind search(
384 FPDFText_FindStart(textpage, world_caps.get(), FPDF_MATCHCASE, 0));
385 EXPECT_FALSE(FPDFText_FindNext(search.get()));
386 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search.get()));
387 EXPECT_EQ(0, FPDFText_GetSchCount(search.get()));
388 }
389
390 {
391 // Default is match anywhere within word, so matching substring works.
392 ScopedFPDFTextFind search(
393 FPDFText_FindStart(textpage, world_substr.get(), 0, 0));
394 EXPECT_TRUE(FPDFText_FindNext(search.get()));
395 EXPECT_EQ(8, FPDFText_GetSchResultIndex(search.get()));
396 EXPECT_EQ(4, FPDFText_GetSchCount(search.get()));
397 }
398
399 {
400 // But can be made to mach word boundaries, in which case this fails.
401 ScopedFPDFTextFind search(FPDFText_FindStart(textpage, world_substr.get(),
403 EXPECT_FALSE(FPDFText_FindNext(search.get()));
404 // TODO(tsepez): investigate strange index/count values in this state.
405 }
406
407 FPDFText_ClosePage(textpage);
408 UnloadPage(page);
409}
410
412 ASSERT_TRUE(OpenDocument("find_text_consecutive.pdf"));
413 FPDF_PAGE page = LoadPage(0);
414 ASSERT_TRUE(page);
415
416 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
417 ASSERT_TRUE(textpage);
418
419 ScopedFPDFWideString aaaa = GetFPDFWideString(L"aaaa");
420
421 {
422 // Search for "aaaa" yields 2 results in "aaaaaaaaaa".
423 ScopedFPDFTextFind search(FPDFText_FindStart(textpage, aaaa.get(), 0, 0));
424 EXPECT_TRUE(search);
425
426 // Remains not found until advanced.
427 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search.get()));
428 EXPECT_EQ(0, FPDFText_GetSchCount(search.get()));
429
430 // First occurrence of "aaaa" in this test page.
431 EXPECT_TRUE(FPDFText_FindNext(search.get()));
432 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search.get()));
433 EXPECT_EQ(4, FPDFText_GetSchCount(search.get()));
434
435 // Last occurrence of "aaaa" in this test page.
436 EXPECT_TRUE(FPDFText_FindNext(search.get()));
437 EXPECT_EQ(4, FPDFText_GetSchResultIndex(search.get()));
438 EXPECT_EQ(4, FPDFText_GetSchCount(search.get()));
439
440 // Found position unchanged when fails to advance.
441 EXPECT_FALSE(FPDFText_FindNext(search.get()));
442 EXPECT_EQ(4, FPDFText_GetSchResultIndex(search.get()));
443 EXPECT_EQ(4, FPDFText_GetSchCount(search.get()));
444
445 // Back to first occurrence.
446 EXPECT_TRUE(FPDFText_FindPrev(search.get()));
447 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search.get()));
448 EXPECT_EQ(4, FPDFText_GetSchCount(search.get()));
449
450 // Found position unchanged when fails to retreat.
451 EXPECT_FALSE(FPDFText_FindPrev(search.get()));
452 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search.get()));
453 EXPECT_EQ(4, FPDFText_GetSchCount(search.get()));
454 }
455
456 {
457 // Search for "aaaa" yields 7 results in "aaaaaaaaaa", when searching with
458 // FPDF_CONSECUTIVE.
459 ScopedFPDFTextFind search(
460 FPDFText_FindStart(textpage, aaaa.get(), FPDF_CONSECUTIVE, 0));
461 EXPECT_TRUE(search);
462
463 // Remains not found until advanced.
464 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search.get()));
465 EXPECT_EQ(0, FPDFText_GetSchCount(search.get()));
466
467 // Find consecutive occurrences of "aaaa" in this test page:
468 for (int i = 0; i < 7; ++i) {
469 EXPECT_TRUE(FPDFText_FindNext(search.get()));
470 EXPECT_EQ(i, FPDFText_GetSchResultIndex(search.get()));
471 EXPECT_EQ(4, FPDFText_GetSchCount(search.get()));
472 }
473
474 // Found position unchanged when fails to advance.
475 EXPECT_FALSE(FPDFText_FindNext(search.get()));
476 EXPECT_EQ(6, FPDFText_GetSchResultIndex(search.get()));
477 EXPECT_EQ(4, FPDFText_GetSchCount(search.get()));
478
479 for (int i = 5; i >= 0; --i) {
480 EXPECT_TRUE(FPDFText_FindPrev(search.get()));
481 EXPECT_EQ(i, FPDFText_GetSchResultIndex(search.get()));
482 EXPECT_EQ(4, FPDFText_GetSchCount(search.get()));
483 }
484
485 // Found position unchanged when fails to retreat.
486 EXPECT_FALSE(FPDFText_FindPrev(search.get()));
487 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search.get()));
488 EXPECT_EQ(4, FPDFText_GetSchCount(search.get()));
489 }
490
491 FPDFText_ClosePage(textpage);
492 UnloadPage(page);
493}
494
496 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
497 FPDF_PAGE page = LoadPage(0);
498 ASSERT_TRUE(page);
499
500 {
501 ScopedFPDFTextPage textpage(FPDFText_LoadPage(page));
502 ASSERT_TRUE(textpage);
503
504 ScopedFPDFWideString search_term = GetFPDFWideString(L"world!");
505 ScopedFPDFTextFind search(
506 FPDFText_FindStart(textpage.get(), search_term.get(), 0, 0));
507 ASSERT_TRUE(search);
508 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search.get()));
509 EXPECT_EQ(0, FPDFText_GetSchCount(search.get()));
510
511 EXPECT_TRUE(FPDFText_FindNext(search.get()));
512 EXPECT_EQ(7, FPDFText_GetSchResultIndex(search.get()));
513 EXPECT_EQ(6, FPDFText_GetSchCount(search.get()));
514
515 EXPECT_TRUE(FPDFText_FindNext(search.get()));
516 EXPECT_EQ(24, FPDFText_GetSchResultIndex(search.get()));
517 EXPECT_EQ(6, FPDFText_GetSchCount(search.get()));
518 }
519
520 UnloadPage(page);
521}
522
524 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
525 FPDF_PAGE page = LoadPage(0);
526 ASSERT_TRUE(page);
527
528 {
529 ScopedFPDFTextPage textpage(FPDFText_LoadPage(page));
530 ASSERT_TRUE(textpage);
531
532 ScopedFPDFWideString search_term = GetFPDFWideString(L" Good");
533 ScopedFPDFTextFind search(
534 FPDFText_FindStart(textpage.get(), search_term.get(), 0, 0));
535 ASSERT_TRUE(search);
536 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search.get()));
537 EXPECT_EQ(0, FPDFText_GetSchCount(search.get()));
538
539 EXPECT_TRUE(FPDFText_FindNext(search.get()));
540 EXPECT_EQ(14, FPDFText_GetSchResultIndex(search.get()));
541 EXPECT_EQ(5, FPDFText_GetSchCount(search.get()));
542
543 EXPECT_FALSE(FPDFText_FindNext(search.get()));
544 }
545
546 UnloadPage(page);
547}
548
550 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
551 FPDF_PAGE page = LoadPage(0);
552 ASSERT_TRUE(page);
553
554 {
555 ScopedFPDFTextPage textpage(FPDFText_LoadPage(page));
556 ASSERT_TRUE(textpage);
557
558 ScopedFPDFWideString search_term = GetFPDFWideString(L"ld! ");
559 ScopedFPDFTextFind search(
560 FPDFText_FindStart(textpage.get(), search_term.get(), 0, 0));
561 ASSERT_TRUE(search);
562 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search.get()));
563 EXPECT_EQ(0, FPDFText_GetSchCount(search.get()));
564
565 EXPECT_TRUE(FPDFText_FindNext(search.get()));
566 EXPECT_EQ(10, FPDFText_GetSchResultIndex(search.get()));
567 EXPECT_EQ(4, FPDFText_GetSchCount(search.get()));
568
569 EXPECT_FALSE(FPDFText_FindNext(search.get()));
570 }
571
572 UnloadPage(page);
573}
574
576 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
577 FPDF_PAGE page = LoadPage(0);
578 ASSERT_TRUE(page);
579
580 {
581 ScopedFPDFTextPage textpage(FPDFText_LoadPage(page));
582 ASSERT_TRUE(textpage);
583
584 ScopedFPDFWideString search_term = GetFPDFWideString(L"ld! G");
585 ScopedFPDFTextFind search(
586 FPDFText_FindStart(textpage.get(), search_term.get(), 0, 0));
587 ASSERT_TRUE(search);
588 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search.get()));
589 EXPECT_EQ(0, FPDFText_GetSchCount(search.get()));
590
591 EXPECT_TRUE(FPDFText_FindNext(search.get()));
592 EXPECT_EQ(10, FPDFText_GetSchResultIndex(search.get()));
593 // Note: Even though `search_term` contains 5 characters,
594 // FPDFText_FindNext() matched "\r\n" in `textpage` against the space in
595 // `search_term`.
596 EXPECT_EQ(6, FPDFText_GetSchCount(search.get()));
597
598 EXPECT_FALSE(FPDFText_FindNext(search.get()));
599 }
600
601 UnloadPage(page);
602}
603
604// Fails on Windows. https://crbug.com/pdfium/1370
605#if BUILDFLAG(IS_WIN)
606#define MAYBE_TextSearchLatinExtended DISABLED_TextSearchLatinExtended
607#else
608#define MAYBE_TextSearchLatinExtended TextSearchLatinExtended
609#endif
611 ASSERT_TRUE(OpenDocument("latin_extended.pdf"));
612 FPDF_PAGE page = LoadPage(0);
613 ASSERT_TRUE(page);
614
615 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
616 ASSERT_TRUE(textpage);
617
618 // Upper/lowercase 'a' with breve.
619 constexpr FPDF_WCHAR kNeedleUpper[] = {0x0102, 0x0000};
620 constexpr FPDF_WCHAR kNeedleLower[] = {0x0103, 0x0000};
621
622 for (const auto* needle : {kNeedleUpper, kNeedleLower}) {
623 ScopedFPDFTextFind search(FPDFText_FindStart(textpage, needle, 0, 0));
624 EXPECT_TRUE(search);
625 EXPECT_EQ(0, FPDFText_GetSchResultIndex(search.get()));
626 EXPECT_EQ(0, FPDFText_GetSchCount(search.get()));
627
628 // Should find 2 results at position 21/22, both with length 1.
629 EXPECT_TRUE(FPDFText_FindNext(search.get()));
630 EXPECT_EQ(2, FPDFText_GetSchResultIndex(search.get()));
631 EXPECT_EQ(1, FPDFText_GetSchCount(search.get()));
632 EXPECT_TRUE(FPDFText_FindNext(search.get()));
633 EXPECT_EQ(3, FPDFText_GetSchResultIndex(search.get()));
634 EXPECT_EQ(1, FPDFText_GetSchCount(search.get()));
635 // And no more than 2 results.
636 EXPECT_FALSE(FPDFText_FindNext(search.get()));
637 }
638
639 FPDFText_ClosePage(textpage);
640 UnloadPage(page);
641}
642
643// Test that the page has characters despite a bad stream length.
645 ASSERT_TRUE(OpenDocument("bug_57.pdf"));
646 FPDF_PAGE page = LoadPage(0);
647 ASSERT_TRUE(page);
648
649 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
650 ASSERT_TRUE(textpage);
651 EXPECT_EQ(13, FPDFText_CountChars(textpage));
652
653 FPDFText_ClosePage(textpage);
654 UnloadPage(page);
655}
656
658 ASSERT_TRUE(OpenDocument("weblinks.pdf"));
659 FPDF_PAGE page = LoadPage(0);
660 ASSERT_TRUE(page);
661
662 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
663 ASSERT_TRUE(textpage);
664
665 {
666 ScopedFPDFPageLink pagelink(FPDFLink_LoadWebLinks(textpage));
667 EXPECT_TRUE(pagelink);
668
669 // Page contains two HTTP-style URLs.
670 EXPECT_EQ(2, FPDFLink_CountWebLinks(pagelink.get()));
671
672 // Only a terminating NUL required for bogus links.
673 EXPECT_EQ(1, FPDFLink_GetURL(pagelink.get(), 2, nullptr, 0));
674 EXPECT_EQ(1, FPDFLink_GetURL(pagelink.get(), 1400, nullptr, 0));
675 EXPECT_EQ(1, FPDFLink_GetURL(pagelink.get(), -1, nullptr, 0));
676 }
677
678 FPDF_PAGELINK pagelink = FPDFLink_LoadWebLinks(textpage);
679 EXPECT_TRUE(pagelink);
680
681 // Query the number of characters required for each link (incl NUL).
682 EXPECT_EQ(25, FPDFLink_GetURL(pagelink, 0, nullptr, 0));
683 EXPECT_EQ(26, FPDFLink_GetURL(pagelink, 1, nullptr, 0));
684
685 static const char expected_url[] = "http://example.com?q=foo";
686 static const size_t expected_len = sizeof(expected_url);
687 unsigned short buffer[128];
688
689 // Retrieve a link with too small a buffer. Buffer will not be
690 // NUL-terminated, but must not be modified past indicated length,
691 // so pre-fill with a pattern to check write bounds.
692 memset(buffer, 0xbd, sizeof(buffer));
693 EXPECT_EQ(1, FPDFLink_GetURL(pagelink, 0, buffer, 1));
694 EXPECT_TRUE(check_unsigned_shorts(expected_url, buffer, 1));
695 EXPECT_EQ(0xbdbd, buffer[1]);
696
697 // Check buffer that doesn't have space for a terminating NUL.
698 memset(buffer, 0xbd, sizeof(buffer));
699 EXPECT_EQ(static_cast<int>(expected_len - 1),
700 FPDFLink_GetURL(pagelink, 0, buffer, expected_len - 1));
701 EXPECT_TRUE(check_unsigned_shorts(expected_url, buffer, expected_len - 1));
702 EXPECT_EQ(0xbdbd, buffer[expected_len - 1]);
703
704 // Retreive link with exactly-sized buffer.
705 memset(buffer, 0xbd, sizeof(buffer));
706 EXPECT_EQ(static_cast<int>(expected_len),
707 FPDFLink_GetURL(pagelink, 0, buffer, expected_len));
708 EXPECT_TRUE(check_unsigned_shorts(expected_url, buffer, expected_len));
709 EXPECT_EQ(0u, buffer[expected_len - 1]);
710 EXPECT_EQ(0xbdbd, buffer[expected_len]);
711
712 // Retreive link with ample-sized-buffer.
713 memset(buffer, 0xbd, sizeof(buffer));
714 EXPECT_EQ(static_cast<int>(expected_len),
715 FPDFLink_GetURL(pagelink, 0, buffer, 128));
716 EXPECT_TRUE(check_unsigned_shorts(expected_url, buffer, expected_len));
717 EXPECT_EQ(0u, buffer[expected_len - 1]);
718 EXPECT_EQ(0xbdbd, buffer[expected_len]);
719
720 // Each link rendered in a single rect in this test page.
721 EXPECT_EQ(1, FPDFLink_CountRects(pagelink, 0));
722 EXPECT_EQ(1, FPDFLink_CountRects(pagelink, 1));
723
724 // Each link rendered in a single rect in this test page.
725 EXPECT_EQ(0, FPDFLink_CountRects(pagelink, -1));
726 EXPECT_EQ(0, FPDFLink_CountRects(pagelink, 2));
727 EXPECT_EQ(0, FPDFLink_CountRects(pagelink, 10000));
728
729 // Check boundary of valid link index with valid rect index.
730 double left = 0.0;
731 double right = 0.0;
732 double top = 0.0;
733 double bottom = 0.0;
734 EXPECT_TRUE(FPDFLink_GetRect(pagelink, 0, 0, &left, &top, &right, &bottom));
735 EXPECT_NEAR(50.828, left, 0.001);
736 EXPECT_NEAR(187.904, right, 0.001);
737 EXPECT_NEAR(97.516, bottom, 0.001);
738 EXPECT_NEAR(108.700, top, 0.001);
739
740 // Check that valid link with invalid rect index leaves parameters unchanged.
741 left = -1.0;
742 right = -1.0;
743 top = -1.0;
744 bottom = -1.0;
745 EXPECT_FALSE(FPDFLink_GetRect(pagelink, 0, 1, &left, &top, &right, &bottom));
746 EXPECT_EQ(-1.0, left);
747 EXPECT_EQ(-1.0, right);
748 EXPECT_EQ(-1.0, bottom);
749 EXPECT_EQ(-1.0, top);
750
751 // Check that invalid link index leaves parameters unchanged.
752 left = -2.0;
753 right = -2.0;
754 top = -2.0;
755 bottom = -2.0;
756 EXPECT_FALSE(FPDFLink_GetRect(pagelink, -1, 0, &left, &top, &right, &bottom));
757 EXPECT_EQ(-2.0, left);
758 EXPECT_EQ(-2.0, right);
759 EXPECT_EQ(-2.0, bottom);
760 EXPECT_EQ(-2.0, top);
761
763 FPDFText_ClosePage(textpage);
764 UnloadPage(page);
765}
766
768 ASSERT_TRUE(OpenDocument("weblinks_across_lines.pdf"));
769 FPDF_PAGE page = LoadPage(0);
770 ASSERT_TRUE(page);
771
772 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
773 ASSERT_TRUE(textpage);
774
775 FPDF_PAGELINK pagelink = FPDFLink_LoadWebLinks(textpage);
776 EXPECT_TRUE(pagelink);
777
778 static const char* const kExpectedUrls[] = {
779 "http://example.com", // from "http://www.example.com?\r\nfoo"
780 "http://example.com/", // from "http://www.example.com/\r\nfoo"
781 "http://example.com/test-foo", // from "http://example.com/test-\r\nfoo"
782 "http://abc.com/test-foo", // from "http://abc.com/test-\r\n\r\nfoo"
783 // Next two links from "http://www.example.com/\r\nhttp://www.abc.com/"
784 "http://example.com/",
785 "http://www.abc.com",
786 };
787 static const int kNumLinks = static_cast<int>(std::size(kExpectedUrls));
788
789 EXPECT_EQ(kNumLinks, FPDFLink_CountWebLinks(pagelink));
790
791 unsigned short buffer[128];
792 for (int i = 0; i < kNumLinks; i++) {
793 const size_t expected_len = strlen(kExpectedUrls[i]) + 1;
794 memset(buffer, 0, sizeof(buffer));
795 EXPECT_EQ(static_cast<int>(expected_len),
796 FPDFLink_GetURL(pagelink, i, nullptr, 0));
797 EXPECT_EQ(static_cast<int>(expected_len),
798 FPDFLink_GetURL(pagelink, i, buffer, std::size(buffer)));
799 EXPECT_TRUE(check_unsigned_shorts(kExpectedUrls[i], buffer, expected_len));
800 }
801
803 FPDFText_ClosePage(textpage);
804 UnloadPage(page);
805}
806
808 ASSERT_TRUE(OpenDocument("bug_650.pdf"));
809 FPDF_PAGE page = LoadPage(0);
810 ASSERT_TRUE(page);
811
812 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
813 ASSERT_TRUE(textpage);
814
815 FPDF_PAGELINK pagelink = FPDFLink_LoadWebLinks(textpage);
816 EXPECT_TRUE(pagelink);
817
818 EXPECT_EQ(2, FPDFLink_CountWebLinks(pagelink));
819 unsigned short buffer[128] = {0};
820 static const char kExpectedUrl[] =
821 "http://tutorial45.com/learn-autocad-basics-day-166/";
822 static const int kUrlSize = static_cast<int>(sizeof(kExpectedUrl));
823
824 EXPECT_EQ(kUrlSize, FPDFLink_GetURL(pagelink, 1, nullptr, 0));
825 EXPECT_EQ(kUrlSize, FPDFLink_GetURL(pagelink, 1, buffer, std::size(buffer)));
826 EXPECT_TRUE(check_unsigned_shorts(kExpectedUrl, buffer, kUrlSize));
827
829 FPDFText_ClosePage(textpage);
830 UnloadPage(page);
831}
832
834 ASSERT_TRUE(OpenDocument("weblinks.pdf"));
835 FPDF_PAGE page = LoadPage(0);
836 ASSERT_TRUE(page);
837
838 FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page);
839 ASSERT_TRUE(text_page);
840
841 FPDF_PAGELINK page_link = FPDFLink_LoadWebLinks(text_page);
842 EXPECT_TRUE(page_link);
843
844 // Test for char indices of a valid link
845 int start_char_index;
846 int char_count;
847 ASSERT_TRUE(
848 FPDFLink_GetTextRange(page_link, 0, &start_char_index, &char_count));
849 EXPECT_EQ(35, start_char_index);
850 EXPECT_EQ(24, char_count);
851
852 // Test for char indices of an invalid link
853 start_char_index = -10;
854 char_count = -8;
855 ASSERT_FALSE(
856 FPDFLink_GetTextRange(page_link, 6, &start_char_index, &char_count));
857 EXPECT_EQ(start_char_index, -10);
858 EXPECT_EQ(char_count, -8);
859
860 // Test for pagelink = nullptr
861 start_char_index = -10;
862 char_count = -8;
863 ASSERT_FALSE(
864 FPDFLink_GetTextRange(nullptr, 0, &start_char_index, &char_count));
865 EXPECT_EQ(start_char_index, -10);
866 EXPECT_EQ(char_count, -8);
867
868 // Test for link_index < 0
869 start_char_index = -10;
870 char_count = -8;
871 ASSERT_FALSE(
872 FPDFLink_GetTextRange(page_link, -4, &start_char_index, &char_count));
873 EXPECT_EQ(start_char_index, -10);
874 EXPECT_EQ(char_count, -8);
875
877 FPDFText_ClosePage(text_page);
878 UnloadPage(page);
879}
880
882 ASSERT_TRUE(OpenDocument("annots.pdf"));
883 FPDF_PAGE page = LoadPage(0);
884 ASSERT_TRUE(page);
885
886 // Get link count via checking annotation subtype
887 int annot_count = FPDFPage_GetAnnotCount(page);
888 ASSERT_EQ(9, annot_count);
889 int annot_subtype_link_count = 0;
890 for (int i = 0; i < annot_count; ++i) {
891 ScopedFPDFAnnotation annot(FPDFPage_GetAnnot(page, i));
892 if (FPDFAnnot_GetSubtype(annot.get()) == FPDF_ANNOT_LINK) {
893 ++annot_subtype_link_count;
894 }
895 }
896 EXPECT_EQ(4, annot_subtype_link_count);
897
898 // Validate that FPDFLink_Enumerate() returns same number of links
899 int start_pos = 0;
900 FPDF_LINK link_annot;
901 int link_count = 0;
902 while (FPDFLink_Enumerate(page, &start_pos, &link_annot)) {
903 ASSERT_TRUE(link_annot);
904 if (start_pos == 1 || start_pos == 2) {
905 // First two links point to first and second page within the document
906 // respectively
907 FPDF_DEST link_dest = FPDFLink_GetDest(document(), link_annot);
908 EXPECT_TRUE(link_dest);
909 EXPECT_EQ(start_pos - 1,
910 FPDFDest_GetDestPageIndex(document(), link_dest));
911 } else if (start_pos == 3) { // points to PDF Spec URL
912 FS_RECTF link_rect;
913 EXPECT_TRUE(FPDFLink_GetAnnotRect(link_annot, &link_rect));
914 EXPECT_NEAR(66.0, link_rect.left, 0.001);
915 EXPECT_NEAR(544.0, link_rect.top, 0.001);
916 EXPECT_NEAR(196.0, link_rect.right, 0.001);
917 EXPECT_NEAR(529.0, link_rect.bottom, 0.001);
918 } else if (start_pos == 4) { // this link has quad points
919 int quad_point_count = FPDFLink_CountQuadPoints(link_annot);
920 EXPECT_EQ(1, quad_point_count);
921 FS_QUADPOINTSF quad_points;
922 EXPECT_TRUE(FPDFLink_GetQuadPoints(link_annot, 0, &quad_points));
923 EXPECT_NEAR(83.0, quad_points.x1, 0.001);
924 EXPECT_NEAR(453.0, quad_points.y1, 0.001);
925 EXPECT_NEAR(178.0, quad_points.x2, 0.001);
926 EXPECT_NEAR(453.0, quad_points.y2, 0.001);
927 EXPECT_NEAR(83.0, quad_points.x3, 0.001);
928 EXPECT_NEAR(440.0, quad_points.y3, 0.001);
929 EXPECT_NEAR(178.0, quad_points.x4, 0.001);
930 EXPECT_NEAR(440.0, quad_points.y4, 0.001);
931 // AnnotRect is same as quad points for this link
932 FS_RECTF link_rect;
933 EXPECT_TRUE(FPDFLink_GetAnnotRect(link_annot, &link_rect));
934 EXPECT_NEAR(link_rect.left, quad_points.x1, 0.001);
935 EXPECT_NEAR(link_rect.top, quad_points.y1, 0.001);
936 EXPECT_NEAR(link_rect.right, quad_points.x4, 0.001);
937 EXPECT_NEAR(link_rect.bottom, quad_points.y4, 0.001);
938 }
939 ++link_count;
940 }
941 EXPECT_EQ(annot_subtype_link_count, link_count);
942
943 UnloadPage(page);
944}
945
947 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
948 FPDF_PAGE page = LoadPage(0);
949 ASSERT_TRUE(page);
950
951 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
952 ASSERT_TRUE(textpage);
953
954 const double kExpectedFontsSizes[] = {12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
955 12, 12, 12, 1, 1, 16, 16, 16, 16, 16,
956 16, 16, 16, 16, 16, 16, 16, 16, 16, 16};
957
958 int count = FPDFText_CountChars(textpage);
959 ASSERT_EQ(std::size(kExpectedFontsSizes), static_cast<size_t>(count));
960 for (int i = 0; i < count; ++i)
961 EXPECT_EQ(kExpectedFontsSizes[i], FPDFText_GetFontSize(textpage, i)) << i;
962
963 FPDFText_ClosePage(textpage);
964 UnloadPage(page);
965}
966
968 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
969 FPDF_PAGE page = LoadPage(0);
970 ASSERT_TRUE(page);
971
972 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
973 ASSERT_TRUE(textpage);
974 std::vector<char> font_name;
975 size_t num_chars1 = strlen("Hello, world!");
976 const char kExpectedFontName1[] = "Times-Roman";
977
978 for (size_t i = 0; i < num_chars1; i++) {
979 int flags = -1;
980 unsigned long length =
981 FPDFText_GetFontInfo(textpage, i, nullptr, 0, &flags);
982 static constexpr unsigned long expected_length = sizeof(kExpectedFontName1);
983 ASSERT_EQ(expected_length, length);
984 EXPECT_EQ(FXFONT_NONSYMBOLIC, flags);
985 font_name.resize(length);
986 std::fill(font_name.begin(), font_name.end(), 'a');
987 flags = -1;
988 EXPECT_EQ(expected_length,
989 FPDFText_GetFontInfo(textpage, i, font_name.data(),
990 font_name.size(), &flags));
991 EXPECT_STREQ(kExpectedFontName1, font_name.data());
992 EXPECT_EQ(FXFONT_NONSYMBOLIC, flags);
993 }
994 // If the size of the buffer is not large enough, the buffer should remain
995 // unchanged.
996 font_name.pop_back();
997 std::fill(font_name.begin(), font_name.end(), 'a');
998 EXPECT_EQ(sizeof(kExpectedFontName1),
999 FPDFText_GetFontInfo(textpage, 0, font_name.data(),
1000 font_name.size(), nullptr));
1001 for (char a : font_name)
1002 EXPECT_EQ('a', a);
1003
1004 // The text is "Hello, world!\r\nGoodbye, world!", so the next two characters
1005 // do not have any font information.
1006 EXPECT_EQ(0u, FPDFText_GetFontInfo(textpage, num_chars1, font_name.data(),
1007 font_name.size(), nullptr));
1008 EXPECT_EQ(0u, FPDFText_GetFontInfo(textpage, num_chars1 + 1, font_name.data(),
1009 font_name.size(), nullptr));
1010
1011 size_t num_chars2 = strlen("Goodbye, world!");
1012 const char kExpectedFontName2[] = "Helvetica";
1013 for (size_t i = num_chars1 + 2; i < num_chars1 + num_chars2 + 2; i++) {
1014 int flags = -1;
1015 unsigned long length =
1016 FPDFText_GetFontInfo(textpage, i, nullptr, 0, &flags);
1017 static constexpr unsigned long expected_length = sizeof(kExpectedFontName2);
1018 ASSERT_EQ(expected_length, length);
1019 EXPECT_EQ(FXFONT_NONSYMBOLIC, flags);
1020 font_name.resize(length);
1021 std::fill(font_name.begin(), font_name.end(), 'a');
1022 flags = -1;
1023 EXPECT_EQ(expected_length,
1024 FPDFText_GetFontInfo(textpage, i, font_name.data(),
1025 font_name.size(), &flags));
1026 EXPECT_STREQ(kExpectedFontName2, font_name.data());
1027 EXPECT_EQ(FXFONT_NONSYMBOLIC, flags);
1028 }
1029
1030 // Now try some out of bounds indices and null pointers to make sure we do not
1031 // crash.
1032 // No textpage.
1033 EXPECT_EQ(0u, FPDFText_GetFontInfo(nullptr, 0, font_name.data(),
1034 font_name.size(), nullptr));
1035 // No buffer.
1036 EXPECT_EQ(sizeof(kExpectedFontName1),
1037 FPDFText_GetFontInfo(textpage, 0, nullptr, 0, nullptr));
1038 // Negative index.
1039 EXPECT_EQ(0u, FPDFText_GetFontInfo(textpage, -1, font_name.data(),
1040 font_name.size(), nullptr));
1041 // Out of bounds index.
1042 EXPECT_EQ(0u, FPDFText_GetFontInfo(textpage, 1000, font_name.data(),
1043 font_name.size(), nullptr));
1044
1045 FPDFText_ClosePage(textpage);
1046 UnloadPage(page);
1047}
1048
1050 ASSERT_TRUE(OpenDocument("bug_583.pdf"));
1051 FPDF_PAGE page = LoadPage(0);
1052 ASSERT_TRUE(page);
1053
1054 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
1055 ASSERT_TRUE(textpage);
1056
1057 ASSERT_EQ(1, FPDFText_CountChars(textpage));
1058 EXPECT_EQ(0U, FPDFText_GetUnicode(textpage, 0));
1059
1060 FPDFText_ClosePage(textpage);
1061 UnloadPage(page);
1062}
1063
1065 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
1066 FPDF_PAGE page = LoadPage(0);
1067 ASSERT_TRUE(page);
1068
1069 {
1070 ScopedFPDFTextPage textpage(FPDFText_LoadPage(page));
1071 ASSERT_TRUE(textpage);
1072
1073 EXPECT_EQ(static_cast<unsigned int>('H'),
1074 FPDFText_GetUnicode(textpage.get(), 0));
1075 EXPECT_EQ(0, FPDFText_IsGenerated(textpage.get(), 0));
1076 EXPECT_EQ(static_cast<unsigned int>(' '),
1077 FPDFText_GetUnicode(textpage.get(), 6));
1078 EXPECT_EQ(0, FPDFText_IsGenerated(textpage.get(), 6));
1079
1080 EXPECT_EQ(static_cast<unsigned int>('\r'),
1081 FPDFText_GetUnicode(textpage.get(), 13));
1082 EXPECT_EQ(1, FPDFText_IsGenerated(textpage.get(), 13));
1083 EXPECT_EQ(static_cast<unsigned int>('\n'),
1084 FPDFText_GetUnicode(textpage.get(), 14));
1085 EXPECT_EQ(1, FPDFText_IsGenerated(textpage.get(), 14));
1086
1087 EXPECT_EQ(-1, FPDFText_IsGenerated(textpage.get(), -1));
1088 EXPECT_EQ(-1, FPDFText_IsGenerated(textpage.get(), kHelloGoodbyeTextSize));
1089 EXPECT_EQ(-1, FPDFText_IsGenerated(nullptr, 6));
1090 }
1091
1092 UnloadPage(page);
1093}
1094
1096 ASSERT_TRUE(OpenDocument("bug_781804.pdf"));
1097 FPDF_PAGE page = LoadPage(0);
1098 ASSERT_TRUE(page);
1099
1100 {
1101 ScopedFPDFTextPage textpage(FPDFText_LoadPage(page));
1102 ASSERT_TRUE(textpage);
1103
1104 EXPECT_EQ(static_cast<unsigned int>('V'),
1105 FPDFText_GetUnicode(textpage.get(), 0));
1106 EXPECT_EQ(0, FPDFText_IsHyphen(textpage.get(), 0));
1107 EXPECT_EQ(static_cast<unsigned int>('\2'),
1108 FPDFText_GetUnicode(textpage.get(), 6));
1109 EXPECT_EQ(1, FPDFText_IsHyphen(textpage.get(), 6));
1110
1111 EXPECT_EQ(static_cast<unsigned int>('U'),
1112 FPDFText_GetUnicode(textpage.get(), 14));
1113 EXPECT_EQ(0, FPDFText_IsHyphen(textpage.get(), 14));
1114 EXPECT_EQ(static_cast<unsigned int>(L'\u2010'),
1115 FPDFText_GetUnicode(textpage.get(), 18));
1116 EXPECT_EQ(0, FPDFText_IsHyphen(textpage.get(), 18));
1117
1118 EXPECT_EQ(-1, FPDFText_IsHyphen(textpage.get(), -1));
1119 EXPECT_EQ(-1, FPDFText_IsHyphen(textpage.get(), 1000));
1120 EXPECT_EQ(-1, FPDFText_IsHyphen(nullptr, 6));
1121 }
1122
1123 UnloadPage(page);
1124}
1125
1127 ASSERT_TRUE(OpenDocument("bug_1388_2.pdf"));
1128 FPDF_PAGE page = LoadPage(0);
1129 ASSERT_TRUE(page);
1130
1131 {
1132 constexpr int kExpectedCharCount = 5;
1133 ScopedFPDFTextPage textpage(FPDFText_LoadPage(page));
1134 ASSERT_TRUE(textpage);
1135 EXPECT_EQ(kExpectedCharCount, FPDFText_CountChars(textpage.get()));
1136
1137 EXPECT_EQ(static_cast<unsigned int>('X'),
1138 FPDFText_GetUnicode(textpage.get(), 0));
1139 EXPECT_EQ(0, FPDFText_HasUnicodeMapError(textpage.get(), 0));
1140 EXPECT_EQ(static_cast<unsigned int>(' '),
1141 FPDFText_GetUnicode(textpage.get(), 1));
1142 EXPECT_EQ(0, FPDFText_HasUnicodeMapError(textpage.get(), 1));
1143
1144 EXPECT_EQ(31u, FPDFText_GetUnicode(textpage.get(), 2));
1145 EXPECT_EQ(1, FPDFText_HasUnicodeMapError(textpage.get(), 2));
1146
1147 EXPECT_EQ(-1, FPDFText_HasUnicodeMapError(textpage.get(), -1));
1148 EXPECT_EQ(-1,
1149 FPDFText_HasUnicodeMapError(textpage.get(), kExpectedCharCount));
1150 EXPECT_EQ(-1, FPDFText_HasUnicodeMapError(nullptr, 0));
1151 }
1152
1153 UnloadPage(page);
1154}
1155
1157 ASSERT_TRUE(OpenDocument("bug_921.pdf"));
1158 FPDF_PAGE page = LoadPage(0);
1159 ASSERT_TRUE(page);
1160
1161 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
1162 ASSERT_TRUE(textpage);
1163
1164 static constexpr unsigned int kData[] = {
1165 1095, 1077, 1083, 1086, 1074, 1077, 1095, 1077, 1089, 1082, 1086, 1077,
1166 32, 1089, 1090, 1088, 1072, 1076, 1072, 1085, 1080, 1077, 46, 32};
1167 static constexpr int kStartIndex = 238;
1168
1169 ASSERT_EQ(268, FPDFText_CountChars(textpage));
1170 for (size_t i = 0; i < std::size(kData); ++i)
1171 EXPECT_EQ(kData[i], FPDFText_GetUnicode(textpage, kStartIndex + i));
1172
1173 unsigned short buffer[std::size(kData) + 1];
1174 memset(buffer, 0xbd, sizeof(buffer));
1175 int count = FPDFText_GetText(textpage, kStartIndex, std::size(kData), buffer);
1176 ASSERT_GT(count, 0);
1177 ASSERT_EQ(std::size(kData) + 1, static_cast<size_t>(count));
1178 for (size_t i = 0; i < std::size(kData); ++i)
1179 EXPECT_EQ(kData[i], buffer[i]);
1180 EXPECT_EQ(0, buffer[std::size(kData)]);
1181
1182 FPDFText_ClosePage(textpage);
1183 UnloadPage(page);
1184}
1185
1187 ASSERT_TRUE(OpenDocument("bug_781804.pdf"));
1188 FPDF_PAGE page = LoadPage(0);
1189 ASSERT_TRUE(page);
1190
1191 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
1192 ASSERT_TRUE(textpage);
1193
1194 // Check that soft hyphens are not included
1195 // Expecting 'Veritaserum', except there is a \uFFFE where the hyphen was in
1196 // the original text. This is a weird thing that Adobe does, which we
1197 // replicate.
1198 constexpr unsigned short soft_expected[] = {
1199 0x0056, 0x0065, 0x0072, 0x0069, 0x0074, 0x0061, 0xfffe,
1200 0x0073, 0x0065, 0x0072, 0x0075, 0x006D, 0x0000};
1201 {
1202 constexpr int count = std::size(soft_expected) - 1;
1203 unsigned short buffer[std::size(soft_expected)];
1204 memset(buffer, 0, sizeof(buffer));
1205
1206 EXPECT_EQ(count + 1, FPDFText_GetText(textpage, 0, count, buffer));
1207 for (int i = 0; i < count; i++)
1208 EXPECT_EQ(soft_expected[i], buffer[i]);
1209 }
1210
1211 // Check that hard hyphens are included
1212 {
1213 // There isn't the \0 in the actual doc, but there is a \r\n, so need to
1214 // add 1 to get aligned.
1215 constexpr size_t offset = std::size(soft_expected) + 1;
1216 // Expecting 'User-\r\ngenerated', the - is a unicode character, so cannot
1217 // store in a char[].
1218 constexpr unsigned short hard_expected[] = {
1219 0x0055, 0x0073, 0x0065, 0x0072, 0x2010, 0x000d, 0x000a, 0x0067, 0x0065,
1220 0x006e, 0x0065, 0x0072, 0x0061, 0x0074, 0x0065, 0x0064, 0x0000};
1221 constexpr int count = std::size(hard_expected) - 1;
1222 unsigned short buffer[std::size(hard_expected)];
1223
1224 EXPECT_EQ(count + 1, FPDFText_GetText(textpage, offset, count, buffer));
1225 for (int i = 0; i < count; i++)
1226 EXPECT_EQ(hard_expected[i], buffer[i]);
1227 }
1228
1229 FPDFText_ClosePage(textpage);
1230 UnloadPage(page);
1231}
1232
1234 // If there is a regression in this test, it will only fail under ASAN
1235 ASSERT_TRUE(OpenDocument("bug_782596.pdf"));
1236 FPDF_PAGE page = LoadPage(0);
1237 ASSERT_TRUE(page);
1238 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
1239 ASSERT_TRUE(textpage);
1240 FPDFText_ClosePage(textpage);
1241 UnloadPage(page);
1242}
1243
1245 ASSERT_TRUE(OpenDocument("control_characters.pdf"));
1246 FPDF_PAGE page = LoadPage(0);
1247 ASSERT_TRUE(page);
1248
1249 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
1250 ASSERT_TRUE(textpage);
1251
1252 // Should not include the control characters in the output
1253 unsigned short buffer[128];
1254 memset(buffer, 0xbd, sizeof(buffer));
1255 int num_chars = FPDFText_GetText(textpage, 0, 128, buffer);
1256 ASSERT_EQ(kHelloGoodbyeTextSize, num_chars);
1257 EXPECT_TRUE(
1258 check_unsigned_shorts(kHelloGoodbyeText, buffer, kHelloGoodbyeTextSize));
1259
1260 // Attempting to get a chunk of text after the control characters
1261 static const char expected_substring[] = "Goodbye, world!";
1262 // Offset is the length of 'Hello, world!\r\n' + 2 control characters in the
1263 // original stream
1264 static const int offset = 17;
1265 memset(buffer, 0xbd, sizeof(buffer));
1266 num_chars = FPDFText_GetText(textpage, offset, 128, buffer);
1267
1268 ASSERT_GE(num_chars, 0);
1269 EXPECT_EQ(sizeof(expected_substring), static_cast<size_t>(num_chars));
1270 EXPECT_TRUE(check_unsigned_shorts(expected_substring, buffer,
1271 sizeof(expected_substring)));
1272
1273 FPDFText_ClosePage(textpage);
1274 UnloadPage(page);
1275}
1276
1277// Testing that hyphen makers (0x0002) are replacing hard hyphens when
1278// the word contains non-ASCII characters.
1280 ASSERT_TRUE(OpenDocument("bug_1029.pdf"));
1281 FPDF_PAGE page = LoadPage(0);
1282 ASSERT_TRUE(page);
1283
1284 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
1285 ASSERT_TRUE(textpage);
1286
1287 constexpr int page_range_offset = 171;
1288 constexpr int page_range_length = 56;
1289
1290 // This text is:
1291 // 'METADATA table. When the split has committed, it noti' followed
1292 // by a 'soft hyphen' (0x0002) and then 'fi'.
1293 //
1294 // The original text has a fi ligature, but that is broken up into
1295 // two characters when the PDF is processed.
1296 constexpr unsigned int expected[] = {
1297 0x004d, 0x0045, 0x0054, 0x0041, 0x0044, 0x0041, 0x0054, 0x0041,
1298 0x0020, 0x0074, 0x0061, 0x0062, 0x006c, 0x0065, 0x002e, 0x0020,
1299 0x0057, 0x0068, 0x0065, 0x006e, 0x0020, 0x0074, 0x0068, 0x0065,
1300 0x0020, 0x0073, 0x0070, 0x006c, 0x0069, 0x0074, 0x0020, 0x0068,
1301 0x0061, 0x0073, 0x0020, 0x0063, 0x006f, 0x006d, 0x006d, 0x0069,
1302 0x0074, 0x0074, 0x0065, 0x0064, 0x002c, 0x0020, 0x0069, 0x0074,
1303 0x0020, 0x006e, 0x006f, 0x0074, 0x0069, 0x0002, 0x0066, 0x0069};
1304 static_assert(page_range_length == std::size(expected),
1305 "Expected should be the same size as the range being "
1306 "extracted from page.");
1307 EXPECT_LT(page_range_offset + page_range_length,
1308 FPDFText_CountChars(textpage));
1309
1310 for (int i = 0; i < page_range_length; ++i) {
1311 EXPECT_EQ(expected[i],
1312 FPDFText_GetUnicode(textpage, page_range_offset + i));
1313 }
1314
1315 FPDFText_ClosePage(textpage);
1316 UnloadPage(page);
1317}
1318
1320 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
1321 FPDF_PAGE page = LoadPage(0);
1322 ASSERT_TRUE(page);
1323
1324 FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
1325 ASSERT_TRUE(textpage);
1326
1327 // Sanity check hello_world.pdf.
1328 // |num_chars| check includes the terminating NUL that is provided.
1329 {
1330 unsigned short buffer[128];
1331 int num_chars = FPDFText_GetText(textpage, 0, 128, buffer);
1332 ASSERT_EQ(kHelloGoodbyeTextSize, num_chars);
1333 EXPECT_TRUE(check_unsigned_shorts(kHelloGoodbyeText, buffer,
1334 kHelloGoodbyeTextSize));
1335 }
1336
1337 // Now test FPDFText_CountRects().
1338 static const int kHelloWorldEnd = strlen("Hello, world!");
1339 static const int kGoodbyeWorldStart = kHelloWorldEnd + 2; // "\r\n"
1340 for (int start = 0; start < kHelloWorldEnd; ++start) {
1341 // Always grab some part of "hello world" and some part of "goodbye world"
1342 // Since -1 means "all".
1343 EXPECT_EQ(2, FPDFText_CountRects(textpage, start, -1));
1344
1345 // No characters always means 0 rects.
1346 EXPECT_EQ(0, FPDFText_CountRects(textpage, start, 0));
1347
1348 // 1 character stays within "hello world"
1349 EXPECT_EQ(1, FPDFText_CountRects(textpage, start, 1));
1350
1351 // When |start| is 0, Having |kGoodbyeWorldStart| char count does not reach
1352 // "goodbye world".
1353 int expected_value = start ? 2 : 1;
1354 EXPECT_EQ(expected_value,
1355 FPDFText_CountRects(textpage, start, kGoodbyeWorldStart));
1356
1357 // Extremely large character count will always return 2 rects because
1358 // |start| starts inside "hello world".
1359 EXPECT_EQ(2, FPDFText_CountRects(textpage, start, 500));
1360 }
1361
1362 // Now test negative counts.
1363 for (int start = 0; start < kHelloWorldEnd; ++start) {
1364 EXPECT_EQ(2, FPDFText_CountRects(textpage, start, -100));
1365 EXPECT_EQ(2, FPDFText_CountRects(textpage, start, -2));
1366 }
1367
1368 // Now test larger start values.
1369 const int kExpectedLength = strlen(kHelloGoodbyeText);
1370 for (int start = kGoodbyeWorldStart + 1; start < kExpectedLength; ++start) {
1371 EXPECT_EQ(1, FPDFText_CountRects(textpage, start, -1));
1372 EXPECT_EQ(0, FPDFText_CountRects(textpage, start, 0));
1373 EXPECT_EQ(1, FPDFText_CountRects(textpage, start, 1));
1374 EXPECT_EQ(1, FPDFText_CountRects(textpage, start, 2));
1375 EXPECT_EQ(1, FPDFText_CountRects(textpage, start, 500));
1376 }
1377
1378 // Now test start values that starts beyond the end of the text.
1379 for (int start = kExpectedLength; start < 100; ++start) {
1380 EXPECT_EQ(0, FPDFText_CountRects(textpage, start, -1));
1381 EXPECT_EQ(0, FPDFText_CountRects(textpage, start, 0));
1382 EXPECT_EQ(0, FPDFText_CountRects(textpage, start, 1));
1383 EXPECT_EQ(0, FPDFText_CountRects(textpage, start, 2));
1384 EXPECT_EQ(0, FPDFText_CountRects(textpage, start, 500));
1385 }
1386
1387 FPDFText_ClosePage(textpage);
1388 UnloadPage(page);
1389}
1390
1392 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
1393 FPDF_PAGE page = LoadPage(0);
1394 ASSERT_TRUE(page);
1395
1396 FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page);
1397 ASSERT_TRUE(text_page);
1398
1399 EXPECT_EQ(2, FPDFPage_CountObjects(page));
1400 FPDF_PAGEOBJECT text_object = FPDFPage_GetObject(page, 0);
1401 ASSERT_TRUE(text_object);
1402
1403 // Positive testing.
1404 constexpr char kHelloText[] = "Hello, world!";
1405 // Return value includes the terminating NUL that is provided.
1406 constexpr unsigned long kHelloUTF16Size = std::size(kHelloText) * 2;
1407 constexpr wchar_t kHelloWideText[] = L"Hello, world!";
1408 unsigned long size = FPDFTextObj_GetText(text_object, text_page, nullptr, 0);
1409 ASSERT_EQ(kHelloUTF16Size, size);
1410
1411 std::vector<unsigned short> buffer(size);
1412 ASSERT_EQ(size,
1413 FPDFTextObj_GetText(text_object, text_page, buffer.data(), size));
1414 ASSERT_EQ(kHelloWideText, GetPlatformWString(buffer.data()));
1415
1416 // Negative testing.
1417 ASSERT_EQ(0U, FPDFTextObj_GetText(nullptr, text_page, nullptr, 0));
1418 ASSERT_EQ(0U, FPDFTextObj_GetText(text_object, nullptr, nullptr, 0));
1419 ASSERT_EQ(0U, FPDFTextObj_GetText(nullptr, nullptr, nullptr, 0));
1420
1421 // Buffer is too small, ensure it's not modified.
1422 buffer.resize(2);
1423 buffer[0] = 'x';
1424 buffer[1] = '\0';
1425 size =
1426 FPDFTextObj_GetText(text_object, text_page, buffer.data(), buffer.size());
1427 ASSERT_EQ(kHelloUTF16Size, size);
1428 ASSERT_EQ('x', buffer[0]);
1429 ASSERT_EQ('\0', buffer[1]);
1430
1431 FPDFText_ClosePage(text_page);
1432 UnloadPage(page);
1433}
1434
1436 static constexpr int kPageCount = 4;
1437 static constexpr FS_RECTF kBoxes[kPageCount] = {
1438 {50.0f, 150.0f, 150.0f, 50.0f},
1439 {50.0f, 150.0f, 150.0f, 50.0f},
1440 {60.0f, 150.0f, 150.0f, 60.0f},
1441 {60.0f, 150.0f, 150.0f, 60.0f},
1442 };
1443 static constexpr const char* kExpectedText[kPageCount] = {
1444 " world!\r\ndbye, world!",
1445 " world!\r\ndbye, world!",
1446 "bye, world!",
1447 "bye, world!",
1448 };
1449
1450 ASSERT_TRUE(OpenDocument("cropped_text.pdf"));
1451 ASSERT_EQ(kPageCount, FPDF_GetPageCount(document()));
1452
1453 for (int i = 0; i < kPageCount; ++i) {
1454 FPDF_PAGE page = LoadPage(i);
1455 ASSERT_TRUE(page);
1456
1457 FS_RECTF box;
1458 EXPECT_TRUE(FPDF_GetPageBoundingBox(page, &box));
1459 EXPECT_EQ(kBoxes[i].left, box.left);
1460 EXPECT_EQ(kBoxes[i].top, box.top);
1461 EXPECT_EQ(kBoxes[i].right, box.right);
1462 EXPECT_EQ(kBoxes[i].bottom, box.bottom);
1463
1464 {
1465 ScopedFPDFTextPage textpage(FPDFText_LoadPage(page));
1466 ASSERT_TRUE(textpage);
1467
1468 unsigned short buffer[128];
1469 memset(buffer, 0xbd, sizeof(buffer));
1470 int num_chars = FPDFText_GetText(textpage.get(), 0, 128, buffer);
1471 ASSERT_EQ(kHelloGoodbyeTextSize, num_chars);
1472 EXPECT_TRUE(check_unsigned_shorts(kHelloGoodbyeText, buffer,
1473 kHelloGoodbyeTextSize));
1474
1475 int expected_char_count = strlen(kExpectedText[i]);
1476 ASSERT_EQ(expected_char_count,
1477 FPDFText_GetBoundedText(textpage.get(), box.left, box.top,
1478 box.right, box.bottom, nullptr, 0));
1479
1480 memset(buffer, 0xbd, sizeof(buffer));
1481 ASSERT_EQ(expected_char_count + 1,
1482 FPDFText_GetBoundedText(textpage.get(), box.left, box.top,
1483 box.right, box.bottom, buffer, 128));
1484 EXPECT_TRUE(
1485 check_unsigned_shorts(kExpectedText[i], buffer, expected_char_count));
1486 }
1487
1488 UnloadPage(page);
1489 }
1490}
1491
1493 ASSERT_TRUE(OpenDocument("bug_1139.pdf"));
1494 FPDF_PAGE page = LoadPage(0);
1495 ASSERT_TRUE(page);
1496
1497 FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page);
1498 ASSERT_TRUE(text_page);
1499
1500 // -1 for CountChars not including the \0, but +1 for the extra control
1501 // character.
1502 EXPECT_EQ(kHelloGoodbyeTextSize, FPDFText_CountChars(text_page));
1503
1504 // There is an extra control character at the beginning of the string, but it
1505 // should not appear in the output nor prevent extracting the text.
1506 unsigned short buffer[128];
1507 int num_chars = FPDFText_GetText(text_page, 0, 128, buffer);
1508 ASSERT_EQ(kHelloGoodbyeTextSize, num_chars);
1509 EXPECT_TRUE(
1510 check_unsigned_shorts(kHelloGoodbyeText, buffer, kHelloGoodbyeTextSize));
1511 FPDFText_ClosePage(text_page);
1512 UnloadPage(page);
1513}
1514
1516 ASSERT_TRUE(OpenDocument("bug_642.pdf"));
1517 FPDF_PAGE page = LoadPage(0);
1518 ASSERT_TRUE(page);
1519 {
1520 ScopedFPDFTextPage text_page(FPDFText_LoadPage(page));
1521 ASSERT_TRUE(text_page);
1522
1523 constexpr char kText[] = "ABCD";
1524 constexpr size_t kTextSize = std::size(kText);
1525 // -1 for CountChars not including the \0
1526 EXPECT_EQ(static_cast<int>(kTextSize) - 1,
1527 FPDFText_CountChars(text_page.get()));
1528
1529 unsigned short buffer[kTextSize];
1530 int num_chars =
1531 FPDFText_GetText(text_page.get(), 0, std::size(buffer) - 1, buffer);
1532 ASSERT_EQ(static_cast<int>(kTextSize), num_chars);
1533 EXPECT_TRUE(check_unsigned_shorts(kText, buffer, kTextSize));
1534 }
1535
1536 UnloadPage(page);
1537}
1538
1540 ASSERT_TRUE(OpenDocument("rotated_text.pdf"));
1541 FPDF_PAGE page = LoadPage(0);
1542 ASSERT_TRUE(page);
1543
1544 FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page);
1545 ASSERT_TRUE(text_page);
1546
1547 static constexpr int kSubstringsSize[] = {
1548 std::size("Hello,"), std::size(" world!\r\n"), std::size("Goodbye,")};
1549
1550 // -1 for CountChars not including the \0, but +1 for the extra control
1551 // character.
1552 EXPECT_EQ(kHelloGoodbyeTextSize, FPDFText_CountChars(text_page));
1553
1554 EXPECT_FLOAT_EQ(-1.0f, FPDFText_GetCharAngle(nullptr, 0));
1555 EXPECT_FLOAT_EQ(-1.0f, FPDFText_GetCharAngle(text_page, -1));
1556 EXPECT_FLOAT_EQ(-1.0f,
1557 FPDFText_GetCharAngle(text_page, kHelloGoodbyeTextSize + 1));
1558
1559 // Test GetCharAngle for every quadrant
1560 EXPECT_NEAR(FXSYS_PI / 4.0, FPDFText_GetCharAngle(text_page, 0), 0.001);
1561 EXPECT_NEAR(3 * FXSYS_PI / 4.0,
1562 FPDFText_GetCharAngle(text_page, kSubstringsSize[0]), 0.001);
1563 EXPECT_NEAR(
1564 5 * FXSYS_PI / 4.0,
1565 FPDFText_GetCharAngle(text_page, kSubstringsSize[0] + kSubstringsSize[1]),
1566 0.001);
1567 EXPECT_NEAR(
1568 7 * FXSYS_PI / 4.0,
1569 FPDFText_GetCharAngle(text_page, kSubstringsSize[0] + kSubstringsSize[1] +
1570 kSubstringsSize[2]),
1571 0.001);
1572
1573 FPDFText_ClosePage(text_page);
1574 UnloadPage(page);
1575}
1576
1578 ASSERT_TRUE(OpenDocument("font_weight.pdf"));
1579 FPDF_PAGE page = LoadPage(0);
1580 ASSERT_TRUE(page);
1581
1582 FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page);
1583 ASSERT_TRUE(text_page);
1584
1585 EXPECT_EQ(2, FPDFText_CountChars(text_page));
1586
1587 EXPECT_EQ(-1, FPDFText_GetFontWeight(nullptr, 0));
1588 EXPECT_EQ(-1, FPDFText_GetFontWeight(text_page, -1));
1589 EXPECT_EQ(-1, FPDFText_GetFontWeight(text_page, 314));
1590
1591 // The font used for this text only specifies /StemV (80); the weight value
1592 // that is returned should be calculated from that (80*5 == 400).
1593 EXPECT_EQ(400, FPDFText_GetFontWeight(text_page, 0));
1594
1595 // Using a /StemV value of 82, the estimate comes out to 410, even though
1596 // /FontWeight is 400.
1597 // TODO(crbug.com/pdfium/1420): Fix this the return value here.
1598 EXPECT_EQ(410, FPDFText_GetFontWeight(text_page, 1));
1599
1600 FPDFText_ClosePage(text_page);
1601 UnloadPage(page);
1602}
1603
1605 ASSERT_TRUE(OpenDocument("text_render_mode.pdf"));
1606 FPDF_PAGE page = LoadPage(0);
1607 ASSERT_TRUE(page);
1608
1609 FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page);
1610 ASSERT_TRUE(text_page);
1611
1612 ASSERT_EQ(12, FPDFText_CountChars(text_page));
1613
1614 ASSERT_EQ(FPDF_TEXTRENDERMODE_UNKNOWN,
1616 ASSERT_EQ(FPDF_TEXTRENDERMODE_UNKNOWN,
1617 FPDFText_GetTextRenderMode(text_page, -1));
1618 ASSERT_EQ(FPDF_TEXTRENDERMODE_UNKNOWN,
1619 FPDFText_GetTextRenderMode(text_page, 314));
1620
1621 ASSERT_EQ(FPDF_TEXTRENDERMODE_FILL, FPDFText_GetTextRenderMode(text_page, 0));
1622
1623 ASSERT_EQ(FPDF_TEXTRENDERMODE_STROKE,
1625
1626 FPDFText_ClosePage(text_page);
1627 UnloadPage(page);
1628}
1629
1631 ASSERT_TRUE(OpenDocument("text_color.pdf"));
1632 FPDF_PAGE page = LoadPage(0);
1633 ASSERT_TRUE(page);
1634
1635 FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page);
1636 ASSERT_TRUE(text_page);
1637
1638 ASSERT_EQ(1, FPDFText_CountChars(text_page));
1639
1640 ASSERT_FALSE(
1641 FPDFText_GetFillColor(nullptr, 0, nullptr, nullptr, nullptr, nullptr));
1642 ASSERT_FALSE(
1643 FPDFText_GetFillColor(text_page, -1, nullptr, nullptr, nullptr, nullptr));
1644 ASSERT_FALSE(FPDFText_GetFillColor(text_page, 314, nullptr, nullptr, nullptr,
1645 nullptr));
1646 ASSERT_FALSE(
1647 FPDFText_GetFillColor(text_page, 0, nullptr, nullptr, nullptr, nullptr));
1648
1649 unsigned int r;
1650 unsigned int g;
1651 unsigned int b;
1652 unsigned int a;
1653 ASSERT_TRUE(FPDFText_GetFillColor(text_page, 0, &r, &g, &b, &a));
1654 ASSERT_EQ(0xffu, r);
1655 ASSERT_EQ(0u, g);
1656 ASSERT_EQ(0u, b);
1657 ASSERT_EQ(0xffu, a);
1658
1659 FPDFText_ClosePage(text_page);
1660 UnloadPage(page);
1661}
1662
1664 ASSERT_TRUE(OpenDocument("text_color.pdf"));
1665 FPDF_PAGE page = LoadPage(0);
1666 ASSERT_TRUE(page);
1667
1668 FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page);
1669 ASSERT_TRUE(text_page);
1670
1671 ASSERT_EQ(1, FPDFText_CountChars(text_page));
1672
1673 ASSERT_FALSE(
1674 FPDFText_GetStrokeColor(nullptr, 0, nullptr, nullptr, nullptr, nullptr));
1675 ASSERT_FALSE(FPDFText_GetStrokeColor(text_page, -1, nullptr, nullptr, nullptr,
1676 nullptr));
1677 ASSERT_FALSE(FPDFText_GetStrokeColor(text_page, 314, nullptr, nullptr,
1678 nullptr, nullptr));
1679 ASSERT_FALSE(FPDFText_GetStrokeColor(text_page, 0, nullptr, nullptr, nullptr,
1680 nullptr));
1681
1682 unsigned int r;
1683 unsigned int g;
1684 unsigned int b;
1685 unsigned int a;
1686 ASSERT_TRUE(FPDFText_GetStrokeColor(text_page, 0, &r, &g, &b, &a));
1687 ASSERT_EQ(0u, r);
1688 ASSERT_EQ(0xffu, g);
1689 ASSERT_EQ(0u, b);
1690 ASSERT_EQ(0xffu, a);
1691
1692 FPDFText_ClosePage(text_page);
1693 UnloadPage(page);
1694}
1695
1697 constexpr char kExpectedText[] = "A1\r\nA2\r\nA3";
1698 constexpr size_t kExpectedTextSize = std::size(kExpectedText);
1699 constexpr FS_MATRIX kExpectedMatrices[] = {
1700 {12.0f, 0.0f, 0.0f, 10.0f, 66.0f, 90.0f},
1701 {12.0f, 0.0f, 0.0f, 10.0f, 66.0f, 90.0f},
1702 {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f},
1703 {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f},
1704 {12.0f, 0.0f, 0.0f, 10.0f, 38.0f, 60.0f},
1705 {12.0f, 0.0f, 0.0f, 10.0f, 38.0f, 60.0f},
1706 {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f},
1707 {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f},
1708 {1.0f, 0.0f, 0.0f, 0.833333, 60.0f, 130.0f},
1709 {1.0f, 0.0f, 0.0f, 0.833333, 60.0f, 130.0f},
1710 };
1711 constexpr size_t kExpectedCount = std::size(kExpectedMatrices);
1712 static_assert(kExpectedCount + 1 == kExpectedTextSize,
1713 "Bad expected matrix size");
1714
1715 ASSERT_TRUE(OpenDocument("font_matrix.pdf"));
1716 FPDF_PAGE page = LoadPage(0);
1717 ASSERT_TRUE(page);
1718
1719 {
1720 ScopedFPDFTextPage text_page(FPDFText_LoadPage(page));
1721 ASSERT_TRUE(text_page);
1722 ASSERT_EQ(static_cast<int>(kExpectedCount),
1723 FPDFText_CountChars(text_page.get()));
1724
1725 {
1726 // Check the characters.
1727 unsigned short buffer[kExpectedTextSize];
1728 ASSERT_EQ(static_cast<int>(kExpectedTextSize),
1729 FPDFText_GetText(text_page.get(), 0, kExpectedCount, buffer));
1730 EXPECT_TRUE(
1731 check_unsigned_shorts(kExpectedText, buffer, kExpectedTextSize));
1732 }
1733
1734 // Check the character matrix.
1735 FS_MATRIX matrix;
1736 for (size_t i = 0; i < kExpectedCount; ++i) {
1737 ASSERT_TRUE(FPDFText_GetMatrix(text_page.get(), i, &matrix)) << i;
1738 EXPECT_FLOAT_EQ(kExpectedMatrices[i].a, matrix.a) << i;
1739 EXPECT_FLOAT_EQ(kExpectedMatrices[i].b, matrix.b) << i;
1740 EXPECT_FLOAT_EQ(kExpectedMatrices[i].c, matrix.c) << i;
1741 EXPECT_FLOAT_EQ(kExpectedMatrices[i].d, matrix.d) << i;
1742 EXPECT_FLOAT_EQ(kExpectedMatrices[i].e, matrix.e) << i;
1743 EXPECT_FLOAT_EQ(kExpectedMatrices[i].f, matrix.f) << i;
1744 }
1745
1746 // Check bad parameters.
1747 EXPECT_FALSE(FPDFText_GetMatrix(nullptr, 0, &matrix));
1748 EXPECT_FALSE(FPDFText_GetMatrix(text_page.get(), 10, &matrix));
1749 EXPECT_FALSE(FPDFText_GetMatrix(text_page.get(), -1, &matrix));
1750 EXPECT_FALSE(FPDFText_GetMatrix(text_page.get(), 0, nullptr));
1751 }
1752
1753 UnloadPage(page);
1754}
1755
1757 // For a size 12 letter 'A'.
1758 constexpr double kExpectedCharWidth = 8.460;
1759 constexpr double kExpectedCharHeight = 6.600;
1760 constexpr float kExpectedLooseCharWidth = 8.664f;
1761 constexpr float kExpectedLooseCharHeight = 12.0f;
1762
1763 ASSERT_TRUE(OpenDocument("font_matrix.pdf"));
1764 FPDF_PAGE page = LoadPage(0);
1765 ASSERT_TRUE(page);
1766
1767 {
1768 ScopedFPDFTextPage text_page(FPDFText_LoadPage(page));
1769 ASSERT_TRUE(text_page);
1770
1771 // Check the character box size.
1772 double left;
1773 double right;
1774 double bottom;
1775 double top;
1776 ASSERT_TRUE(
1777 FPDFText_GetCharBox(text_page.get(), 0, &left, &right, &bottom, &top));
1778 EXPECT_NEAR(kExpectedCharWidth, right - left, 0.001);
1779 EXPECT_NEAR(kExpectedCharHeight, top - bottom, 0.001);
1780 ASSERT_TRUE(
1781 FPDFText_GetCharBox(text_page.get(), 4, &left, &right, &bottom, &top));
1782 EXPECT_NEAR(kExpectedCharWidth, right - left, 0.001);
1783 EXPECT_NEAR(kExpectedCharHeight, top - bottom, 0.001);
1784 ASSERT_TRUE(
1785 FPDFText_GetCharBox(text_page.get(), 8, &left, &right, &bottom, &top));
1786 EXPECT_NEAR(kExpectedCharWidth, right - left, 0.001);
1787 EXPECT_NEAR(kExpectedCharHeight, top - bottom, 0.001);
1788
1789 // Check the loose character box size.
1790 FS_RECTF rect;
1791 ASSERT_TRUE(FPDFText_GetLooseCharBox(text_page.get(), 0, &rect));
1792 EXPECT_FLOAT_EQ(kExpectedLooseCharWidth, rect.right - rect.left);
1793 EXPECT_FLOAT_EQ(kExpectedLooseCharHeight, rect.top - rect.bottom);
1794 ASSERT_TRUE(FPDFText_GetLooseCharBox(text_page.get(), 4, &rect));
1795 EXPECT_FLOAT_EQ(kExpectedLooseCharWidth, rect.right - rect.left);
1796 EXPECT_FLOAT_EQ(kExpectedLooseCharHeight, rect.top - rect.bottom);
1797 ASSERT_TRUE(FPDFText_GetLooseCharBox(text_page.get(), 8, &rect));
1798 EXPECT_FLOAT_EQ(kExpectedLooseCharWidth, rect.right - rect.left);
1799 EXPECT_NEAR(kExpectedLooseCharHeight, rect.top - rect.bottom, 0.00001);
1800 }
1801
1802 UnloadPage(page);
1803}
1804
1806 ASSERT_TRUE(OpenDocument("bug_1591.pdf"));
1807 FPDF_PAGE page = LoadPage(0);
1808 ASSERT_TRUE(page);
1809
1810 {
1811 ScopedFPDFTextPage text_page(FPDFText_LoadPage(page));
1812 ASSERT_TRUE(text_page);
1813 ASSERT_EQ(5, FPDFText_CountChars(text_page.get()));
1814
1815 EXPECT_EQ(49u, FPDFText_GetUnicode(text_page.get(), 0));
1816 EXPECT_EQ(32u, FPDFText_GetUnicode(text_page.get(), 1));
1817 EXPECT_EQ(50u, FPDFText_GetUnicode(text_page.get(), 2));
1818 EXPECT_EQ(32u, FPDFText_GetUnicode(text_page.get(), 3));
1819 EXPECT_EQ(49u, FPDFText_GetUnicode(text_page.get(), 4));
1820
1821 // Check the character box size.
1822 double left;
1823 double right;
1824 double bottom;
1825 double top;
1826 ASSERT_TRUE(
1827 FPDFText_GetCharBox(text_page.get(), 0, &left, &right, &bottom, &top));
1828 EXPECT_DOUBLE_EQ(63.439998626708984, left);
1829 EXPECT_DOUBLE_EQ(65.360000610351562, right);
1830 EXPECT_DOUBLE_EQ(50.0, bottom);
1831 EXPECT_DOUBLE_EQ(61.520000457763672, top);
1832 ASSERT_TRUE(
1833 FPDFText_GetCharBox(text_page.get(), 1, &left, &right, &bottom, &top));
1834 EXPECT_DOUBLE_EQ(62.007999420166016, left);
1835 EXPECT_DOUBLE_EQ(62.007999420166016, right);
1836 EXPECT_DOUBLE_EQ(50.0, bottom);
1837 EXPECT_DOUBLE_EQ(50.0, top);
1838 ASSERT_TRUE(
1839 FPDFText_GetCharBox(text_page.get(), 2, &left, &right, &bottom, &top));
1840 EXPECT_DOUBLE_EQ(86.0, left);
1841 EXPECT_DOUBLE_EQ(88.400001525878906, right);
1842 EXPECT_DOUBLE_EQ(50.0, bottom);
1843 EXPECT_DOUBLE_EQ(50.240001678466797, top);
1844 ASSERT_TRUE(
1845 FPDFText_GetCharBox(text_page.get(), 3, &left, &right, &bottom, &top));
1846 EXPECT_DOUBLE_EQ(86.010002136230469, left);
1847 EXPECT_DOUBLE_EQ(86.010002136230469, right);
1848 EXPECT_DOUBLE_EQ(50.0, bottom);
1849 EXPECT_DOUBLE_EQ(50.0, top);
1850 ASSERT_TRUE(
1851 FPDFText_GetCharBox(text_page.get(), 4, &left, &right, &bottom, &top));
1852 EXPECT_DOUBLE_EQ(99.44000244140625, left);
1853 EXPECT_DOUBLE_EQ(101.36000061035156, right);
1854 EXPECT_DOUBLE_EQ(50.0, bottom);
1855 EXPECT_DOUBLE_EQ(61.520000457763672, top);
1856 }
1857
1858 UnloadPage(page);
1859}
1860
1862 constexpr char kExpectedText[] =
1863 "{fay,jeff,sanjay,wilsonh,kerr,m3b,tushar,\x02k es,gruber}@google.com";
1864 constexpr int kExpectedTextCount = std::size(kExpectedText) - 1;
1865
1866 ASSERT_TRUE(OpenDocument("bigtable_mini.pdf"));
1867 FPDF_PAGE page = LoadPage(0);
1868 ASSERT_TRUE(page);
1869
1870 {
1871 ScopedFPDFTextPage text_page(FPDFText_LoadPage(page));
1872 ASSERT_TRUE(text_page);
1873 int char_count = FPDFText_CountChars(text_page.get());
1874 ASSERT_GE(char_count, 0);
1875 ASSERT_EQ(kExpectedTextCount, char_count);
1876
1877 for (int i = 0; i < kExpectedTextCount; ++i) {
1878 EXPECT_EQ(static_cast<uint32_t>(kExpectedText[i]),
1879 FPDFText_GetUnicode(text_page.get(), i));
1880 }
1881 }
1882
1883 UnloadPage(page);
1884}
1885
1887 ASSERT_TRUE(OpenDocument("bug_1769.pdf"));
1888 FPDF_PAGE page = LoadPage(0);
1889 ASSERT_TRUE(page);
1890
1891 {
1892 ScopedFPDFTextPage textpage(FPDFText_LoadPage(page));
1893 ASSERT_TRUE(textpage);
1894
1895 unsigned short buffer[128] = {};
1896 // TODO(crbug.com/pdfium/1769): Improve text extraction.
1897 // The first instance of "world" is visible to the human eye and should be
1898 // extracted as is. The second instance is not, so how it should be
1899 // extracted is debatable.
1900 ASSERT_EQ(10, FPDFText_GetText(textpage.get(), 0, 128, buffer));
1901 EXPECT_TRUE(check_unsigned_shorts("wo d wo d", buffer, 10));
1902 }
1903
1904 UnloadPage(page);
1905}
FPDF_EXPORT int FPDF_CALLCONV FPDFPage_GetAnnotCount(FPDF_PAGE page)
#define FPDF_ANNOT_LINK
Definition fpdf_annot.h:22
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_GetAnnotRect(FPDF_LINK link_annot, FS_RECTF *rect)
Definition fpdf_doc.cpp:402
FPDF_EXPORT int FPDF_CALLCONV FPDFLink_CountQuadPoints(FPDF_LINK link_annot)
Definition fpdf_doc.cpp:412
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_GetQuadPoints(FPDF_LINK link_annot, int quad_index, FS_QUADPOINTSF *quad_points)
Definition fpdf_doc.cpp:419
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_Enumerate(FPDF_PAGE page, int *start_pos, FPDF_LINK *link_annot)
Definition fpdf_doc.cpp:363
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDFTextObj_GetText(FPDF_PAGEOBJECT text_object, FPDF_TEXTPAGE text_page, FPDF_WCHAR *buffer, unsigned long length)
FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV FPDFPage_GetObject(FPDF_PAGE page, int index)
FPDF_EXPORT int FPDF_CALLCONV FPDFPage_CountObjects(FPDF_PAGE page)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_GetStrokeColor(FPDF_TEXTPAGE text_page, int index, unsigned int *R, unsigned int *G, unsigned int *B, unsigned int *A)
FPDF_EXPORT int FPDF_CALLCONV FPDFLink_GetURL(FPDF_PAGELINK link_page, int link_index, unsigned short *buffer, int buflen)
FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetText(FPDF_TEXTPAGE page, int start_index, int char_count, unsigned short *result)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_GetTextRange(FPDF_PAGELINK link_page, int link_index, int *start_char_index, int *char_count)
FPDF_EXPORT int FPDF_CALLCONV FPDFText_IsGenerated(FPDF_TEXTPAGE text_page, int index)
Definition fpdf_text.cpp:74
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_GetCharOrigin(FPDF_TEXTPAGE text_page, int index, double *x, double *y)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_GetFillColor(FPDF_TEXTPAGE text_page, int index, unsigned int *R, unsigned int *G, unsigned int *B, unsigned int *A)
FPDF_EXPORT int FPDF_CALLCONV FPDFText_IsHyphen(FPDF_TEXTPAGE text_page, int index)
Definition fpdf_text.cpp:84
FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetCharIndexAtPos(FPDF_TEXTPAGE text_page, double x, double y, double xTolerance, double yTolerance)
FPDF_EXPORT void FPDF_CALLCONV FPDFLink_CloseWebLinks(FPDF_PAGELINK link_page)
FPDF_EXPORT float FPDF_CALLCONV FPDFText_GetCharAngle(FPDF_TEXTPAGE text_page, int index)
FPDF_EXPORT int FPDF_CALLCONV FPDFText_HasUnicodeMapError(FPDF_TEXTPAGE text_page, int index)
Definition fpdf_text.cpp:96
FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetBoundedText(FPDF_TEXTPAGE text_page, double left, double top, double right, double bottom, unsigned short *buffer, int buflen)
FPDF_EXPORT int FPDF_CALLCONV FPDFLink_CountRects(FPDF_PAGELINK link_page, int link_index)
FPDF_EXPORT int FPDF_CALLCONV FPDFText_GetFontWeight(FPDF_TEXTPAGE text_page, int index)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_GetLooseCharBox(FPDF_TEXTPAGE text_page, int index, FS_RECTF *rect)
FPDF_EXPORT double FPDF_CALLCONV FPDFText_GetFontSize(FPDF_TEXTPAGE text_page, int index)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_GetCharBox(FPDF_TEXTPAGE text_page, int index, double *left, double *right, double *bottom, double *top)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_GetRect(FPDF_PAGELINK link_page, int link_index, int rect_index, double *left, double *top, double *right, double *bottom)
FPDF_EXPORT FPDF_TEXT_RENDERMODE FPDF_CALLCONV FPDFText_GetTextRenderMode(FPDF_TEXTPAGE text_page, int index)
FPDF_EXPORT int FPDF_CALLCONV FPDFText_CountRects(FPDF_TEXTPAGE text_page, int start, int count)
FPDF_EXPORT int FPDF_CALLCONV FPDFText_CountChars(FPDF_TEXTPAGE text_page)
Definition fpdf_text.cpp:59
FPDF_EXPORT FPDF_TEXTPAGE FPDF_CALLCONV FPDFText_LoadPage(FPDF_PAGE page)
Definition fpdf_text.cpp:40
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_GetMatrix(FPDF_TEXTPAGE text_page, int index, FS_MATRIX *matrix)
FPDF_EXPORT void FPDF_CALLCONV FPDFText_ClosePage(FPDF_TEXTPAGE text_page)
Definition fpdf_text.cpp:53
FPDF_EXPORT FPDF_PAGELINK FPDF_CALLCONV FPDFLink_LoadWebLinks(FPDF_TEXTPAGE text_page)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDFText_GetFontInfo(FPDF_TEXTPAGE text_page, int index, void *buffer, unsigned long buflen, int *flags)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFText_GetRect(FPDF_TEXTPAGE text_page, int rect_index, double *left, double *top, double *right, double *bottom)
FPDF_EXPORT unsigned int FPDF_CALLCONV FPDFText_GetUnicode(FPDF_TEXTPAGE text_page, int index)
Definition fpdf_text.cpp:65
FPDF_EXPORT int FPDF_CALLCONV FPDFLink_CountWebLinks(FPDF_PAGELINK link_page)
#define FPDF_MATCHWHOLEWORD
Definition fpdf_text.h:487
#define FPDF_CONSECUTIVE
Definition fpdf_text.h:489
#define FPDF_MATCHCASE
Definition fpdf_text.h:485
#define MAYBE_TextSearchLatinExtended
TEST_F(FPDFTextEmbedderTest, Text)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetPageBoundingBox(FPDF_PAGE page, FS_RECTF *rect)
#define FXFONT_NONSYMBOLIC
Definition fx_font.h:32
#define FXSYS_PI
Definition fx_system.h:43