| // Copyright 2018 PDFium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "core/fxge/fx_font.h" |
| |
| #include <algorithm> |
| |
| #include "core/fxcrt/fx_safe_types.h" |
| #include "core/fxcrt/fx_system.h" |
| #include "core/fxge/cfx_glyphbitmap.h" |
| #include "core/fxge/dib/cfx_dibitmap.h" |
| #include "core/fxge/fx_freetype.h" |
| #include "core/fxge/text_glyph_pos.h" |
| |
| 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) { |
| if (string_span.size() < static_cast<uint32_t>(offset + length)) |
| return ByteString(); |
| |
| string_span = string_span.subspan(offset, length); |
| return ByteString(string_span.data(), string_span.size()); |
| } |
| |
| } // namespace |
| |
| FX_RECT GetGlyphsBBox(const std::vector<TextGlyphPos>& glyphs, int anti_alias) { |
| FX_RECT rect; |
| bool bStarted = false; |
| for (const TextGlyphPos& glyph : glyphs) { |
| if (!glyph.m_pGlyph) |
| continue; |
| |
| Optional<CFX_Point> point = glyph.GetOrigin({0, 0}); |
| if (!point.has_value()) |
| continue; |
| |
| int char_width = glyph.m_pGlyph->GetBitmap()->GetWidth(); |
| if (anti_alias == FT_RENDER_MODE_LCD) |
| char_width /= 3; |
| |
| FX_SAFE_INT32 char_right = point.value().x; |
| char_right += char_width; |
| if (!char_right.IsValid()) |
| continue; |
| |
| FX_SAFE_INT32 char_bottom = point.value().y; |
| char_bottom += glyph.m_pGlyph->GetBitmap()->GetHeight(); |
| if (!char_bottom.IsValid()) |
| continue; |
| |
| if (bStarted) { |
| rect.left = std::min(rect.left, point.value().x); |
| rect.top = std::min(rect.top, point.value().y); |
| rect.right = pdfium::base::ValueOrDieForType<int32_t>( |
| pdfium::base::CheckMax(rect.right, char_right)); |
| rect.bottom = pdfium::base::ValueOrDieForType<int32_t>( |
| pdfium::base::CheckMax(rect.bottom, char_bottom)); |
| continue; |
| } |
| |
| rect.left = point.value().x; |
| rect.top = point.value().y; |
| rect.right = char_right.ValueOrDie(); |
| rect.bottom = char_bottom.ValueOrDie(); |
| bStarted = true; |
| } |
| return rect; |
| } |
| |
| ByteString GetNameFromTT(pdfium::span<const uint8_t> name_table, |
| uint32_t name_id) { |
| if (name_table.size() < 6) |
| return ByteString(); |
| |
| uint32_t name_count = FXSYS_UINT16_GET_MSBFIRST(&name_table[2]); |
| uint32_t string_offset = FXSYS_UINT16_GET_MSBFIRST(&name_table[4]); |
| // We will ignore the possibility of overlap of structures and |
| // string table as if it's all corrupt there's not a lot we can do. |
| if (name_table.size() < string_offset) |
| return ByteString(); |
| |
| pdfium::span<const uint8_t> string_span = name_table.subspan(string_offset); |
| name_table = name_table.subspan(6); |
| if (name_table.size() < name_count * 12) |
| return ByteString(); |
| |
| for (uint32_t i = 0; i < name_count; |
| i++, name_table = name_table.subspan(12)) { |
| if (FXSYS_UINT16_GET_MSBFIRST(&name_table[6]) == name_id) { |
| const uint16_t platform_identifier = |
| FXSYS_UINT16_GET_MSBFIRST(name_table); |
| const uint16_t platform_encoding = |
| FXSYS_UINT16_GET_MSBFIRST(&name_table[2]); |
| |
| if (platform_identifier == kNamePlatformMac && |
| platform_encoding == kNameMacEncodingRoman) { |
| return GetStringFromTable(string_span, |
| FXSYS_UINT16_GET_MSBFIRST(&name_table[10]), |
| FXSYS_UINT16_GET_MSBFIRST(&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, FXSYS_UINT16_GET_MSBFIRST(&name_table[10]), |
| FXSYS_UINT16_GET_MSBFIRST(&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(); |
| } |
| |
| int GetTTCIndex(pdfium::span<const uint8_t> pFontData, uint32_t font_offset) { |
| const uint8_t* p = pFontData.data() + 8; |
| uint32_t nfont = FXSYS_UINT32_GET_MSBFIRST(p); |
| uint32_t index; |
| for (index = 0; index < nfont; index++) { |
| p = pFontData.data() + 12 + index * 4; |
| if (FXSYS_UINT32_GET_MSBFIRST(p) == font_offset) |
| return index; |
| } |
| return 0; |
| } |
| |
| wchar_t PDF_UnicodeFromAdobeName(const char* name) { |
| return (wchar_t)(FXFT_unicode_from_adobe_name(name) & 0x7FFFFFFF); |
| } |
| |
| ByteString PDF_AdobeNameFromUnicode(wchar_t unicode) { |
| char glyph_name[64]; |
| FXFT_adobe_name_from_unicode(glyph_name, unicode); |
| return ByteString(glyph_name); |
| } |