OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" | 7 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <set> | 10 #include <set> |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 if (size != GDI_ERROR) { | 213 if (size != GDI_ERROR) { |
214 LPBYTE buffer = FX_Alloc(BYTE, size); | 214 LPBYTE buffer = FX_Alloc(BYTE, size); |
215 ::GetFontData(hDC, 'eman', 0, buffer, size); | 215 ::GetFontData(hDC, 'eman', 0, buffer, size); |
216 result = GetNameFromTT(buffer, size, 6); | 216 result = GetNameFromTT(buffer, size, 6); |
217 FX_Free(buffer); | 217 FX_Free(buffer); |
218 } | 218 } |
219 return result; | 219 return result; |
220 } | 220 } |
221 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | 221 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ |
222 | 222 |
223 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
224 struct FX_LANG2CS { | |
225 uint32_t uLang; | |
226 uint8_t uCharset; | |
227 }; | |
228 const FX_LANG2CS gs_FXLang2CharsetTable[] = { | |
229 {3109, 0}, {3121, 178}, {3129, 162}, {3139, 204}, {3141, 204}, | |
230 {3166, 0}, {3184, 238}, {3197, 0}, {3201, 0}, {3239, 161}, | |
231 {3241, 0}, {3246, 0}, {3247, 186}, {3248, 0}, {3259, 178}, | |
232 {3267, 0}, {3273, 0}, {3276, 0}, {3301, 0}, {3310, 1}, | |
233 {3325, 177}, {3329, 1}, {3338, 238}, {3341, 238}, {3345, 1}, | |
234 {3355, 0}, {3370, 0}, {3371, 0}, {3383, 128}, {3424, 204}, | |
235 {3427, 1}, {3428, 129}, {3436, 178}, {3464, 186}, {3466, 186}, | |
236 {3486, 204}, {3487, 0}, {3493, 1}, {3494, 0}, {3508, 0}, | |
237 {3518, 0}, {3520, 0}, {3569, 1}, {3580, 238}, {3588, 0}, | |
238 {3645, 238}, {3651, 204}, {3672, 238}, {3673, 238}, {3678, 238}, | |
239 {3679, 238}, {3683, 0}, {3684, 0}, {3693, 1}, {3697, 1}, | |
240 {3700, 222}, {3710, 162}, {3734, 204}, {3741, 178}, {3749, 162}, | |
241 {3763, 163}, {3886, 134}, {105943, 0}, {106375, 1}, {3923451837, 134}, | |
242 {3923451838, 136}, | |
243 }; | |
244 | |
245 uint32_t FX_GetLangHashCode(const FX_CHAR* pStr) { | |
246 ASSERT(pStr); | |
247 int32_t iLength = FXSYS_strlen(pStr); | |
248 const FX_CHAR* pStrEnd = pStr + iLength; | |
249 uint32_t uHashCode = 0; | |
250 while (pStr < pStrEnd) | |
251 uHashCode = 31 * uHashCode + tolower(*pStr++); | |
252 return uHashCode; | |
253 } | |
254 | |
255 uint8_t FX_GetCsFromLangCode(uint32_t uCode) { | |
256 int32_t iStart = 0; | |
257 int32_t iEnd = FX_ArraySize(gs_FXLang2CharsetTable) - 1; | |
258 while (iStart <= iEnd) { | |
259 int32_t iMid = (iStart + iEnd) / 2; | |
260 const FX_LANG2CS& charset = gs_FXLang2CharsetTable[iMid]; | |
261 if (uCode == charset.uLang) | |
262 return charset.uCharset; | |
263 | |
264 if (uCode < charset.uLang) | |
265 iEnd = iMid - 1; | |
266 else | |
267 iStart = iMid + 1; | |
268 } | |
269 return FXFONT_ANSI_CHARSET; | |
270 } | |
271 | |
272 uint8_t FX_GetCharsetFromLang(const FX_CHAR* pLang, int32_t iLength) { | |
273 ASSERT(pLang); | |
274 if (iLength < 0) | |
275 iLength = FXSYS_strlen(pLang); | |
276 | |
277 uint32_t uHash = FX_GetLangHashCode(pLang); | |
278 return FX_GetCsFromLangCode(uHash); | |
279 } | |
280 | |
281 void CFString2CFXByteString(CFStringRef src, CFX_ByteString& dest) { | |
282 SInt32 len = CFStringGetLength(src); | |
283 CFRange range = CFRangeMake(0, len); | |
284 CFIndex used = 0; | |
285 UInt8* pBuffer = (UInt8*)calloc(len + 1, sizeof(UInt8)); | |
286 CFStringGetBytes(src, range, kCFStringEncodingASCII, 0, false, pBuffer, len, | |
287 &used); | |
288 dest = (FX_CHAR*)pBuffer; | |
289 free(pBuffer); | |
290 } | |
291 | |
292 bool HasCharSet(CFArrayRef languages, const std::vector<uint8_t>& charsets) { | |
293 for (int i = 0; i < CFArrayGetCount(languages); ++i) { | |
294 CFStringRef language = (CFStringRef)CFArrayGetValueAtIndex(languages, i); | |
295 uint8_t charset = FX_GetCharsetFromLang( | |
296 CFStringGetCStringPtr(language, kCFStringEncodingMacRoman), -1); | |
297 if (pdfium::ContainsValue(charsets, charset)) | |
298 return true; | |
299 } | |
300 return false; | |
301 } | |
302 | |
303 void FX_GetCharWidth(CTFontRef font, UniChar start, UniChar end, int* width) { | |
304 CGFloat size = CTFontGetSize(font); | |
305 for (; start <= end; ++start) { | |
306 CGGlyph pGlyph = 0; | |
307 CFIndex count = 1; | |
308 CTFontGetGlyphsForCharacters(font, &start, &pGlyph, count); | |
309 CGSize advances; | |
310 CTFontGetAdvancesForGlyphs(font, kCTFontDefaultOrientation, &pGlyph, | |
311 &advances, 1); | |
312 *width = (int)(advances.width / size * 1000); | |
313 width++; | |
314 } | |
315 } | |
316 | |
317 void InsertWidthArray(CTFontRef font, | |
318 int start, | |
319 int end, | |
320 CPDF_Array* pWidthArray) { | |
321 int size = end - start + 1; | |
322 int* widths = FX_Alloc(int, size); | |
323 FX_GetCharWidth(font, start, end, widths); | |
324 int i; | |
325 for (i = 1; i < size; i++) { | |
326 if (widths[i] != *widths) | |
327 break; | |
328 } | |
329 if (i == size) { | |
330 int first = pWidthArray->GetIntegerAt(pWidthArray->GetCount() - 1); | |
331 pWidthArray->AddInteger(first + size - 1); | |
332 pWidthArray->AddInteger(*widths); | |
333 } else { | |
334 CPDF_Array* pWidthArray1 = new CPDF_Array; | |
335 pWidthArray->Add(pWidthArray1); | |
336 for (i = 0; i < size; i++) { | |
337 pWidthArray1->AddInteger(widths[i]); | |
338 } | |
339 } | |
340 FX_Free(widths); | |
341 } | |
342 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
343 | |
344 void InsertWidthArray1(CFX_Font* pFont, | 223 void InsertWidthArray1(CFX_Font* pFont, |
345 CFX_UnicodeEncoding* pEncoding, | 224 CFX_UnicodeEncoding* pEncoding, |
346 FX_WCHAR start, | 225 FX_WCHAR start, |
347 FX_WCHAR end, | 226 FX_WCHAR end, |
348 CPDF_Array* pWidthArray) { | 227 CPDF_Array* pWidthArray) { |
349 int size = end - start + 1; | 228 int size = end - start + 1; |
350 int* widths = FX_Alloc(int, size); | 229 int* widths = FX_Alloc(int, size); |
351 int i; | 230 int i; |
352 for (i = 0; i < size; i++) { | 231 for (i = 0; i < size; i++) { |
353 int glyph_index = pEncoding->GlyphFromCharCode(start + i); | 232 int glyph_index = pEncoding->GlyphFromCharCode(start + i); |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 if (!pRootObj) | 392 if (!pRootObj) |
514 return; | 393 return; |
515 | 394 |
516 m_pRootDict = pRootObj->GetDict(); | 395 m_pRootDict = pRootObj->GetDict(); |
517 if (!m_pRootDict) | 396 if (!m_pRootDict) |
518 return; | 397 return; |
519 | 398 |
520 CPDF_Object* pInfoObj = GetOrParseIndirectObject(m_pParser->GetInfoObjNum()); | 399 CPDF_Object* pInfoObj = GetOrParseIndirectObject(m_pParser->GetInfoObjNum()); |
521 if (pInfoObj) | 400 if (pInfoObj) |
522 m_pInfoDict = pInfoObj->GetDict(); | 401 m_pInfoDict = pInfoObj->GetDict(); |
523 if (CPDF_Array* pIDArray = m_pParser->GetIDArray()) { | |
524 m_ID1 = pIDArray->GetStringAt(0); | |
525 m_ID2 = pIDArray->GetStringAt(1); | |
526 } | |
527 } | 402 } |
528 | 403 |
529 void CPDF_Document::LoadDoc() { | 404 void CPDF_Document::LoadDoc() { |
530 LoadDocInternal(); | 405 LoadDocInternal(); |
531 m_PageList.SetSize(RetrievePageCount()); | 406 m_PageList.SetSize(RetrievePageCount()); |
532 } | 407 } |
533 | 408 |
534 void CPDF_Document::LoadLinearizedDoc(CPDF_Dictionary* pLinearizationParams) { | 409 void CPDF_Document::LoadLinearizedDoc(CPDF_Dictionary* pLinearizationParams) { |
535 m_bLinearized = true; | 410 m_bLinearized = true; |
536 LoadDocInternal(); | 411 LoadDocInternal(); |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
729 if (!m_pParser) { | 604 if (!m_pParser) { |
730 #ifndef PDF_ENABLE_XFA | 605 #ifndef PDF_ENABLE_XFA |
731 return 0; | 606 return 0; |
732 #else // PDF_ENABLE_XFA | 607 #else // PDF_ENABLE_XFA |
733 return 0xFFFFFFFF; | 608 return 0xFFFFFFFF; |
734 #endif | 609 #endif |
735 } | 610 } |
736 return m_pParser->GetPermissions(); | 611 return m_pParser->GetPermissions(); |
737 } | 612 } |
738 | 613 |
739 FX_BOOL CPDF_Document::IsFormStream(uint32_t objnum, FX_BOOL& bForm) const { | |
740 CPDF_Object* pObj = GetIndirectObject(objnum); | |
741 if (pObj) { | |
742 CPDF_Stream* pStream = pObj->AsStream(); | |
743 bForm = pStream && pStream->GetDict()->GetStringBy("Subtype") == "Form"; | |
744 return TRUE; | |
745 } | |
746 if (!m_pParser) { | |
747 bForm = FALSE; | |
748 return TRUE; | |
749 } | |
750 return m_pParser->IsFormStream(objnum, bForm); | |
751 } | |
752 | |
753 CPDF_Font* CPDF_Document::LoadFont(CPDF_Dictionary* pFontDict) { | 614 CPDF_Font* CPDF_Document::LoadFont(CPDF_Dictionary* pFontDict) { |
754 ASSERT(pFontDict); | 615 ASSERT(pFontDict); |
755 return m_pDocPage->GetFont(pFontDict, FALSE); | 616 return m_pDocPage->GetFont(pFontDict, FALSE); |
756 } | 617 } |
757 | 618 |
758 CPDF_StreamAcc* CPDF_Document::LoadFontFile(CPDF_Stream* pStream) { | 619 CPDF_StreamAcc* CPDF_Document::LoadFontFile(CPDF_Stream* pStream) { |
759 return m_pDocPage->GetFontFileStreamAcc(pStream); | 620 return m_pDocPage->GetFontFileStreamAcc(pStream); |
760 } | 621 } |
761 | 622 |
762 CPDF_ColorSpace* CPDF_Document::LoadColorSpace(CPDF_Object* pCSObj, | 623 CPDF_ColorSpace* CPDF_Document::LoadColorSpace(CPDF_Object* pCSObj, |
(...skipping 12 matching lines...) Expand all Loading... |
775 } | 636 } |
776 | 637 |
777 CPDF_Image* CPDF_Document::LoadImageF(CPDF_Object* pObj) { | 638 CPDF_Image* CPDF_Document::LoadImageF(CPDF_Object* pObj) { |
778 if (!pObj) | 639 if (!pObj) |
779 return nullptr; | 640 return nullptr; |
780 | 641 |
781 ASSERT(pObj->GetObjNum()); | 642 ASSERT(pObj->GetObjNum()); |
782 return m_pDocPage->GetImage(pObj); | 643 return m_pDocPage->GetImage(pObj); |
783 } | 644 } |
784 | 645 |
785 void CPDF_Document::RemoveColorSpaceFromPageData(CPDF_Object* pCSObj) { | |
786 GetPageData()->ReleaseColorSpace(pCSObj); | |
787 } | |
788 | |
789 void CPDF_Document::ClearPageData() { | |
790 GetPageData()->Clear(FALSE); | |
791 } | |
792 | |
793 void CPDF_Document::ClearRenderData() { | |
794 m_pDocRender->Clear(FALSE); | |
795 } | |
796 | |
797 void CPDF_Document::ClearRenderFont() { | |
798 CFX_FontCache* pCache = m_pDocRender->GetFontCache(); | |
799 if (pCache) | |
800 pCache->FreeCache(FALSE); | |
801 } | |
802 | |
803 void CPDF_Document::CreateNewDoc() { | 646 void CPDF_Document::CreateNewDoc() { |
804 ASSERT(!m_pRootDict && !m_pInfoDict); | 647 ASSERT(!m_pRootDict && !m_pInfoDict); |
805 m_pRootDict = new CPDF_Dictionary; | 648 m_pRootDict = new CPDF_Dictionary; |
806 m_pRootDict->SetAtName("Type", "Catalog"); | 649 m_pRootDict->SetAtName("Type", "Catalog"); |
807 int objnum = AddIndirectObject(m_pRootDict); | 650 int objnum = AddIndirectObject(m_pRootDict); |
808 CPDF_Dictionary* pPages = new CPDF_Dictionary; | 651 CPDF_Dictionary* pPages = new CPDF_Dictionary; |
809 pPages->SetAtName("Type", "Pages"); | 652 pPages->SetAtName("Type", "Pages"); |
810 pPages->SetAtNumber("Count", 0); | 653 pPages->SetAtNumber("Count", 0); |
811 pPages->SetAt("Kids", new CPDF_Array); | 654 pPages->SetAt("Kids", new CPDF_Array); |
812 objnum = AddIndirectObject(pPages); | 655 objnum = AddIndirectObject(pPages); |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1229 pFontDesc->SetAtInteger("CapHeight", capheight); | 1072 pFontDesc->SetAtInteger("CapHeight", capheight); |
1230 pFontDesc->SetAtInteger("StemV", pLogFont->lfWeight / 5); | 1073 pFontDesc->SetAtInteger("StemV", pLogFont->lfWeight / 5); |
1231 AddIndirectObject(pFontDesc); | 1074 AddIndirectObject(pFontDesc); |
1232 pFontDict->SetAtReference("FontDescriptor", this, pFontDesc); | 1075 pFontDict->SetAtReference("FontDescriptor", this, pFontDesc); |
1233 hFont = SelectObject(hDC, hFont); | 1076 hFont = SelectObject(hDC, hFont); |
1234 DeleteObject(hFont); | 1077 DeleteObject(hFont); |
1235 DeleteDC(hDC); | 1078 DeleteDC(hDC); |
1236 return LoadFont(pBaseDict); | 1079 return LoadFont(pBaseDict); |
1237 } | 1080 } |
1238 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | 1081 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ |
1239 | |
1240 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
1241 CPDF_Font* CPDF_Document::AddMacFont(CTFontRef pFont, | |
1242 FX_BOOL bVert, | |
1243 FX_BOOL bTranslateName) { | |
1244 CTFontRef font = (CTFontRef)pFont; | |
1245 CTFontDescriptorRef descriptor = CTFontCopyFontDescriptor(font); | |
1246 if (!descriptor) | |
1247 return nullptr; | |
1248 | |
1249 CFArrayRef languages = (CFArrayRef)CTFontDescriptorCopyAttribute( | |
1250 descriptor, kCTFontLanguagesAttribute); | |
1251 if (!languages) { | |
1252 CFRelease(descriptor); | |
1253 return nullptr; | |
1254 } | |
1255 | |
1256 bool bCJK = | |
1257 HasCharSet(languages, {FXFONT_CHINESEBIG5_CHARSET, FXFONT_GB2312_CHARSET, | |
1258 FXFONT_HANGEUL_CHARSET, FXFONT_SHIFTJIS_CHARSET}); | |
1259 CFRelease(descriptor); | |
1260 CFDictionaryRef traits = (CFDictionaryRef)CTFontCopyTraits(font); | |
1261 if (!traits) { | |
1262 CFRelease(languages); | |
1263 return nullptr; | |
1264 } | |
1265 | |
1266 CFNumberRef sybolicTrait = | |
1267 (CFNumberRef)CFDictionaryGetValue(traits, kCTFontSymbolicTrait); | |
1268 CTFontSymbolicTraits trait = 0; | |
1269 CFNumberGetValue(sybolicTrait, kCFNumberSInt32Type, &trait); | |
1270 int flags = 0; | |
1271 if (trait & kCTFontItalicTrait) | |
1272 flags |= PDFFONT_ITALIC; | |
1273 if (trait & kCTFontMonoSpaceTrait) | |
1274 flags |= PDFFONT_FIXEDPITCH; | |
1275 if (trait & kCTFontModernSerifsClass) | |
1276 flags |= PDFFONT_SERIF; | |
1277 if (trait & kCTFontScriptsClass) | |
1278 flags |= PDFFONT_SCRIPT; | |
1279 | |
1280 CFNumberRef weightTrait = | |
1281 (CFNumberRef)CFDictionaryGetValue(traits, kCTFontWeightTrait); | |
1282 Float32 weight = 0; | |
1283 CFNumberGetValue(weightTrait, kCFNumberFloat32Type, &weight); | |
1284 int italicangle = CTFontGetSlantAngle(font); | |
1285 int ascend = CTFontGetAscent(font); | |
1286 int descend = CTFontGetDescent(font); | |
1287 int capheight = CTFontGetCapHeight(font); | |
1288 CGRect box = CTFontGetBoundingBox(font); | |
1289 int bbox[4]; | |
1290 bbox[0] = box.origin.x; | |
1291 bbox[1] = box.origin.y; | |
1292 bbox[2] = box.origin.x + box.size.width; | |
1293 bbox[3] = box.origin.y + box.size.height; | |
1294 CFX_ByteString basefont; | |
1295 if (bTranslateName && bCJK) { | |
1296 CFStringRef postName = CTFontCopyPostScriptName(font); | |
1297 CFString2CFXByteString(postName, basefont); | |
1298 CFRelease(postName); | |
1299 } | |
1300 if (basefont.IsEmpty()) { | |
1301 CFStringRef fullName = CTFontCopyFullName(font); | |
1302 CFString2CFXByteString(fullName, basefont); | |
1303 CFRelease(fullName); | |
1304 } | |
1305 basefont.Replace(" ", ""); | |
1306 CPDF_Dictionary* pBaseDict = new CPDF_Dictionary; | |
1307 CPDF_Dictionary* pFontDict = pBaseDict; | |
1308 if (!bCJK) { | |
1309 if (HasCharSet(languages, {FXFONT_ANSI_CHARSET, FXFONT_DEFAULT_CHARSET, | |
1310 FXFONT_SYMBOL_CHARSET})) { | |
1311 if (HasCharSet(languages, {FXFONT_SYMBOL_CHARSET})) { | |
1312 flags |= PDFFONT_SYMBOLIC; | |
1313 } else { | |
1314 flags |= PDFFONT_NONSYMBOLIC; | |
1315 } | |
1316 pBaseDict->SetAtName("Encoding", "WinAnsiEncoding"); | |
1317 } else { | |
1318 flags |= PDFFONT_NONSYMBOLIC; | |
1319 size_t i; | |
1320 for (i = 0; i < FX_ArraySize(g_FX_CharsetUnicodes); ++i) { | |
1321 if (HasCharSet(languages, {g_FX_CharsetUnicodes[i].m_Charset})) | |
1322 break; | |
1323 } | |
1324 if (i < FX_ArraySize(g_FX_CharsetUnicodes)) { | |
1325 CPDF_Dictionary* pEncoding = new CPDF_Dictionary; | |
1326 pEncoding->SetAtName("BaseEncoding", "WinAnsiEncoding"); | |
1327 CPDF_Array* pArray = new CPDF_Array; | |
1328 pArray->AddInteger(128); | |
1329 const uint16_t* pUnicodes = g_FX_CharsetUnicodes[i].m_pUnicodes; | |
1330 for (int j = 0; j < 128; j++) { | |
1331 CFX_ByteString name = PDF_AdobeNameFromUnicode(pUnicodes[j]); | |
1332 pArray->AddName(name.IsEmpty() ? ".notdef" : name); | |
1333 } | |
1334 pEncoding->SetAt("Differences", pArray); | |
1335 AddIndirectObject(pEncoding); | |
1336 pBaseDict->SetAtReference("Encoding", this, pEncoding); | |
1337 } | |
1338 } | |
1339 if (weight > 0.0 && trait & kCTFontItalicTrait) | |
1340 basefont += ",BoldItalic"; | |
1341 else if (weight > 0.0) | |
1342 basefont += ",Bold"; | |
1343 else if (trait & kCTFontItalicTrait) | |
1344 basefont += ",Italic"; | |
1345 | |
1346 pBaseDict->SetAtName("Subtype", "TrueType"); | |
1347 pBaseDict->SetAtName("BaseFont", basefont); | |
1348 pBaseDict->SetAtNumber("FirstChar", 32); | |
1349 pBaseDict->SetAtNumber("LastChar", 255); | |
1350 int char_widths[224]; | |
1351 FX_GetCharWidth(font, 32, 255, char_widths); | |
1352 CPDF_Array* pWidths = new CPDF_Array; | |
1353 for (int i = 0; i < 224; i++) | |
1354 pWidths->AddInteger(char_widths[i]); | |
1355 pBaseDict->SetAt("Widths", pWidths); | |
1356 } else { | |
1357 flags |= PDFFONT_NONSYMBOLIC; | |
1358 CFX_ByteString cmap; | |
1359 CFX_ByteString ordering; | |
1360 int supplement; | |
1361 bool bFound = false; | |
1362 CPDF_Array* pWidthArray = new CPDF_Array; | |
1363 if (HasCharSet(languages, {FXFONT_CHINESEBIG5_CHARSET})) { | |
1364 cmap = bVert ? "ETenms-B5-V" : "ETenms-B5-H"; | |
1365 ordering = "CNS1"; | |
1366 supplement = 4; | |
1367 pWidthArray->AddInteger(1); | |
1368 InsertWidthArray(font, 0x20, 0x7e, pWidthArray); | |
1369 bFound = true; | |
1370 } | |
1371 if (!bFound && HasCharSet(languages, {FXFONT_GB2312_CHARSET})) { | |
1372 cmap = bVert ? "GBK-EUC-V" : "GBK-EUC-H"; | |
1373 ordering = "GB1", supplement = 2; | |
1374 pWidthArray->AddInteger(7716); | |
1375 InsertWidthArray(font, 0x20, 0x20, pWidthArray); | |
1376 pWidthArray->AddInteger(814); | |
1377 InsertWidthArray(font, 0x21, 0x7e, pWidthArray); | |
1378 bFound = true; | |
1379 } | |
1380 if (!bFound && HasCharSet(languages, {FXFONT_HANGEUL_CHARSET})) { | |
1381 cmap = bVert ? "KSCms-UHC-V" : "KSCms-UHC-H"; | |
1382 ordering = "Korea1"; | |
1383 supplement = 2; | |
1384 pWidthArray->AddInteger(1); | |
1385 InsertWidthArray(font, 0x20, 0x7e, pWidthArray); | |
1386 bFound = true; | |
1387 } | |
1388 if (!bFound && HasCharSet(languages, {FXFONT_SHIFTJIS_CHARSET})) { | |
1389 cmap = bVert ? "90ms-RKSJ-V" : "90ms-RKSJ-H"; | |
1390 ordering = "Japan1"; | |
1391 supplement = 5; | |
1392 pWidthArray->AddInteger(231); | |
1393 InsertWidthArray(font, 0x20, 0x7d, pWidthArray); | |
1394 pWidthArray->AddInteger(326); | |
1395 InsertWidthArray(font, 0xa0, 0xa0, pWidthArray); | |
1396 pWidthArray->AddInteger(327); | |
1397 InsertWidthArray(font, 0xa1, 0xdf, pWidthArray); | |
1398 pWidthArray->AddInteger(631); | |
1399 InsertWidthArray(font, 0x7e, 0x7e, pWidthArray); | |
1400 } | |
1401 pBaseDict->SetAtName("Subtype", "Type0"); | |
1402 pBaseDict->SetAtName("BaseFont", basefont); | |
1403 pBaseDict->SetAtName("Encoding", cmap); | |
1404 | |
1405 pFontDict = new CPDF_Dictionary; | |
1406 pFontDict->SetAt("W", pWidthArray); | |
1407 pFontDict->SetAtName("Type", "Font"); | |
1408 pFontDict->SetAtName("Subtype", "CIDFontType2"); | |
1409 pFontDict->SetAtName("BaseFont", basefont); | |
1410 CPDF_Dictionary* pCIDSysInfo = new CPDF_Dictionary; | |
1411 pCIDSysInfo->SetAtString("Registry", "Adobe"); | |
1412 pCIDSysInfo->SetAtString("Ordering", ordering); | |
1413 pCIDSysInfo->SetAtInteger("Supplement", supplement); | |
1414 pFontDict->SetAt("CIDSystemInfo", pCIDSysInfo); | |
1415 CPDF_Array* pArray = new CPDF_Array; | |
1416 pBaseDict->SetAt("DescendantFonts", pArray); | |
1417 AddIndirectObject(pFontDict); | |
1418 pArray->AddReference(this, pFontDict); | |
1419 } | |
1420 AddIndirectObject(pBaseDict); | |
1421 CPDF_Dictionary* pFontDesc = new CPDF_Dictionary; | |
1422 pFontDesc->SetAtName("Type", "FontDescriptor"); | |
1423 pFontDesc->SetAtName("FontName", basefont); | |
1424 pFontDesc->SetAtInteger("Flags", flags); | |
1425 CPDF_Array* pBBox = new CPDF_Array; | |
1426 for (int i = 0; i < 4; i++) | |
1427 pBBox->AddInteger(bbox[i]); | |
1428 | |
1429 pFontDesc->SetAt("FontBBox", pBBox); | |
1430 pFontDesc->SetAtInteger("ItalicAngle", italicangle); | |
1431 pFontDesc->SetAtInteger("Ascent", ascend); | |
1432 pFontDesc->SetAtInteger("Descent", descend); | |
1433 pFontDesc->SetAtInteger("CapHeight", capheight); | |
1434 CGFloat fStemV = 0; | |
1435 int16_t min_width = SHRT_MAX; | |
1436 | |
1437 static const UniChar stem_chars[] = {'i', 'I', '!', '1'}; | |
1438 CGGlyph glyphs[FX_ArraySize(stem_chars)]; | |
1439 CGRect boundingRects[FX_ArraySize(stem_chars)]; | |
1440 | |
1441 const size_t count = FX_ArraySize(stem_chars); | |
1442 if (CTFontGetGlyphsForCharacters(font, stem_chars, glyphs, count)) { | |
1443 CTFontGetBoundingRectsForGlyphs(font, kCTFontHorizontalOrientation, glyphs, | |
1444 boundingRects, count); | |
1445 for (size_t i = 0; i < count; i++) { | |
1446 int16_t width = boundingRects[i].size.width; | |
1447 if (width > 0 && width < min_width) { | |
1448 min_width = width; | |
1449 fStemV = min_width; | |
1450 } | |
1451 } | |
1452 } | |
1453 pFontDesc->SetAtInteger("StemV", fStemV); | |
1454 AddIndirectObject(pFontDesc); | |
1455 pFontDict->SetAtReference("FontDescriptor", this, pFontDesc); | |
1456 CFRelease(traits); | |
1457 CFRelease(languages); | |
1458 return LoadFont(pBaseDict); | |
1459 } | |
1460 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
OLD | NEW |