Redo FPDFText_GetLooseCharBox() top/bottom calculation
Undo the fix in https://pdfium-review.googlesource.com/128730, and
instead calculate the char box's top/bottom values using the font's
bounding box values. This makes the loose char box looser for
diacritics.
Bug: 42270568, 395640955
Change-Id: Ie2f7be699331f609dfab60104daf5c369cc94dff
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/128770
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/core/fpdftext/cpdf_textpage.cpp b/core/fpdftext/cpdf_textpage.cpp
index 4e63f15..47cff23 100644
--- a/core/fpdftext/cpdf_textpage.cpp
+++ b/core/fpdftext/cpdf_textpage.cpp
@@ -290,23 +290,22 @@
return char_box;
}
- int ascent = charinfo.text_object()->GetFont()->GetTypeAscent();
- int descent = charinfo.text_object()->GetFont()->GetTypeDescent();
- if (ascent != descent) {
+ FX_RECT font_bbox = charinfo.text_object()->GetFont()->GetFontBBox();
+ if (font_bbox.Height() != 0) {
+ // Compute `left` and `right` based on the individual character's `width`.
float width = charinfo.text_object()->GetCharWidth(charinfo.char_code());
- float font_scale = font_size / (ascent - descent);
-
CFX_Matrix inverse_matrix = charinfo.matrix().GetInverse();
CFX_PointF original_origin = inverse_matrix.Transform(charinfo.origin());
-
float left = original_origin.x;
float right = original_origin.x + (is_vert_writing ? -width : width);
- float bottom = original_origin.y + descent * font_scale;
- float top = original_origin.y + ascent * font_scale;
+
+ // Compute `bottom` and `top` based on the font bounding box. This allows
+ // the bounds to include diacritics, whereas using the ascent / descent
+ // values will not.
+ float bottom = font_bbox.bottom * font_size / 1000;
+ float top = font_bbox.top * font_size / 1000;
CFX_FloatRect char_box(left, bottom, right, top);
- char_box = charinfo.matrix().TransformRect(char_box);
- char_box.Union(charinfo.char_box());
- return char_box;
+ return charinfo.matrix().TransformRect(char_box);
}
}
diff --git a/fpdfsdk/fpdf_text_embeddertest.cpp b/fpdfsdk/fpdf_text_embeddertest.cpp
index b54bab7..e20360f 100644
--- a/fpdfsdk/fpdf_text_embeddertest.cpp
+++ b/fpdfsdk/fpdf_text_embeddertest.cpp
@@ -192,8 +192,8 @@
EXPECT_TRUE(FPDFText_GetLooseCharBox(textpage.get(), 4, &rect));
EXPECT_FLOAT_EQ(40.664001f, rect.left);
EXPECT_FLOAT_EQ(46.664001f, rect.right);
- EXPECT_FLOAT_EQ(47.667271f, rect.bottom);
- EXPECT_FLOAT_EQ(59.667271f, rect.top);
+ EXPECT_FLOAT_EQ(46.375999f, rect.bottom);
+ EXPECT_FLOAT_EQ(61.771999f, rect.top);
double x = 0.0;
double y = 0.0;
@@ -1769,7 +1769,7 @@
static constexpr double kExpectedCharWidth = 8.460;
static constexpr double kExpectedCharHeight = 6.600;
static constexpr float kExpectedLooseCharWidth = 8.664f;
- static constexpr float kExpectedLooseCharHeight = 10.0f;
+ static constexpr float kExpectedLooseCharHeight = 12.82999f;
ASSERT_TRUE(OpenDocument("font_matrix.pdf"));
ScopedEmbedderTestPage page = LoadScopedPage(0);
@@ -1811,7 +1811,7 @@
EXPECT_FLOAT_EQ(kExpectedLooseCharHeight, rect.top - rect.bottom);
ASSERT_TRUE(FPDFText_GetLooseCharBox(text_page.get(), 4, &rect));
EXPECT_FLOAT_EQ(kExpectedLooseCharWidth, rect.right - rect.left);
- EXPECT_FLOAT_EQ(kExpectedLooseCharHeight, rect.top - rect.bottom);
+ EXPECT_NEAR(kExpectedLooseCharHeight, rect.top - rect.bottom, 0.00001);
ASSERT_TRUE(FPDFText_GetLooseCharBox(text_page.get(), 8, &rect));
EXPECT_FLOAT_EQ(kExpectedLooseCharWidth, rect.right - rect.left);
EXPECT_NEAR(kExpectedLooseCharHeight, rect.top - rect.bottom, 0.00001);
@@ -1866,7 +1866,7 @@
EXPECT_NEAR(10.055, top - bottom, 0.001);
// Check the loose character box size.
- static constexpr float kExpectedLooseCharDimension = 14.612f;
+ static constexpr float kExpectedLooseCharDimension = 17.013f;
FS_RECTF rect;
ASSERT_TRUE(FPDFText_GetLooseCharBox(
text_page.get(), GetRotatedTextFirstCharIndexForQuadrant(0), &rect));
@@ -1936,7 +1936,7 @@
// Check the loose character box size.
static constexpr float kExpectedLooseCharWidth = 8.664f;
- static constexpr float kExpectedLooseCharHeight = 12.0f;
+ static constexpr float kExpectedLooseCharHeight = 15.396f;
FS_RECTF rect;
ASSERT_TRUE(FPDFText_GetLooseCharBox(
text_page.get(), GetRotatedText90FirstCharIndexForQuadrant(0), &rect));
@@ -1979,8 +1979,8 @@
FS_RECTF rect;
ASSERT_TRUE(FPDFText_GetLooseCharBox(text_page.get(), 0, &rect));
EXPECT_NEAR(7.824f, rect.right - rect.left, 0.001f);
- EXPECT_NEAR(12.988f, rect.top - rect.bottom, 0.001f);
- EXPECT_NEAR(750.238f, rect.top, 0.001f);
+ EXPECT_NEAR(15.912f, rect.top - rect.bottom, 0.001f);
+ EXPECT_NEAR(752.422f, rect.top, 0.001f);
EXPECT_EQ(u'Ă', FPDFText_GetUnicode(text_page.get(), 2));
@@ -1992,8 +1992,8 @@
ASSERT_TRUE(FPDFText_GetLooseCharBox(text_page.get(), 2, &rect));
EXPECT_NEAR(7.824f, rect.right - rect.left, 0.001f);
- EXPECT_NEAR(13.24f, rect.top - rect.bottom, 0.001f);
- EXPECT_NEAR(750.49f, rect.top, 0.001f);
+ EXPECT_NEAR(15.912f, rect.top - rect.bottom, 0.001f);
+ EXPECT_NEAR(752.422f, rect.top, 0.001f);
}
TEST_F(FPDFTextEmbedderTest, SmallType3Glyph) {