• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <string>
8 #include <vector>
9 
10 #include "build/build_config.h"
11 #include "core/fxcrt/compiler_specific.h"
12 #include "testing/embedder_test.h"
13 #include "testing/embedder_test_environment.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace {
18 
19 extern "C" {
20 
FakeRelease(FPDF_SYSFONTINFO * pThis)21 void FakeRelease(FPDF_SYSFONTINFO* pThis) {}
FakeEnumFonts(FPDF_SYSFONTINFO * pThis,void * pMapper)22 void FakeEnumFonts(FPDF_SYSFONTINFO* pThis, void* pMapper) {}
23 
FakeMapFont(FPDF_SYSFONTINFO * pThis,int weight,FPDF_BOOL bItalic,int charset,int pitch_family,const char * face,FPDF_BOOL * bExact)24 void* 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 
FakeGetFont(FPDF_SYSFONTINFO * pThis,const char * face)35 void* FakeGetFont(FPDF_SYSFONTINFO* pThis, const char* face) {
36   // Any non-null return will do.
37   return pThis;
38 }
39 
FakeGetFontData(FPDF_SYSFONTINFO * pThis,void * hFont,unsigned int table,unsigned char * buffer,unsigned long buf_size)40 unsigned 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 
FakeGetFaceName(FPDF_SYSFONTINFO * pThis,void * hFont,char * buffer,unsigned long buf_size)48 unsigned long FakeGetFaceName(FPDF_SYSFONTINFO* pThis,
49                               void* hFont,
50                               char* buffer,
51                               unsigned long buf_size) {
52   return 0;
53 }
54 
FakeGetFontCharset(FPDF_SYSFONTINFO * pThis,void * hFont)55 int FakeGetFontCharset(FPDF_SYSFONTINFO* pThis, void* hFont) {
56   return 1;
57 }
58 
FakeDeleteFont(FPDF_SYSFONTINFO * pThis,void * hFont)59 void FakeDeleteFont(FPDF_SYSFONTINFO* pThis, void* hFont) {}
60 
61 }  // extern "C"
62 
63 class FPDFUnavailableSysFontInfoEmbedderTest : public EmbedderTest {
64  public:
65   FPDFUnavailableSysFontInfoEmbedderTest() = default;
66   ~FPDFUnavailableSysFontInfoEmbedderTest() override = default;
67 
SetUp()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 
TearDown()82   void TearDown() override {
83     FPDF_SetSystemFontInfo(nullptr);
84     EmbedderTest::TearDown();
85 
86     // Bouncing the library is the only reliable way to fully undo the initial
87     // FPDF_SetSystemFontInfo() call at the moment.
88     EmbedderTestEnvironment::GetInstance()->TearDown();
89     EmbedderTestEnvironment::GetInstance()->SetUp();
90   }
91 
92   FPDF_SYSFONTINFO font_info_;
93 };
94 
95 class FPDFSysFontInfoEmbedderTest : public EmbedderTest {
96  public:
97   FPDFSysFontInfoEmbedderTest() = default;
98   ~FPDFSysFontInfoEmbedderTest() override = default;
99 
SetUp()100   void SetUp() override {
101     EmbedderTest::SetUp();
102     font_info_ = FPDF_GetDefaultSystemFontInfo();
103     ASSERT_TRUE(font_info_);
104     FPDF_SetSystemFontInfo(font_info_);
105   }
106 
TearDown()107   void TearDown() override {
108     EmbedderTest::TearDown();
109 
110     // 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
115     // FPDF_SetSystemFontInfo() call at the moment.
116     EmbedderTestEnvironment::GetInstance()->TearDown();
117 
118     EmbedderTestEnvironment::GetInstance()->SetUp();
119   }
120 
121   FPDF_SYSFONTINFO* font_info_;
122 };
123 
124 }  // namespace
125 
TEST_F(FPDFUnavailableSysFontInfoEmbedderTest,Bug972518)126 TEST_F(FPDFUnavailableSysFontInfoEmbedderTest, Bug972518) {
127   ASSERT_TRUE(OpenDocument("bug_972518.pdf"));
128   ASSERT_EQ(1, FPDF_GetPageCount(document()));
129 
130   ScopedEmbedderTestPage page = LoadScopedPage(0);
131   ASSERT_TRUE(page);
132 }
133 
TEST_F(FPDFSysFontInfoEmbedderTest,DefaultSystemFontInfo)134 TEST_F(FPDFSysFontInfoEmbedderTest, DefaultSystemFontInfo) {
135   ASSERT_TRUE(OpenDocument("hello_world.pdf"));
136   ASSERT_EQ(1, FPDF_GetPageCount(document()));
137 
138   ScopedEmbedderTestPage page = LoadScopedPage(0);
139   ASSERT_TRUE(page);
140 
141   {
142     // Not checking the rendering because it will depend on the fonts installed.
143     ScopedFPDFBitmap bitmap = RenderPage(page.get());
144     ASSERT_EQ(200, FPDFBitmap_GetWidth(bitmap.get()));
145     ASSERT_EQ(200, FPDFBitmap_GetHeight(bitmap.get()));
146   }
147 }
148 
TEST_F(FPDFSysFontInfoEmbedderTest,DefaultTTFMap)149 TEST_F(FPDFSysFontInfoEmbedderTest, DefaultTTFMap) {
150   static constexpr int kExpectedCharsets[] = {
151       FXFONT_ANSI_CHARSET,        FXFONT_SHIFTJIS_CHARSET,
152       FXFONT_HANGEUL_CHARSET,     FXFONT_GB2312_CHARSET,
153       FXFONT_CHINESEBIG5_CHARSET, FXFONT_ARABIC_CHARSET,
154       FXFONT_CYRILLIC_CHARSET,    FXFONT_EASTERNEUROPEAN_CHARSET,
155   };
156   std::vector<int> charsets;
157 
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) {
163     charsets.push_back(cfmap->charset);
164     // SAFETY: requires FPDF_GetDefaultTTFMap() to provide a sentinel.
165     UNSAFE_BUFFERS(++cfmap);
166   }
167 
168   // Confirm end marks only occur as a pair.
169   EXPECT_EQ(cfmap->charset, -1);
170   EXPECT_EQ(cfmap->fontname, nullptr);
171 
172   EXPECT_THAT(charsets, testing::UnorderedElementsAreArray(kExpectedCharsets));
173 }
174 
TEST_F(FPDFSysFontInfoEmbedderTest,DefaultTTFMapCountAndEntries)175 TEST_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 }
213