blob: a7ac264fe06178f7845ff87614a2dc07cdc25d22 [file] [log] [blame]
// Copyright 2016 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.
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
#include "core/fpdfapi/font/cpdf_type1font.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fxge/cfx_gemodule.h"
#include "core/fxge/fx_freetype.h"
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
#include "core/fxge/apple/apple_int.h"
#endif
namespace {
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
struct GlyphNameMap {
const char* m_pStrAdobe;
const char* m_pStrUnicode;
};
const GlyphNameMap g_GlyphNameSubsts[] = {{"ff", "uniFB00"},
{"ffi", "uniFB03"},
{"ffl", "uniFB04"},
{"fi", "uniFB01"},
{"fl", "uniFB02"}};
int compareString(const void* key, const void* element) {
return FXSYS_stricmp(static_cast<const char*>(key),
static_cast<const GlyphNameMap*>(element)->m_pStrAdobe);
}
const char* GlyphNameRemap(const char* pStrAdobe) {
const GlyphNameMap* found = static_cast<const GlyphNameMap*>(
bsearch(pStrAdobe, g_GlyphNameSubsts, FX_ArraySize(g_GlyphNameSubsts),
sizeof(GlyphNameMap), compareString));
return found ? found->m_pStrUnicode : nullptr;
}
#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
bool FT_UseType1Charmap(FXFT_Face face) {
if (FXFT_Get_Face_CharmapCount(face) == 0) {
return false;
}
if (FXFT_Get_Face_CharmapCount(face) == 1 &&
FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[0]) ==
FXFT_ENCODING_UNICODE) {
return false;
}
if (FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[0]) ==
FXFT_ENCODING_UNICODE) {
FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[1]);
} else {
FXFT_Set_Charmap(face, FXFT_Get_Face_Charmaps(face)[0]);
}
return true;
}
} // namespace
CPDF_Type1Font::CPDF_Type1Font() : m_Base14Font(-1) {}
bool CPDF_Type1Font::IsType1Font() const {
return true;
}
const CPDF_Type1Font* CPDF_Type1Font::AsType1Font() const {
return this;
}
CPDF_Type1Font* CPDF_Type1Font::AsType1Font() {
return this;
}
bool CPDF_Type1Font::Load() {
m_Base14Font = PDF_GetStandardFontName(&m_BaseFont);
if (m_Base14Font >= 0) {
CPDF_Dictionary* pFontDesc = m_pFontDict->GetDictFor("FontDescriptor");
if (pFontDesc && pFontDesc->KeyExist("Flags"))
m_Flags = pFontDesc->GetIntegerFor("Flags");
else
m_Flags = m_Base14Font >= 12 ? FXFONT_SYMBOLIC : FXFONT_NONSYMBOLIC;
if (m_Base14Font < 4) {
for (int i = 0; i < 256; i++)
m_CharWidth[i] = 600;
}
if (m_Base14Font == 12)
m_BaseEncoding = PDFFONT_ENCODING_ADOBE_SYMBOL;
else if (m_Base14Font == 13)
m_BaseEncoding = PDFFONT_ENCODING_ZAPFDINGBATS;
else if (m_Flags & FXFONT_NONSYMBOLIC)
m_BaseEncoding = PDFFONT_ENCODING_STANDARD;
}
return LoadCommon();
}
int CPDF_Type1Font::GlyphFromCharCodeExt(uint32_t charcode) {
if (charcode > 0xff) {
return -1;
}
int index = m_ExtGID[(uint8_t)charcode];
if (index == 0xffff) {
return -1;
}
return index;
}
void CPDF_Type1Font::LoadGlyphMap() {
if (!m_Font.GetFace())
return;
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
bool bCoreText = true;
CQuartz2D& quartz2d =
static_cast<CApplePlatform*>(CFX_GEModule::Get()->GetPlatformData())
->m_quartz2d;
if (!m_Font.GetPlatformFont()) {
if (m_Font.GetPsName() == "DFHeiStd-W5")
bCoreText = false;
m_Font.SetPlatformFont(
quartz2d.CreateFont(m_Font.GetFontData(), m_Font.GetSize()));
if (!m_Font.GetPlatformFont())
bCoreText = false;
}
#endif
if (!IsEmbedded() && (m_Base14Font < 12) && m_Font.IsTTFont()) {
if (FT_UseTTCharmap(m_Font.GetFace(), 3, 0)) {
bool bGotOne = false;
for (int charcode = 0; charcode < 256; charcode++) {
const uint8_t prefix[4] = {0x00, 0xf0, 0xf1, 0xf2};
for (int j = 0; j < 4; j++) {
uint16_t unicode = prefix[j] * 256 + charcode;
m_GlyphIndex[charcode] =
FXFT_Get_Char_Index(m_Font.GetFace(), unicode);
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
CalcExtGID(charcode);
#endif
if (m_GlyphIndex[charcode]) {
bGotOne = true;
break;
}
}
}
if (bGotOne) {
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
if (!bCoreText)
memcpy(m_ExtGID, m_GlyphIndex, 256);
#endif
return;
}
}
FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE);
if (m_BaseEncoding == 0) {
m_BaseEncoding = PDFFONT_ENCODING_STANDARD;
}
for (int charcode = 0; charcode < 256; charcode++) {
const char* name =
GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode);
if (!name)
continue;
m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
m_GlyphIndex[charcode] = FXFT_Get_Char_Index(
m_Font.GetFace(), m_Encoding.m_Unicodes[charcode]);
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
CalcExtGID(charcode);
#endif
if (m_GlyphIndex[charcode] == 0 && strcmp(name, ".notdef") == 0) {
m_Encoding.m_Unicodes[charcode] = 0x20;
m_GlyphIndex[charcode] = FXFT_Get_Char_Index(m_Font.GetFace(), 0x20);
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
CalcExtGID(charcode);
#endif
}
}
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
if (!bCoreText)
memcpy(m_ExtGID, m_GlyphIndex, 256);
#endif
return;
}
FT_UseType1Charmap(m_Font.GetFace());
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
if (bCoreText) {
if (m_Flags & FXFONT_SYMBOLIC) {
for (int charcode = 0; charcode < 256; charcode++) {
const char* name =
GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode);
if (name) {
m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
m_GlyphIndex[charcode] =
FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
SetExtGID(name, charcode);
} else {
m_GlyphIndex[charcode] =
FXFT_Get_Char_Index(m_Font.GetFace(), charcode);
wchar_t unicode = 0;
if (m_GlyphIndex[charcode]) {
unicode =
FT_UnicodeFromCharCode(PDFFONT_ENCODING_STANDARD, charcode);
}
char name_glyph[256];
memset(name_glyph, 0, sizeof(name_glyph));
FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode],
name_glyph, 256);
name_glyph[255] = 0;
if (unicode == 0 && name_glyph[0] != 0) {
unicode = PDF_UnicodeFromAdobeName(name_glyph);
}
m_Encoding.m_Unicodes[charcode] = unicode;
SetExtGID(name_glyph, charcode);
}
}
return;
}
bool bUnicode = false;
if (0 == FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE)) {
bUnicode = true;
}
for (int charcode = 0; charcode < 256; charcode++) {
const char* name =
GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode);
if (!name) {
continue;
}
m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
const char* pStrUnicode = GlyphNameRemap(name);
if (pStrUnicode &&
0 == FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name)) {
name = pStrUnicode;
}
m_GlyphIndex[charcode] =
FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
SetExtGID(name, charcode);
if (m_GlyphIndex[charcode] == 0) {
if (strcmp(name, ".notdef") != 0 && strcmp(name, "space") != 0) {
m_GlyphIndex[charcode] = FXFT_Get_Char_Index(
m_Font.GetFace(),
bUnicode ? m_Encoding.m_Unicodes[charcode] : charcode);
CalcExtGID(charcode);
} else {
m_Encoding.m_Unicodes[charcode] = 0x20;
m_GlyphIndex[charcode] =
bUnicode ? FXFT_Get_Char_Index(m_Font.GetFace(), 0x20) : 0xffff;
CalcExtGID(charcode);
}
}
}
return;
}
#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
if (m_Flags & FXFONT_SYMBOLIC) {
for (int charcode = 0; charcode < 256; charcode++) {
const char* name =
GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode);
if (name) {
m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
m_GlyphIndex[charcode] =
FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
} else {
m_GlyphIndex[charcode] =
FXFT_Get_Char_Index(m_Font.GetFace(), charcode);
if (m_GlyphIndex[charcode]) {
wchar_t unicode =
FT_UnicodeFromCharCode(PDFFONT_ENCODING_STANDARD, charcode);
if (unicode == 0) {
char name_glyph[256];
memset(name_glyph, 0, sizeof(name_glyph));
FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode],
name_glyph, 256);
name_glyph[255] = 0;
if (name_glyph[0] != 0) {
unicode = PDF_UnicodeFromAdobeName(name_glyph);
}
}
m_Encoding.m_Unicodes[charcode] = unicode;
}
}
}
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
if (!bCoreText)
memcpy(m_ExtGID, m_GlyphIndex, 256);
#endif
return;
}
bool bUnicode = false;
if (0 == FXFT_Select_Charmap(m_Font.GetFace(), FXFT_ENCODING_UNICODE)) {
bUnicode = true;
}
for (int charcode = 0; charcode < 256; charcode++) {
const char* name = GetAdobeCharName(m_BaseEncoding, m_CharNames, charcode);
if (!name) {
continue;
}
m_Encoding.m_Unicodes[charcode] = PDF_UnicodeFromAdobeName(name);
m_GlyphIndex[charcode] = FXFT_Get_Name_Index(m_Font.GetFace(), (char*)name);
if (m_GlyphIndex[charcode] == 0) {
if (strcmp(name, ".notdef") != 0 && strcmp(name, "space") != 0) {
m_GlyphIndex[charcode] = FXFT_Get_Char_Index(
m_Font.GetFace(),
bUnicode ? m_Encoding.m_Unicodes[charcode] : charcode);
} else {
m_Encoding.m_Unicodes[charcode] = 0x20;
m_GlyphIndex[charcode] = 0xffff;
}
}
}
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
if (!bCoreText)
memcpy(m_ExtGID, m_GlyphIndex, 256);
#endif
}
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
void CPDF_Type1Font::SetExtGID(const char* name, int charcode) {
CFStringRef name_ct = CFStringCreateWithCStringNoCopy(
kCFAllocatorDefault, name, kCFStringEncodingASCII, kCFAllocatorNull);
m_ExtGID[charcode] =
CGFontGetGlyphWithGlyphName((CGFontRef)m_Font.GetPlatformFont(), name_ct);
if (name_ct)
CFRelease(name_ct);
}
void CPDF_Type1Font::CalcExtGID(int charcode) {
char name_glyph[256];
FXFT_Get_Glyph_Name(m_Font.GetFace(), m_GlyphIndex[charcode], name_glyph,
256);
name_glyph[255] = 0;
SetExtGID(name_glyph, charcode);
}
#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_