| // 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); |
| } |