blob: 006730288b929c0b83dc5c23a61f35dbdff6ed43 [file] [log] [blame]
// 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));
const char* checksum = []() {
#if BUILDFLAG(IS_WIN)
if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
return "76fd535f7d490d963598474494d0701e";
#endif
return "b26f1c171fcdbf185823364185adacf0";
}();
EXPECT_STREQ(checksum, 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 "cd357c6afbf17bb2ac48817df5d9eaad";
}
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)