// Copyright 2019 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "core/fxge/cfx_folderfontinfo.h"

#include <utility>

#include "core/fxcrt/fx_codepage.h"
#include "core/fxge/fx_font.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

constexpr char kArial[] = "Arial";
constexpr char kCourierNew[] = "Courier New";
constexpr char kTimesNewRoman[] = "TimesNewRoman";
constexpr char kSymbol[] = "Symbol";
constexpr char kBookshelfSymbol7[] = "Bookshelf Symbol 7";
constexpr char kCalibri[] = "Calibri";
constexpr char kBookshelf[] = "Bookshelf";
constexpr char kBook[] = "Book";
constexpr char kTofuBold[] = "Tofu, Bold Italic";
constexpr char kTofu[] = "Tofu";
constexpr char kLatoUltraBold[] = "Lato Ultra-Bold";
constexpr char kLato[] = "Lato";
constexpr char kOxygenSansSansBold[] = "Oxygen-Sans Sans-Bold";
constexpr char kOxygenSans[] = "Oxygen-Sans";
constexpr char kOxygen[] = "Oxygen";
constexpr char kComicSansMS[] = "Comic Sans MS";

}  // namespace

class CFXFolderFontInfoTest : public ::testing::Test {
 public:
  CFXFolderFontInfoTest() {
    AddDummyFont(kArial, FX_CharsetFlag::kANSI);
    AddDummyFont(kCourierNew, FX_CharsetFlag::kANSI);
    AddDummyFont(kTimesNewRoman, FX_CharsetFlag::kNone);
    AddDummyFont(kBookshelfSymbol7, FX_CharsetFlag::kSymbol);
    AddDummyFont(kSymbol, FX_CharsetFlag::kSymbol);
    AddDummyFont(kTofuBold, FX_CharsetFlag::kSymbol);
    AddDummyFont(kLatoUltraBold, FX_CharsetFlag::kANSI);
    AddDummyFont(kOxygenSansSansBold, FX_CharsetFlag::kANSI);
    AddDummyFont(kComicSansMS, FX_CharsetFlag::kANSI);
  }

  void* FindFont(int weight,
                 bool bItalic,
                 FX_Charset charset,
                 int pitch_family,
                 const char* family,
                 bool bMatchName) {
    return font_info_.FindFont(weight, bItalic, charset, pitch_family, family,
                               bMatchName);
  }

  ByteString GetFaceName(void* font) {
    return static_cast<CFX_FolderFontInfo::FontFaceInfo*>(font)->face_name_;
  }

 private:
  void AddDummyFont(const char* font_name, FX_CharsetFlag charset) {
    auto info = std::make_unique<CFX_FolderFontInfo::FontFaceInfo>(
        /*filePath=*/"", font_name, /*fontTables=*/"",
        /*fontOffset=*/0, /*fileSize=*/0);
    info->charsets_ = charset;
    font_info_.font_list_[font_name] = std::move(info);
  }

  CFX_FolderFontInfo font_info_;
};

TEST_F(CFXFolderFontInfoTest, TestFindFont) {
  // Find "Symbol" font
  void* font = FindFont(/*weight=*/0, /*bItalic=*/false, FX_Charset::kSymbol,
                        pdfium::kFontPitchFamilyRoman, kSymbol,
                        /*bMatchName=*/true);
  ASSERT_TRUE(font);
  EXPECT_EQ(GetFaceName(font), kSymbol);

  // Find "Calibri" font that is not present in the installed fonts
  EXPECT_FALSE(FindFont(/*weight=*/0, /*bItalic=*/false, FX_Charset::kSymbol,
                        pdfium::kFontPitchFamilyRoman, kCalibri,
                        /*bMatchName=*/true));

  // Find the closest matching font to "Bookshelf" font that is present in the
  // installed fonts
  font = FindFont(/*weight=*/0, /*bItalic=*/false, FX_Charset::kSymbol,
                  pdfium::kFontPitchFamilyRoman, kBookshelf,
                  /*bMatchName=*/true);
  ASSERT_TRUE(font);
  EXPECT_EQ(GetFaceName(font), kBookshelfSymbol7);

  // Find "Book" font is expected to fail, because none of the installed fonts
  // is in the same font family.
  EXPECT_FALSE(FindFont(/*weight=*/0, /*bItalic=*/false, FX_Charset::kSymbol,
                        pdfium::kFontPitchFamilyRoman, kBook,
                        /*bMatchName=*/true));

  // Find the closest matching font for "Tofu" in the installed fonts, which
  // has "," following the string "Tofu".
  font = FindFont(/*weight=*/0, /*bItalic=*/false, FX_Charset::kSymbol,
                  pdfium::kFontPitchFamilyRoman, kTofu,
                  /*bMatchName=*/true);
  ASSERT_TRUE(font);
  EXPECT_EQ(GetFaceName(font), kTofuBold);

  // Find the closest matching font for "Lato" in the installed fonts, which
  // has a space character following the string "Lato".
  font = FindFont(/*weight=*/0, /*bItalic=*/false, FX_Charset::kANSI,
                  pdfium::kFontPitchFamilyRoman, kLato,
                  /*bMatchName=*/true);
  ASSERT_TRUE(font);
  EXPECT_EQ(GetFaceName(font), kLatoUltraBold);

  // Find the closest matching font for "Oxygen" in the installed fonts,
  // which has "-" following the string "Oxygen".
  font = FindFont(/*weight=*/0, /*bItalic=*/false, FX_Charset::kANSI,
                  pdfium::kFontPitchFamilyRoman, kOxygen,
                  /*bMatchName=*/true);
  ASSERT_TRUE(font);
  EXPECT_EQ(GetFaceName(font), kOxygenSansSansBold);

  // Find the closest matching font for "Oxygen-Sans" in the installed fonts,
  // to test matching a family name with "-".
  font = FindFont(/*weight=*/0, /*bItalic=*/false, FX_Charset::kANSI,
                  pdfium::kFontPitchFamilyRoman, kOxygenSans,
                  /*bMatchName=*/true);
  ASSERT_TRUE(font);
  EXPECT_EQ(GetFaceName(font), kOxygenSansSansBold);

  // Find "Symbol" font when name matching is false
  font = FindFont(/*weight=*/0, /*bItalic=*/false, FX_Charset::kSymbol,
                  pdfium::kFontPitchFamilyRoman, kSymbol,
                  /*bMatchName=*/false);
  ASSERT_TRUE(font);
  EXPECT_EQ(GetFaceName(font), kBookshelfSymbol7);

  font = FindFont(700, false, FX_Charset::kANSI, pdfium::kFontPitchFamilyFixed,
                  kComicSansMS, true);
  ASSERT_TRUE(font);
  EXPECT_EQ(GetFaceName(font), kComicSansMS);
}
