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