blob: 3039ac7f5916095a754ee56caddfefefa389964e [file] [log] [blame] [edit]
// Copyright 2016 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
#include "core/fxge/android/cfpf_skiafont.h"
#include <algorithm>
#include "core/fxcrt/fx_codepage.h"
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/fx_system.h"
#include "core/fxge/android/cfpf_skiafontmgr.h"
#include "core/fxge/android/cfpf_skiapathfont.h"
#include "core/fxge/freetype/fx_freetype.h"
#include "third_party/base/numerics/safe_conversions.h"
#define FPF_EM_ADJUST(em, a) (em == 0 ? (a) : (a)*1000 / em)
CFPF_SkiaFont::CFPF_SkiaFont(CFPF_SkiaFontMgr* pFontMgr,
const CFPF_SkiaPathFont* pFont,
uint32_t dwStyle,
FX_Charset uCharset)
: m_pFontMgr(pFontMgr),
m_pFont(pFont),
m_Face(m_pFontMgr->GetFontFace(m_pFont->path(), m_pFont->face_index())),
m_dwStyle(dwStyle),
m_uCharset(uCharset) {}
CFPF_SkiaFont::~CFPF_SkiaFont() = default;
ByteString CFPF_SkiaFont::GetFamilyName() {
if (!m_Face)
return ByteString();
return ByteString(FXFT_Get_Face_Family_Name(GetFaceRec()));
}
ByteString CFPF_SkiaFont::GetPsName() {
if (!m_Face)
return ByteString();
return FT_Get_Postscript_Name(GetFaceRec());
}
int32_t CFPF_SkiaFont::GetGlyphIndex(wchar_t wUnicode) {
if (!m_Face)
return wUnicode;
if (FXFT_Select_Charmap(GetFaceRec(), FT_ENCODING_UNICODE))
return 0;
return FT_Get_Char_Index(GetFaceRec(), wUnicode);
}
int32_t CFPF_SkiaFont::GetGlyphWidth(int32_t iGlyphIndex) {
if (!m_Face)
return 0;
if (FT_Load_Glyph(GetFaceRec(), iGlyphIndex,
FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) {
return 0;
}
return static_cast<int32_t>(
FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
FXFT_Get_Glyph_HoriAdvance(GetFaceRec())));
}
int32_t CFPF_SkiaFont::GetAscent() const {
if (!m_Face)
return 0;
return FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
FXFT_Get_Face_Ascender(GetFaceRec()));
}
int32_t CFPF_SkiaFont::GetDescent() const {
if (!m_Face)
return 0;
return FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
FXFT_Get_Face_Descender(GetFaceRec()));
}
bool CFPF_SkiaFont::GetGlyphBBox(int32_t iGlyphIndex, FX_RECT& rtBBox) {
if (!m_Face)
return false;
if (FXFT_Is_Face_Tricky(GetFaceRec())) {
if (FT_Set_Char_Size(GetFaceRec(), 0, 1000 * 64, 72, 72))
return false;
if (FT_Load_Glyph(GetFaceRec(), iGlyphIndex,
FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) {
FT_Set_Pixel_Sizes(GetFaceRec(), 0, 64);
return false;
}
FT_Glyph glyph;
if (FT_Get_Glyph(GetFaceRec()->glyph, &glyph)) {
FT_Set_Pixel_Sizes(GetFaceRec(), 0, 64);
return false;
}
FT_BBox cbox;
FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &cbox);
int32_t x_ppem = GetFaceRec()->size->metrics.x_ppem;
int32_t y_ppem = GetFaceRec()->size->metrics.y_ppem;
rtBBox.left = static_cast<int32_t>(FPF_EM_ADJUST(x_ppem, cbox.xMin));
rtBBox.right = static_cast<int32_t>(FPF_EM_ADJUST(x_ppem, cbox.xMax));
rtBBox.top = static_cast<int32_t>(FPF_EM_ADJUST(y_ppem, cbox.yMax));
rtBBox.bottom = static_cast<int32_t>(FPF_EM_ADJUST(y_ppem, cbox.yMin));
rtBBox.top = std::min(rtBBox.top, GetAscent());
rtBBox.bottom = std::max(rtBBox.bottom, GetDescent());
FT_Done_Glyph(glyph);
return FT_Set_Pixel_Sizes(GetFaceRec(), 0, 64) == 0;
}
if (FT_Load_Glyph(GetFaceRec(), iGlyphIndex,
FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) {
return false;
}
rtBBox.left = static_cast<int32_t>(
FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
FXFT_Get_Glyph_HoriBearingX(GetFaceRec())));
rtBBox.bottom = static_cast<int32_t>(
FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
FXFT_Get_Glyph_HoriBearingY(GetFaceRec())));
rtBBox.right = static_cast<int32_t>(
FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
FXFT_Get_Glyph_HoriBearingX(GetFaceRec()) +
FXFT_Get_Glyph_Width(GetFaceRec())));
rtBBox.top = static_cast<int32_t>(
FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
FXFT_Get_Glyph_HoriBearingY(GetFaceRec()) -
FXFT_Get_Glyph_Height(GetFaceRec())));
return true;
}
bool CFPF_SkiaFont::GetBBox(FX_RECT& rtBBox) {
if (!m_Face) {
return false;
}
rtBBox.left =
static_cast<int32_t>(FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
FXFT_Get_Face_xMin(GetFaceRec())));
rtBBox.top =
static_cast<int32_t>(FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
FXFT_Get_Face_yMin(GetFaceRec())));
rtBBox.right =
static_cast<int32_t>(FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
FXFT_Get_Face_xMax(GetFaceRec())));
rtBBox.bottom =
static_cast<int32_t>(FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
FXFT_Get_Face_yMax(GetFaceRec())));
return true;
}
int32_t CFPF_SkiaFont::GetHeight() const {
if (!m_Face)
return 0;
return FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
FXFT_Get_Face_Height(GetFaceRec()));
}
int32_t CFPF_SkiaFont::GetItalicAngle() const {
if (!m_Face)
return 0;
auto* info = static_cast<TT_Postscript*>(
FT_Get_Sfnt_Table(GetFaceRec(), ft_sfnt_post));
return info ? static_cast<int32_t>(info->italicAngle) : 0;
}
uint32_t CFPF_SkiaFont::GetFontData(uint32_t dwTable,
pdfium::span<uint8_t> pBuffer) {
if (!m_Face)
return 0;
FT_ULong ulSize = pdfium::base::checked_cast<FT_ULong>(pBuffer.size());
if (FT_Load_Sfnt_Table(GetFaceRec(), dwTable, 0, pBuffer.data(), &ulSize))
return 0;
return pdfium::base::checked_cast<uint32_t>(ulSize);
}