// 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/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"

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

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

    device_ = std::make_unique<CFX_DefaultRenderDevice>();
    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_STREQ(GetEmptyBitmapChecksum(), GetBitmapChecksum().c_str());
  }

  void TearDown() override {
    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() {
    CRYPT_md5_context context = CRYPT_MD5Start();
    for (int i = 0; i < bitmap_->GetHeight(); ++i)
      CRYPT_MD5Update(&context, bitmap_->GetScanline(i));
    uint8_t digest[16];
    CRYPT_MD5Finish(&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));
  EXPECT_STREQ("b26f1c171fcdbf185823364185adacf0", GetBitmapChecksum().c_str());
}

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

#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 (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
      return "6181929583fd7651169306852397806f";
    return "268b71a8660b51e31c6bf30fc7ff1e08";
  }
};

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_STREQ(GetLargeTextBlobChecksum(), GetBitmapChecksum().c_str());
}

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_STREQ(GetLargeTextBlobChecksum(), GetBitmapChecksum().c_str());
}
#endif  // !BUILDFLAG(IS_WIN)
