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

#include "xfa/fde/cfde_textout.h"

#include <memory>

#include "build/build_config.h"
#include "core/fdrm/fx_crypt.h"
#include "core/fxcrt/bytestring.h"
#include "core/fxcrt/fx_codepage.h"
#include "core/fxcrt/fx_coordinates.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxge/cfx_defaultrenderdevice.h"
#include "core/fxge/cfx_gemodule.h"
#include "core/fxge/cfx_glyphcache.h"
#include "core/fxge/dib/cfx_dibitmap.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/utils/hash.h"
#include "xfa/fgas/font/cfgas_fontmgr.h"
#include "xfa/fgas/font/cfgas_gefont.h"
#include "xfa/fgas/font/cfgas_gemodule.h"

namespace pdfium {

class CFDETextOutTest : public testing::Test {
 public:
  CFDETextOutTest() = default;
  ~CFDETextOutTest() override = default;

  void SetUp() override {
    CFX_Size bitmap_size = GetBitmapSize();
    bitmap_ = MakeRetain<CFX_DIBitmap>();
    ASSERT_TRUE(bitmap_->Create(bitmap_size.width, bitmap_size.height,
                                FXDIB_Format::kBgra));

    device_ = std::make_unique<CFX_DefaultRenderDevice>();
    ASSERT_TRUE(device_->Attach(bitmap_));

    font_ = LoadFont();
    ASSERT_TRUE(font_);

    text_out_ = std::make_unique<CFDE_TextOut>();
    text_out_->SetFont(font_);
    text_out_->SetFontSize(12.0f);

    EXPECT_EQ(GetEmptyBitmapChecksum(), GetBitmapChecksum());
  }

  void TearDown() override {
    // reverse order form SetUp()
    text_out_.reset();
    font_.Reset();
    device_.reset();
    bitmap_.Reset();
  }

  virtual RetainPtr<CFGAS_GEFont> LoadFont() {
    const wchar_t kFontFamily[] = L"Arimo Bold";
    return CFGAS_GEFont::LoadFont(kFontFamily, /*dwFontStyles=*/0,
                                  FX_CodePage::kDefANSI);
  }

  virtual CFX_Size GetBitmapSize() { return CFX_Size(200, 100); }

  virtual const char* GetEmptyBitmapChecksum() {
    static const char kEmptyBitmapChecksum[] =
        "a042237c5493fdb9656b94a83608d11a";
    return kEmptyBitmapChecksum;
  }

  CFX_DefaultRenderDevice* device() { return device_.get(); }
  CFDE_TextOut& text_out() { return *text_out_; }

  ByteString GetBitmapChecksum() {
    CryptMd5Context context = CryptMd5Start();
    for (int i = 0; i < bitmap_->GetHeight(); ++i) {
      CryptMd5Update(&context, bitmap_->GetScanline(i));
    }
    uint8_t digest[16];
    CryptMd5Finish(&context, digest);
    return ByteString(CryptToBase16(digest).c_str());
  }

 private:
  RetainPtr<CFX_DIBitmap> bitmap_;
  std::unique_ptr<CFX_DefaultRenderDevice> device_;
  RetainPtr<CFGAS_GEFont> font_;
  std::unique_ptr<CFDE_TextOut> text_out_;
};

TEST_F(CFDETextOutTest, DrawLogicTextBasic) {
  text_out().DrawLogicText(device(), L"foo", CFX_RectF(0, 0, 2100, 100));
  const char* checksum = []() {
#if defined(PDF_USE_SKIA) && BUILDFLAG(IS_WIN)
    if (CFX_GEModule::Get()->UseSkiaRenderer()) {
      return "bc1f736237b08d13db06c09f6becc9f7";
    }
#endif
    return "c143f8450f661a489cc9423de7cc1acc";
  }();
  EXPECT_EQ(checksum, GetBitmapChecksum());
}

TEST_F(CFDETextOutTest, DrawLogicTextEmptyRect) {
  text_out().DrawLogicText(device(), L"foo", CFX_RectF());
  EXPECT_EQ(GetEmptyBitmapChecksum(), GetBitmapChecksum());
}

#if !BUILDFLAG(IS_WIN)
// This test depends on a particular font being present.
class CFDETextOutLargeBitmapTest : public CFDETextOutTest {
 public:
  CFDETextOutLargeBitmapTest() = default;
  ~CFDETextOutLargeBitmapTest() override = default;

  RetainPtr<CFGAS_GEFont> LoadFont() override {
    const wchar_t kFontFamily[] = L"DejaVu Sans";
    auto* font_manager = CFGAS_GEModule::Get()->GetFontMgr();
    return font_manager->LoadFont(kFontFamily, /*dwFontStyles=*/0,
                                  FX_CodePage::kFailure);
  }

  CFX_Size GetBitmapSize() override { return CFX_Size(2100, 20); }

  const char* GetEmptyBitmapChecksum() override {
    static const char kEmptyLargeBitmapChecksum[] =
        "101745f76351fd5d916bf3817b71563c";
    return kEmptyLargeBitmapChecksum;
  }

  const char* GetLargeTextBlobChecksum() {
#if defined(PDF_USE_SKIA)
    if (CFX_GEModule::Get()->UseSkiaRenderer()) {
      return "e9aaffff1ea680bd5dc40a7b8904788d";
    }
#endif
    return "add7cf2819b3e1397d8a60a9ec436a86";
  }
};

TEST_F(CFDETextOutLargeBitmapTest, DrawLogicTextBug953881) {
  FDE_TextStyle styles;
  styles.single_line_ = true;
  text_out().SetStyles(styles);
  text_out().SetAlignment(FDE_TextAlignment::kCenterLeft);
  text_out().SetFontSize(10.0f);

  static const wchar_t kText[] =
      L"SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"
      L"SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSssssssssss"
      L"sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
      L"sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
      L"sssssssssssssssssssssssssssssssssssssssssssssssssnnnnnnnnnnn"
      "\xfeba"
      L"Sssssssssssssssssss"
      "\xfeba"
      L"iiiiisssss";
  text_out().DrawLogicText(device(), WideString(kText),
                           CFX_RectF(3, 3, 2048, 10));
  EXPECT_EQ(GetLargeTextBlobChecksum(), GetBitmapChecksum());
}

TEST_F(CFDETextOutLargeBitmapTest, DrawLogicTextBug1342078) {
  FDE_TextStyle styles;
  styles.single_line_ = true;
  text_out().SetStyles(styles);
  text_out().SetAlignment(FDE_TextAlignment::kCenterLeft);
  text_out().SetFontSize(10.0f);

  static const wchar_t kText[] =
      L"SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"
      L"SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSssssssssss"
      L"sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
      L"sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
      L"sssssssssssssssssssssssssssssssssssssssssssssssssnnnnnnnnnnn"
      "\xfeba"
      L"Sssssssssssssssssss"
      "\xfeba"
      L"iiiiiiiiiisssss";
  text_out().DrawLogicText(device(), WideString(kText),
                           CFX_RectF(3, 3, 2048, 10));
  EXPECT_EQ(GetLargeTextBlobChecksum(), GetBitmapChecksum());
}
#endif  // !BUILDFLAG(IS_WIN)

}  // namespace pdfium
