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