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