Move CFX_GlyphBitmap creation code into CFX_Face::RenderGlyph()
Instead of calling FreeType code to create a CFX_GlyphBitmap in
CFX_GlyphCache::RenderGlyph(), delegate the work to CFX_Face.
Then many FXFT_ macros go away. As part of simplifying the code to use
FreeType structs directly inside CFX_Face, remove some unsigned int to
int conversions. Then many for-loops in CFX_Face::RenderGlyph() can use
more unsigned values when indexing into arrays.
Bug: pdfium:2037
Change-Id: Ia49f85179da87e7aa15ad1063685cb8513d1307a
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/114790
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Dominik Röttsches <drott@chromium.org>
diff --git a/core/fxge/cfx_face.cpp b/core/fxge/cfx_face.cpp
index 44df5a2..24baa8f 100644
--- a/core/fxge/cfx_face.cpp
+++ b/core/fxge/cfx_face.cpp
@@ -4,11 +4,28 @@
#include "core/fxge/cfx_face.h"
+#include <algorithm>
+#include <memory>
#include <utility>
+#include "core/fxge/cfx_font.h"
+#include "core/fxge/cfx_fontmgr.h"
+#include "core/fxge/cfx_gemodule.h"
+#include "core/fxge/cfx_glyphbitmap.h"
+#include "core/fxge/cfx_substfont.h"
+#include "core/fxge/dib/cfx_dibitmap.h"
+#include "core/fxge/dib/fx_dib.h"
#include "core/fxge/fx_fontencoding.h"
+#include "core/fxge/scoped_font_transform.h"
#include "third_party/base/check.h"
#include "third_party/base/numerics/safe_conversions.h"
+#include "third_party/base/numerics/safe_math.h"
+
+namespace {
+
+constexpr int kMaxGlyphDimension = 2048;
+
+} // namespace
// static
RetainPtr<CFX_Face> CFX_Face::New(FT_Library library,
@@ -108,6 +125,127 @@
return {GetRec()->stream->base, GetRec()->stream->size};
}
+std::unique_ptr<CFX_GlyphBitmap> CFX_Face::RenderGlyph(const CFX_Font* pFont,
+ uint32_t glyph_index,
+ bool bFontStyle,
+ const CFX_Matrix& matrix,
+ int dest_width,
+ int anti_alias) {
+ FT_Matrix ft_matrix;
+ ft_matrix.xx = matrix.a / 64 * 65536;
+ ft_matrix.xy = matrix.c / 64 * 65536;
+ ft_matrix.yx = matrix.b / 64 * 65536;
+ ft_matrix.yy = matrix.d / 64 * 65536;
+ bool bUseCJKSubFont = false;
+ const CFX_SubstFont* pSubstFont = pFont->GetSubstFont();
+ if (pSubstFont) {
+ bUseCJKSubFont = pSubstFont->m_bSubstCJK && bFontStyle;
+ int angle;
+ if (bUseCJKSubFont) {
+ angle = pSubstFont->m_bItalicCJK ? -15 : 0;
+ } else {
+ angle = pSubstFont->m_ItalicAngle;
+ }
+ if (angle) {
+ int skew = CFX_Font::GetSkewFromAngle(angle);
+ if (pFont->IsVertical()) {
+ ft_matrix.yx += ft_matrix.yy * skew / 100;
+ } else {
+ ft_matrix.xy -= ft_matrix.xx * skew / 100;
+ }
+ }
+ if (pSubstFont->IsBuiltInGenericFont()) {
+ pFont->AdjustMMParams(glyph_index, dest_width,
+ pFont->GetSubstFont()->m_Weight);
+ }
+ }
+
+ ScopedFontTransform scoped_transform(pdfium::WrapRetain(this), &ft_matrix);
+ int load_flags = FT_LOAD_NO_BITMAP | FT_LOAD_PEDANTIC;
+ if (!IsTtOt()) {
+ load_flags |= FT_LOAD_NO_HINTING;
+ }
+ FXFT_FaceRec* rec = GetRec();
+ int error = FT_Load_Glyph(rec, glyph_index, load_flags);
+ if (error) {
+ // if an error is returned, try to reload glyphs without hinting.
+ if (load_flags & FT_LOAD_NO_HINTING) {
+ return nullptr;
+ }
+
+ load_flags |= FT_LOAD_NO_HINTING;
+ load_flags &= ~FT_LOAD_PEDANTIC;
+ error = FT_Load_Glyph(rec, glyph_index, load_flags);
+ if (error) {
+ return nullptr;
+ }
+ }
+
+ auto* glyph = rec->glyph;
+ int weight;
+ if (bUseCJKSubFont) {
+ weight = pSubstFont->m_WeightCJK;
+ } else {
+ weight = pSubstFont ? pSubstFont->m_Weight : 0;
+ }
+ 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);
+ if (level.ValueOrDefault(-1) < 0) {
+ return nullptr;
+ }
+
+ level = level *
+ (abs(static_cast<int>(ft_matrix.xx)) +
+ abs(static_cast<int>(ft_matrix.xy))) /
+ 36655;
+ FT_Outline_Embolden(&glyph->outline, level.ValueOrDefault(0));
+ }
+ FT_Library_SetLcdFilter(CFX_GEModule::Get()->GetFontMgr()->GetFTLibrary(),
+ FT_LCD_FILTER_DEFAULT);
+ error = FT_Render_Glyph(glyph, static_cast<FT_Render_Mode>(anti_alias));
+ if (error) {
+ return nullptr;
+ }
+
+ const FT_Bitmap& bitmap = glyph->bitmap;
+ if (bitmap.width > kMaxGlyphDimension || bitmap.rows > kMaxGlyphDimension) {
+ return nullptr;
+ }
+ int dib_width = bitmap.width;
+ auto pGlyphBitmap =
+ std::make_unique<CFX_GlyphBitmap>(glyph->bitmap_left, glyph->bitmap_top);
+ pGlyphBitmap->GetBitmap()->Create(dib_width, bitmap.rows,
+ anti_alias == FT_RENDER_MODE_MONO
+ ? FXDIB_Format::k1bppMask
+ : FXDIB_Format::k8bppMask);
+ int dest_pitch = pGlyphBitmap->GetBitmap()->GetPitch();
+ uint8_t* pDestBuf = pGlyphBitmap->GetBitmap()->GetWritableBuffer().data();
+ const uint8_t* pSrcBuf = bitmap.buffer;
+ if (anti_alias != FT_RENDER_MODE_MONO &&
+ bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
+ unsigned int bytes = anti_alias == FT_RENDER_MODE_LCD ? 3 : 1;
+ for (unsigned int i = 0; i < bitmap.rows; i++) {
+ for (unsigned int n = 0; n < bitmap.width; n++) {
+ uint8_t data =
+ (pSrcBuf[i * bitmap.pitch + n / 8] & (0x80 >> (n % 8))) ? 255 : 0;
+ for (unsigned int b = 0; b < bytes; b++) {
+ pDestBuf[i * dest_pitch + n * bytes + b] = data;
+ }
+ }
+ }
+ } else {
+ FXSYS_memset(pDestBuf, 0, dest_pitch * bitmap.rows);
+ int rowbytes = std::min(abs(bitmap.pitch), dest_pitch);
+ for (unsigned int row = 0; row < bitmap.rows; row++) {
+ FXSYS_memcpy(pDestBuf + row * dest_pitch, pSrcBuf + row * bitmap.pitch,
+ rowbytes);
+ }
+ }
+ return pGlyphBitmap;
+}
+
bool CFX_Face::SelectCharMap(fxge::FontEncoding encoding) {
FT_Error error =
FT_Select_Charmap(GetRec(), static_cast<FT_Encoding>(encoding));
diff --git a/core/fxge/cfx_face.h b/core/fxge/cfx_face.h
index d8f96c0..1c85af1 100644
--- a/core/fxge/cfx_face.h
+++ b/core/fxge/cfx_face.h
@@ -7,6 +7,8 @@
#include <stdint.h>
+#include <memory>
+
#include "build/build_config.h"
#include "core/fxcrt/bytestring.h"
#include "core/fxcrt/fx_coordinates.h"
@@ -19,6 +21,9 @@
enum class FontEncoding : uint32_t;
}
+class CFX_Font;
+class CFX_GlyphBitmap;
+
class CFX_Face final : public Retainable, public Observable {
public:
static RetainPtr<CFX_Face> New(FT_Library library,
@@ -56,6 +61,13 @@
pdfium::span<uint8_t> GetData() const;
+ std::unique_ptr<CFX_GlyphBitmap> RenderGlyph(const CFX_Font* pFont,
+ uint32_t glyph_index,
+ bool bFontStyle,
+ const CFX_Matrix& matrix,
+ int dest_width,
+ int anti_alias);
+
bool SelectCharMap(fxge::FontEncoding encoding);
FXFT_FaceRec* GetRec() { return m_pRec.get(); }
diff --git a/core/fxge/cfx_glyphcache.cpp b/core/fxge/cfx_glyphcache.cpp
index 076ddbb..a5610c6 100644
--- a/core/fxge/cfx_glyphcache.cpp
+++ b/core/fxge/cfx_glyphcache.cpp
@@ -8,8 +8,6 @@
#include <stdarg.h>
-#include <algorithm>
-#include <limits>
#include <memory>
#include <utility>
@@ -18,15 +16,9 @@
#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "core/fxge/cfx_defaultrenderdevice.h"
#include "core/fxge/cfx_font.h"
-#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/freetype/fx_freetype.h"
-#include "core/fxge/scoped_font_transform.h"
-#include "third_party/base/numerics/safe_math.h"
#if defined(PDF_USE_SKIA)
#include "third_party/skia/include/core/SkStream.h" // nogncheck
@@ -50,8 +42,6 @@
constexpr uint32_t kInvalidGlyphIndex = static_cast<uint32_t>(-1);
-constexpr int kMaxGlyphDimension = 2048;
-
struct UniqueKeyGen {
void Generate(int count, ...);
@@ -123,117 +113,12 @@
const CFX_Matrix& matrix,
int dest_width,
int anti_alias) {
- if (!GetFaceRec())
+ if (!m_Face) {
return nullptr;
-
- FT_Matrix ft_matrix;
- ft_matrix.xx = matrix.a / 64 * 65536;
- ft_matrix.xy = matrix.c / 64 * 65536;
- ft_matrix.yx = matrix.b / 64 * 65536;
- ft_matrix.yy = matrix.d / 64 * 65536;
- bool bUseCJKSubFont = false;
- const CFX_SubstFont* pSubstFont = pFont->GetSubstFont();
- if (pSubstFont) {
- bUseCJKSubFont = pSubstFont->m_bSubstCJK && bFontStyle;
- int angle;
- if (bUseCJKSubFont)
- angle = pSubstFont->m_bItalicCJK ? -15 : 0;
- else
- angle = pSubstFont->m_ItalicAngle;
- if (angle) {
- int skew = CFX_Font::GetSkewFromAngle(angle);
- if (pFont->IsVertical())
- ft_matrix.yx += ft_matrix.yy * skew / 100;
- else
- ft_matrix.xy -= ft_matrix.xx * skew / 100;
- }
- if (pSubstFont->IsBuiltInGenericFont()) {
- pFont->AdjustMMParams(glyph_index, dest_width,
- pFont->GetSubstFont()->m_Weight);
- }
}
- ScopedFontTransform scoped_transform(GetFace(), &ft_matrix);
- int load_flags = FT_LOAD_NO_BITMAP | FT_LOAD_PEDANTIC;
- if (!GetFace()->IsTtOt()) {
- load_flags |= FT_LOAD_NO_HINTING;
- }
- int error = FT_Load_Glyph(GetFaceRec(), glyph_index, load_flags);
- if (error) {
- // if an error is returned, try to reload glyphs without hinting.
- if (load_flags & FT_LOAD_NO_HINTING)
- return nullptr;
-
- load_flags |= FT_LOAD_NO_HINTING;
- load_flags &= ~FT_LOAD_PEDANTIC;
- error = FT_Load_Glyph(GetFaceRec(), glyph_index, load_flags);
- if (error)
- return nullptr;
- }
-
- int weight;
- if (bUseCJKSubFont)
- weight = pSubstFont->m_WeightCJK;
- else
- weight = pSubstFont ? pSubstFont->m_Weight : 0;
- 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);
- if (level.ValueOrDefault(-1) < 0)
- return nullptr;
-
- level = level *
- (abs(static_cast<int>(ft_matrix.xx)) +
- abs(static_cast<int>(ft_matrix.xy))) /
- 36655;
- FT_Outline_Embolden(FXFT_Get_Glyph_Outline(GetFaceRec()),
- level.ValueOrDefault(0));
- }
- FT_Library_SetLcdFilter(CFX_GEModule::Get()->GetFontMgr()->GetFTLibrary(),
- FT_LCD_FILTER_DEFAULT);
- error = FXFT_Render_Glyph(GetFaceRec(), anti_alias);
- if (error)
- return nullptr;
-
- int bmwidth = FXFT_Get_Bitmap_Width(FXFT_Get_Glyph_Bitmap(GetFaceRec()));
- int bmheight = FXFT_Get_Bitmap_Rows(FXFT_Get_Glyph_Bitmap(GetFaceRec()));
- if (bmwidth > kMaxGlyphDimension || bmheight > kMaxGlyphDimension)
- return nullptr;
- int dib_width = bmwidth;
- auto pGlyphBitmap =
- std::make_unique<CFX_GlyphBitmap>(FXFT_Get_Glyph_BitmapLeft(GetFaceRec()),
- FXFT_Get_Glyph_BitmapTop(GetFaceRec()));
- pGlyphBitmap->GetBitmap()->Create(dib_width, bmheight,
- anti_alias == FT_RENDER_MODE_MONO
- ? FXDIB_Format::k1bppMask
- : FXDIB_Format::k8bppMask);
- int dest_pitch = pGlyphBitmap->GetBitmap()->GetPitch();
- int src_pitch = FXFT_Get_Bitmap_Pitch(FXFT_Get_Glyph_Bitmap(GetFaceRec()));
- uint8_t* pDestBuf = pGlyphBitmap->GetBitmap()->GetWritableBuffer().data();
- uint8_t* pSrcBuf = static_cast<uint8_t*>(
- FXFT_Get_Bitmap_Buffer(FXFT_Get_Glyph_Bitmap(GetFaceRec())));
- if (anti_alias != FT_RENDER_MODE_MONO &&
- FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(GetFaceRec())) ==
- FT_PIXEL_MODE_MONO) {
- int bytes = anti_alias == FT_RENDER_MODE_LCD ? 3 : 1;
- for (int i = 0; i < bmheight; i++) {
- for (int n = 0; n < bmwidth; n++) {
- uint8_t data =
- (pSrcBuf[i * src_pitch + n / 8] & (0x80 >> (n % 8))) ? 255 : 0;
- for (int b = 0; b < bytes; b++)
- pDestBuf[i * dest_pitch + n * bytes + b] = data;
- }
- }
- } else {
- FXSYS_memset(pDestBuf, 0, dest_pitch * bmheight);
- int rowbytes = std::min(abs(src_pitch), dest_pitch);
- for (int row = 0; row < bmheight; row++) {
- FXSYS_memcpy(pDestBuf + row * dest_pitch, pSrcBuf + row * src_pitch,
- rowbytes);
- }
- }
- return pGlyphBitmap;
+ return m_Face->RenderGlyph(pFont, glyph_index, bFontStyle, matrix, dest_width,
+ anti_alias);
}
const CFX_Path* CFX_GlyphCache::LoadGlyphPath(const CFX_Font* pFont,
diff --git a/core/fxge/freetype/fx_freetype.h b/core/fxge/freetype/fx_freetype.h
index afd6604..4bf4b68 100644
--- a/core/fxge/freetype/fx_freetype.h
+++ b/core/fxge/freetype/fx_freetype.h
@@ -53,9 +53,6 @@
std::unique_ptr<FT_MM_Var, FXFTMMVarDeleter> const variation_desc_;
};
-#define FXFT_Render_Glyph(face, mode) \
- FT_Render_Glyph((face)->glyph, static_cast<enum FT_Render_Mode_>(mode))
-
#define FXFT_Get_Glyph_HoriBearingX(face) (face)->glyph->metrics.horiBearingX
#define FXFT_Get_Glyph_HoriBearingY(face) (face)->glyph->metrics.horiBearingY
#define FXFT_Get_Glyph_Width(face) (face)->glyph->metrics.width
@@ -65,14 +62,6 @@
#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)
-#define FXFT_Get_Glyph_Bitmap(face) (face)->glyph->bitmap
-#define FXFT_Get_Bitmap_Width(bitmap) (bitmap).width
-#define FXFT_Get_Bitmap_Rows(bitmap) (bitmap).rows
-#define FXFT_Get_Bitmap_PixelMode(bitmap) (bitmap).pixel_mode
-#define FXFT_Get_Bitmap_Pitch(bitmap) (bitmap).pitch
-#define FXFT_Get_Bitmap_Buffer(bitmap) (bitmap).buffer
-#define FXFT_Get_Glyph_BitmapLeft(face) (face)->glyph->bitmap_left
-#define FXFT_Get_Glyph_BitmapTop(face) (face)->glyph->bitmap_top
int FXFT_unicode_from_adobe_name(const char* glyph_name);
void FXFT_adobe_name_from_unicode(char* name, wchar_t unicode);