blob: 6f0a1aa587fe4f370bc5276d194f26537a26d8cf [file] [log] [blame]
K. Moon832a6942022-10-31 20:11:31 +00001// Copyright 2019 The PDFium Authors
Lei Zhang533ade12019-02-07 18:41:37 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "public/fpdf_sysfontinfo.h"
6
Lei Zhangee390602024-06-26 16:24:13 +00007#include <string>
Lei Zhang69defca2020-09-21 18:16:23 +00008#include <vector>
Lei Zhangf49c47d2020-05-12 03:14:12 +00009
Lei Zhangee390602024-06-26 16:24:13 +000010#include "build/build_config.h"
Tom Sepezb0874842024-06-11 00:35:07 +000011#include "core/fxcrt/compiler_specific.h"
Lei Zhang533ade12019-02-07 18:41:37 +000012#include "testing/embedder_test.h"
Tom Sepez72f520c2020-08-24 23:43:46 +000013#include "testing/embedder_test_environment.h"
Lei Zhang69defca2020-09-21 18:16:23 +000014#include "testing/gmock/include/gmock/gmock.h"
Lei Zhang533ade12019-02-07 18:41:37 +000015#include "testing/gtest/include/gtest/gtest.h"
16
17namespace {
18
Tom Sepez47472962019-06-19 18:28:04 +000019extern "C" {
20
21void FakeRelease(FPDF_SYSFONTINFO* pThis) {}
22void FakeEnumFonts(FPDF_SYSFONTINFO* pThis, void* pMapper) {}
23
24void* FakeMapFont(FPDF_SYSFONTINFO* pThis,
25 int weight,
26 FPDF_BOOL bItalic,
27 int charset,
28 int pitch_family,
29 const char* face,
30 FPDF_BOOL* bExact) {
31 // Any non-null return will do.
32 return pThis;
33}
34
35void* FakeGetFont(FPDF_SYSFONTINFO* pThis, const char* face) {
36 // Any non-null return will do.
37 return pThis;
38}
39
40unsigned long FakeGetFontData(FPDF_SYSFONTINFO* pThis,
41 void* hFont,
42 unsigned int table,
43 unsigned char* buffer,
44 unsigned long buf_size) {
45 return 0;
46}
47
48unsigned long FakeGetFaceName(FPDF_SYSFONTINFO* pThis,
49 void* hFont,
50 char* buffer,
51 unsigned long buf_size) {
52 return 0;
53}
54
55int FakeGetFontCharset(FPDF_SYSFONTINFO* pThis, void* hFont) {
56 return 1;
57}
58
59void FakeDeleteFont(FPDF_SYSFONTINFO* pThis, void* hFont) {}
60
61} // extern "C"
62
63class FPDFUnavailableSysFontInfoEmbedderTest : public EmbedderTest {
64 public:
65 FPDFUnavailableSysFontInfoEmbedderTest() = default;
66 ~FPDFUnavailableSysFontInfoEmbedderTest() override = default;
67
68 void SetUp() override {
69 EmbedderTest::SetUp();
70 font_info_.version = 1;
71 font_info_.Release = FakeRelease;
72 font_info_.EnumFonts = FakeEnumFonts;
73 font_info_.MapFont = FakeMapFont;
74 font_info_.GetFont = FakeGetFont;
75 font_info_.GetFontData = FakeGetFontData;
76 font_info_.GetFaceName = FakeGetFaceName;
77 font_info_.GetFontCharset = FakeGetFontCharset;
78 font_info_.DeleteFont = FakeDeleteFont;
79 FPDF_SetSystemFontInfo(&font_info_);
80 }
81
Tom Sepez72f520c2020-08-24 23:43:46 +000082 void TearDown() override {
Lei Zhanga7fca8a2024-02-21 20:05:15 +000083 FPDF_SetSystemFontInfo(nullptr);
Tom Sepez72f520c2020-08-24 23:43:46 +000084 EmbedderTest::TearDown();
85
Lei Zhanga7fca8a2024-02-21 20:05:15 +000086 // Bouncing the library is the only reliable way to fully undo the initial
Lei Zhang69defca2020-09-21 18:16:23 +000087 // FPDF_SetSystemFontInfo() call at the moment.
Tom Sepez72f520c2020-08-24 23:43:46 +000088 EmbedderTestEnvironment::GetInstance()->TearDown();
89 EmbedderTestEnvironment::GetInstance()->SetUp();
90 }
91
Tom Sepez47472962019-06-19 18:28:04 +000092 FPDF_SYSFONTINFO font_info_;
93};
94
Lei Zhang533ade12019-02-07 18:41:37 +000095class FPDFSysFontInfoEmbedderTest : public EmbedderTest {
96 public:
97 FPDFSysFontInfoEmbedderTest() = default;
98 ~FPDFSysFontInfoEmbedderTest() override = default;
99
100 void SetUp() override {
101 EmbedderTest::SetUp();
102 font_info_ = FPDF_GetDefaultSystemFontInfo();
103 ASSERT_TRUE(font_info_);
104 FPDF_SetSystemFontInfo(font_info_);
105 }
106
107 void TearDown() override {
108 EmbedderTest::TearDown();
Tom Sepez72f520c2020-08-24 23:43:46 +0000109
Lei Zhanga7fca8a2024-02-21 20:05:15 +0000110 // After releasing `font_info_` from PDFium, it is safe to free it.
111 FPDF_SetSystemFontInfo(nullptr);
112 FPDF_FreeDefaultSystemFontInfo(font_info_);
113
114 // Bouncing the library is the only reliable way to fully undo the initial
Lei Zhang69defca2020-09-21 18:16:23 +0000115 // FPDF_SetSystemFontInfo() call at the moment.
Tom Sepez72f520c2020-08-24 23:43:46 +0000116 EmbedderTestEnvironment::GetInstance()->TearDown();
117
Tom Sepez72f520c2020-08-24 23:43:46 +0000118 EmbedderTestEnvironment::GetInstance()->SetUp();
Lei Zhang533ade12019-02-07 18:41:37 +0000119 }
120
121 FPDF_SYSFONTINFO* font_info_;
122};
123
124} // namespace
125
AbdAlRahmanGadc0589222024-06-28 01:28:29 +0000126TEST_F(FPDFUnavailableSysFontInfoEmbedderTest, Bug972518) {
Tom Sepez47472962019-06-19 18:28:04 +0000127 ASSERT_TRUE(OpenDocument("bug_972518.pdf"));
128 ASSERT_EQ(1, FPDF_GetPageCount(document()));
129
Helmut Januschka62d69b22024-09-19 18:57:06 +0000130 ScopedEmbedderTestPage page = LoadScopedPage(0);
Tom Sepez47472962019-06-19 18:28:04 +0000131 ASSERT_TRUE(page);
Tom Sepez47472962019-06-19 18:28:04 +0000132}
133
Lei Zhang533ade12019-02-07 18:41:37 +0000134TEST_F(FPDFSysFontInfoEmbedderTest, DefaultSystemFontInfo) {
135 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
136 ASSERT_EQ(1, FPDF_GetPageCount(document()));
137
Helmut Januschka62d69b22024-09-19 18:57:06 +0000138 ScopedEmbedderTestPage page = LoadScopedPage(0);
Lei Zhang533ade12019-02-07 18:41:37 +0000139 ASSERT_TRUE(page);
140
141 {
142 // Not checking the rendering because it will depend on the fonts installed.
Helmut Januschka62d69b22024-09-19 18:57:06 +0000143 ScopedFPDFBitmap bitmap = RenderPage(page.get());
Lei Zhang533ade12019-02-07 18:41:37 +0000144 ASSERT_EQ(200, FPDFBitmap_GetWidth(bitmap.get()));
145 ASSERT_EQ(200, FPDFBitmap_GetHeight(bitmap.get()));
146 }
Lei Zhang533ade12019-02-07 18:41:37 +0000147}
Tom Sepez3c04fb32020-01-09 20:19:05 +0000148
149TEST_F(FPDFSysFontInfoEmbedderTest, DefaultTTFMap) {
Lei Zhang69defca2020-09-21 18:16:23 +0000150 static constexpr int kExpectedCharsets[] = {
151 FXFONT_ANSI_CHARSET, FXFONT_SHIFTJIS_CHARSET,
Tom Sepez3c04fb32020-01-09 20:19:05 +0000152 FXFONT_HANGEUL_CHARSET, FXFONT_GB2312_CHARSET,
153 FXFONT_CHINESEBIG5_CHARSET, FXFONT_ARABIC_CHARSET,
154 FXFONT_CYRILLIC_CHARSET, FXFONT_EASTERNEUROPEAN_CHARSET,
155 };
Lei Zhang69defca2020-09-21 18:16:23 +0000156 std::vector<int> charsets;
Tom Sepez3c04fb32020-01-09 20:19:05 +0000157
158 const FPDF_CharsetFontMap* cfmap = FPDF_GetDefaultTTFMap();
159 ASSERT_TRUE(cfmap);
160
161 // Stop at either end mark.
162 while (cfmap->charset != -1 && cfmap->fontname) {
Lei Zhang69defca2020-09-21 18:16:23 +0000163 charsets.push_back(cfmap->charset);
Tom Sepezb0874842024-06-11 00:35:07 +0000164 // SAFETY: requires FPDF_GetDefaultTTFMap() to provide a sentinel.
165 UNSAFE_BUFFERS(++cfmap);
Tom Sepez3c04fb32020-01-09 20:19:05 +0000166 }
167
168 // Confirm end marks only occur as a pair.
169 EXPECT_EQ(cfmap->charset, -1);
170 EXPECT_EQ(cfmap->fontname, nullptr);
Lei Zhang69defca2020-09-21 18:16:23 +0000171
172 EXPECT_THAT(charsets, testing::UnorderedElementsAreArray(kExpectedCharsets));
Tom Sepez3c04fb32020-01-09 20:19:05 +0000173}
Lei Zhangee390602024-06-26 16:24:13 +0000174
175TEST_F(FPDFSysFontInfoEmbedderTest, DefaultTTFMapCountAndEntries) {
176 static constexpr int kExpectedCharsets[] = {
177 FXFONT_ANSI_CHARSET,
178 FXFONT_GB2312_CHARSET,
179 FXFONT_CHINESEBIG5_CHARSET,
180 FXFONT_SHIFTJIS_CHARSET,
181 FXFONT_HANGEUL_CHARSET,
182 FXFONT_CYRILLIC_CHARSET,
183 FXFONT_EASTERNEUROPEAN_CHARSET,
184 FXFONT_ARABIC_CHARSET,
185 };
186 static const std::string kExpectedFontNames[] = {
187 "Helvetica", "SimSun", "MingLiU", "MS Gothic", "Batang", "Arial",
188#if BUILDFLAG(IS_WIN)
189 "Tahoma",
190#else
191 "Arial",
192#endif
193 "Arial",
194 };
195 std::vector<int> charsets;
196 std::vector<const char*> font_names;
197
198 const size_t count = FPDF_GetDefaultTTFMapCount();
199 for (size_t i = 0; i < count; ++i) {
200 const FPDF_CharsetFontMap* entry = FPDF_GetDefaultTTFMapEntry(i);
201 ASSERT_TRUE(entry);
202 charsets.push_back(entry->charset);
203 font_names.push_back(entry->fontname);
204 }
205
206 EXPECT_THAT(charsets, testing::ElementsAreArray(kExpectedCharsets));
207 EXPECT_THAT(font_names, testing::ElementsAreArray(kExpectedFontNames));
208
209 // Test out of bound indices.
210 EXPECT_FALSE(FPDF_GetDefaultTTFMapEntry(count));
211 EXPECT_FALSE(FPDF_GetDefaultTTFMapEntry(9999));
212}