Rewrite and rename CPDF_Font::TT2PDF()
Change the value parameter for TT2PDF() from FT_Pos to int64_t, so it
does not depend on FreeType. Change the other parameter from CFX_Face to
the font's units per EM value. Also give the function a more descriptive
name. Then update all the callers accordingly.
Change-Id: Id3e8b828831025c0f5740947dc128222e07d0ca4
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/115770
Reviewed-by: Dominik Röttsches <drott@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/font/cpdf_font.cpp b/core/fpdfapi/font/cpdf_font.cpp
index e87aa36..6726cf8 100644
--- a/core/fpdfapi/font/cpdf_font.cpp
+++ b/core/fpdfapi/font/cpdf_font.cpp
@@ -222,12 +222,13 @@
if (face) {
// Note that `m_FontBBox` is deliberately flipped.
const FX_RECT raw_bbox = face->GetBBox();
- m_FontBBox.left = TT2PDF(raw_bbox.left, face);
- m_FontBBox.bottom = TT2PDF(raw_bbox.top, face);
- m_FontBBox.right = TT2PDF(raw_bbox.right, face);
- m_FontBBox.top = TT2PDF(raw_bbox.bottom, face);
- m_Ascent = TT2PDF(face->GetAscender(), face);
- m_Descent = TT2PDF(face->GetDescender(), face);
+ const uint16_t upem = face->GetUnitsPerEm();
+ m_FontBBox.left = NormalizeFontMetric(raw_bbox.left, upem);
+ m_FontBBox.bottom = NormalizeFontMetric(raw_bbox.top, upem);
+ m_FontBBox.right = NormalizeFontMetric(raw_bbox.right, upem);
+ m_FontBBox.top = NormalizeFontMetric(raw_bbox.bottom, upem);
+ m_Ascent = NormalizeFontMetric(face->GetAscender(), upem);
+ m_Descent = NormalizeFontMetric(face->GetDescender(), upem);
} else {
bool bFirst = true;
for (int i = 0; i < 256; i++) {
@@ -407,13 +408,13 @@
}
// static
-int CPDF_Font::TT2PDF(FT_Pos m, const RetainPtr<CFX_Face>& face) {
- int upm = face->GetUnitsPerEm();
- if (upm == 0)
- return pdfium::base::saturated_cast<int>(m);
+int CPDF_Font::NormalizeFontMetric(int64_t value, uint16_t upem) {
+ if (upem == 0) {
+ return pdfium::base::saturated_cast<int>(value);
+ }
- const double dm = (m * 1000.0 + upm / 2) / upm;
- return pdfium::base::saturated_cast<int>(dm);
+ const double scaled_value = (value * 1000.0 + upem / 2) / upem;
+ return pdfium::base::saturated_cast<int>(scaled_value);
}
// static
@@ -421,9 +422,11 @@
FXFT_FaceRec* rec = face->GetRec();
pdfium::base::ClampedNumeric<FT_Pos> left = FXFT_Get_Glyph_HoriBearingX(rec);
pdfium::base::ClampedNumeric<FT_Pos> top = FXFT_Get_Glyph_HoriBearingY(rec);
- return FX_RECT(TT2PDF(left, face), TT2PDF(top, face),
- TT2PDF(left + FXFT_Get_Glyph_Width(rec), face),
- TT2PDF(top - FXFT_Get_Glyph_Height(rec), face));
+ const uint16_t upem = face->GetUnitsPerEm();
+ return FX_RECT(NormalizeFontMetric(left, upem),
+ NormalizeFontMetric(top, upem),
+ NormalizeFontMetric(left + FXFT_Get_Glyph_Width(rec), upem),
+ NormalizeFontMetric(top - FXFT_Get_Glyph_Height(rec), upem));
}
// static
diff --git a/core/fpdfapi/font/cpdf_font.h b/core/fpdfapi/font/cpdf_font.h
index e2f9cf3..7c733eb 100644
--- a/core/fpdfapi/font/cpdf_font.h
+++ b/core/fpdfapi/font/cpdf_font.h
@@ -139,7 +139,11 @@
CPDF_Font(CPDF_Document* pDocument, RetainPtr<CPDF_Dictionary> pFontDict);
~CPDF_Font() override;
- static int TT2PDF(FT_Pos m, const RetainPtr<CFX_Face>& face);
+ // Take a font metric `value` and scale it down by the font's `upem`. If the
+ // font is not scalable, i.e. `upem` is 0, then return `value` as is.
+ // If the computed result is excessively large and does not fit in an int,
+ // NormalizeFontMetric() handles that with `saturated_cast()`.
+ static int NormalizeFontMetric(int64_t value, uint16_t upem);
static FX_RECT GetCharBBoxForFace(const RetainPtr<CFX_Face>& face);
// Commonly used wrappers for UseTTCharmap().
diff --git a/core/fpdfapi/font/cpdf_simplefont.cpp b/core/fpdfapi/font/cpdf_simplefont.cpp
index eecdf5a..b411257 100644
--- a/core/fpdfapi/font/cpdf_simplefont.cpp
+++ b/core/fpdfapi/font/cpdf_simplefont.cpp
@@ -91,7 +91,8 @@
m_CharBBox[charcode] = GetCharBBoxForFace(face);
if (m_bUseFontWidth) {
- int TT_Width = TT2PDF(FXFT_Get_Glyph_HoriAdvance(face_rec), face);
+ int TT_Width = NormalizeFontMetric(FXFT_Get_Glyph_HoriAdvance(face_rec),
+ face->GetUnitsPerEm());
if (m_CharWidth[charcode] == 0xffff) {
m_CharWidth[charcode] = TT_Width;
} else if (TT_Width && !IsEmbedded()) {