// static
CFGAS_GEFont* CFGAS_GEFont::LoadFont(CFX_Font* pExtFont,
                                     IFGAS_FontMgr* pFontMgr) {
  CFGAS_GEFont* pFont = new CFGAS_GEFont(pFontMgr);
  if (!pFont->LoadFontInternal(pExtFont)) {
    pFont->Release();
    return nullptr;
  }
  return pFont;
}
// static
CFGAS_GEFont* CFGAS_GEFont::LoadFont(IFX_Stream* pFontStream,
                                     IFGAS_FontMgr* pFontMgr,
                                     FX_BOOL bSaveStream) {
  CFGAS_GEFont* pFont = new CFGAS_GEFont(pFontMgr);
  if (!pFont->LoadFontInternal(pFontStream, bSaveStream)) {
    pFont->Release();
    return nullptr;
  }
  return pFont;
}
// static
CFGAS_GEFont* CFGAS_GEFont::LoadFont(const uint8_t* pBuffer,
                                     int32_t iLength,
                                     IFGAS_FontMgr* pFontMgr) {
  CFGAS_GEFont* pFont = new CFGAS_GEFont(pFontMgr);
  if (!pFont->LoadFontInternal(pBuffer, iLength)) {
    pFont->Release();
    return nullptr;
  }
  return pFont;
}
// static
CFGAS_GEFont* CFGAS_GEFont::LoadFont(const FX_WCHAR* pszFontFamily,
                                     uint32_t dwFontStyles,
                                     uint16_t wCodePage,
                                     IFGAS_FontMgr* pFontMgr) {
#if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
  if (pFontMgr) {
    return pFontMgr->GetFontByCodePage(wCodePage, dwFontStyles, pszFontFamily);
  }
  return nullptr;
#else
  CFGAS_GEFont* pFont = new CFGAS_GEFont(pFontMgr);
  if (!pFont->LoadFontInternal(pszFontFamily, dwFontStyles, wCodePage)) {
    pFont->Release();
    return nullptr;
  }
  return pFont;
#endif
}
int32_t CFGAS_GEFont::GetGlyphIndex(FX_WCHAR wUnicode,
                                    FX_BOOL bRecursive,
                                    CFGAS_GEFont** ppFont,
                                    FX_BOOL bCharCode) {
  ASSERT(m_pFontEncoding);
  int32_t iGlyphIndex = m_pFontEncoding->GlyphFromCharCode(wUnicode);
  if (iGlyphIndex > 0) {
    if (ppFont) {
      *ppFont = this;
    }
    return iGlyphIndex;
  }
  const FGAS_FONTUSB* pFontUSB = FGAS_GetUnicodeBitField(wUnicode);
  if (!pFontUSB) {
    return 0xFFFF;
  }
  uint16_t wBitField = pFontUSB->wBitField;
  if (wBitField >= 128) {
    return 0xFFFF;
  }
  auto it = m_FontMapper.find(wUnicode);
  CFGAS_GEFont* pFont = it != m_FontMapper.end() ? it->second : nullptr;
  if (pFont && pFont != this) {
    iGlyphIndex = pFont->GetGlyphIndex(wUnicode, FALSE, nullptr, bCharCode);
    if (iGlyphIndex != 0xFFFF) {
      int32_t i = m_SubstFonts.Find(pFont);
      if (i > -1) {
        iGlyphIndex |= ((i + 1) << 24);
        if (ppFont)
          *ppFont = pFont;
        return iGlyphIndex;
      }
    }
  }
  if (m_pFontMgr && bRecursive) {
    CFX_WideString wsFamily;
    GetFamilyName(wsFamily);
#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    CFGAS_GEFont* pFont = m_pFontMgr->GetDefFontByUnicode(
        wUnicode, GetFontStyles(), wsFamily.c_str());
#else
    CFGAS_GEFont* pFont = m_pFontMgr->GetFontByUnicode(
        wUnicode, GetFontStyles(), wsFamily.c_str());
    if (!pFont)
      pFont = m_pFontMgr->GetFontByUnicode(wUnicode, GetFontStyles(), nullptr);
#endif
    if (pFont) {
      if (pFont == this) {
        pFont->Release();
        return 0xFFFF;
      }
      m_FontMapper[wUnicode] = pFont;
      int32_t i = m_SubstFonts.GetSize();
      m_SubstFonts.Add(pFont);
      iGlyphIndex = pFont->GetGlyphIndex(wUnicode, FALSE, nullptr, bCharCode);
      if (iGlyphIndex != 0xFFFF) {
        iGlyphIndex |= ((i + 1) << 24);
        if (ppFont)
          *ppFont = pFont;
        return iGlyphIndex;
      }
    }
  }
  return 0xFFFF;
}