Allow reading font name from Windows `name` table entry.
This change adds support for reading font names from the TTF table from
both Mac/MacRoman and Windows/Unicode name entries. Before, only
Mac/MacRoman was supported.
Bug: pdfium:1427
Change-Id: I435265c43d4fb85664323d6a674244690e60cc21
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/62830
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcrt/widestring.cpp b/core/fxcrt/widestring.cpp
index 5a637cb..8da9e8d 100644
--- a/core/fxcrt/widestring.cpp
+++ b/core/fxcrt/widestring.cpp
@@ -947,6 +947,24 @@
return result;
}
+WideString WideString::FromUTF16BE(const unsigned short* wstr, size_t wlen) {
+ if (!wstr || wlen == 0)
+ return WideString();
+
+ WideString result;
+ {
+ // Span's lifetime must end before ReleaseBuffer() below.
+ pdfium::span<wchar_t> buf = result.GetBuffer(wlen);
+ for (size_t i = 0; i < wlen; i++) {
+ auto wch = wstr[i];
+ wch = (wch >> 8) | (wch << 8);
+ buf[i] = wch;
+ }
+ }
+ result.ReleaseBuffer(wlen);
+ return result;
+}
+
void WideString::SetAt(size_t index, wchar_t c) {
ASSERT(IsValidIndex(index));
ReallocBeforeWrite(m_pData->m_nDataLength);
diff --git a/core/fxcrt/widestring.h b/core/fxcrt/widestring.h
index 2723e95..3373067 100644
--- a/core/fxcrt/widestring.h
+++ b/core/fxcrt/widestring.h
@@ -67,6 +67,8 @@
static WideString FromUTF8(ByteStringView str) WARN_UNUSED_RESULT;
static WideString FromUTF16LE(const unsigned short* str,
size_t len) WARN_UNUSED_RESULT;
+ static WideString FromUTF16BE(const unsigned short* wstr,
+ size_t wlen) WARN_UNUSED_RESULT;
static size_t WStringLength(const unsigned short* str) WARN_UNUSED_RESULT;
diff --git a/core/fxge/fx_font.cpp b/core/fxge/fx_font.cpp
index fc47a33c..fe2d6b1 100644
--- a/core/fxge/fx_font.cpp
+++ b/core/fxge/fx_font.cpp
@@ -13,6 +13,12 @@
namespace {
+// These numbers come from the OpenType name table specification.
+constexpr uint16_t kNamePlatformMac = 1;
+constexpr uint16_t kNameMacEncodingRoman = 0;
+constexpr uint16_t kNamePlatformWindows = 3;
+constexpr uint16_t kNameWindowsEncodingUnicode = 1;
+
ByteString GetStringFromTable(pdfium::span<const uint8_t> string_span,
uint16_t offset,
uint16_t length) {
@@ -88,11 +94,31 @@
for (uint32_t i = 0; i < name_count;
i++, name_table = name_table.subspan(12)) {
- if (GET_TT_SHORT(&name_table[6]) == name_id &&
- GET_TT_SHORT(&name_table[0]) == 1 &&
- GET_TT_SHORT(&name_table[2]) == 0) {
- return GetStringFromTable(string_span, GET_TT_SHORT(&name_table[10]),
- GET_TT_SHORT(&name_table[8]));
+ if (GET_TT_SHORT(&name_table[6]) == name_id) {
+ const uint16_t platform_identifier = GET_TT_SHORT(name_table);
+ const uint16_t platform_encoding = GET_TT_SHORT(&name_table[2]);
+
+ if (platform_identifier == kNamePlatformMac &&
+ platform_encoding == kNameMacEncodingRoman) {
+ return GetStringFromTable(string_span, GET_TT_SHORT(&name_table[10]),
+ GET_TT_SHORT(&name_table[8]));
+ }
+ if (platform_identifier == kNamePlatformWindows &&
+ platform_encoding == kNameWindowsEncodingUnicode) {
+ // This name is always UTF16-BE and we have to convert it to UTF8.
+ ByteString utf16_be =
+ GetStringFromTable(string_span, GET_TT_SHORT(&name_table[10]),
+ GET_TT_SHORT(&name_table[8]));
+ if (utf16_be.IsEmpty() || utf16_be.GetLength() % 2 != 0) {
+ return ByteString();
+ }
+
+ pdfium::span<const uint8_t> raw_span = utf16_be.raw_span();
+ return WideString::FromUTF16BE(
+ reinterpret_cast<const uint16_t*>(raw_span.data()),
+ raw_span.size() / 2)
+ .ToUTF8();
+ }
}
}
return ByteString();
diff --git a/core/fxge/fx_font_unittest.cpp b/core/fxge/fx_font_unittest.cpp
index 1f98645..e550f0a 100644
--- a/core/fxge/fx_font_unittest.cpp
+++ b/core/fxge/fx_font_unittest.cpp
@@ -2,9 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <string>
+
+#include "core/fxge/cfx_folderfontinfo.h"
+#include "core/fxge/cfx_fontmapper.h"
#include "core/fxge/fx_font.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/utils/path_service.h"
TEST(FXFontTest, PDF_AdobeNameFromUnicode) {
EXPECT_STREQ("", PDF_AdobeNameFromUnicode(0x0000).c_str());
@@ -15,3 +20,25 @@
EXPECT_STREQ("angkhankhuthai", PDF_AdobeNameFromUnicode(0x0e5a).c_str());
EXPECT_STREQ("Euro", PDF_AdobeNameFromUnicode(0x20ac).c_str());
}
+
+TEST(FXFontTest, ReadFontNameFromMicrosoftEntries) {
+ std::string test_data_dir;
+ PathService::GetTestDataDir(&test_data_dir);
+ ASSERT(!test_data_dir.empty());
+
+ CFX_FontMapper font_mapper(nullptr);
+
+ {
+ // |folder_font_info| has to be deallocated before the |font_mapper| or we
+ // run into UnownedPtr class issues with ASAN.
+ CFX_FolderFontInfo folder_font_info;
+ folder_font_info.AddPath(
+ (test_data_dir + PATH_SEPARATOR + "font_tests").c_str());
+
+ font_mapper.SetSystemFontInfo(SystemFontInfoIface::CreateDefault(nullptr));
+ ASSERT_TRUE(folder_font_info.EnumFontList(&font_mapper));
+ }
+
+ ASSERT_EQ(1, font_mapper.GetFaceSize());
+ ASSERT_EQ("Test", font_mapper.GetFaceName(0));
+}
diff --git a/testing/resources/font_tests/name_windows.ttf b/testing/resources/font_tests/name_windows.ttf
new file mode 100644
index 0000000..019ecef
--- /dev/null
+++ b/testing/resources/font_tests/name_windows.ttf
Binary files differ