xref: /aosp_15_r20/external/pdfium/xfa/fde/cfde_textout_unittest.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2022 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker 
5*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fde/cfde_textout.h"
6*3ac0a46fSAndroid Build Coastguard Worker 
7*3ac0a46fSAndroid Build Coastguard Worker #include <memory>
8*3ac0a46fSAndroid Build Coastguard Worker 
9*3ac0a46fSAndroid Build Coastguard Worker #include "build/build_config.h"
10*3ac0a46fSAndroid Build Coastguard Worker #include "core/fdrm/fx_crypt.h"
11*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/bytestring.h"
12*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_codepage.h"
13*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/fx_coordinates.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxcrt/retain_ptr.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxge/cfx_defaultrenderdevice.h"
16*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxge/dib/cfx_dibitmap.h"
17*3ac0a46fSAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
18*3ac0a46fSAndroid Build Coastguard Worker #include "testing/utils/hash.h"
19*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fgas/font/cfgas_fontmgr.h"
20*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fgas/font/cfgas_gefont.h"
21*3ac0a46fSAndroid Build Coastguard Worker #include "xfa/fgas/font/cfgas_gemodule.h"
22*3ac0a46fSAndroid Build Coastguard Worker 
23*3ac0a46fSAndroid Build Coastguard Worker class CFDETextOutTest : public testing::Test {
24*3ac0a46fSAndroid Build Coastguard Worker  public:
25*3ac0a46fSAndroid Build Coastguard Worker   CFDETextOutTest() = default;
26*3ac0a46fSAndroid Build Coastguard Worker   ~CFDETextOutTest() override = default;
27*3ac0a46fSAndroid Build Coastguard Worker 
SetUp()28*3ac0a46fSAndroid Build Coastguard Worker   void SetUp() override {
29*3ac0a46fSAndroid Build Coastguard Worker     CFX_Size bitmap_size = GetBitmapSize();
30*3ac0a46fSAndroid Build Coastguard Worker     bitmap_ = pdfium::MakeRetain<CFX_DIBitmap>();
31*3ac0a46fSAndroid Build Coastguard Worker     ASSERT_TRUE(bitmap_->Create(bitmap_size.width, bitmap_size.height,
32*3ac0a46fSAndroid Build Coastguard Worker                                 FXDIB_Format::kArgb));
33*3ac0a46fSAndroid Build Coastguard Worker 
34*3ac0a46fSAndroid Build Coastguard Worker     device_ = std::make_unique<CFX_DefaultRenderDevice>();
35*3ac0a46fSAndroid Build Coastguard Worker     device_->Attach(bitmap_);
36*3ac0a46fSAndroid Build Coastguard Worker 
37*3ac0a46fSAndroid Build Coastguard Worker     font_ = LoadFont();
38*3ac0a46fSAndroid Build Coastguard Worker     ASSERT_TRUE(font_);
39*3ac0a46fSAndroid Build Coastguard Worker 
40*3ac0a46fSAndroid Build Coastguard Worker     text_out_ = std::make_unique<CFDE_TextOut>();
41*3ac0a46fSAndroid Build Coastguard Worker     text_out_->SetFont(font_);
42*3ac0a46fSAndroid Build Coastguard Worker     text_out_->SetFontSize(12.0f);
43*3ac0a46fSAndroid Build Coastguard Worker 
44*3ac0a46fSAndroid Build Coastguard Worker     EXPECT_STREQ(GetEmptyBitmapChecksum(), GetBitmapChecksum().c_str());
45*3ac0a46fSAndroid Build Coastguard Worker   }
46*3ac0a46fSAndroid Build Coastguard Worker 
TearDown()47*3ac0a46fSAndroid Build Coastguard Worker   void TearDown() override {
48*3ac0a46fSAndroid Build Coastguard Worker     text_out_.reset();
49*3ac0a46fSAndroid Build Coastguard Worker     font_.Reset();
50*3ac0a46fSAndroid Build Coastguard Worker     device_.reset();
51*3ac0a46fSAndroid Build Coastguard Worker     bitmap_.Reset();
52*3ac0a46fSAndroid Build Coastguard Worker   }
53*3ac0a46fSAndroid Build Coastguard Worker 
LoadFont()54*3ac0a46fSAndroid Build Coastguard Worker   virtual RetainPtr<CFGAS_GEFont> LoadFont() {
55*3ac0a46fSAndroid Build Coastguard Worker     const wchar_t kFontFamily[] = L"Arimo Bold";
56*3ac0a46fSAndroid Build Coastguard Worker     return CFGAS_GEFont::LoadFont(kFontFamily, /*dwFontStyles=*/0,
57*3ac0a46fSAndroid Build Coastguard Worker                                   FX_CodePage::kDefANSI);
58*3ac0a46fSAndroid Build Coastguard Worker   }
59*3ac0a46fSAndroid Build Coastguard Worker 
GetBitmapSize()60*3ac0a46fSAndroid Build Coastguard Worker   virtual CFX_Size GetBitmapSize() { return CFX_Size(200, 100); }
61*3ac0a46fSAndroid Build Coastguard Worker 
GetEmptyBitmapChecksum()62*3ac0a46fSAndroid Build Coastguard Worker   virtual const char* GetEmptyBitmapChecksum() {
63*3ac0a46fSAndroid Build Coastguard Worker     static const char kEmptyBitmapChecksum[] =
64*3ac0a46fSAndroid Build Coastguard Worker         "a042237c5493fdb9656b94a83608d11a";
65*3ac0a46fSAndroid Build Coastguard Worker     return kEmptyBitmapChecksum;
66*3ac0a46fSAndroid Build Coastguard Worker   }
67*3ac0a46fSAndroid Build Coastguard Worker 
device()68*3ac0a46fSAndroid Build Coastguard Worker   CFX_DefaultRenderDevice* device() { return device_.get(); }
text_out()69*3ac0a46fSAndroid Build Coastguard Worker   CFDE_TextOut& text_out() { return *text_out_; }
70*3ac0a46fSAndroid Build Coastguard Worker 
GetBitmapChecksum()71*3ac0a46fSAndroid Build Coastguard Worker   ByteString GetBitmapChecksum() {
72*3ac0a46fSAndroid Build Coastguard Worker     CRYPT_md5_context context = CRYPT_MD5Start();
73*3ac0a46fSAndroid Build Coastguard Worker     for (int i = 0; i < bitmap_->GetHeight(); ++i)
74*3ac0a46fSAndroid Build Coastguard Worker       CRYPT_MD5Update(&context, bitmap_->GetScanline(i));
75*3ac0a46fSAndroid Build Coastguard Worker     uint8_t digest[16];
76*3ac0a46fSAndroid Build Coastguard Worker     CRYPT_MD5Finish(&context, digest);
77*3ac0a46fSAndroid Build Coastguard Worker     return ByteString(CryptToBase16(digest).c_str());
78*3ac0a46fSAndroid Build Coastguard Worker   }
79*3ac0a46fSAndroid Build Coastguard Worker 
80*3ac0a46fSAndroid Build Coastguard Worker  private:
81*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CFX_DIBitmap> bitmap_;
82*3ac0a46fSAndroid Build Coastguard Worker   std::unique_ptr<CFX_DefaultRenderDevice> device_;
83*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CFGAS_GEFont> font_;
84*3ac0a46fSAndroid Build Coastguard Worker   std::unique_ptr<CFDE_TextOut> text_out_;
85*3ac0a46fSAndroid Build Coastguard Worker };
86*3ac0a46fSAndroid Build Coastguard Worker 
TEST_F(CFDETextOutTest,DrawLogicTextBasic)87*3ac0a46fSAndroid Build Coastguard Worker TEST_F(CFDETextOutTest, DrawLogicTextBasic) {
88*3ac0a46fSAndroid Build Coastguard Worker   text_out().DrawLogicText(device(), L"foo", CFX_RectF(0, 0, 2100, 100));
89*3ac0a46fSAndroid Build Coastguard Worker   const char* checksum = []() {
90*3ac0a46fSAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
91*3ac0a46fSAndroid Build Coastguard Worker     if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
92*3ac0a46fSAndroid Build Coastguard Worker       return "76fd535f7d490d963598474494d0701e";
93*3ac0a46fSAndroid Build Coastguard Worker #endif
94*3ac0a46fSAndroid Build Coastguard Worker     return "b26f1c171fcdbf185823364185adacf0";
95*3ac0a46fSAndroid Build Coastguard Worker   }();
96*3ac0a46fSAndroid Build Coastguard Worker   EXPECT_STREQ(checksum, GetBitmapChecksum().c_str());
97*3ac0a46fSAndroid Build Coastguard Worker }
98*3ac0a46fSAndroid Build Coastguard Worker 
TEST_F(CFDETextOutTest,DrawLogicTextEmptyRect)99*3ac0a46fSAndroid Build Coastguard Worker TEST_F(CFDETextOutTest, DrawLogicTextEmptyRect) {
100*3ac0a46fSAndroid Build Coastguard Worker   text_out().DrawLogicText(device(), L"foo", CFX_RectF());
101*3ac0a46fSAndroid Build Coastguard Worker   EXPECT_STREQ(GetEmptyBitmapChecksum(), GetBitmapChecksum().c_str());
102*3ac0a46fSAndroid Build Coastguard Worker }
103*3ac0a46fSAndroid Build Coastguard Worker 
104*3ac0a46fSAndroid Build Coastguard Worker #if !BUILDFLAG(IS_WIN)
105*3ac0a46fSAndroid Build Coastguard Worker // This test depends on a particular font being present.
106*3ac0a46fSAndroid Build Coastguard Worker class CFDETextOutLargeBitmapTest : public CFDETextOutTest {
107*3ac0a46fSAndroid Build Coastguard Worker  public:
108*3ac0a46fSAndroid Build Coastguard Worker   CFDETextOutLargeBitmapTest() = default;
109*3ac0a46fSAndroid Build Coastguard Worker   ~CFDETextOutLargeBitmapTest() override = default;
110*3ac0a46fSAndroid Build Coastguard Worker 
LoadFont()111*3ac0a46fSAndroid Build Coastguard Worker   RetainPtr<CFGAS_GEFont> LoadFont() override {
112*3ac0a46fSAndroid Build Coastguard Worker     const wchar_t kFontFamily[] = L"DejaVu Sans";
113*3ac0a46fSAndroid Build Coastguard Worker     auto* font_manager = CFGAS_GEModule::Get()->GetFontMgr();
114*3ac0a46fSAndroid Build Coastguard Worker     return font_manager->LoadFont(kFontFamily, /*dwFontStyles=*/0,
115*3ac0a46fSAndroid Build Coastguard Worker                                   FX_CodePage::kFailure);
116*3ac0a46fSAndroid Build Coastguard Worker   }
117*3ac0a46fSAndroid Build Coastguard Worker 
GetBitmapSize()118*3ac0a46fSAndroid Build Coastguard Worker   CFX_Size GetBitmapSize() override { return CFX_Size(2100, 20); }
119*3ac0a46fSAndroid Build Coastguard Worker 
GetEmptyBitmapChecksum()120*3ac0a46fSAndroid Build Coastguard Worker   const char* GetEmptyBitmapChecksum() override {
121*3ac0a46fSAndroid Build Coastguard Worker     static const char kEmptyLargeBitmapChecksum[] =
122*3ac0a46fSAndroid Build Coastguard Worker         "101745f76351fd5d916bf3817b71563c";
123*3ac0a46fSAndroid Build Coastguard Worker     return kEmptyLargeBitmapChecksum;
124*3ac0a46fSAndroid Build Coastguard Worker   }
125*3ac0a46fSAndroid Build Coastguard Worker 
GetLargeTextBlobChecksum()126*3ac0a46fSAndroid Build Coastguard Worker   const char* GetLargeTextBlobChecksum() {
127*3ac0a46fSAndroid Build Coastguard Worker     if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
128*3ac0a46fSAndroid Build Coastguard Worker       return "cd357c6afbf17bb2ac48817df5d9eaad";
129*3ac0a46fSAndroid Build Coastguard Worker     }
130*3ac0a46fSAndroid Build Coastguard Worker     return "268b71a8660b51e31c6bf30fc7ff1e08";
131*3ac0a46fSAndroid Build Coastguard Worker   }
132*3ac0a46fSAndroid Build Coastguard Worker };
133*3ac0a46fSAndroid Build Coastguard Worker 
TEST_F(CFDETextOutLargeBitmapTest,DrawLogicTextBug953881)134*3ac0a46fSAndroid Build Coastguard Worker TEST_F(CFDETextOutLargeBitmapTest, DrawLogicTextBug953881) {
135*3ac0a46fSAndroid Build Coastguard Worker   FDE_TextStyle styles;
136*3ac0a46fSAndroid Build Coastguard Worker   styles.single_line_ = true;
137*3ac0a46fSAndroid Build Coastguard Worker   text_out().SetStyles(styles);
138*3ac0a46fSAndroid Build Coastguard Worker   text_out().SetAlignment(FDE_TextAlignment::kCenterLeft);
139*3ac0a46fSAndroid Build Coastguard Worker   text_out().SetFontSize(10.0f);
140*3ac0a46fSAndroid Build Coastguard Worker 
141*3ac0a46fSAndroid Build Coastguard Worker   static const wchar_t kText[] =
142*3ac0a46fSAndroid Build Coastguard Worker       L"SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"
143*3ac0a46fSAndroid Build Coastguard Worker       L"SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSssssssssss"
144*3ac0a46fSAndroid Build Coastguard Worker       L"sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
145*3ac0a46fSAndroid Build Coastguard Worker       L"sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
146*3ac0a46fSAndroid Build Coastguard Worker       L"sssssssssssssssssssssssssssssssssssssssssssssssssnnnnnnnnnnn"
147*3ac0a46fSAndroid Build Coastguard Worker       "\xfeba"
148*3ac0a46fSAndroid Build Coastguard Worker       L"Sssssssssssssssssss"
149*3ac0a46fSAndroid Build Coastguard Worker       "\xfeba"
150*3ac0a46fSAndroid Build Coastguard Worker       L"iiiiisssss";
151*3ac0a46fSAndroid Build Coastguard Worker   text_out().DrawLogicText(device(), WideString(kText),
152*3ac0a46fSAndroid Build Coastguard Worker                            CFX_RectF(3, 3, 2048, 10));
153*3ac0a46fSAndroid Build Coastguard Worker   EXPECT_STREQ(GetLargeTextBlobChecksum(), GetBitmapChecksum().c_str());
154*3ac0a46fSAndroid Build Coastguard Worker }
155*3ac0a46fSAndroid Build Coastguard Worker 
TEST_F(CFDETextOutLargeBitmapTest,DrawLogicTextBug1342078)156*3ac0a46fSAndroid Build Coastguard Worker TEST_F(CFDETextOutLargeBitmapTest, DrawLogicTextBug1342078) {
157*3ac0a46fSAndroid Build Coastguard Worker   FDE_TextStyle styles;
158*3ac0a46fSAndroid Build Coastguard Worker   styles.single_line_ = true;
159*3ac0a46fSAndroid Build Coastguard Worker   text_out().SetStyles(styles);
160*3ac0a46fSAndroid Build Coastguard Worker   text_out().SetAlignment(FDE_TextAlignment::kCenterLeft);
161*3ac0a46fSAndroid Build Coastguard Worker   text_out().SetFontSize(10.0f);
162*3ac0a46fSAndroid Build Coastguard Worker 
163*3ac0a46fSAndroid Build Coastguard Worker   static const wchar_t kText[] =
164*3ac0a46fSAndroid Build Coastguard Worker       L"SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"
165*3ac0a46fSAndroid Build Coastguard Worker       L"SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSssssssssss"
166*3ac0a46fSAndroid Build Coastguard Worker       L"sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
167*3ac0a46fSAndroid Build Coastguard Worker       L"sssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss"
168*3ac0a46fSAndroid Build Coastguard Worker       L"sssssssssssssssssssssssssssssssssssssssssssssssssnnnnnnnnnnn"
169*3ac0a46fSAndroid Build Coastguard Worker       "\xfeba"
170*3ac0a46fSAndroid Build Coastguard Worker       L"Sssssssssssssssssss"
171*3ac0a46fSAndroid Build Coastguard Worker       "\xfeba"
172*3ac0a46fSAndroid Build Coastguard Worker       L"iiiiiiiiiisssss";
173*3ac0a46fSAndroid Build Coastguard Worker   text_out().DrawLogicText(device(), WideString(kText),
174*3ac0a46fSAndroid Build Coastguard Worker                            CFX_RectF(3, 3, 2048, 10));
175*3ac0a46fSAndroid Build Coastguard Worker   EXPECT_STREQ(GetLargeTextBlobChecksum(), GetBitmapChecksum().c_str());
176*3ac0a46fSAndroid Build Coastguard Worker }
177*3ac0a46fSAndroid Build Coastguard Worker #endif  // !BUILDFLAG(IS_WIN)
178