1// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "fx_fpf.h"
8
9#include <algorithm>
10
11#if _FX_OS_ == _FX_ANDROID_
12#include "fpf_skiafont.h"
13#include "fpf_skiafontmgr.h"
14#define FPF_EM_ADJUST(em, a) (em == 0 ? (a) : (a)*1000 / em)
15CFPF_SkiaFont::CFPF_SkiaFont()
16    : m_pFontMgr(NULL),
17      m_pFontDes(NULL),
18      m_Face(NULL),
19      m_dwStyle(0),
20      m_uCharset(0),
21      m_dwRefCount(0) {}
22CFPF_SkiaFont::~CFPF_SkiaFont() {
23  if (m_Face) {
24    FXFT_Done_Face(m_Face);
25  }
26}
27void CFPF_SkiaFont::Release() {
28  if (--m_dwRefCount == 0) {
29    delete this;
30  }
31}
32IFPF_Font* CFPF_SkiaFont::Retain() {
33  m_dwRefCount++;
34  return (IFPF_Font*)this;
35}
36FPF_HFONT CFPF_SkiaFont::GetHandle() {
37  return NULL;
38}
39CFX_ByteString CFPF_SkiaFont::GetFamilyName() {
40  if (!m_Face) {
41    return CFX_ByteString();
42  }
43  return CFX_ByteString(FXFT_Get_Face_Family_Name(m_Face));
44}
45CFX_WideString CFPF_SkiaFont::GetPsName() {
46  if (!m_Face) {
47    return CFX_WideString();
48  }
49  return CFX_WideString::FromLocal(FXFT_Get_Postscript_Name(m_Face));
50}
51int32_t CFPF_SkiaFont::GetGlyphIndex(FX_WCHAR wUnicode) {
52  if (!m_Face) {
53    return wUnicode;
54  }
55  if (FXFT_Select_Charmap(m_Face, FXFT_ENCODING_UNICODE)) {
56    return 0;
57  }
58  return FXFT_Get_Char_Index(m_Face, wUnicode);
59}
60int32_t CFPF_SkiaFont::GetGlyphWidth(int32_t iGlyphIndex) {
61  if (!m_Face) {
62    return 0;
63  }
64  if (FXFT_Load_Glyph(
65          m_Face, iGlyphIndex,
66          FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) {
67    return 0;
68  }
69  return FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face),
70                       FXFT_Get_Glyph_HoriAdvance(m_Face));
71}
72int32_t CFPF_SkiaFont::GetAscent() const {
73  if (!m_Face) {
74    return 0;
75  }
76  return FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face),
77                       FXFT_Get_Face_Ascender(m_Face));
78}
79int32_t CFPF_SkiaFont::GetDescent() const {
80  if (!m_Face) {
81    return 0;
82  }
83  return FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face),
84                       FXFT_Get_Face_Descender(m_Face));
85}
86FX_BOOL CFPF_SkiaFont::GetGlyphBBox(int32_t iGlyphIndex, FX_RECT& rtBBox) {
87  if (!m_Face) {
88    return FALSE;
89  }
90  if (FXFT_Is_Face_Tricky(m_Face)) {
91    if (FXFT_Set_Char_Size(m_Face, 0, 1000 * 64, 72, 72)) {
92      return FALSE;
93    }
94    if (FXFT_Load_Glyph(m_Face, iGlyphIndex,
95                        FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) {
96      FXFT_Set_Pixel_Sizes(m_Face, 0, 64);
97      return FALSE;
98    }
99    FXFT_Glyph glyph;
100    if (FXFT_Get_Glyph(m_Face->glyph, &glyph)) {
101      FXFT_Set_Pixel_Sizes(m_Face, 0, 64);
102      return FALSE;
103    }
104    FXFT_BBox cbox;
105    FXFT_Glyph_Get_CBox(glyph, FXFT_GLYPH_BBOX_PIXELS, &cbox);
106    int32_t x_ppem = m_Face->size->metrics.x_ppem;
107    int32_t y_ppem = m_Face->size->metrics.y_ppem;
108    rtBBox.left = FPF_EM_ADJUST(x_ppem, cbox.xMin);
109    rtBBox.right = FPF_EM_ADJUST(x_ppem, cbox.xMax);
110    rtBBox.top = FPF_EM_ADJUST(y_ppem, cbox.yMax);
111    rtBBox.bottom = FPF_EM_ADJUST(y_ppem, cbox.yMin);
112    rtBBox.top = std::min(rtBBox.top, GetAscent());
113    rtBBox.bottom = std::max(rtBBox.bottom, GetDescent());
114    FXFT_Done_Glyph(glyph);
115    return FXFT_Set_Pixel_Sizes(m_Face, 0, 64) == 0;
116  }
117  if (FXFT_Load_Glyph(
118          m_Face, iGlyphIndex,
119          FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) {
120    return FALSE;
121  }
122  rtBBox.left = FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face),
123                              FXFT_Get_Glyph_HoriBearingX(m_Face));
124  rtBBox.bottom = FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face),
125                                FXFT_Get_Glyph_HoriBearingY(m_Face));
126  rtBBox.right = FPF_EM_ADJUST(
127      FXFT_Get_Face_UnitsPerEM(m_Face),
128      FXFT_Get_Glyph_HoriBearingX(m_Face) + FXFT_Get_Glyph_Width(m_Face));
129  rtBBox.top = FPF_EM_ADJUST(
130      FXFT_Get_Face_UnitsPerEM(m_Face),
131      FXFT_Get_Glyph_HoriBearingY(m_Face) - FXFT_Get_Glyph_Height(m_Face));
132  return TRUE;
133}
134FX_BOOL CFPF_SkiaFont::GetBBox(FX_RECT& rtBBox) {
135  if (!m_Face) {
136    return FALSE;
137  }
138  rtBBox.left = FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face),
139                              FXFT_Get_Face_xMin(m_Face));
140  rtBBox.top = FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face),
141                             FXFT_Get_Face_yMin(m_Face));
142  rtBBox.right = FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face),
143                               FXFT_Get_Face_xMax(m_Face));
144  rtBBox.bottom = FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face),
145                                FXFT_Get_Face_yMax(m_Face));
146  return TRUE;
147}
148int32_t CFPF_SkiaFont::GetHeight() const {
149  if (!m_Face) {
150    return 0;
151  }
152  return FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face),
153                       FXFT_Get_Face_Height(m_Face));
154}
155int32_t CFPF_SkiaFont::GetItalicAngle() const {
156  if (!m_Face) {
157    return 0;
158  }
159  TT_Postscript* ttInfo =
160      (TT_Postscript*)FT_Get_Sfnt_Table(m_Face, ft_sfnt_post);
161  if (ttInfo) {
162    return ttInfo->italicAngle;
163  }
164  return 0;
165}
166FX_DWORD CFPF_SkiaFont::GetFontData(FX_DWORD dwTable,
167                                    uint8_t* pBuffer,
168                                    FX_DWORD dwSize) {
169  if (!m_Face) {
170    return 0;
171  }
172  FT_ULong ulSize = pdfium::base::checked_cast<FT_ULong>(dwSize);
173  if (FXFT_Load_Sfnt_Table(m_Face, dwTable, 0, pBuffer, &ulSize)) {
174    return 0;
175  }
176  return pdfium::base::checked_cast<FX_DWORD>(ulSize);
177}
178FX_BOOL CFPF_SkiaFont::InitFont(CFPF_SkiaFontMgr* pFontMgr,
179                                CFPF_SkiaFontDescriptor* pFontDes,
180                                const CFX_ByteStringC& bsFamily,
181                                FX_DWORD dwStyle,
182                                uint8_t uCharset) {
183  if (!pFontMgr || !pFontDes) {
184    return FALSE;
185  }
186  switch (pFontDes->GetType()) {
187    case FPF_SKIAFONTTYPE_Path: {
188      CFPF_SkiaPathFont* pFont = (CFPF_SkiaPathFont*)pFontDes;
189      m_Face = pFontMgr->GetFontFace(pFont->m_pPath, pFont->m_iFaceIndex);
190    } break;
191    case FPF_SKIAFONTTYPE_File: {
192      CFPF_SkiaFileFont* pFont = (CFPF_SkiaFileFont*)pFontDes;
193      m_Face = pFontMgr->GetFontFace(pFont->m_pFile, pFont->m_iFaceIndex);
194    } break;
195    case FPF_SKIAFONTTYPE_Buffer: {
196      CFPF_SkiaBufferFont* pFont = (CFPF_SkiaBufferFont*)pFontDes;
197      m_Face = pFontMgr->GetFontFace((const uint8_t*)pFont->m_pBuffer,
198                                     pFont->m_szBuffer, pFont->m_iFaceIndex);
199    } break;
200    default:
201      return FALSE;
202  }
203  if (!m_Face) {
204    return FALSE;
205  }
206  m_dwStyle = dwStyle;
207  m_uCharset = uCharset;
208  m_pFontMgr = pFontMgr;
209  m_pFontDes = pFontDes;
210  m_dwRefCount = 1;
211  return TRUE;
212}
213#endif
214