std::unique_ptr<CPDF_Object> CPDF_FontEncoding::Realize( WeakPtr<ByteStringPool> pPool) { int predefined = 0; for (int cs = PDFFONT_ENCODING_WINANSI; cs < PDFFONT_ENCODING_ZAPFDINGBATS; cs++) { const uint16_t* pSrc = PDF_UnicodesForPredefinedCharSet(cs); bool match = true; for (size_t i = 0; i < FX_ArraySize(m_Unicodes); i++) { if (m_Unicodes[i] != pSrc[i]) { match = false; break; } } if (match) { predefined = cs; break; } } if (predefined) { const char* pName; if (predefined == PDFFONT_ENCODING_WINANSI) pName = "WinAnsiEncoding"; else if (predefined == PDFFONT_ENCODING_MACROMAN) pName = "MacRomanEncoding"; else if (predefined == PDFFONT_ENCODING_MACEXPERT) pName = "MacExpertEncoding"; else return nullptr; return pdfium::MakeUnique<CPDF_Name>(pPool, pName); } const uint16_t* pStandard = PDF_UnicodesForPredefinedCharSet(PDFFONT_ENCODING_WINANSI); auto pDiff = pdfium::MakeUnique<CPDF_Array>(); for (size_t i = 0; i < FX_ArraySize(m_Unicodes); i++) { if (pStandard[i] == m_Unicodes[i]) continue; pDiff->AddNew<CPDF_Number>(static_cast<int>(i)); pDiff->AddNew<CPDF_Name>(PDF_AdobeNameFromUnicode(m_Unicodes[i])); } auto pDict = pdfium::MakeUnique<CPDF_Dictionary>(pPool); pDict->SetNewFor<CPDF_Name>("BaseEncoding", "WinAnsiEncoding"); pDict->SetFor("Differences", std::move(pDiff)); return std::move(pDict); }
size_t CPDF_Document::CalculateEncodingDict(int charset, CPDF_Dictionary* pBaseDict) { size_t i; for (i = 0; i < FX_ArraySize(g_FX_CharsetUnicodes); ++i) { if (g_FX_CharsetUnicodes[i].m_Charset == charset) break; } if (i == FX_ArraySize(g_FX_CharsetUnicodes)) return i; CPDF_Dictionary* pEncodingDict = new CPDF_Dictionary(m_pByteStringPool); pEncodingDict->SetNameFor("BaseEncoding", "WinAnsiEncoding"); CPDF_Array* pArray = new CPDF_Array; pArray->AddInteger(128); const uint16_t* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes; for (int j = 0; j < 128; j++) { CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]); pArray->AddName(name.IsEmpty() ? ".notdef" : name); } pEncodingDict->SetFor("Differences", pArray); pBaseDict->SetReferenceFor("Encoding", this, AddIndirectObject(pEncodingDict)); return i; }
CPDF_Font* CPDF_Document::AddFont(CFX_Font* pFont, int charset, FX_BOOL bVert) { if (pFont == NULL) { return NULL; } FX_BOOL bCJK = charset == FXFONT_CHINESEBIG5_CHARSET || charset == FXFONT_GB2312_CHARSET || charset == FXFONT_HANGEUL_CHARSET || charset == FXFONT_SHIFTJIS_CHARSET; CFX_ByteString basefont = pFont->GetFamilyName(); basefont.Replace(" ", ""); int flags = 0; if (pFont->IsBold()) { flags |= PDFFONT_FORCEBOLD; } if (pFont->IsItalic()) { flags |= PDFFONT_ITALIC; } if (pFont->IsFixedWidth()) { flags |= PDFFONT_FIXEDPITCH; } CPDF_Dictionary* pBaseDict = FX_NEW CPDF_Dictionary; pBaseDict->SetAtName("Type", "Font"); IFX_FontEncoding* pEncoding = FXGE_CreateUnicodeEncoding(pFont); CPDF_Dictionary* pFontDict = pBaseDict; if (!bCJK) { CPDF_Array* pWidths = FX_NEW CPDF_Array; int charcode; for (charcode = 32; charcode < 128; charcode ++) { int glyph_index = pEncoding->GlyphFromCharCode(charcode); int char_width = pFont->GetGlyphWidth(glyph_index); pWidths->AddInteger(char_width); } if (charset == FXFONT_ANSI_CHARSET || charset == FXFONT_DEFAULT_CHARSET || charset == FXFONT_SYMBOL_CHARSET) { if (charset == FXFONT_SYMBOL_CHARSET) { flags |= PDFFONT_SYMBOLIC; } else { flags |= PDFFONT_NONSYMBOLIC; } pBaseDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding"); for (charcode = 128; charcode <= 255; charcode ++) { int glyph_index = pEncoding->GlyphFromCharCode(charcode); int char_width = pFont->GetGlyphWidth(glyph_index); pWidths->AddInteger(char_width); } } else { flags |= PDFFONT_NONSYMBOLIC; int i; for (i = 0; i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes); i ++) if (g_FX_CharsetUnicodes[i].m_Charset == charset) { break; } if (i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes)) { CPDF_Dictionary* pEncodingDict = FX_NEW CPDF_Dictionary; pEncodingDict->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding"); CPDF_Array* pArray = FX_NEW CPDF_Array; pArray->AddInteger(128); const FX_WCHAR* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes; for (int j = 0; j < 128; j ++) { CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]); if (name.IsEmpty()) { pArray->AddName(FX_BSTRC(".notdef")); } else { pArray->AddName(name); } int glyph_index = pEncoding->GlyphFromCharCode(pUnicodes[j]); int char_width = pFont->GetGlyphWidth(glyph_index); pWidths->AddInteger(char_width); } pEncodingDict->SetAt(FX_BSTRC("Differences"), pArray); AddIndirectObject(pEncodingDict); pBaseDict->SetAtReference(FX_BSTRC("Encoding"), this, pEncodingDict); } } if (pFont->IsBold() && pFont->IsItalic()) { basefont += ",BoldItalic"; } else if (pFont->IsBold()) { basefont += ",Bold"; } else if (pFont->IsItalic()) { basefont += ",Italic"; } pBaseDict->SetAtName("Subtype", "TrueType"); pBaseDict->SetAtName("BaseFont", basefont); pBaseDict->SetAtNumber("FirstChar", 32); pBaseDict->SetAtNumber("LastChar", 255); pBaseDict->SetAt("Widths", pWidths); } else { flags |= PDFFONT_NONSYMBOLIC; pFontDict = FX_NEW CPDF_Dictionary; CFX_ByteString cmap; CFX_ByteString ordering; int supplement; CPDF_Array* pWidthArray = FX_NEW CPDF_Array; switch (charset) { case FXFONT_CHINESEBIG5_CHARSET: cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H"; ordering = "CNS1"; supplement = 4; pWidthArray->AddInteger(1); _InsertWidthArray1(pFont, pEncoding, 0x20, 0x7e, pWidthArray); break; case FXFONT_GB2312_CHARSET: cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H"; ordering = "GB1", supplement = 2; pWidthArray->AddInteger(7716); _InsertWidthArray1(pFont, pEncoding, 0x20, 0x20, pWidthArray); pWidthArray->AddInteger(814); _InsertWidthArray1(pFont, pEncoding, 0x21, 0x7e, pWidthArray); break; case FXFONT_HANGEUL_CHARSET: cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H"; ordering = "Korea1"; supplement = 2; pWidthArray->AddInteger(1); _InsertWidthArray1(pFont, pEncoding, 0x20, 0x7e, pWidthArray); break; case FXFONT_SHIFTJIS_CHARSET: cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H"; ordering = "Japan1"; supplement = 5; pWidthArray->AddInteger(231); _InsertWidthArray1(pFont, pEncoding, 0x20, 0x7d, pWidthArray); pWidthArray->AddInteger(326); _InsertWidthArray1(pFont, pEncoding, 0xa0, 0xa0, pWidthArray); pWidthArray->AddInteger(327); _InsertWidthArray1(pFont, pEncoding, 0xa1, 0xdf, pWidthArray); pWidthArray->AddInteger(631); _InsertWidthArray1(pFont, pEncoding, 0x7e, 0x7e, pWidthArray); break; } pBaseDict->SetAtName("Subtype", "Type0"); pBaseDict->SetAtName("BaseFont", basefont); pBaseDict->SetAtName("Encoding", cmap); pFontDict->SetAt("W", pWidthArray); pFontDict->SetAtName("Type", "Font"); pFontDict->SetAtName("Subtype", "CIDFontType2"); pFontDict->SetAtName("BaseFont", basefont); CPDF_Dictionary* pCIDSysInfo = FX_NEW CPDF_Dictionary; pCIDSysInfo->SetAtString("Registry", "Adobe"); pCIDSysInfo->SetAtString("Ordering", ordering); pCIDSysInfo->SetAtInteger("Supplement", supplement); pFontDict->SetAt("CIDSystemInfo", pCIDSysInfo); CPDF_Array* pArray = FX_NEW CPDF_Array; pBaseDict->SetAt("DescendantFonts", pArray); AddIndirectObject(pFontDict); pArray->AddReference(this, pFontDict); } AddIndirectObject(pBaseDict); CPDF_Dictionary* pFontDesc = FX_NEW CPDF_Dictionary; pFontDesc->SetAtName("Type", "FontDescriptor"); pFontDesc->SetAtName("FontName", basefont); pFontDesc->SetAtInteger("Flags", flags); pFontDesc->SetAtInteger("ItalicAngle", pFont->m_pSubstFont ? pFont->m_pSubstFont->m_ItalicAngle : 0); pFontDesc->SetAtInteger("Ascent", pFont->GetAscent()); pFontDesc->SetAtInteger("Descent", pFont->GetDescent()); FX_RECT bbox; pFont->GetBBox(bbox); CPDF_Array* pBBox = FX_NEW CPDF_Array; pBBox->AddInteger(bbox.left); pBBox->AddInteger(bbox.bottom); pBBox->AddInteger(bbox.right); pBBox->AddInteger(bbox.top); pFontDesc->SetAt("FontBBox", pBBox); FX_INT32 nStemV = 0; if (pFont->m_pSubstFont) { nStemV = pFont->m_pSubstFont->m_Weight / 5; } else { static const FX_CHAR stem_chars[] = {'i', 'I', '!', '1'}; const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]); FX_DWORD glyph = pEncoding->GlyphFromCharCode(stem_chars[0]); nStemV = pFont->GetGlyphWidth(glyph); for (size_t i = 1; i < count; i++) { glyph = pEncoding->GlyphFromCharCode(stem_chars[i]); int width = pFont->GetGlyphWidth(glyph); if (width > 0 && width < nStemV) { nStemV = width; } } } if (pEncoding) { delete pEncoding; } pFontDesc->SetAtInteger("StemV", nStemV); AddIndirectObject(pFontDesc); pFontDict->SetAtReference("FontDescriptor", this, pFontDesc); return LoadFont(pBaseDict); }
CPDF_Font* CPDF_Document::AddMacFont(CTFontRef pFont, FX_BOOL bVert, FX_BOOL bTranslateName) { CTFontRef font = (CTFontRef)pFont; CTFontDescriptorRef descriptor = CTFontCopyFontDescriptor(font); if (descriptor == NULL) { return NULL; } CFX_ByteString basefont; FX_BOOL bCJK = FALSE; int flags = 0, italicangle = 0, ascend = 0, descend = 0, capheight = 0, bbox[4]; FXSYS_memset32(bbox, 0, sizeof(int) * 4); CFArrayRef languages = (CFArrayRef)CTFontDescriptorCopyAttribute(descriptor, kCTFontLanguagesAttribute); if (languages == NULL) { CFRelease(descriptor); return NULL; } CFX_DWordArray charSets; charSets.Add(FXFONT_CHINESEBIG5_CHARSET); charSets.Add(FXFONT_GB2312_CHARSET); charSets.Add(FXFONT_HANGEUL_CHARSET); charSets.Add(FXFONT_SHIFTJIS_CHARSET); if (IsHasCharSet(languages, charSets)) { bCJK = TRUE; } CFRelease(descriptor); CFDictionaryRef traits = (CFDictionaryRef)CTFontCopyTraits(font); if (traits == NULL) { CFRelease(languages); return NULL; } CFNumberRef sybolicTrait = (CFNumberRef)CFDictionaryGetValue(traits, kCTFontSymbolicTrait); CTFontSymbolicTraits trait = 0; CFNumberGetValue(sybolicTrait, kCFNumberSInt32Type, &trait); if (trait & kCTFontItalicTrait) { flags |= PDFFONT_ITALIC; } if (trait & kCTFontMonoSpaceTrait) { flags |= PDFFONT_FIXEDPITCH; } if (trait & kCTFontModernSerifsClass) { flags |= PDFFONT_SERIF; } if (trait & kCTFontScriptsClass) { flags |= PDFFONT_SCRIPT; } CFNumberRef weightTrait = (CFNumberRef)CFDictionaryGetValue(traits, kCTFontWeightTrait); Float32 weight = 0; CFNumberGetValue(weightTrait, kCFNumberFloat32Type, &weight); italicangle = CTFontGetSlantAngle(font); ascend = CTFontGetAscent(font); descend = CTFontGetDescent(font); capheight = CTFontGetCapHeight(font); CGRect box = CTFontGetBoundingBox(font); bbox[0] = box.origin.x; bbox[1] = box.origin.y; bbox[2] = box.origin.x + box.size.width; bbox[3] = box.origin.y + box.size.height; if (bTranslateName && bCJK) { CFStringRef postName = CTFontCopyPostScriptName(font); _CFString2CFXByteString(postName, basefont); CFRelease(postName); } if (basefont.IsEmpty()) { CFStringRef fullName = CTFontCopyFullName(font); _CFString2CFXByteString(fullName, basefont); CFRelease(fullName); } basefont.Replace(" ", ""); CPDF_Dictionary* pFontDict = NULL; CPDF_Dictionary* pBaseDict = FX_NEW CPDF_Dictionary; pFontDict = pBaseDict; if (!bCJK) { charSets.RemoveAll(); charSets.Add(FXFONT_ANSI_CHARSET); charSets.Add(FXFONT_DEFAULT_CHARSET); charSets.Add(FXFONT_SYMBOL_CHARSET); if (IsHasCharSet(languages, charSets)) { charSets.RemoveAll(); charSets.Add(FXFONT_SYMBOL_CHARSET); if (IsHasCharSet(languages, charSets)) { flags |= PDFFONT_SYMBOLIC; } else { flags |= PDFFONT_NONSYMBOLIC; } pBaseDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding"); } else { flags |= PDFFONT_NONSYMBOLIC; int i; for (i = 0; i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes); i ++) { charSets.RemoveAll(); charSets.Add(g_FX_CharsetUnicodes[i].m_Charset); if (IsHasCharSet(languages, charSets)) { break; } } if (i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes)) { CPDF_Dictionary* pEncoding = FX_NEW CPDF_Dictionary; pEncoding->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding"); CPDF_Array* pArray = FX_NEW CPDF_Array; pArray->AddInteger(128); const FX_WCHAR* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes; for (int j = 0; j < 128; j ++) { CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]); if (name.IsEmpty()) { pArray->AddName(FX_BSTRC(".notdef")); } else { pArray->AddName(name); } } pEncoding->SetAt(FX_BSTRC("Differences"), pArray); AddIndirectObject(pEncoding); pBaseDict->SetAtReference(FX_BSTRC("Encoding"), this, pEncoding); } } if (weight > 0.0 && trait & kCTFontItalicTrait) { basefont += ",BoldItalic"; } else if (weight > 0.0) { basefont += ",Bold"; } else if (trait & kCTFontItalicTrait) { basefont += ",Italic"; } pBaseDict->SetAtName("Subtype", "TrueType"); pBaseDict->SetAtName("BaseFont", basefont); pBaseDict->SetAtNumber("FirstChar", 32); pBaseDict->SetAtNumber("LastChar", 255); int char_widths[224]; FX_GetCharWidth(font, 32, 255, char_widths); CPDF_Array* pWidths = FX_NEW CPDF_Array; for (int i = 0; i < 224; i ++) { pWidths->AddInteger(char_widths[i]); } pBaseDict->SetAt("Widths", pWidths); } else { flags |= PDFFONT_NONSYMBOLIC; CPDF_Array* pArray = NULL; pFontDict = FX_NEW CPDF_Dictionary; CFX_ByteString cmap; CFX_ByteString ordering; int supplement; FX_BOOL bFound = FALSE; CPDF_Array* pWidthArray = FX_NEW CPDF_Array; charSets.RemoveAll(); charSets.Add(FXFONT_CHINESEBIG5_CHARSET); if (IsHasCharSet(languages, charSets)) { cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H"; ordering = "CNS1"; supplement = 4; pWidthArray->AddInteger(1); _InsertWidthArray(font, 0x20, 0x7e, pWidthArray); bFound = TRUE; } charSets.RemoveAll(); charSets.Add(FXFONT_GB2312_CHARSET); if (!bFound && IsHasCharSet(languages, charSets)) { cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H"; ordering = "GB1", supplement = 2; pWidthArray->AddInteger(7716); _InsertWidthArray(font, 0x20, 0x20, pWidthArray); pWidthArray->AddInteger(814); _InsertWidthArray(font, 0x21, 0x7e, pWidthArray); bFound = TRUE; } charSets.RemoveAll(); charSets.Add(FXFONT_HANGEUL_CHARSET); if (!bFound && IsHasCharSet(languages, charSets)) { cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H"; ordering = "Korea1"; supplement = 2; pWidthArray->AddInteger(1); _InsertWidthArray(font, 0x20, 0x7e, pWidthArray); bFound = TRUE; } charSets.RemoveAll(); charSets.Add(FXFONT_SHIFTJIS_CHARSET); if (!bFound && IsHasCharSet(languages, charSets)) { cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H"; ordering = "Japan1"; supplement = 5; pWidthArray->AddInteger(231); _InsertWidthArray(font, 0x20, 0x7d, pWidthArray); pWidthArray->AddInteger(326); _InsertWidthArray(font, 0xa0, 0xa0, pWidthArray); pWidthArray->AddInteger(327); _InsertWidthArray(font, 0xa1, 0xdf, pWidthArray); pWidthArray->AddInteger(631); _InsertWidthArray(font, 0x7e, 0x7e, pWidthArray); } pBaseDict->SetAtName("Subtype", "Type0"); pBaseDict->SetAtName("BaseFont", basefont); pBaseDict->SetAtName("Encoding", cmap); pFontDict->SetAt("W", pWidthArray); pFontDict->SetAtName("Type", "Font"); pFontDict->SetAtName("Subtype", "CIDFontType2"); pFontDict->SetAtName("BaseFont", basefont); CPDF_Dictionary* pCIDSysInfo = FX_NEW CPDF_Dictionary; pCIDSysInfo->SetAtString("Registry", "Adobe"); pCIDSysInfo->SetAtString("Ordering", ordering); pCIDSysInfo->SetAtInteger("Supplement", supplement); pFontDict->SetAt("CIDSystemInfo", pCIDSysInfo); pArray = FX_NEW CPDF_Array; pBaseDict->SetAt("DescendantFonts", pArray); AddIndirectObject(pFontDict); pArray->AddReference(this, pFontDict); } AddIndirectObject(pBaseDict); CPDF_Dictionary* pFontDesc = FX_NEW CPDF_Dictionary; pFontDesc->SetAtName("Type", "FontDescriptor"); pFontDesc->SetAtName("FontName", basefont); pFontDesc->SetAtInteger("Flags", flags); CPDF_Array* pBBox = FX_NEW CPDF_Array; for (int i = 0; i < 4; i ++) { pBBox->AddInteger(bbox[i]); } pFontDesc->SetAt("FontBBox", pBBox); pFontDesc->SetAtInteger("ItalicAngle", italicangle); pFontDesc->SetAtInteger("Ascent", ascend); pFontDesc->SetAtInteger("Descent", descend); pFontDesc->SetAtInteger("CapHeight", capheight); CGFloat fStemV = 0; int16_t min_width = SHRT_MAX; static const UniChar stem_chars[] = {'i', 'I', '!', '1'}; const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]); CGGlyph glyphs[count]; CGRect boundingRects[count]; if (CTFontGetGlyphsForCharacters(font, stem_chars, glyphs, count)) { CTFontGetBoundingRectsForGlyphs(font, kCTFontHorizontalOrientation, glyphs, boundingRects, count); for (size_t i = 0; i < count; i++) { int16_t width = boundingRects[i].size.width; if (width > 0 && width < min_width) { min_width = width; fStemV = min_width; } } } pFontDesc->SetAtInteger("StemV", fStemV); AddIndirectObject(pFontDesc); pFontDict->SetAtReference("FontDescriptor", this, pFontDesc); CFRelease(traits); CFRelease(languages); return LoadFont(pBaseDict); }
CPDF_Font* CPDF_Document::AddWindowsFont(LOGFONTA* pLogFont, FX_BOOL bVert, FX_BOOL bTranslateName) { pLogFont->lfHeight = -1000; pLogFont->lfWidth = 0; HGDIOBJ hFont = CreateFontIndirectA(pLogFont); HDC hDC = CreateCompatibleDC(NULL); hFont = SelectObject(hDC, hFont); int tm_size = GetOutlineTextMetrics(hDC, 0, NULL); if (tm_size == 0) { hFont = SelectObject(hDC, hFont); DeleteObject(hFont); DeleteDC(hDC); return NULL; } LPBYTE tm_buf = FX_Alloc(BYTE, tm_size); OUTLINETEXTMETRIC* ptm = (OUTLINETEXTMETRIC*)tm_buf; GetOutlineTextMetrics(hDC, tm_size, ptm); int flags = 0, italicangle, ascend, descend, capheight, bbox[4]; if (pLogFont->lfItalic) { flags |= PDFFONT_ITALIC; } if ((pLogFont->lfPitchAndFamily & 3) == FIXED_PITCH) { flags |= PDFFONT_FIXEDPITCH; } if ((pLogFont->lfPitchAndFamily & 0xf8) == FF_ROMAN) { flags |= PDFFONT_SERIF; } if ((pLogFont->lfPitchAndFamily & 0xf8) == FF_SCRIPT) { flags |= PDFFONT_SCRIPT; } FX_BOOL bCJK = pLogFont->lfCharSet == CHINESEBIG5_CHARSET || pLogFont->lfCharSet == GB2312_CHARSET || pLogFont->lfCharSet == HANGEUL_CHARSET || pLogFont->lfCharSet == SHIFTJIS_CHARSET; CFX_ByteString basefont; if (bTranslateName && bCJK) { basefont = _FPDF_GetPSNameFromTT(hDC); } if (basefont.IsEmpty()) { basefont = pLogFont->lfFaceName; } italicangle = ptm->otmItalicAngle / 10; ascend = ptm->otmrcFontBox.top; descend = ptm->otmrcFontBox.bottom; capheight = ptm->otmsCapEmHeight; bbox[0] = ptm->otmrcFontBox.left; bbox[1] = ptm->otmrcFontBox.bottom; bbox[2] = ptm->otmrcFontBox.right; bbox[3] = ptm->otmrcFontBox.top; FX_Free(tm_buf); basefont.Replace(" ", ""); CPDF_Dictionary* pBaseDict = FX_NEW CPDF_Dictionary; pBaseDict->SetAtName("Type", "Font"); CPDF_Dictionary* pFontDict = pBaseDict; if (!bCJK) { if (pLogFont->lfCharSet == ANSI_CHARSET || pLogFont->lfCharSet == DEFAULT_CHARSET || pLogFont->lfCharSet == SYMBOL_CHARSET) { if (pLogFont->lfCharSet == SYMBOL_CHARSET) { flags |= PDFFONT_SYMBOLIC; } else { flags |= PDFFONT_NONSYMBOLIC; } pBaseDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding"); } else { flags |= PDFFONT_NONSYMBOLIC; int i; for (i = 0; i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes); i ++) if (g_FX_CharsetUnicodes[i].m_Charset == pLogFont->lfCharSet) { break; } if (i < sizeof g_FX_CharsetUnicodes / sizeof(FX_CharsetUnicodes)) { CPDF_Dictionary* pEncoding = FX_NEW CPDF_Dictionary; pEncoding->SetAtName(FX_BSTRC("BaseEncoding"), "WinAnsiEncoding"); CPDF_Array* pArray = FX_NEW CPDF_Array; pArray->AddInteger(128); const FX_WCHAR* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes; for (int j = 0; j < 128; j ++) { CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]); if (name.IsEmpty()) { pArray->AddName(FX_BSTRC(".notdef")); } else { pArray->AddName(name); } } pEncoding->SetAt(FX_BSTRC("Differences"), pArray); AddIndirectObject(pEncoding); pBaseDict->SetAtReference(FX_BSTRC("Encoding"), this, pEncoding); } } if (pLogFont->lfWeight > FW_MEDIUM && pLogFont->lfItalic) { basefont += ",BoldItalic"; } else if (pLogFont->lfWeight > FW_MEDIUM) { basefont += ",Bold"; } else if (pLogFont->lfItalic) { basefont += ",Italic"; } pBaseDict->SetAtName("Subtype", "TrueType"); pBaseDict->SetAtName("BaseFont", basefont); pBaseDict->SetAtNumber("FirstChar", 32); pBaseDict->SetAtNumber("LastChar", 255); int char_widths[224]; GetCharWidth(hDC, 32, 255, char_widths); CPDF_Array* pWidths = FX_NEW CPDF_Array; for (int i = 0; i < 224; i ++) { pWidths->AddInteger(char_widths[i]); } pBaseDict->SetAt("Widths", pWidths); } else { flags |= PDFFONT_NONSYMBOLIC; pFontDict = FX_NEW CPDF_Dictionary; CFX_ByteString cmap; CFX_ByteString ordering; int supplement; CPDF_Array* pWidthArray = FX_NEW CPDF_Array; switch (pLogFont->lfCharSet) { case CHINESEBIG5_CHARSET: cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H"; ordering = "CNS1"; supplement = 4; pWidthArray->AddInteger(1); _InsertWidthArray(hDC, 0x20, 0x7e, pWidthArray); break; case GB2312_CHARSET: cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H"; ordering = "GB1", supplement = 2; pWidthArray->AddInteger(7716); _InsertWidthArray(hDC, 0x20, 0x20, pWidthArray); pWidthArray->AddInteger(814); _InsertWidthArray(hDC, 0x21, 0x7e, pWidthArray); break; case HANGEUL_CHARSET: cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H"; ordering = "Korea1"; supplement = 2; pWidthArray->AddInteger(1); _InsertWidthArray(hDC, 0x20, 0x7e, pWidthArray); break; case SHIFTJIS_CHARSET: cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H"; ordering = "Japan1"; supplement = 5; pWidthArray->AddInteger(231); _InsertWidthArray(hDC, 0x20, 0x7d, pWidthArray); pWidthArray->AddInteger(326); _InsertWidthArray(hDC, 0xa0, 0xa0, pWidthArray); pWidthArray->AddInteger(327); _InsertWidthArray(hDC, 0xa1, 0xdf, pWidthArray); pWidthArray->AddInteger(631); _InsertWidthArray(hDC, 0x7e, 0x7e, pWidthArray); break; } pBaseDict->SetAtName("Subtype", "Type0"); pBaseDict->SetAtName("BaseFont", basefont); pBaseDict->SetAtName("Encoding", cmap); pFontDict->SetAt("W", pWidthArray); pFontDict->SetAtName("Type", "Font"); pFontDict->SetAtName("Subtype", "CIDFontType2"); pFontDict->SetAtName("BaseFont", basefont); CPDF_Dictionary* pCIDSysInfo = FX_NEW CPDF_Dictionary; pCIDSysInfo->SetAtString("Registry", "Adobe"); pCIDSysInfo->SetAtString("Ordering", ordering); pCIDSysInfo->SetAtInteger("Supplement", supplement); pFontDict->SetAt("CIDSystemInfo", pCIDSysInfo); CPDF_Array* pArray = FX_NEW CPDF_Array; pBaseDict->SetAt("DescendantFonts", pArray); AddIndirectObject(pFontDict); pArray->AddReference(this, pFontDict); } AddIndirectObject(pBaseDict); CPDF_Dictionary* pFontDesc = FX_NEW CPDF_Dictionary; pFontDesc->SetAtName("Type", "FontDescriptor"); pFontDesc->SetAtName("FontName", basefont); pFontDesc->SetAtInteger("Flags", flags); CPDF_Array* pBBox = FX_NEW CPDF_Array; for (int i = 0; i < 4; i ++) { pBBox->AddInteger(bbox[i]); } pFontDesc->SetAt("FontBBox", pBBox); pFontDesc->SetAtInteger("ItalicAngle", italicangle); pFontDesc->SetAtInteger("Ascent", ascend); pFontDesc->SetAtInteger("Descent", descend); pFontDesc->SetAtInteger("CapHeight", capheight); pFontDesc->SetAtInteger("StemV", pLogFont->lfWeight / 5); AddIndirectObject(pFontDesc); pFontDict->SetAtReference("FontDescriptor", this, pFontDesc); hFont = SelectObject(hDC, hFont); DeleteObject(hFont); DeleteDC(hDC); return LoadFont(pBaseDict); }