Move some FreeType-specific code from CFX_Font to CFX_Face
- Move CFX_Font::GetGlyphWidthImpl() code into CFX_Face::GetGlyphWidth()
- Do the same for CFX_Font::LoadGlyphPathImpl()
- Move CFX_Font::GetWeightLevel(), GetSkewFromAngle(), and
AdjustMMParams() into CFX_Face, now that they have no callers in
CFX_Font
- Rename AdjustMMParams() to AdjustVariationParams()
- Move several array constants and helper functions from cfx_font.cpp to
cfx_face.cpp
- Duplicate a couple of constants and a macro
- Remove FXFT_Get_Glyph_Outline()
Bug: pdfium:2037
Change-Id: Iae437b293b3f479ccb9f4a66c5f3f78bf18b61f6
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/114775
Reviewed-by: Dominik Röttsches <drott@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxge/cfx_face.cpp b/core/fxge/cfx_face.cpp
index 24baa8f..d6f9fcb 100644
--- a/core/fxge/cfx_face.cpp
+++ b/core/fxge/cfx_face.cpp
@@ -5,6 +5,7 @@
#include "core/fxge/cfx_face.h"
#include <algorithm>
+#include <limits>
#include <memory>
#include <utility>
@@ -12,6 +13,7 @@
#include "core/fxge/cfx_fontmgr.h"
#include "core/fxge/cfx_gemodule.h"
#include "core/fxge/cfx_glyphbitmap.h"
+#include "core/fxge/cfx_path.h"
#include "core/fxge/cfx_substfont.h"
#include "core/fxge/dib/cfx_dibitmap.h"
#include "core/fxge/dib/fx_dib.h"
@@ -21,10 +23,182 @@
#include "third_party/base/numerics/safe_conversions.h"
#include "third_party/base/numerics/safe_math.h"
+#define EM_ADJUST(em, a) (em == 0 ? (a) : (a) * 1000 / em)
+
namespace {
+struct OUTLINE_PARAMS {
+ UnownedPtr<CFX_Path> m_pPath;
+ FT_Pos m_CurX;
+ FT_Pos m_CurY;
+ float m_CoordUnit;
+};
+
+constexpr int kThousandthMinInt = std::numeric_limits<int>::min() / 1000;
+constexpr int kThousandthMaxInt = std::numeric_limits<int>::max() / 1000;
+
constexpr int kMaxGlyphDimension = 2048;
+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,
+ 70, 72, 72, 74, 74, 74, 76, 76, 76, 78, 78, 78, 80, 80, 80,
+ 82, 82, 82, 84, 84, 84, 84, 86, 86, 86, 88, 88, 88, 88, 90,
+ 90, 90, 90, 92, 92, 92, 92, 94, 94, 94, 94, 96, 96, 96, 96,
+ 96, 98, 98, 98, 98, 100, 100, 100, 100, 100, 102, 102, 102, 102, 102,
+ 104, 104, 104, 104, 104, 106, 106, 106, 106, 106,
+};
+
+constexpr uint8_t kWeightPow11[] = {
+ 0, 4, 7, 8, 9, 10, 12, 13, 15, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 39, 40, 40, 41,
+ 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46,
+ 46, 43, 47, 47, 48, 48, 48, 48, 45, 50, 50, 50, 46, 51, 51, 51, 52,
+ 52, 52, 52, 53, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 55,
+ 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58,
+};
+
+constexpr uint8_t kWeightPowShiftJis[] = {
+ 0, 0, 2, 4, 6, 8, 10, 14, 16, 20, 22, 26, 28, 32, 34,
+ 38, 42, 44, 48, 52, 56, 60, 64, 66, 70, 74, 78, 82, 86, 90,
+ 96, 96, 96, 96, 98, 98, 98, 100, 100, 100, 100, 102, 102, 102, 102,
+ 104, 104, 104, 104, 104, 106, 106, 106, 106, 106, 108, 108, 108, 108, 108,
+ 110, 110, 110, 110, 110, 112, 112, 112, 112, 112, 112, 114, 114, 114, 114,
+ 114, 114, 114, 116, 116, 116, 116, 116, 116, 116, 118, 118, 118, 118, 118,
+ 118, 118, 120, 120, 120, 120, 120, 120, 120, 120,
+};
+
+constexpr size_t kWeightPowArraySize = 100;
+static_assert(kWeightPowArraySize == std::size(kWeightPow), "Wrong size");
+static_assert(kWeightPowArraySize == std::size(kWeightPow11), "Wrong size");
+static_assert(kWeightPowArraySize == std::size(kWeightPowShiftJis),
+ "Wrong size");
+
+// Returns negative values on failure.
+int GetWeightLevel(FX_Charset charset, size_t index) {
+ if (index >= kWeightPowArraySize) {
+ return -1;
+ }
+
+ if (charset == FX_Charset::kShiftJIS) {
+ return kWeightPowShiftJis[index];
+ }
+ return kWeightPow11[index];
+}
+
+int GetSkewFromAngle(int angle) {
+ static constexpr int8_t kAngleSkew[] = {
+ -0, -2, -3, -5, -7, -9, -11, -12, -14, -16, -18, -19, -21, -23, -25,
+ -27, -29, -31, -32, -34, -36, -38, -40, -42, -45, -47, -49, -51, -53, -55,
+ };
+
+ // |angle| is non-positive so |-angle| is used as the index. Need to make sure
+ // |angle| != INT_MIN since -INT_MIN is undefined.
+ if (angle > 0 || angle == std::numeric_limits<int>::min() ||
+ static_cast<size_t>(-angle) >= std::size(kAngleSkew)) {
+ return -58;
+ }
+ return kAngleSkew[-angle];
+}
+
+void Outline_CheckEmptyContour(OUTLINE_PARAMS* param) {
+ size_t size;
+ {
+ pdfium::span<const CFX_Path::Point> points = param->m_pPath->GetPoints();
+ size = points.size();
+
+ if (size >= 2 &&
+ points[size - 2].IsTypeAndOpen(CFX_Path::Point::Type::kMove) &&
+ points[size - 2].m_Point == points[size - 1].m_Point) {
+ size -= 2;
+ }
+ if (size >= 4 &&
+ points[size - 4].IsTypeAndOpen(CFX_Path::Point::Type::kMove) &&
+ points[size - 3].IsTypeAndOpen(CFX_Path::Point::Type::kBezier) &&
+ points[size - 3].m_Point == points[size - 4].m_Point &&
+ points[size - 2].m_Point == points[size - 4].m_Point &&
+ points[size - 1].m_Point == points[size - 4].m_Point) {
+ size -= 4;
+ }
+ }
+ // Only safe after |points| has been destroyed.
+ param->m_pPath->GetPoints().resize(size);
+}
+
+int Outline_MoveTo(const FT_Vector* to, void* user) {
+ OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
+
+ Outline_CheckEmptyContour(param);
+
+ param->m_pPath->ClosePath();
+ param->m_pPath->AppendPoint(
+ CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
+ CFX_Path::Point::Type::kMove);
+
+ param->m_CurX = to->x;
+ param->m_CurY = to->y;
+ return 0;
+}
+
+int Outline_LineTo(const FT_Vector* to, void* user) {
+ OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
+
+ param->m_pPath->AppendPoint(
+ CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
+ CFX_Path::Point::Type::kLine);
+
+ param->m_CurX = to->x;
+ param->m_CurY = to->y;
+ return 0;
+}
+
+int Outline_ConicTo(const FT_Vector* control, const FT_Vector* to, void* user) {
+ OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
+
+ param->m_pPath->AppendPoint(
+ CFX_PointF((param->m_CurX + (control->x - param->m_CurX) * 2 / 3) /
+ param->m_CoordUnit,
+ (param->m_CurY + (control->y - param->m_CurY) * 2 / 3) /
+ param->m_CoordUnit),
+ CFX_Path::Point::Type::kBezier);
+
+ param->m_pPath->AppendPoint(
+ CFX_PointF((control->x + (to->x - control->x) / 3) / param->m_CoordUnit,
+ (control->y + (to->y - control->y) / 3) / param->m_CoordUnit),
+ CFX_Path::Point::Type::kBezier);
+
+ param->m_pPath->AppendPoint(
+ CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
+ CFX_Path::Point::Type::kBezier);
+
+ param->m_CurX = to->x;
+ param->m_CurY = to->y;
+ return 0;
+}
+
+int Outline_CubicTo(const FT_Vector* control1,
+ const FT_Vector* control2,
+ const FT_Vector* to,
+ void* user) {
+ OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
+
+ param->m_pPath->AppendPoint(CFX_PointF(control1->x / param->m_CoordUnit,
+ control1->y / param->m_CoordUnit),
+ CFX_Path::Point::Type::kBezier);
+
+ param->m_pPath->AppendPoint(CFX_PointF(control2->x / param->m_CoordUnit,
+ control2->y / param->m_CoordUnit),
+ CFX_Path::Point::Type::kBezier);
+
+ param->m_pPath->AppendPoint(
+ CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
+ CFX_Path::Point::Type::kBezier);
+
+ param->m_CurX = to->x;
+ param->m_CurY = to->y;
+ return 0;
+}
+
} // namespace
// static
@@ -147,7 +321,7 @@
angle = pSubstFont->m_ItalicAngle;
}
if (angle) {
- int skew = CFX_Font::GetSkewFromAngle(angle);
+ int skew = GetSkewFromAngle(angle);
if (pFont->IsVertical()) {
ft_matrix.yx += ft_matrix.yy * skew / 100;
} else {
@@ -155,8 +329,8 @@
}
}
if (pSubstFont->IsBuiltInGenericFont()) {
- pFont->AdjustMMParams(glyph_index, dest_width,
- pFont->GetSubstFont()->m_Weight);
+ pFont->GetFace()->AdjustVariationParams(glyph_index, dest_width,
+ pFont->GetSubstFont()->m_Weight);
}
}
@@ -191,7 +365,7 @@
if (pSubstFont && !pSubstFont->IsBuiltInGenericFont() && weight > 400) {
uint32_t index = (weight - 400) / 10;
pdfium::base::CheckedNumeric<signed long> level =
- CFX_Font::GetWeightLevel(pSubstFont->m_Charset, index);
+ GetWeightLevel(pSubstFont->m_Charset, index);
if (level.ValueOrDefault(-1) < 0) {
return nullptr;
}
@@ -246,6 +420,96 @@
return pGlyphBitmap;
}
+std::unique_ptr<CFX_Path> CFX_Face::LoadGlyphPath(
+ uint32_t glyph_index,
+ int dest_width,
+ bool is_vertical,
+ const CFX_SubstFont* subst_font) {
+ FXFT_FaceRec* rec = GetRec();
+ FT_Set_Pixel_Sizes(rec, 0, 64);
+ FT_Matrix ft_matrix = {65536, 0, 0, 65536};
+ if (subst_font) {
+ if (subst_font->m_ItalicAngle) {
+ int skew = GetSkewFromAngle(subst_font->m_ItalicAngle);
+ if (is_vertical) {
+ ft_matrix.yx += ft_matrix.yy * skew / 100;
+ } else {
+ ft_matrix.xy -= ft_matrix.xx * skew / 100;
+ }
+ }
+ if (subst_font->IsBuiltInGenericFont()) {
+ AdjustVariationParams(glyph_index, dest_width, subst_font->m_Weight);
+ }
+ }
+ ScopedFontTransform scoped_transform(pdfium::WrapRetain(this), &ft_matrix);
+ int load_flags = FT_LOAD_NO_BITMAP;
+ if (!IsTtOt() || !IsTricky()) {
+ load_flags |= FT_LOAD_NO_HINTING;
+ }
+ if (FT_Load_Glyph(rec, glyph_index, load_flags)) {
+ return nullptr;
+ }
+ if (subst_font && !subst_font->IsBuiltInGenericFont() &&
+ subst_font->m_Weight > 400) {
+ uint32_t index = std::min<uint32_t>((subst_font->m_Weight - 400) / 10,
+ kWeightPowArraySize - 1);
+ int level;
+ if (subst_font->m_Charset == FX_Charset::kShiftJIS) {
+ level = kWeightPowShiftJis[index] * 65536 / 36655;
+ } else {
+ level = kWeightPow[index];
+ }
+ FT_Outline_Embolden(&rec->glyph->outline, level);
+ }
+
+ FT_Outline_Funcs funcs;
+ funcs.move_to = Outline_MoveTo;
+ funcs.line_to = Outline_LineTo;
+ funcs.conic_to = Outline_ConicTo;
+ funcs.cubic_to = Outline_CubicTo;
+ funcs.shift = 0;
+ funcs.delta = 0;
+
+ auto pPath = std::make_unique<CFX_Path>();
+ OUTLINE_PARAMS params;
+ params.m_pPath = pPath.get();
+ params.m_CurX = params.m_CurY = 0;
+ params.m_CoordUnit = 64 * 64.0;
+
+ FT_Outline_Decompose(&rec->glyph->outline, &funcs, ¶ms);
+ if (pPath->GetPoints().empty()) {
+ return nullptr;
+ }
+
+ Outline_CheckEmptyContour(¶ms);
+ pPath->ClosePath();
+ return pPath;
+}
+
+int CFX_Face::GetGlyphWidth(uint32_t glyph_index,
+ int dest_width,
+ int weight,
+ const CFX_SubstFont* subst_font) {
+ if (subst_font && subst_font->IsBuiltInGenericFont()) {
+ AdjustVariationParams(glyph_index, dest_width, weight);
+ }
+
+ FXFT_FaceRec* rec = GetRec();
+ int err = FT_Load_Glyph(
+ rec, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
+ if (err) {
+ return 0;
+ }
+
+ FT_Pos horizontal_advance = rec->glyph->metrics.horiAdvance;
+ if (horizontal_advance < kThousandthMinInt ||
+ horizontal_advance > kThousandthMaxInt) {
+ return 0;
+ }
+
+ return static_cast<int>(EM_ADJUST(GetUnitsPerEm(), horizontal_advance));
+}
+
bool CFX_Face::SelectCharMap(fxge::FontEncoding encoding) {
FT_Error error =
FT_Select_Charmap(GetRec(), static_cast<FT_Encoding>(encoding));
@@ -258,3 +522,47 @@
}
CFX_Face::~CFX_Face() = default;
+
+void CFX_Face::AdjustVariationParams(int glyph_index,
+ int dest_width,
+ int weight) {
+ DCHECK(dest_width >= 0);
+
+ FXFT_FaceRec* rec = GetRec();
+ ScopedFXFTMMVar variation_desc(rec);
+ if (!variation_desc) {
+ return;
+ }
+
+ FT_Pos coords[2];
+ if (weight == 0) {
+ coords[0] = variation_desc.GetAxisDefault(0) / 65536;
+ } else {
+ coords[0] = weight;
+ }
+
+ if (dest_width == 0) {
+ coords[1] = variation_desc.GetAxisDefault(1) / 65536;
+ } else {
+ FT_Long min_param = variation_desc.GetAxisMin(1) / 65536;
+ FT_Long max_param = variation_desc.GetAxisMax(1) / 65536;
+ coords[1] = min_param;
+ FT_Set_MM_Design_Coordinates(rec, 2, coords);
+ FT_Load_Glyph(rec, glyph_index,
+ FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
+ FT_Pos min_width = rec->glyph->metrics.horiAdvance * 1000 / GetUnitsPerEm();
+ coords[1] = max_param;
+ FT_Set_MM_Design_Coordinates(rec, 2, coords);
+ FT_Load_Glyph(rec, glyph_index,
+ FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
+ FT_Pos max_width = rec->glyph->metrics.horiAdvance * 1000 / GetUnitsPerEm();
+ if (max_width == min_width) {
+ return;
+ }
+ FT_Pos param = min_param + (max_param - min_param) *
+ (dest_width - min_width) /
+ (max_width - min_width);
+ coords[1] = param;
+ }
+ FT_Set_MM_Design_Coordinates(rec, 2, coords);
+}
diff --git a/core/fxge/cfx_face.h b/core/fxge/cfx_face.h
index 1c85af1..9534488 100644
--- a/core/fxge/cfx_face.h
+++ b/core/fxge/cfx_face.h
@@ -23,6 +23,8 @@
class CFX_Font;
class CFX_GlyphBitmap;
+class CFX_Path;
+class CFX_SubstFont;
class CFX_Face final : public Retainable, public Observable {
public:
@@ -67,6 +69,14 @@
const CFX_Matrix& matrix,
int dest_width,
int anti_alias);
+ std::unique_ptr<CFX_Path> LoadGlyphPath(uint32_t glyph_index,
+ int dest_width,
+ bool is_vertical,
+ const CFX_SubstFont* subst_font);
+ int GetGlyphWidth(uint32_t glyph_index,
+ int dest_width,
+ int weight,
+ const CFX_SubstFont* subst_font);
bool SelectCharMap(fxge::FontEncoding encoding);
@@ -77,6 +87,8 @@
CFX_Face(FXFT_FaceRec* pRec, RetainPtr<Retainable> pDesc);
~CFX_Face() override;
+ void AdjustVariationParams(int glyph_index, int dest_width, int weight);
+
ScopedFXFTFaceRec const m_pRec;
RetainPtr<Retainable> const m_pDesc;
};
diff --git a/core/fxge/cfx_font.cpp b/core/fxge/cfx_font.cpp
index b5b7511..e48a6bc 100644
--- a/core/fxge/cfx_font.cpp
+++ b/core/fxge/cfx_font.cpp
@@ -38,13 +38,6 @@
constexpr int kThousandthMinInt = std::numeric_limits<int>::min() / 1000;
constexpr int kThousandthMaxInt = std::numeric_limits<int>::max() / 1000;
-struct OUTLINE_PARAMS {
- UnownedPtr<CFX_Path> m_pPath;
- FT_Pos m_CurX;
- FT_Pos m_CurY;
- float m_CoordUnit;
-};
-
FX_RECT FXRectFromFTPos(FT_Pos left, FT_Pos top, FT_Pos right, FT_Pos bottom) {
return FX_RECT(pdfium::base::checked_cast<int32_t>(left),
pdfium::base::checked_cast<int32_t>(top),
@@ -81,148 +74,10 @@
void FTStreamClose(FXFT_StreamRec* stream) {}
#endif // PDF_ENABLE_XFA
-void Outline_CheckEmptyContour(OUTLINE_PARAMS* param) {
- size_t size;
- {
- pdfium::span<const CFX_Path::Point> points = param->m_pPath->GetPoints();
- size = points.size();
-
- if (size >= 2 &&
- points[size - 2].IsTypeAndOpen(CFX_Path::Point::Type::kMove) &&
- points[size - 2].m_Point == points[size - 1].m_Point) {
- size -= 2;
- }
- if (size >= 4 &&
- points[size - 4].IsTypeAndOpen(CFX_Path::Point::Type::kMove) &&
- points[size - 3].IsTypeAndOpen(CFX_Path::Point::Type::kBezier) &&
- points[size - 3].m_Point == points[size - 4].m_Point &&
- points[size - 2].m_Point == points[size - 4].m_Point &&
- points[size - 1].m_Point == points[size - 4].m_Point) {
- size -= 4;
- }
- }
- // Only safe after |points| has been destroyed.
- param->m_pPath->GetPoints().resize(size);
-}
-
-int Outline_MoveTo(const FT_Vector* to, void* user) {
- OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
-
- Outline_CheckEmptyContour(param);
-
- param->m_pPath->ClosePath();
- param->m_pPath->AppendPoint(
- CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
- CFX_Path::Point::Type::kMove);
-
- param->m_CurX = to->x;
- param->m_CurY = to->y;
- return 0;
-}
-
-int Outline_LineTo(const FT_Vector* to, void* user) {
- OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
-
- param->m_pPath->AppendPoint(
- CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
- CFX_Path::Point::Type::kLine);
-
- param->m_CurX = to->x;
- param->m_CurY = to->y;
- return 0;
-}
-
-int Outline_ConicTo(const FT_Vector* control, const FT_Vector* to, void* user) {
- OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
-
- param->m_pPath->AppendPoint(
- CFX_PointF((param->m_CurX + (control->x - param->m_CurX) * 2 / 3) /
- param->m_CoordUnit,
- (param->m_CurY + (control->y - param->m_CurY) * 2 / 3) /
- param->m_CoordUnit),
- CFX_Path::Point::Type::kBezier);
-
- param->m_pPath->AppendPoint(
- CFX_PointF((control->x + (to->x - control->x) / 3) / param->m_CoordUnit,
- (control->y + (to->y - control->y) / 3) / param->m_CoordUnit),
- CFX_Path::Point::Type::kBezier);
-
- param->m_pPath->AppendPoint(
- CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
- CFX_Path::Point::Type::kBezier);
-
- param->m_CurX = to->x;
- param->m_CurY = to->y;
- return 0;
-}
-
-int Outline_CubicTo(const FT_Vector* control1,
- const FT_Vector* control2,
- const FT_Vector* to,
- void* user) {
- OUTLINE_PARAMS* param = static_cast<OUTLINE_PARAMS*>(user);
-
- param->m_pPath->AppendPoint(CFX_PointF(control1->x / param->m_CoordUnit,
- control1->y / param->m_CoordUnit),
- CFX_Path::Point::Type::kBezier);
-
- param->m_pPath->AppendPoint(CFX_PointF(control2->x / param->m_CoordUnit,
- control2->y / param->m_CoordUnit),
- CFX_Path::Point::Type::kBezier);
-
- param->m_pPath->AppendPoint(
- CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit),
- CFX_Path::Point::Type::kBezier);
-
- param->m_CurX = to->x;
- param->m_CurY = to->y;
- return 0;
-}
-
bool ShouldAppendStyle(const ByteString& style) {
return !style.IsEmpty() && style != "Regular";
}
-constexpr int8_t kAngleSkew[] = {
- -0, -2, -3, -5, -7, -9, -11, -12, -14, -16, -18, -19, -21, -23, -25,
- -27, -29, -31, -32, -34, -36, -38, -40, -42, -45, -47, -49, -51, -53, -55,
-};
-
-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,
- 70, 72, 72, 74, 74, 74, 76, 76, 76, 78, 78, 78, 80, 80, 80,
- 82, 82, 82, 84, 84, 84, 84, 86, 86, 86, 88, 88, 88, 88, 90,
- 90, 90, 90, 92, 92, 92, 92, 94, 94, 94, 94, 96, 96, 96, 96,
- 96, 98, 98, 98, 98, 100, 100, 100, 100, 100, 102, 102, 102, 102, 102,
- 104, 104, 104, 104, 104, 106, 106, 106, 106, 106,
-};
-
-constexpr uint8_t kWeightPow11[] = {
- 0, 4, 7, 8, 9, 10, 12, 13, 15, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 39, 40, 40, 41,
- 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46,
- 46, 43, 47, 47, 48, 48, 48, 48, 45, 50, 50, 50, 46, 51, 51, 51, 52,
- 52, 52, 52, 53, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 55,
- 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58,
-};
-
-constexpr uint8_t kWeightPowShiftJis[] = {
- 0, 0, 2, 4, 6, 8, 10, 14, 16, 20, 22, 26, 28, 32, 34,
- 38, 42, 44, 48, 52, 56, 60, 64, 66, 70, 74, 78, 82, 86, 90,
- 96, 96, 96, 96, 98, 98, 98, 100, 100, 100, 100, 102, 102, 102, 102,
- 104, 104, 104, 104, 104, 106, 106, 106, 106, 106, 108, 108, 108, 108, 108,
- 110, 110, 110, 110, 110, 112, 112, 112, 112, 112, 112, 114, 114, 114, 114,
- 114, 114, 114, 116, 116, 116, 116, 116, 116, 116, 118, 118, 118, 118, 118,
- 118, 118, 120, 120, 120, 120, 120, 120, 120, 120,
-};
-
-constexpr size_t kWeightPowArraySize = 100;
-static_assert(kWeightPowArraySize == std::size(kWeightPow), "Wrong size");
-static_assert(kWeightPowArraySize == std::size(kWeightPow11), "Wrong size");
-static_assert(kWeightPowArraySize == std::size(kWeightPowShiftJis),
- "Wrong size");
-
} // namespace
const CFX_Font::CharsetFontMap CFX_Font::kDefaultTTFMap[] = {
@@ -402,19 +257,9 @@
int weight) const {
if (!m_Face)
return 0;
- if (m_pSubstFont && m_pSubstFont->IsBuiltInGenericFont())
- AdjustMMParams(glyph_index, dest_width, weight);
- int err =
- FT_Load_Glyph(m_Face->GetRec(), glyph_index,
- FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
- if (err)
- return 0;
- FT_Pos horiAdvance = FXFT_Get_Glyph_HoriAdvance(m_Face->GetRec());
- if (horiAdvance < kThousandthMinInt || horiAdvance > kThousandthMaxInt)
- return 0;
-
- return static_cast<int>(EM_ADJUST(m_Face->GetUnitsPerEm(), horiAdvance));
+ return m_Face->GetGlyphWidth(glyph_index, dest_width, weight,
+ m_pSubstFont.get());
}
bool CFX_Font::LoadEmbedded(pdfium::span<const uint8_t> src_span,
@@ -615,109 +460,13 @@
m_GlyphCache = nullptr;
}
-void CFX_Font::AdjustMMParams(int glyph_index,
- int dest_width,
- int weight) const {
- DCHECK(dest_width >= 0);
- ScopedFXFTMMVar variation_desc(m_Face->GetRec());
- if (!variation_desc) {
- return;
- }
-
- FT_Pos coords[2];
- if (weight == 0) {
- coords[0] = variation_desc.GetAxisDefault(0) / 65536;
- } else {
- coords[0] = weight;
- }
-
- if (dest_width == 0) {
- coords[1] = variation_desc.GetAxisDefault(1) / 65536;
- } else {
- FT_Long min_param = variation_desc.GetAxisMin(1) / 65536;
- FT_Long max_param = variation_desc.GetAxisMax(1) / 65536;
- coords[1] = min_param;
- FT_Set_MM_Design_Coordinates(m_Face->GetRec(), 2, coords);
- FT_Load_Glyph(m_Face->GetRec(), glyph_index,
- FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
- FT_Pos min_width = FXFT_Get_Glyph_HoriAdvance(m_Face->GetRec()) * 1000 /
- m_Face->GetUnitsPerEm();
- coords[1] = max_param;
- FT_Set_MM_Design_Coordinates(m_Face->GetRec(), 2, coords);
- FT_Load_Glyph(m_Face->GetRec(), glyph_index,
- FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
- FT_Pos max_width = FXFT_Get_Glyph_HoriAdvance(m_Face->GetRec()) * 1000 /
- m_Face->GetUnitsPerEm();
- if (max_width == min_width) {
- return;
- }
- FT_Pos param = min_param + (max_param - min_param) *
- (dest_width - min_width) /
- (max_width - min_width);
- coords[1] = param;
- }
- FT_Set_MM_Design_Coordinates(m_Face->GetRec(), 2, coords);
-}
-
std::unique_ptr<CFX_Path> CFX_Font::LoadGlyphPathImpl(uint32_t glyph_index,
int dest_width) const {
if (!m_Face)
return nullptr;
- FT_Set_Pixel_Sizes(m_Face->GetRec(), 0, 64);
- FT_Matrix ft_matrix = {65536, 0, 0, 65536};
- if (m_pSubstFont) {
- if (m_pSubstFont->m_ItalicAngle) {
- int skew = GetSkewFromAngle(m_pSubstFont->m_ItalicAngle);
- if (m_bVertical)
- ft_matrix.yx += ft_matrix.yy * skew / 100;
- else
- ft_matrix.xy -= ft_matrix.xx * skew / 100;
- }
- if (m_pSubstFont->IsBuiltInGenericFont())
- AdjustMMParams(glyph_index, dest_width, m_pSubstFont->m_Weight);
- }
- ScopedFontTransform scoped_transform(m_Face, &ft_matrix);
- int load_flags = FT_LOAD_NO_BITMAP;
- if (!m_Face->IsTtOt() || !m_Face->IsTricky()) {
- load_flags |= FT_LOAD_NO_HINTING;
- }
- if (FT_Load_Glyph(m_Face->GetRec(), glyph_index, load_flags))
- return nullptr;
- if (m_pSubstFont && !m_pSubstFont->IsBuiltInGenericFont() &&
- m_pSubstFont->m_Weight > 400) {
- uint32_t index = std::min<uint32_t>((m_pSubstFont->m_Weight - 400) / 10,
- kWeightPowArraySize - 1);
- int level;
- if (m_pSubstFont->m_Charset == FX_Charset::kShiftJIS)
- level = kWeightPowShiftJis[index] * 65536 / 36655;
- else
- level = kWeightPow[index];
- FT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face->GetRec()), level);
- }
-
- FT_Outline_Funcs funcs;
- funcs.move_to = Outline_MoveTo;
- funcs.line_to = Outline_LineTo;
- funcs.conic_to = Outline_ConicTo;
- funcs.cubic_to = Outline_CubicTo;
- funcs.shift = 0;
- funcs.delta = 0;
-
- auto pPath = std::make_unique<CFX_Path>();
- OUTLINE_PARAMS params;
- params.m_pPath = pPath.get();
- params.m_CurX = params.m_CurY = 0;
- params.m_CoordUnit = 64 * 64.0;
-
- FT_Outline_Decompose(FXFT_Get_Glyph_Outline(m_Face->GetRec()), &funcs,
- ¶ms);
- if (pPath->GetPoints().empty())
- return nullptr;
-
- Outline_CheckEmptyContour(¶ms);
- pPath->ClosePath();
- return pPath;
+ return m_Face->LoadGlyphPath(glyph_index, dest_width, m_bVertical,
+ m_pSubstFont.get());
}
const CFX_GlyphBitmap* CFX_Font::LoadGlyphBitmap(
@@ -737,27 +486,6 @@
return GetOrCreateGlyphCache()->LoadGlyphPath(this, glyph_index, dest_width);
}
-// static
-int CFX_Font::GetWeightLevel(FX_Charset charset, size_t index) {
- if (index >= kWeightPowArraySize)
- return -1;
-
- if (charset == FX_Charset::kShiftJIS)
- return kWeightPowShiftJis[index];
- return kWeightPow11[index];
-}
-
-// static
-int CFX_Font::GetSkewFromAngle(int angle) {
- // |angle| is non-positive so |-angle| is used as the index. Need to make sure
- // |angle| != INT_MIN since -INT_MIN is undefined.
- if (angle > 0 || angle == std::numeric_limits<int>::min() ||
- static_cast<size_t>(-angle) >= std::size(kAngleSkew)) {
- return -58;
- }
- return kAngleSkew[-angle];
-}
-
#if defined(PDF_USE_SKIA)
CFX_TypeFace* CFX_Font::GetDeviceCache() const {
return GetOrCreateGlyphCache()->GetDeviceCache(this);
diff --git a/core/fxge/cfx_font.h b/core/fxge/cfx_font.h
index 09041e1..e78114a 100644
--- a/core/fxge/cfx_font.h
+++ b/core/fxge/cfx_font.h
@@ -58,12 +58,6 @@
static const char kDefaultAnsiFontName[];
static const char kUniversalDefaultFontName[];
- // Returns negative values on failure.
- static int GetWeightLevel(FX_Charset charset, size_t index);
-
- // |angle| is typically negative.
- static int GetSkewFromAngle(int angle);
-
static ByteString GetDefaultFontNameByCharset(FX_Charset nCharset);
static FX_Charset GetCharSetFromUnicode(uint16_t word);
@@ -132,7 +126,6 @@
void SetFontType(FontType type) { m_FontType = type; }
uint64_t GetObjectTag() const { return m_ObjectTag; }
pdfium::span<uint8_t> GetFontSpan() const { return m_FontData; }
- void AdjustMMParams(int glyph_index, int dest_width, int weight) const;
std::unique_ptr<CFX_Path> LoadGlyphPathImpl(uint32_t glyph_index,
int dest_width) const;
int GetGlyphWidthImpl(uint32_t glyph_index, int dest_width, int weight) const;
diff --git a/core/fxge/freetype/fx_freetype.h b/core/fxge/freetype/fx_freetype.h
index 4bf4b68..c2c1d72 100644
--- a/core/fxge/freetype/fx_freetype.h
+++ b/core/fxge/freetype/fx_freetype.h
@@ -61,7 +61,6 @@
#define FXFT_Get_Charmap_PlatformID(charmap) (charmap)->platform_id
#define FXFT_Get_Charmap_EncodingID(charmap) (charmap)->encoding_id
#define FXFT_Get_Glyph_HoriAdvance(face) (face)->glyph->metrics.horiAdvance
-#define FXFT_Get_Glyph_Outline(face) &((face)->glyph->outline)
int FXFT_unicode_from_adobe_name(const char* glyph_name);
void FXFT_adobe_name_from_unicode(char* name, wchar_t unicode);