• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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