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