Demonstrate FPDFText_GetLooseCharBox() bug with generated chars

Check in a minimized PDF that demonstrates the bug. Compare the current
FPDFText_GetLooseCharBox() behavior against FPDFText_GetCharBox().

Bug: 399689604
Change-Id: Iff604b85b546f8506408fbf9ff933670d461e54b
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/129190
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/fpdf_text_embeddertest.cpp b/fpdfsdk/fpdf_text_embeddertest.cpp
index e20360f..d2d7a57 100644
--- a/fpdfsdk/fpdf_text_embeddertest.cpp
+++ b/fpdfsdk/fpdf_text_embeddertest.cpp
@@ -1996,6 +1996,34 @@
   EXPECT_NEAR(752.422f, rect.top, 0.001f);
 }
 
+TEST_F(FPDFTextEmbedderTest, Bug399689604) {
+  ASSERT_TRUE(OpenDocument("bug_399689604.pdf"));
+  ScopedEmbedderTestPage page = LoadScopedPage(0);
+  ASSERT_TRUE(page);
+
+  ScopedFPDFTextPage text_page(FPDFText_LoadPage(page.get()));
+  ASSERT_TRUE(text_page);
+
+  EXPECT_EQ(1, FPDFText_IsGenerated(text_page.get(), 5));
+  double left;
+  double right;
+  double bottom;
+  double top;
+  ASSERT_TRUE(
+      FPDFText_GetCharBox(text_page.get(), 5, &left, &right, &bottom, &top));
+  EXPECT_DOUBLE_EQ(0.0, right - left);
+  EXPECT_DOUBLE_EQ(0.0, top - bottom);
+  EXPECT_NEAR(100.0, top, 0.001);
+
+  // TODO(crbug.com/399689604): Should have an empty rect like
+  // FPDFText_GetCharBox().
+  FS_RECTF rect;
+  ASSERT_TRUE(FPDFText_GetLooseCharBox(text_page.get(), 5, &rect));
+  EXPECT_NEAR(2.99f, rect.right - rect.left, 0.001f);
+  EXPECT_NEAR(15.345f, rect.top - rect.bottom, 0.001f);
+  EXPECT_NEAR(11.733f, rect.top, 0.001f);
+}
+
 TEST_F(FPDFTextEmbedderTest, SmallType3Glyph) {
   ASSERT_TRUE(OpenDocument("bug_1591.pdf"));
   ScopedEmbedderTestPage page = LoadScopedPage(0);
diff --git a/testing/resources/bug_399689604.in b/testing/resources/bug_399689604.in
new file mode 100644
index 0000000..8ed89ee
--- /dev/null
+++ b/testing/resources/bug_399689604.in
@@ -0,0 +1,46 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+endobj
+{{object 2 0}} <<
+  /Type /Pages
+  /Count 1
+  /Kids [3 0 R]
+>>
+endobj
+{{object 3 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Contents 4 0 R
+  /MediaBox [0 0 200 200]
+  /Resources <<
+    /ProcSet [/PDF /Text]
+    /Font <<
+      /F1 5 0 R
+    >>
+  >>
+>>
+endobj
+{{object 4 0}} <<
+  {{streamlen}}
+>>
+stream
+BT
+/F1 11.96 Tf
+1 0 0 1 50 100 Tm
+[(Hello)-300(world)-200(!)] TJ
+ET
+endstream
+endobj
+{{object 5 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Times-Roman
+>>
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/bug_399689604.pdf b/testing/resources/bug_399689604.pdf
new file mode 100644
index 0000000..6e39095
--- /dev/null
+++ b/testing/resources/bug_399689604.pdf
@@ -0,0 +1,58 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+endobj
+2 0 obj <<
+  /Type /Pages
+  /Count 1
+  /Kids [3 0 R]
+>>
+endobj
+3 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /Contents 4 0 R
+  /MediaBox [0 0 200 200]
+  /Resources <<
+    /ProcSet [/PDF /Text]
+    /Font <<
+      /F1 5 0 R
+    >>
+  >>
+>>
+endobj
+4 0 obj <<
+  /Length 67
+>>
+stream
+BT
+/F1 11.96 Tf
+1 0 0 1 50 100 Tm
+[(Hello)-300(world)-200(!)] TJ
+ET
+endstream
+endobj
+5 0 obj <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Times-Roman
+>>
+endobj
+xref
+0 6
+0000000000 65535 f 
+0000000015 00000 n 
+0000000068 00000 n 
+0000000131 00000 n 
+0000000309 00000 n 
+0000000428 00000 n 
+trailer <<
+  /Root 1 0 R
+  /Size 6
+>>
+startxref
+506
+%%EOF