// Copyright 2016 PDFium Authors. All rights reserved.
// 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/fpdfapi/font/cpdf_truetypefont.h"

#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fxge/fx_font.h"

namespace {

const uint8_t kPrefix[4] = {0x00, 0xf0, 0xf1, 0xf2};

}  // namespace

CPDF_TrueTypeFont::CPDF_TrueTypeFont(CPDF_Document* pDocument,
                                     CPDF_Dictionary* pFontDict)
    : CPDF_SimpleFont(pDocument, pFontDict) {}

CPDF_TrueTypeFont::~CPDF_TrueTypeFont() = default;

bool CPDF_TrueTypeFont::IsTrueTypeFont() const {
  return true;
}

const CPDF_TrueTypeFont* CPDF_TrueTypeFont::AsTrueTypeFont() const {
  return this;
}

CPDF_TrueTypeFont* CPDF_TrueTypeFont::AsTrueTypeFont() {
  return this;
}

bool CPDF_TrueTypeFont::Load() {
  return LoadCommon();
}

void CPDF_TrueTypeFont::LoadGlyphMap() {
  if (!m_Font.GetFace())
    return;

  int baseEncoding = m_BaseEncoding;
  if (m_pFontFile && m_Font.GetFace()->num_charmaps > 0 &&
      (baseEncoding == PDFFONT_ENCODING_MACROMAN ||
       baseEncoding == PDFFONT_ENCODING_WINANSI) &&
      FontStyleIsSymbolic(m_Flags)) {
    bool bSupportWin = false;
    bool bSupportMac = false;
    for (int i = 0; i < FXFT_Get_Face_CharmapCount(m_Font.GetFace()); i++) {
      int platform_id = FXFT_Get_Charmap_PlatformID(
          FXFT_Get_Face_Charmaps(m_Font.GetFace())[i]);
      if (platform_id == 0 || platform_id == 3) {
        bSupportWin = true;
      } else if (platform_id == 0 || platform_id == 1) {
        bSupportMac = true;
      }
    }
    if (baseEncoding == PDFFONT_ENCODING_WINANSI && !bSupportWin) {
      baseEncoding =
          bSupportMac ? PDFFONT_ENCODING_MACROMAN : PDFFONT_ENCODING_BUILTIN;
    } else if (baseEncoding == PDFFONT_ENCODING_MACROMAN && !bSupportMac) {
      baseEncoding =
          bSupportWin ? PDFFONT_ENCODING_WINANSI : PDFFONT_ENCODING_BUILTIN;
    }
  }
  if (((baseEncoding == PDFFONT_ENCODING_MACROMAN ||
        baseEncoding == PDFFONT_ENCODING_WINANSI) &&
       m_CharNames.empty()) ||
      FontStyleIsNonSymbolic(m_Flags)) {
    if (!FXFT_Has_Glyph_Names(m_Font.GetFace()) &&
        (!m_Font.GetFace()->num_charmaps || !m_Font.GetFace()->charmaps)) {
      int nStartChar = m_pFontDict->GetIntegerFor("FirstChar");
      if (nStartChar < 0 || nStartChar > 255)
        return;

      int charcode = 0;
      for (; charcode < nStartChar; charcode++)
        m_GlyphIndex[charcode] = 0;
      uint16_t nGlyph = charcode - nStartChar + 3;
      for (; charcode < 256; charcode++, nGlyph++)
        m_GlyphIndex[charcode] = nGlyph;
      return;
    }
    bool bMSUnicode = FT_UseTTCharmap(m_Font.GetFace(), 3, 1);
    bool bMacRoman = false;
    bool bMSSymbol = false;
    if (!bMSUnicode) {
      if (FontStyleIsNonSymbolic(m_Flags)) {
        bMacRoman = FT_UseTTCharmap(m_Font.GetFace(), 1, 0);
        bMSSymbol = !bMacRoman && FT_UseTTCharmap(m_Font.GetFace(), 3, 0);
      } else {
        bMSSymbol = FT_UseTTCharmap(m_Font.GetFace(), 3, 0);
        bMacRoman = !bMSSymbol && FT_UseTTCharmap(m_Font.GetFace(), 1, 0);
      }
    }
    bool bToUnicode = m_pFontDict->KeyExist("ToUnicode");
    for (uint32_t charcode = 0; charcode < 256; charcode++) {
      const char* name = GetAdobeCharName(baseEncoding, m_CharNames, charcode);
      if (!name) {
        m_GlyphIndex[charcode] =
            m_pFontFile ? FT_Get_Char_Index(m_Font.GetFace(), charcode) : -1;
        continue;
      }
      m_Encoding.SetUnicode(charcode, PDF_UnicodeFromAdobeName(name));
      if (bMSSymbol) {
        for (size_t j = 0; j < FX_ArraySize(kPrefix); j++) {
          uint16_t unicode = kPrefix[j] * 256 + charcode;
          m_GlyphIndex[charcode] = FT_Get_Char_Index(m_Font.GetFace(), unicode);
          if (m_GlyphIndex[charcode])
            break;
        }
      } else if (m_Encoding.UnicodeFromCharCode(charcode)) {
        if (bMSUnicode) {
          m_GlyphIndex[charcode] = FT_Get_Char_Index(
              m_Font.GetFace(), m_Encoding.UnicodeFromCharCode(charcode));
        } else if (bMacRoman) {
          uint32_t maccode =
              FT_CharCodeFromUnicode(FT_ENCODING_APPLE_ROMAN,
                                     m_Encoding.UnicodeFromCharCode(charcode));
          if (!maccode) {
            m_GlyphIndex[charcode] =
                FXFT_Get_Name_Index(m_Font.GetFace(), name);
          } else {
            m_GlyphIndex[charcode] =
                FT_Get_Char_Index(m_Font.GetFace(), maccode);
          }
        }
      }
      if ((m_GlyphIndex[charcode] != 0 && m_GlyphIndex[charcode] != 0xffff) ||
          !name) {
        continue;
      }
      if (strcmp(name, ".notdef") == 0) {
        m_GlyphIndex[charcode] = FT_Get_Char_Index(m_Font.GetFace(), 32);
        continue;
      }
      m_GlyphIndex[charcode] = FXFT_Get_Name_Index(m_Font.GetFace(), name);
      if (m_GlyphIndex[charcode] != 0 || !bToUnicode)
        continue;

      WideString wsUnicode = UnicodeFromCharCode(charcode);
      if (!wsUnicode.IsEmpty()) {
        m_GlyphIndex[charcode] =
            FT_Get_Char_Index(m_Font.GetFace(), wsUnicode[0]);
        m_Encoding.SetUnicode(charcode, wsUnicode[0]);
      }
    }
    return;
  }
  if (FT_UseTTCharmap(m_Font.GetFace(), 3, 0)) {
    bool bFound = false;
    for (int charcode = 0; charcode < 256; charcode++) {
      for (size_t j = 0; j < FX_ArraySize(kPrefix); j++) {
        uint16_t unicode = kPrefix[j] * 256 + charcode;
        m_GlyphIndex[charcode] = FT_Get_Char_Index(m_Font.GetFace(), unicode);
        if (m_GlyphIndex[charcode]) {
          bFound = true;
          break;
        }
      }
    }
    if (bFound) {
      if (baseEncoding != PDFFONT_ENCODING_BUILTIN) {
        for (uint32_t charcode = 0; charcode < 256; charcode++) {
          const char* name =
              GetAdobeCharName(baseEncoding, m_CharNames, charcode);
          if (name)
            m_Encoding.SetUnicode(charcode, PDF_UnicodeFromAdobeName(name));
        }
      } else if (FT_UseTTCharmap(m_Font.GetFace(), 1, 0)) {
        for (int charcode = 0; charcode < 256; charcode++) {
          m_Encoding.SetUnicode(
              charcode,
              FT_UnicodeFromCharCode(FT_ENCODING_APPLE_ROMAN, charcode));
        }
      }
      return;
    }
  }
  if (FT_UseTTCharmap(m_Font.GetFace(), 1, 0)) {
    bool bFound = false;
    for (int charcode = 0; charcode < 256; charcode++) {
      m_GlyphIndex[charcode] = FT_Get_Char_Index(m_Font.GetFace(), charcode);
      m_Encoding.SetUnicode(
          charcode, FT_UnicodeFromCharCode(FT_ENCODING_APPLE_ROMAN, charcode));
      if (m_GlyphIndex[charcode]) {
        bFound = true;
      }
    }
    if (m_pFontFile || bFound)
      return;
  }
  if (FXFT_Select_Charmap(m_Font.GetFace(), FT_ENCODING_UNICODE) == 0) {
    bool bFound = false;
    const uint16_t* pUnicodes = PDF_UnicodesForPredefinedCharSet(baseEncoding);
    for (uint32_t charcode = 0; charcode < 256; charcode++) {
      if (m_pFontFile) {
        m_Encoding.SetUnicode(charcode, charcode);
      } else {
        const char* name = GetAdobeCharName(0, m_CharNames, charcode);
        if (name)
          m_Encoding.SetUnicode(charcode, PDF_UnicodeFromAdobeName(name));
        else if (pUnicodes)
          m_Encoding.SetUnicode(charcode, pUnicodes[charcode]);
      }
      m_GlyphIndex[charcode] = FT_Get_Char_Index(
          m_Font.GetFace(), m_Encoding.UnicodeFromCharCode(charcode));
      if (m_GlyphIndex[charcode])
        bFound = true;
    }
    if (bFound)
      return;
  }
  for (int charcode = 0; charcode < 256; charcode++)
    m_GlyphIndex[charcode] = charcode;
}
