1 // Copyright 2019 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 "public/fpdf_sysfontinfo.h"
6
7 #include <vector>
8
9 #include "testing/embedder_test.h"
10 #include "testing/embedder_test_environment.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace {
15
16 extern "C" {
17
FakeRelease(FPDF_SYSFONTINFO * pThis)18 void FakeRelease(FPDF_SYSFONTINFO* pThis) {}
FakeEnumFonts(FPDF_SYSFONTINFO * pThis,void * pMapper)19 void FakeEnumFonts(FPDF_SYSFONTINFO* pThis, void* pMapper) {}
20
FakeMapFont(FPDF_SYSFONTINFO * pThis,int weight,FPDF_BOOL bItalic,int charset,int pitch_family,const char * face,FPDF_BOOL * bExact)21 void* FakeMapFont(FPDF_SYSFONTINFO* pThis,
22 int weight,
23 FPDF_BOOL bItalic,
24 int charset,
25 int pitch_family,
26 const char* face,
27 FPDF_BOOL* bExact) {
28 // Any non-null return will do.
29 return pThis;
30 }
31
FakeGetFont(FPDF_SYSFONTINFO * pThis,const char * face)32 void* FakeGetFont(FPDF_SYSFONTINFO* pThis, const char* face) {
33 // Any non-null return will do.
34 return pThis;
35 }
36
FakeGetFontData(FPDF_SYSFONTINFO * pThis,void * hFont,unsigned int table,unsigned char * buffer,unsigned long buf_size)37 unsigned long FakeGetFontData(FPDF_SYSFONTINFO* pThis,
38 void* hFont,
39 unsigned int table,
40 unsigned char* buffer,
41 unsigned long buf_size) {
42 return 0;
43 }
44
FakeGetFaceName(FPDF_SYSFONTINFO * pThis,void * hFont,char * buffer,unsigned long buf_size)45 unsigned long FakeGetFaceName(FPDF_SYSFONTINFO* pThis,
46 void* hFont,
47 char* buffer,
48 unsigned long buf_size) {
49 return 0;
50 }
51
FakeGetFontCharset(FPDF_SYSFONTINFO * pThis,void * hFont)52 int FakeGetFontCharset(FPDF_SYSFONTINFO* pThis, void* hFont) {
53 return 1;
54 }
55
FakeDeleteFont(FPDF_SYSFONTINFO * pThis,void * hFont)56 void FakeDeleteFont(FPDF_SYSFONTINFO* pThis, void* hFont) {}
57
58 } // extern "C"
59
60 class FPDFUnavailableSysFontInfoEmbedderTest : public EmbedderTest {
61 public:
62 FPDFUnavailableSysFontInfoEmbedderTest() = default;
63 ~FPDFUnavailableSysFontInfoEmbedderTest() override = default;
64
SetUp()65 void SetUp() override {
66 EmbedderTest::SetUp();
67 font_info_.version = 1;
68 font_info_.Release = FakeRelease;
69 font_info_.EnumFonts = FakeEnumFonts;
70 font_info_.MapFont = FakeMapFont;
71 font_info_.GetFont = FakeGetFont;
72 font_info_.GetFontData = FakeGetFontData;
73 font_info_.GetFaceName = FakeGetFaceName;
74 font_info_.GetFontCharset = FakeGetFontCharset;
75 font_info_.DeleteFont = FakeDeleteFont;
76 FPDF_SetSystemFontInfo(&font_info_);
77 }
78
TearDown()79 void TearDown() override {
80 EmbedderTest::TearDown();
81
82 // Bouncing the library is the only reliable way to undo the
83 // FPDF_SetSystemFontInfo() call at the moment.
84 EmbedderTestEnvironment::GetInstance()->TearDown();
85 EmbedderTestEnvironment::GetInstance()->SetUp();
86 }
87
88 FPDF_SYSFONTINFO font_info_;
89 };
90
91 class FPDFSysFontInfoEmbedderTest : public EmbedderTest {
92 public:
93 FPDFSysFontInfoEmbedderTest() = default;
94 ~FPDFSysFontInfoEmbedderTest() override = default;
95
SetUp()96 void SetUp() override {
97 EmbedderTest::SetUp();
98 font_info_ = FPDF_GetDefaultSystemFontInfo();
99 ASSERT_TRUE(font_info_);
100 FPDF_SetSystemFontInfo(font_info_);
101 }
102
TearDown()103 void TearDown() override {
104 EmbedderTest::TearDown();
105
106 // Bouncing the library is the only reliable way to undo the
107 // FPDF_SetSystemFontInfo() call at the moment.
108 EmbedderTestEnvironment::GetInstance()->TearDown();
109
110 // After shutdown, it is safe to release the font info.
111 FPDF_FreeDefaultSystemFontInfo(font_info_);
112
113 EmbedderTestEnvironment::GetInstance()->SetUp();
114 }
115
116 FPDF_SYSFONTINFO* font_info_;
117 };
118
119 } // namespace
120
TEST_F(FPDFUnavailableSysFontInfoEmbedderTest,Bug_972518)121 TEST_F(FPDFUnavailableSysFontInfoEmbedderTest, Bug_972518) {
122 ASSERT_TRUE(OpenDocument("bug_972518.pdf"));
123 ASSERT_EQ(1, FPDF_GetPageCount(document()));
124
125 FPDF_PAGE page = LoadPage(0);
126 ASSERT_TRUE(page);
127 UnloadPage(page);
128 }
129
TEST_F(FPDFSysFontInfoEmbedderTest,DefaultSystemFontInfo)130 TEST_F(FPDFSysFontInfoEmbedderTest, DefaultSystemFontInfo) {
131 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
132 ASSERT_EQ(1, FPDF_GetPageCount(document()));
133
134 FPDF_PAGE page = LoadPage(0);
135 ASSERT_TRUE(page);
136
137 {
138 // Not checking the rendering because it will depend on the fonts installed.
139 ScopedFPDFBitmap bitmap = RenderPage(page);
140 ASSERT_EQ(200, FPDFBitmap_GetWidth(bitmap.get()));
141 ASSERT_EQ(200, FPDFBitmap_GetHeight(bitmap.get()));
142 }
143
144 UnloadPage(page);
145 }
146
TEST_F(FPDFSysFontInfoEmbedderTest,DefaultTTFMap)147 TEST_F(FPDFSysFontInfoEmbedderTest, DefaultTTFMap) {
148 static constexpr int kExpectedCharsets[] = {
149 FXFONT_ANSI_CHARSET, FXFONT_SHIFTJIS_CHARSET,
150 FXFONT_HANGEUL_CHARSET, FXFONT_GB2312_CHARSET,
151 FXFONT_CHINESEBIG5_CHARSET, FXFONT_ARABIC_CHARSET,
152 FXFONT_CYRILLIC_CHARSET, FXFONT_EASTERNEUROPEAN_CHARSET,
153 };
154 std::vector<int> charsets;
155
156 const FPDF_CharsetFontMap* cfmap = FPDF_GetDefaultTTFMap();
157 ASSERT_TRUE(cfmap);
158
159 // Stop at either end mark.
160 while (cfmap->charset != -1 && cfmap->fontname) {
161 charsets.push_back(cfmap->charset);
162 ++cfmap;
163 }
164
165 // Confirm end marks only occur as a pair.
166 EXPECT_EQ(cfmap->charset, -1);
167 EXPECT_EQ(cfmap->fontname, nullptr);
168
169 EXPECT_THAT(charsets, testing::UnorderedElementsAreArray(kExpectedCharsets));
170 }
171