Encapsulate more bounding box code in CFX_Face
Add GetCharBBox() and GetGlyphBBox() to CFX_Face. These methods move
existing FreeType calls into CFX_Face.
Bug: pdfium:2037
Change-Id: I05f9b1d90f142f914ff7f35ad748c3db87abbea0
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/114796
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
Reviewed-by: Dominik Röttsches <drott@chromium.org>
diff --git a/core/fpdfapi/font/cpdf_cidfont.cpp b/core/fpdfapi/font/cpdf_cidfont.cpp
index f540505..b0bcfd5 100644
--- a/core/fpdfapi/font/cpdf_cidfont.cpp
+++ b/core/fpdfapi/font/cpdf_cidfont.cpp
@@ -134,16 +134,6 @@
{8818, 0, 129, 127, 0, 19, 114}, {8819, 0, 129, 127, 0, 218, 108},
};
-// Boundary value to avoid integer overflow when adding 1/64th of the value.
-constexpr int kMaxRectTop = 2114445437;
-
-int FTPosToCBoxInt(FT_Pos pos) {
- // Boundary values to avoid integer overflow when multiplied by 1000.
- constexpr FT_Pos kMinCBox = -2147483;
- constexpr FT_Pos kMaxCBox = 2147483;
- return static_cast<int>(std::clamp(pos, kMinCBox, kMaxCBox));
-}
-
#if !BUILDFLAG(IS_WIN)
bool IsValidEmbeddedCharcodeFromUnicodeCharset(CIDSet charset) {
@@ -528,45 +518,7 @@
int glyph_index = GlyphFromCharCode(charcode, &bVert);
RetainPtr<CFX_Face> face = m_Font.GetFace();
if (face) {
- FXFT_FaceRec* face_rec = face->GetRec();
- if (face->IsTricky()) {
- int err = FT_Load_Glyph(face_rec, glyph_index,
- FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
- if (!err) {
- FT_Glyph glyph;
- err = FT_Get_Glyph(face_rec->glyph, &glyph);
- if (!err) {
- FT_BBox cbox;
- FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &cbox);
- const int xMin = FTPosToCBoxInt(cbox.xMin);
- const int xMax = FTPosToCBoxInt(cbox.xMax);
- const int yMin = FTPosToCBoxInt(cbox.yMin);
- const int yMax = FTPosToCBoxInt(cbox.yMax);
- const int pixel_size_x = face_rec->size->metrics.x_ppem;
- const int pixel_size_y = face_rec->size->metrics.y_ppem;
- if (pixel_size_x == 0 || pixel_size_y == 0) {
- rect = FX_RECT(xMin, yMax, xMax, yMin);
- } else {
- rect =
- FX_RECT(xMin * 1000 / pixel_size_x, yMax * 1000 / pixel_size_y,
- xMax * 1000 / pixel_size_x, yMin * 1000 / pixel_size_y);
- }
- rect.top = std::min(rect.top, static_cast<int>(face->GetAscender()));
- rect.bottom =
- std::max(rect.bottom, static_cast<int>(face->GetDescender()));
- FT_Done_Glyph(glyph);
- }
- }
- } else {
- int err = FT_Load_Glyph(face_rec, glyph_index, FT_LOAD_NO_SCALE);
- if (err == 0) {
- rect = GetCharBBoxForFace(face);
- if (rect.top <= kMaxRectTop)
- rect.top += rect.top / 64;
- else
- rect.top = std::numeric_limits<int>::max();
- }
- }
+ rect = face->GetCharBBox(charcode, glyph_index);
}
if (!m_pFontFile && m_Charset == CIDSET_JAPAN1) {
uint16_t cid = CIDFromCharCode(charcode);
diff --git a/core/fpdfapi/font/cpdf_font.cpp b/core/fpdfapi/font/cpdf_font.cpp
index 7432814..66e385d 100644
--- a/core/fpdfapi/font/cpdf_font.cpp
+++ b/core/fpdfapi/font/cpdf_font.cpp
@@ -31,10 +31,8 @@
#include "core/fxcrt/stl_util.h"
#include "core/fxge/cfx_fontmapper.h"
#include "core/fxge/cfx_substfont.h"
-#include "core/fxge/freetype/fx_freetype.h"
#include "core/fxge/fx_font.h"
#include "third_party/base/check.h"
-#include "third_party/base/numerics/clamped_math.h"
namespace {
@@ -407,18 +405,6 @@
}
// static
-FX_RECT CPDF_Font::GetCharBBoxForFace(const RetainPtr<CFX_Face>& face) {
- 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);
- 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
bool CPDF_Font::UseTTCharmap(const RetainPtr<CFX_Face>& face,
int platform_id,
int encoding_id) {
diff --git a/core/fpdfapi/font/cpdf_font.h b/core/fpdfapi/font/cpdf_font.h
index 84e45a9..af0a82b 100644
--- a/core/fpdfapi/font/cpdf_font.h
+++ b/core/fpdfapi/font/cpdf_font.h
@@ -22,7 +22,6 @@
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/unowned_ptr.h"
#include "core/fxge/cfx_font.h"
-#include "core/fxge/freetype/fx_freetype.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
class CFX_DIBitmap;
@@ -139,8 +138,6 @@
CPDF_Font(CPDF_Document* pDocument, RetainPtr<CPDF_Dictionary> pFontDict);
~CPDF_Font() override;
- static FX_RECT GetCharBBoxForFace(const RetainPtr<CFX_Face>& face);
-
// Commonly used wrappers for UseTTCharmap().
static bool UseTTCharmapMSUnicode(const RetainPtr<CFX_Face>& face) {
return UseTTCharmap(face, 3, 1);
diff --git a/core/fpdfapi/font/cpdf_simplefont.cpp b/core/fpdfapi/font/cpdf_simplefont.cpp
index b411257..d740302 100644
--- a/core/fpdfapi/font/cpdf_simplefont.cpp
+++ b/core/fpdfapi/font/cpdf_simplefont.cpp
@@ -88,7 +88,7 @@
if (err)
return;
- m_CharBBox[charcode] = GetCharBBoxForFace(face);
+ m_CharBBox[charcode] = face->GetGlyphBBox();
if (m_bUseFontWidth) {
int TT_Width = NormalizeFontMetric(FXFT_Get_Glyph_HoriAdvance(face_rec),
diff --git a/core/fxge/cfx_face.cpp b/core/fxge/cfx_face.cpp
index 265fa1b..2a565fa 100644
--- a/core/fxge/cfx_face.cpp
+++ b/core/fxge/cfx_face.cpp
@@ -18,11 +18,13 @@
#include "core/fxge/cfx_substfont.h"
#include "core/fxge/dib/cfx_dibitmap.h"
#include "core/fxge/dib/fx_dib.h"
+#include "core/fxge/fx_font.h"
#include "core/fxge/fx_fontencoding.h"
#include "core/fxge/scoped_font_transform.h"
#include "third_party/base/check.h"
#include "third_party/base/check_op.h"
#include "third_party/base/notreached.h"
+#include "third_party/base/numerics/clamped_math.h"
#include "third_party/base/numerics/safe_conversions.h"
#include "third_party/base/numerics/safe_math.h"
@@ -42,6 +44,9 @@
constexpr int kMaxGlyphDimension = 2048;
+// Boundary value to avoid integer overflow when adding 1/64th of the value.
+constexpr int kMaxRectTop = 2114445437;
+
constexpr uint8_t kWeightPow[] = {
0, 6, 12, 14, 16, 18, 22, 24, 28, 30, 32, 34, 36, 38, 40,
42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70,
@@ -104,6 +109,13 @@
return kAngleSkew[-angle];
}
+int FTPosToCBoxInt(FT_Pos pos) {
+ // Boundary values to avoid integer overflow when multiplied by 1000.
+ constexpr FT_Pos kMinCBox = -2147483;
+ constexpr FT_Pos kMaxCBox = 2147483;
+ return static_cast<int>(std::clamp(pos, kMinCBox, kMaxCBox));
+}
+
void Outline_CheckEmptyContour(OUTLINE_PARAMS* param) {
size_t size;
{
@@ -652,6 +664,61 @@
return FT_Get_Name_Index(GetRec(), name);
}
+FX_RECT CFX_Face::GetCharBBox(uint32_t code, int glyph_index) {
+ FX_RECT rect;
+ FXFT_FaceRec* rec = GetRec();
+ if (IsTricky()) {
+ int err =
+ FT_Load_Glyph(rec, glyph_index, FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
+ if (!err) {
+ FT_Glyph glyph;
+ err = FT_Get_Glyph(rec->glyph, &glyph);
+ if (!err) {
+ FT_BBox cbox;
+ FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &cbox);
+ const int xMin = FTPosToCBoxInt(cbox.xMin);
+ const int xMax = FTPosToCBoxInt(cbox.xMax);
+ const int yMin = FTPosToCBoxInt(cbox.yMin);
+ const int yMax = FTPosToCBoxInt(cbox.yMax);
+ const int pixel_size_x = rec->size->metrics.x_ppem;
+ const int pixel_size_y = rec->size->metrics.y_ppem;
+ if (pixel_size_x == 0 || pixel_size_y == 0) {
+ rect = FX_RECT(xMin, yMax, xMax, yMin);
+ } else {
+ rect =
+ FX_RECT(xMin * 1000 / pixel_size_x, yMax * 1000 / pixel_size_y,
+ xMax * 1000 / pixel_size_x, yMin * 1000 / pixel_size_y);
+ }
+ rect.top = std::min(rect.top, static_cast<int>(GetAscender()));
+ rect.bottom = std::max(rect.bottom, static_cast<int>(GetDescender()));
+ FT_Done_Glyph(glyph);
+ }
+ }
+ } else {
+ int err = FT_Load_Glyph(rec, glyph_index, FT_LOAD_NO_SCALE);
+ if (err == 0) {
+ rect = GetGlyphBBox();
+ if (rect.top <= kMaxRectTop) {
+ rect.top += rect.top / 64;
+ } else {
+ rect.top = std::numeric_limits<int>::max();
+ }
+ }
+ }
+ return rect;
+}
+
+FX_RECT CFX_Face::GetGlyphBBox() const {
+ const auto* glyph = GetRec()->glyph;
+ pdfium::base::ClampedNumeric<FT_Pos> left = glyph->metrics.horiBearingX;
+ pdfium::base::ClampedNumeric<FT_Pos> top = glyph->metrics.horiBearingY;
+ const uint16_t upem = GetUnitsPerEm();
+ return FX_RECT(NormalizeFontMetric(left, upem),
+ NormalizeFontMetric(top, upem),
+ NormalizeFontMetric(left + glyph->metrics.width, upem),
+ NormalizeFontMetric(top - glyph->metrics.height, upem));
+}
+
std::vector<CFX_Face::CharCodeAndIndex> CFX_Face::GetCharCodesAndIndices(
char32_t max_char) {
CharCodeAndIndex char_code_and_index;
diff --git a/core/fxge/cfx_face.h b/core/fxge/cfx_face.h
index 944d731..bc3d71f 100644
--- a/core/fxge/cfx_face.h
+++ b/core/fxge/cfx_face.h
@@ -84,6 +84,8 @@
absl::optional<std::array<uint8_t, 2>> GetOs2Panose();
int GetGlyphCount() const;
+ // TODO(crbug.com/pdfium/2037): Can this method be private?
+ FX_RECT GetGlyphBBox() const;
std::unique_ptr<CFX_GlyphBitmap> RenderGlyph(const CFX_Font* pFont,
uint32_t glyph_index,
bool bFontStyle,
@@ -102,6 +104,8 @@
int GetCharIndex(uint32_t code);
int GetNameIndex(const char* name);
+ FX_RECT GetCharBBox(uint32_t code, int glyph_index);
+
std::vector<CharCodeAndIndex> GetCharCodesAndIndices(char32_t max_char);
CharMap GetCurrentCharMap() const;