K. Moon | 832a694 | 2022-10-31 20:11:31 +0000 | [diff] [blame] | 1 | // Copyright 2019 The PDFium Authors |
Lei Zhang | 533ade1 | 2019-02-07 18:41:37 +0000 | [diff] [blame] | 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 | |
Lei Zhang | ee39060 | 2024-06-26 16:24:13 +0000 | [diff] [blame] | 7 | #include <string> |
Lei Zhang | 69defca | 2020-09-21 18:16:23 +0000 | [diff] [blame] | 8 | #include <vector> |
Lei Zhang | f49c47d | 2020-05-12 03:14:12 +0000 | [diff] [blame] | 9 | |
Lei Zhang | ee39060 | 2024-06-26 16:24:13 +0000 | [diff] [blame] | 10 | #include "build/build_config.h" |
Tom Sepez | b087484 | 2024-06-11 00:35:07 +0000 | [diff] [blame] | 11 | #include "core/fxcrt/compiler_specific.h" |
Lei Zhang | 533ade1 | 2019-02-07 18:41:37 +0000 | [diff] [blame] | 12 | #include "testing/embedder_test.h" |
Tom Sepez | 72f520c | 2020-08-24 23:43:46 +0000 | [diff] [blame] | 13 | #include "testing/embedder_test_environment.h" |
Lei Zhang | 69defca | 2020-09-21 18:16:23 +0000 | [diff] [blame] | 14 | #include "testing/gmock/include/gmock/gmock.h" |
Lei Zhang | 533ade1 | 2019-02-07 18:41:37 +0000 | [diff] [blame] | 15 | #include "testing/gtest/include/gtest/gtest.h" |
| 16 | |
| 17 | namespace { |
| 18 | |
Tom Sepez | 4747296 | 2019-06-19 18:28:04 +0000 | [diff] [blame] | 19 | extern "C" { |
| 20 | |
| 21 | void FakeRelease(FPDF_SYSFONTINFO* pThis) {} |
| 22 | void FakeEnumFonts(FPDF_SYSFONTINFO* pThis, void* pMapper) {} |
| 23 | |
| 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 | |
| 35 | void* FakeGetFont(FPDF_SYSFONTINFO* pThis, const char* face) { |
| 36 | // Any non-null return will do. |
| 37 | return pThis; |
| 38 | } |
| 39 | |
| 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 | |
| 48 | unsigned long FakeGetFaceName(FPDF_SYSFONTINFO* pThis, |
| 49 | void* hFont, |
| 50 | char* buffer, |
| 51 | unsigned long buf_size) { |
| 52 | return 0; |
| 53 | } |
| 54 | |
| 55 | int FakeGetFontCharset(FPDF_SYSFONTINFO* pThis, void* hFont) { |
| 56 | return 1; |
| 57 | } |
| 58 | |
| 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 | |
| 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 Sepez | 72f520c | 2020-08-24 23:43:46 +0000 | [diff] [blame] | 82 | void TearDown() override { |
Lei Zhang | a7fca8a | 2024-02-21 20:05:15 +0000 | [diff] [blame] | 83 | FPDF_SetSystemFontInfo(nullptr); |
Tom Sepez | 72f520c | 2020-08-24 23:43:46 +0000 | [diff] [blame] | 84 | EmbedderTest::TearDown(); |
| 85 | |
Lei Zhang | a7fca8a | 2024-02-21 20:05:15 +0000 | [diff] [blame] | 86 | // Bouncing the library is the only reliable way to fully undo the initial |
Lei Zhang | 69defca | 2020-09-21 18:16:23 +0000 | [diff] [blame] | 87 | // FPDF_SetSystemFontInfo() call at the moment. |
Tom Sepez | 72f520c | 2020-08-24 23:43:46 +0000 | [diff] [blame] | 88 | EmbedderTestEnvironment::GetInstance()->TearDown(); |
| 89 | EmbedderTestEnvironment::GetInstance()->SetUp(); |
| 90 | } |
| 91 | |
Tom Sepez | 4747296 | 2019-06-19 18:28:04 +0000 | [diff] [blame] | 92 | FPDF_SYSFONTINFO font_info_; |
| 93 | }; |
| 94 | |
Lei Zhang | 533ade1 | 2019-02-07 18:41:37 +0000 | [diff] [blame] | 95 | class 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 Sepez | 72f520c | 2020-08-24 23:43:46 +0000 | [diff] [blame] | 109 | |
Lei Zhang | a7fca8a | 2024-02-21 20:05:15 +0000 | [diff] [blame] | 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 |
Lei Zhang | 69defca | 2020-09-21 18:16:23 +0000 | [diff] [blame] | 115 | // FPDF_SetSystemFontInfo() call at the moment. |
Tom Sepez | 72f520c | 2020-08-24 23:43:46 +0000 | [diff] [blame] | 116 | EmbedderTestEnvironment::GetInstance()->TearDown(); |
| 117 | |
Tom Sepez | 72f520c | 2020-08-24 23:43:46 +0000 | [diff] [blame] | 118 | EmbedderTestEnvironment::GetInstance()->SetUp(); |
Lei Zhang | 533ade1 | 2019-02-07 18:41:37 +0000 | [diff] [blame] | 119 | } |
| 120 | |
| 121 | FPDF_SYSFONTINFO* font_info_; |
| 122 | }; |
| 123 | |
| 124 | } // namespace |
| 125 | |
AbdAlRahmanGad | c058922 | 2024-06-28 01:28:29 +0000 | [diff] [blame] | 126 | TEST_F(FPDFUnavailableSysFontInfoEmbedderTest, Bug972518) { |
Tom Sepez | 4747296 | 2019-06-19 18:28:04 +0000 | [diff] [blame] | 127 | ASSERT_TRUE(OpenDocument("bug_972518.pdf")); |
| 128 | ASSERT_EQ(1, FPDF_GetPageCount(document())); |
| 129 | |
Helmut Januschka | 62d69b2 | 2024-09-19 18:57:06 +0000 | [diff] [blame] | 130 | ScopedEmbedderTestPage page = LoadScopedPage(0); |
Tom Sepez | 4747296 | 2019-06-19 18:28:04 +0000 | [diff] [blame] | 131 | ASSERT_TRUE(page); |
Tom Sepez | 4747296 | 2019-06-19 18:28:04 +0000 | [diff] [blame] | 132 | } |
| 133 | |
Lei Zhang | 533ade1 | 2019-02-07 18:41:37 +0000 | [diff] [blame] | 134 | TEST_F(FPDFSysFontInfoEmbedderTest, DefaultSystemFontInfo) { |
| 135 | ASSERT_TRUE(OpenDocument("hello_world.pdf")); |
| 136 | ASSERT_EQ(1, FPDF_GetPageCount(document())); |
| 137 | |
Helmut Januschka | 62d69b2 | 2024-09-19 18:57:06 +0000 | [diff] [blame] | 138 | ScopedEmbedderTestPage page = LoadScopedPage(0); |
Lei Zhang | 533ade1 | 2019-02-07 18:41:37 +0000 | [diff] [blame] | 139 | ASSERT_TRUE(page); |
| 140 | |
| 141 | { |
| 142 | // Not checking the rendering because it will depend on the fonts installed. |
Helmut Januschka | 62d69b2 | 2024-09-19 18:57:06 +0000 | [diff] [blame] | 143 | ScopedFPDFBitmap bitmap = RenderPage(page.get()); |
Lei Zhang | 533ade1 | 2019-02-07 18:41:37 +0000 | [diff] [blame] | 144 | ASSERT_EQ(200, FPDFBitmap_GetWidth(bitmap.get())); |
| 145 | ASSERT_EQ(200, FPDFBitmap_GetHeight(bitmap.get())); |
| 146 | } |
Lei Zhang | 533ade1 | 2019-02-07 18:41:37 +0000 | [diff] [blame] | 147 | } |
Tom Sepez | 3c04fb3 | 2020-01-09 20:19:05 +0000 | [diff] [blame] | 148 | |
| 149 | TEST_F(FPDFSysFontInfoEmbedderTest, DefaultTTFMap) { |
Lei Zhang | 69defca | 2020-09-21 18:16:23 +0000 | [diff] [blame] | 150 | static constexpr int kExpectedCharsets[] = { |
| 151 | FXFONT_ANSI_CHARSET, FXFONT_SHIFTJIS_CHARSET, |
Tom Sepez | 3c04fb3 | 2020-01-09 20:19:05 +0000 | [diff] [blame] | 152 | FXFONT_HANGEUL_CHARSET, FXFONT_GB2312_CHARSET, |
| 153 | FXFONT_CHINESEBIG5_CHARSET, FXFONT_ARABIC_CHARSET, |
| 154 | FXFONT_CYRILLIC_CHARSET, FXFONT_EASTERNEUROPEAN_CHARSET, |
| 155 | }; |
Lei Zhang | 69defca | 2020-09-21 18:16:23 +0000 | [diff] [blame] | 156 | std::vector<int> charsets; |
Tom Sepez | 3c04fb3 | 2020-01-09 20:19:05 +0000 | [diff] [blame] | 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) { |
Lei Zhang | 69defca | 2020-09-21 18:16:23 +0000 | [diff] [blame] | 163 | charsets.push_back(cfmap->charset); |
Tom Sepez | b087484 | 2024-06-11 00:35:07 +0000 | [diff] [blame] | 164 | // SAFETY: requires FPDF_GetDefaultTTFMap() to provide a sentinel. |
| 165 | UNSAFE_BUFFERS(++cfmap); |
Tom Sepez | 3c04fb3 | 2020-01-09 20:19:05 +0000 | [diff] [blame] | 166 | } |
| 167 | |
| 168 | // Confirm end marks only occur as a pair. |
| 169 | EXPECT_EQ(cfmap->charset, -1); |
| 170 | EXPECT_EQ(cfmap->fontname, nullptr); |
Lei Zhang | 69defca | 2020-09-21 18:16:23 +0000 | [diff] [blame] | 171 | |
| 172 | EXPECT_THAT(charsets, testing::UnorderedElementsAreArray(kExpectedCharsets)); |
Tom Sepez | 3c04fb3 | 2020-01-09 20:19:05 +0000 | [diff] [blame] | 173 | } |
Lei Zhang | ee39060 | 2024-06-26 16:24:13 +0000 | [diff] [blame] | 174 | |
| 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 | } |