xref: /aosp_15_r20/external/pdfium/core/fxge/fx_font.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2018 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 "core/fxge/fx_font.h"
6 
7 #include <algorithm>
8 
9 #include "core/fxcrt/fx_safe_types.h"
10 #include "core/fxcrt/fx_system.h"
11 #include "core/fxcrt/widestring.h"
12 #include "core/fxge/cfx_glyphbitmap.h"
13 #include "core/fxge/dib/cfx_dibitmap.h"
14 #include "core/fxge/freetype/fx_freetype.h"
15 #include "core/fxge/text_glyph_pos.h"
16 
17 namespace {
18 
19 // These numbers come from the OpenType name table specification.
20 constexpr uint16_t kNameMacEncodingRoman = 0;
21 constexpr uint16_t kNameWindowsEncodingUnicode = 1;
22 
GetStringFromTable(pdfium::span<const uint8_t> string_span,uint16_t offset,uint16_t length)23 ByteString GetStringFromTable(pdfium::span<const uint8_t> string_span,
24                               uint16_t offset,
25                               uint16_t length) {
26   if (string_span.size() < static_cast<uint32_t>(offset + length))
27     return ByteString();
28 
29   string_span = string_span.subspan(offset, length);
30   return ByteString(string_span.data(), string_span.size());
31 }
32 
33 }  // namespace
34 
GetGlyphsBBox(const std::vector<TextGlyphPos> & glyphs,int anti_alias)35 FX_RECT GetGlyphsBBox(const std::vector<TextGlyphPos>& glyphs, int anti_alias) {
36   FX_RECT rect;
37   bool bStarted = false;
38   for (const TextGlyphPos& glyph : glyphs) {
39     if (!glyph.m_pGlyph)
40       continue;
41 
42     absl::optional<CFX_Point> point = glyph.GetOrigin({0, 0});
43     if (!point.has_value())
44       continue;
45 
46     int char_width = glyph.m_pGlyph->GetBitmap()->GetWidth();
47     if (anti_alias == FT_RENDER_MODE_LCD)
48       char_width /= 3;
49 
50     FX_SAFE_INT32 char_right = point.value().x;
51     char_right += char_width;
52     if (!char_right.IsValid())
53       continue;
54 
55     FX_SAFE_INT32 char_bottom = point.value().y;
56     char_bottom += glyph.m_pGlyph->GetBitmap()->GetHeight();
57     if (!char_bottom.IsValid())
58       continue;
59 
60     if (bStarted) {
61       rect.left = std::min(rect.left, point.value().x);
62       rect.top = std::min(rect.top, point.value().y);
63       rect.right = pdfium::base::ValueOrDieForType<int32_t>(
64           pdfium::base::CheckMax(rect.right, char_right));
65       rect.bottom = pdfium::base::ValueOrDieForType<int32_t>(
66           pdfium::base::CheckMax(rect.bottom, char_bottom));
67       continue;
68     }
69 
70     rect.left = point.value().x;
71     rect.top = point.value().y;
72     rect.right = char_right.ValueOrDie();
73     rect.bottom = char_bottom.ValueOrDie();
74     bStarted = true;
75   }
76   return rect;
77 }
78 
GetNameFromTT(pdfium::span<const uint8_t> name_table,uint32_t name_id)79 ByteString GetNameFromTT(pdfium::span<const uint8_t> name_table,
80                          uint32_t name_id) {
81   if (name_table.size() < 6)
82     return ByteString();
83 
84   uint32_t name_count = FXSYS_UINT16_GET_MSBFIRST(&name_table[2]);
85   uint32_t string_offset = FXSYS_UINT16_GET_MSBFIRST(&name_table[4]);
86   // We will ignore the possibility of overlap of structures and
87   // string table as if it's all corrupt there's not a lot we can do.
88   if (name_table.size() < string_offset)
89     return ByteString();
90 
91   pdfium::span<const uint8_t> string_span = name_table.subspan(string_offset);
92   name_table = name_table.subspan(6);
93   if (name_table.size() < name_count * 12)
94     return ByteString();
95 
96   for (uint32_t i = 0; i < name_count;
97        i++, name_table = name_table.subspan(12)) {
98     if (FXSYS_UINT16_GET_MSBFIRST(&name_table[6]) == name_id) {
99       const uint16_t platform_identifier =
100           FXSYS_UINT16_GET_MSBFIRST(name_table);
101       const uint16_t platform_encoding =
102           FXSYS_UINT16_GET_MSBFIRST(&name_table[2]);
103 
104       if (platform_identifier == kNamePlatformMac &&
105           platform_encoding == kNameMacEncodingRoman) {
106         return GetStringFromTable(string_span,
107                                   FXSYS_UINT16_GET_MSBFIRST(&name_table[10]),
108                                   FXSYS_UINT16_GET_MSBFIRST(&name_table[8]));
109       }
110       if (platform_identifier == kNamePlatformWindows &&
111           platform_encoding == kNameWindowsEncodingUnicode) {
112         // This name is always UTF16-BE and we have to convert it to UTF8.
113         ByteString utf16_be = GetStringFromTable(
114             string_span, FXSYS_UINT16_GET_MSBFIRST(&name_table[10]),
115             FXSYS_UINT16_GET_MSBFIRST(&name_table[8]));
116         if (utf16_be.IsEmpty() || utf16_be.GetLength() % 2 != 0) {
117           return ByteString();
118         }
119 
120         pdfium::span<const uint8_t> raw_span = utf16_be.raw_span();
121         return WideString::FromUTF16BE(
122                    reinterpret_cast<const uint16_t*>(raw_span.data()),
123                    raw_span.size() / 2)
124             .ToUTF8();
125       }
126     }
127   }
128   return ByteString();
129 }
130 
GetTTCIndex(pdfium::span<const uint8_t> pFontData,size_t font_offset)131 size_t GetTTCIndex(pdfium::span<const uint8_t> pFontData, size_t font_offset) {
132   pdfium::span<const uint8_t> p = pFontData.subspan(8);
133   size_t nfont = FXSYS_UINT32_GET_MSBFIRST(p.data());
134   for (size_t index = 0; index < nfont; index++) {
135     p = pFontData.subspan(12 + index * 4);
136     if (FXSYS_UINT32_GET_MSBFIRST(p.data()) == font_offset)
137       return index;
138   }
139   return 0;
140 }
141 
UnicodeFromAdobeName(const char * name)142 wchar_t UnicodeFromAdobeName(const char* name) {
143   return (wchar_t)(FXFT_unicode_from_adobe_name(name) & 0x7FFFFFFF);
144 }
145 
AdobeNameFromUnicode(wchar_t unicode)146 ByteString AdobeNameFromUnicode(wchar_t unicode) {
147   char glyph_name[64];
148   FXFT_adobe_name_from_unicode(glyph_name, unicode);
149   return ByteString(glyph_name);
150 }
151