| // 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 m_Face->GetFamilyName(); |
| } |
| |
| 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( |
| m_Face->GetUnitsPerEm(), FXFT_Get_Glyph_HoriAdvance(GetFaceRec()))); |
| } |
| |
| int32_t CFPF_SkiaFont::GetAscent() const { |
| if (!m_Face) |
| return 0; |
| return FPF_EM_ADJUST(m_Face->GetUnitsPerEm(), m_Face->GetAscender()); |
| } |
| |
| int32_t CFPF_SkiaFont::GetDescent() const { |
| if (!m_Face) |
| return 0; |
| return FPF_EM_ADJUST(m_Face->GetUnitsPerEm(), m_Face->GetDescender()); |
| } |
| |
| bool CFPF_SkiaFont::GetGlyphBBox(int32_t iGlyphIndex, FX_RECT& rtBBox) { |
| if (!m_Face) |
| return false; |
| if (m_Face->IsTricky()) { |
| 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; |
| } |
| const uint16_t em = m_Face->GetUnitsPerEm(); |
| rtBBox.left = static_cast<int32_t>( |
| FPF_EM_ADJUST(em, FXFT_Get_Glyph_HoriBearingX(GetFaceRec()))); |
| rtBBox.bottom = static_cast<int32_t>( |
| FPF_EM_ADJUST(em, FXFT_Get_Glyph_HoriBearingY(GetFaceRec()))); |
| rtBBox.right = static_cast<int32_t>( |
| FPF_EM_ADJUST(em, FXFT_Get_Glyph_HoriBearingX(GetFaceRec()) + |
| FXFT_Get_Glyph_Width(GetFaceRec()))); |
| rtBBox.top = static_cast<int32_t>( |
| FPF_EM_ADJUST(em, FXFT_Get_Glyph_HoriBearingY(GetFaceRec()) - |
| FXFT_Get_Glyph_Height(GetFaceRec()))); |
| return true; |
| } |
| |
| bool CFPF_SkiaFont::GetBBox(FX_RECT& rtBBox) { |
| if (!m_Face) { |
| return false; |
| } |
| |
| const uint16_t em = m_Face->GetUnitsPerEm(); |
| const FX_RECT raw_bbox = m_Face->GetBBox(); |
| rtBBox.left = static_cast<int32_t>(FPF_EM_ADJUST(em, raw_bbox.left)); |
| rtBBox.top = static_cast<int32_t>(FPF_EM_ADJUST(em, raw_bbox.top)); |
| rtBBox.right = static_cast<int32_t>(FPF_EM_ADJUST(em, raw_bbox.right)); |
| rtBBox.bottom = static_cast<int32_t>(FPF_EM_ADJUST(em, raw_bbox.bottom)); |
| return true; |
| } |
| |
| int32_t CFPF_SkiaFont::GetHeight() const { |
| if (!m_Face) |
| return 0; |
| return FPF_EM_ADJUST(m_Face->GetUnitsPerEm(), m_Face->GetHeight()); |
| } |
| |
| 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); |
| } |