1// Copyright 2014 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// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7#include "../../include/pdfwindow/PDFWindow.h" 8#include "../../include/pdfwindow/PWL_Wnd.h" 9#include "../../include/pdfwindow/PWL_FontMap.h" 10 11#define DEFAULT_FONT_NAME "Helvetica" 12 13/* ------------------------------ CPWL_FontMap ------------------------------ */ 14 15CPWL_FontMap::CPWL_FontMap(IFX_SystemHandler* pSystemHandler) : 16 m_pPDFDoc(NULL), 17 m_pSystemHandler(pSystemHandler) 18{ 19 ASSERT(m_pSystemHandler != NULL); 20} 21 22CPWL_FontMap::~CPWL_FontMap() 23{ 24 if (m_pPDFDoc) 25 { 26 delete m_pPDFDoc; 27 m_pPDFDoc = NULL; 28 } 29 30 Empty(); 31} 32 33void CPWL_FontMap::SetSystemHandler(IFX_SystemHandler* pSystemHandler) 34{ 35 m_pSystemHandler = pSystemHandler; 36} 37 38CPDF_Document* CPWL_FontMap::GetDocument() 39{ 40 if (!m_pPDFDoc) 41 { 42 if (CPDF_ModuleMgr::Get()) 43 { 44 m_pPDFDoc = new CPDF_Document; 45 m_pPDFDoc->CreateNewDoc(); 46 } 47 } 48 49 return m_pPDFDoc; 50} 51 52CPDF_Font* CPWL_FontMap::GetPDFFont(FX_INT32 nFontIndex) 53{ 54 if (nFontIndex >=0 && nFontIndex < m_aData.GetSize()) 55 { 56 if (CPWL_FontMap_Data* pData = m_aData.GetAt(nFontIndex)) 57 { 58 return pData->pFont; 59 } 60 } 61 62 return NULL; 63} 64 65CFX_ByteString CPWL_FontMap::GetPDFFontAlias(FX_INT32 nFontIndex) 66{ 67 if (nFontIndex >=0 && nFontIndex < m_aData.GetSize()) 68 { 69 if (CPWL_FontMap_Data* pData = m_aData.GetAt(nFontIndex)) 70 { 71 return pData->sFontName; 72 } 73 } 74 75 return ""; 76} 77 78FX_BOOL CPWL_FontMap::KnowWord(FX_INT32 nFontIndex, FX_WORD word) 79{ 80 if (nFontIndex >=0 && nFontIndex < m_aData.GetSize()) 81 { 82 if (m_aData.GetAt(nFontIndex)) 83 { 84 return CharCodeFromUnicode(nFontIndex, word) >= 0; 85 } 86 } 87 88 return FALSE; 89} 90 91FX_INT32 CPWL_FontMap::GetWordFontIndex(FX_WORD word, FX_INT32 nCharset, FX_INT32 nFontIndex) 92{ 93 if (nFontIndex > 0) 94 { 95 if (KnowWord(nFontIndex, word)) 96 return nFontIndex; 97 } 98 else 99 { 100 if (const CPWL_FontMap_Data* pData = GetFontMapData(0)) 101 { 102 if (nCharset == DEFAULT_CHARSET || 103 pData->nCharset == SYMBOL_CHARSET || 104 nCharset == pData->nCharset) 105 { 106 if (KnowWord(0, word)) 107 { 108 return 0; 109 } 110 } 111 } 112 } 113 114 FX_INT32 nNewFontIndex = -1; 115 116 nNewFontIndex = this->GetFontIndex(GetNativeFontName(nCharset), nCharset, TRUE); 117 if (nNewFontIndex >= 0) 118 { 119 if (KnowWord(nNewFontIndex, word)) 120 return nNewFontIndex; 121 } 122 123 nNewFontIndex = this->GetFontIndex("Arial Unicode MS", DEFAULT_CHARSET, FALSE); 124 if (nNewFontIndex >= 0) 125 { 126 if (KnowWord(nNewFontIndex, word)) 127 return nNewFontIndex; 128 } 129 130 return -1; 131} 132 133FX_INT32 CPWL_FontMap::CharCodeFromUnicode(FX_INT32 nFontIndex, FX_WORD word) 134{ 135 if (CPWL_FontMap_Data* pData = m_aData.GetAt(nFontIndex)) 136 { 137 if (pData->pFont) 138 { 139 if (pData->pFont->IsUnicodeCompatible()) 140 { 141 int nCharCode = pData->pFont->CharCodeFromUnicode(word); 142 pData->pFont->GlyphFromCharCode(nCharCode); 143 return nCharCode; 144 } 145 else 146 { 147 if (word < 0xFF) 148 return word; 149 } 150 } 151 } 152 153 return -1; 154} 155 156CFX_ByteString CPWL_FontMap::GetNativeFontName(FX_INT32 nCharset) 157{ 158 //searching native font is slow, so we must save time 159 for (FX_INT32 i=0,sz=m_aNativeFont.GetSize(); i<sz; i++) 160 { 161 if (CPWL_FontMap_Native* pData = m_aNativeFont.GetAt(i)) 162 { 163 if (pData->nCharset == nCharset) 164 return pData->sFontName; 165 } 166 } 167 168 CFX_ByteString sNew = GetNativeFont(nCharset); 169 170 if (!sNew.IsEmpty()) 171 { 172 CPWL_FontMap_Native* pNewData = new CPWL_FontMap_Native; 173 pNewData->nCharset = nCharset; 174 pNewData->sFontName = sNew; 175 176 m_aNativeFont.Add(pNewData); 177 } 178 179 return sNew; 180} 181 182void CPWL_FontMap::Empty() 183{ 184 { 185 for (FX_INT32 i=0, sz=m_aData.GetSize(); i<sz; i++) 186 delete m_aData.GetAt(i); 187 188 m_aData.RemoveAll(); 189 } 190 { 191 for (FX_INT32 i=0, sz=m_aNativeFont.GetSize(); i<sz; i++) 192 delete m_aNativeFont.GetAt(i); 193 194 m_aNativeFont.RemoveAll(); 195 } 196} 197 198void CPWL_FontMap::Initial(FX_LPCSTR fontname) 199{ 200 CFX_ByteString sFontName = fontname; 201 202 if (sFontName.IsEmpty()) 203 sFontName = DEFAULT_FONT_NAME; 204 205 GetFontIndex(sFontName, ANSI_CHARSET, FALSE); 206 207 //GetFontIndex(this->GetNativeFontName(nCharset), nCharset); 208} 209 210 211/* 212List of currently supported standard fonts: 213Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique 214Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique 215Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic 216Symbol, ZapfDingbats 217*/ 218 219const char* g_sDEStandardFontName[] = {"Courier", "Courier-Bold", "Courier-BoldOblique", "Courier-Oblique", 220 "Helvetica", "Helvetica-Bold", "Helvetica-BoldOblique", "Helvetica-Oblique", 221 "Times-Roman", "Times-Bold", "Times-Italic", "Times-BoldItalic", 222 "Symbol", "ZapfDingbats"}; 223 224FX_BOOL CPWL_FontMap::IsStandardFont(const CFX_ByteString& sFontName) 225{ 226 for (FX_INT32 i=0; i<14; i++) 227 { 228 if (sFontName == g_sDEStandardFontName[i]) 229 return TRUE; 230 } 231 232 return FALSE; 233} 234 235FX_INT32 CPWL_FontMap::FindFont(const CFX_ByteString& sFontName, FX_INT32 nCharset) 236{ 237 for (FX_INT32 i=0,sz=m_aData.GetSize(); i<sz; i++) 238 { 239 if (CPWL_FontMap_Data* pData = m_aData.GetAt(i)) 240 { 241 if (nCharset == DEFAULT_CHARSET || nCharset == pData->nCharset) 242 { 243 if (sFontName.IsEmpty() || pData->sFontName == sFontName) 244 return i; 245 } 246 } 247 } 248 249 return -1; 250} 251 252FX_INT32 CPWL_FontMap::GetFontIndex(const CFX_ByteString& sFontName, FX_INT32 nCharset, FX_BOOL bFind) 253{ 254 FX_INT32 nFontIndex = FindFont(EncodeFontAlias(sFontName, nCharset), nCharset); 255 if (nFontIndex >= 0) return nFontIndex; 256 257// nFontIndex = FindFont("", nCharset); 258// if (nFontIndex >= 0) return nFontIndex; 259 260 CFX_ByteString sAlias; 261 CPDF_Font* pFont = NULL; 262 263 if (bFind) 264 pFont = FindFontSameCharset(sAlias, nCharset); 265 266 if (!pFont) 267 { 268 CFX_ByteString sTemp = sFontName; 269 pFont = AddFontToDocument(GetDocument(), sTemp, nCharset); 270 271 /* 272 if (FindFont(sAlias)) 273 { 274 sAlias = EncodeFontAlias(sTemp, nCharset); 275 } 276 else 277 */ 278 { 279 sAlias = EncodeFontAlias(sTemp, nCharset); 280 } 281 } 282 283 AddedFont(pFont, sAlias); 284 285 return AddFontData(pFont, sAlias, nCharset); 286} 287 288FX_INT32 CPWL_FontMap::GetPWLFontIndex(FX_WORD word, FX_INT32 nCharset) 289{ 290 FX_INT32 nFind = -1; 291 292 for (FX_INT32 i=0,sz=m_aData.GetSize(); i<sz; i++) 293 { 294 if (CPWL_FontMap_Data* pData = m_aData.GetAt(i)) 295 { 296 if (pData->nCharset == nCharset) 297 { 298 nFind = i; 299 break; 300 } 301 } 302 } 303 304 CPDF_Font* pNewFont = GetPDFFont(nFind); 305 306 if (!pNewFont) return -1; 307 308 /* 309 if (CPDF_Font* pFont = GetPDFFont(nFind)) 310 { 311 PWLFont.AddWordToFontDict(pFontDict, word); 312 } 313 */ 314 315 CFX_ByteString sAlias = EncodeFontAlias("Arial_Chrome", nCharset); 316 AddedFont(pNewFont, sAlias); 317 318 return AddFontData(pNewFont, sAlias, nCharset); 319} 320 321CPDF_Font* CPWL_FontMap::FindFontSameCharset(CFX_ByteString& sFontAlias, FX_INT32 nCharset) 322{ 323 return NULL; 324} 325 326FX_INT32 CPWL_FontMap::AddFontData(CPDF_Font* pFont, const CFX_ByteString& sFontAlias, FX_INT32 nCharset) 327{ 328 CPWL_FontMap_Data* pNewData = new CPWL_FontMap_Data; 329 pNewData->pFont = pFont; 330 pNewData->sFontName = sFontAlias; 331 pNewData->nCharset = nCharset; 332 333 m_aData.Add(pNewData); 334 335 return m_aData.GetSize() -1; 336} 337 338void CPWL_FontMap::AddedFont(CPDF_Font* pFont, const CFX_ByteString& sFontAlias) 339{ 340} 341 342CFX_ByteString CPWL_FontMap::GetFontName(FX_INT32 nFontIndex) 343{ 344 if (nFontIndex >=0 && nFontIndex < m_aData.GetSize()) 345 { 346 if (CPWL_FontMap_Data* pData = m_aData.GetAt(nFontIndex)) 347 { 348 return pData->sFontName; 349 } 350 } 351 352 return ""; 353} 354 355CFX_ByteString CPWL_FontMap::GetNativeFont(FX_INT32 nCharset) 356{ 357 CFX_ByteString sFontName; 358 359 if (nCharset == DEFAULT_CHARSET) 360 nCharset = GetNativeCharset(); 361 362 sFontName = GetDefaultFontByCharset(nCharset); 363 364 if (m_pSystemHandler) 365 { 366 if (m_pSystemHandler->FindNativeTrueTypeFont(nCharset, sFontName)) 367 return sFontName; 368 369 sFontName = m_pSystemHandler->GetNativeTrueTypeFont(nCharset); 370 } 371 372 return sFontName; 373} 374 375CPDF_Font* CPWL_FontMap::AddFontToDocument(CPDF_Document* pDoc, CFX_ByteString& sFontName, FX_BYTE nCharset) 376{ 377 if (IsStandardFont(sFontName)) 378 return AddStandardFont(pDoc, sFontName); 379 else 380 return AddSystemFont(pDoc, sFontName, nCharset); 381} 382 383CPDF_Font* CPWL_FontMap::AddStandardFont(CPDF_Document* pDoc, CFX_ByteString& sFontName) 384{ 385 if (!pDoc) return NULL; 386 387 CPDF_Font* pFont = NULL; 388 389 if (sFontName == "ZapfDingbats") 390 pFont = pDoc->AddStandardFont(sFontName, NULL); 391 else 392 { 393 CPDF_FontEncoding fe(PDFFONT_ENCODING_WINANSI); 394 pFont = pDoc->AddStandardFont(sFontName, &fe); 395 } 396 397 return pFont; 398} 399 400CPDF_Font* CPWL_FontMap::AddSystemFont(CPDF_Document* pDoc, CFX_ByteString& sFontName, FX_BYTE nCharset) 401{ 402 if (!pDoc) return NULL; 403 404 if (sFontName.IsEmpty()) sFontName = GetNativeFont(nCharset); 405 if (nCharset == DEFAULT_CHARSET) nCharset = GetNativeCharset(); 406 407 if (m_pSystemHandler) 408 return m_pSystemHandler->AddNativeTrueTypeFontToPDF(pDoc, sFontName, nCharset); 409 410 return NULL; 411} 412 413CFX_ByteString CPWL_FontMap::EncodeFontAlias(const CFX_ByteString& sFontName, FX_INT32 nCharset) 414{ 415 CFX_ByteString sPostfix; 416 sPostfix.Format("_%02X", nCharset); 417 return EncodeFontAlias(sFontName) + sPostfix; 418} 419 420CFX_ByteString CPWL_FontMap::EncodeFontAlias(const CFX_ByteString& sFontName) 421{ 422 CFX_ByteString sRet = sFontName; 423 sRet.Remove(' '); 424 return sRet; 425} 426 427FX_INT32 CPWL_FontMap::GetFontMapCount() const 428{ 429 return m_aData.GetSize(); 430} 431 432const CPWL_FontMap_Data* CPWL_FontMap::GetFontMapData(FX_INT32 nIndex) const 433{ 434 if (nIndex >=0 && nIndex < m_aData.GetSize()) 435 { 436 return m_aData.GetAt(nIndex); 437 } 438 439 return NULL; 440} 441 442FX_INT32 CPWL_FontMap::GetNativeCharset() 443{ 444 FX_BYTE nCharset = ANSI_CHARSET; 445 FX_INT32 iCodePage = FXSYS_GetACP(); 446 switch (iCodePage) 447 { 448 case 932://Japan 449 nCharset = SHIFTJIS_CHARSET; 450 break; 451 case 936://Chinese (PRC, Singapore) 452 nCharset = GB2312_CHARSET; 453 break; 454 case 950://Chinese (Taiwan; Hong Kong SAR, PRC) 455 nCharset = GB2312_CHARSET; 456 break; 457 case 1252://Windows 3.1 Latin 1 (US, Western Europe) 458 nCharset = ANSI_CHARSET; 459 break; 460 case 874://Thai 461 nCharset = THAI_CHARSET; 462 break; 463 case 949://Korean 464 nCharset = HANGUL_CHARSET; 465 break; 466 case 1200://Unicode (BMP of ISO 10646) 467 nCharset = ANSI_CHARSET; 468 break; 469 case 1250://Windows 3.1 Eastern European 470 nCharset = EASTEUROPE_CHARSET; 471 break; 472 case 1251://Windows 3.1 Cyrillic 473 nCharset = RUSSIAN_CHARSET; 474 break; 475 case 1253://Windows 3.1 Greek 476 nCharset = GREEK_CHARSET; 477 break; 478 case 1254://Windows 3.1 Turkish 479 nCharset = TURKISH_CHARSET; 480 break; 481 case 1255://Hebrew 482 nCharset = HEBREW_CHARSET; 483 break; 484 case 1256://Arabic 485 nCharset = ARABIC_CHARSET; 486 break; 487 case 1257://Baltic 488 nCharset = BALTIC_CHARSET; 489 break; 490 case 1258://Vietnamese 491 nCharset = VIETNAMESE_CHARSET; 492 break; 493 case 1361://Korean(Johab) 494 nCharset = JOHAB_CHARSET; 495 break; 496 } 497 return nCharset; 498} 499 500const CPWL_FontMap::CharsetFontMap CPWL_FontMap::defaultTTFMap[] = { 501 { ANSI_CHARSET, "Helvetica" }, 502 { GB2312_CHARSET, "SimSun" }, 503 { CHINESEBIG5_CHARSET, "MingLiU" }, 504 { SHIFTJIS_CHARSET, "MS Gothic" }, 505 { HANGUL_CHARSET, "Batang" }, 506 { RUSSIAN_CHARSET, "Arial" }, 507#if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ || _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ 508 { EASTEUROPE_CHARSET, "Arial" }, 509#else 510 { EASTEUROPE_CHARSET, "Tahoma" }, 511#endif 512 { ARABIC_CHARSET, "Arial" }, 513 { -1, NULL } 514}; 515 516CFX_ByteString CPWL_FontMap::GetDefaultFontByCharset(FX_INT32 nCharset) 517{ 518 int i = 0; 519 while (defaultTTFMap[i].charset != -1) { 520 if (nCharset == defaultTTFMap[i].charset) 521 return defaultTTFMap[i].fontname; 522 ++i; 523 } 524 return ""; 525} 526 527FX_INT32 CPWL_FontMap::CharSetFromUnicode(FX_WORD word, FX_INT32 nOldCharset) 528{ 529 if(m_pSystemHandler && (-1 != m_pSystemHandler->GetCharSet())) 530 return m_pSystemHandler->GetCharSet(); 531 //to avoid CJK Font to show ASCII 532 if (word < 0x7F) return ANSI_CHARSET; 533 //follow the old charset 534 if (nOldCharset != DEFAULT_CHARSET) return nOldCharset; 535 536 //find new charset 537 if ((word >= 0x4E00 && word <= 0x9FA5) || 538 (word >= 0xE7C7 && word <= 0xE7F3) || 539 (word >= 0x3000 && word <= 0x303F) || //��"��" "��" "��" "��" 540 (word >= 0x2000 && word <= 0x206F)) 541 { 542 return GB2312_CHARSET; 543 } 544 545 if (((word >= 0x3040) && (word <= 0x309F)) || 546 ((word >= 0x30A0) && (word <= 0x30FF)) || 547 ((word >= 0x31F0) && (word <= 0x31FF)) || 548 ((word >= 0xFF00) && (word <= 0xFFEF)) ) 549 { 550 return SHIFTJIS_CHARSET; 551 } 552 553 if (((word >= 0xAC00) && (word <= 0xD7AF)) || 554 ((word >= 0x1100) && (word <= 0x11FF)) || 555 ((word >= 0x3130) && (word <= 0x318F))) 556 { 557 return HANGUL_CHARSET; 558 } 559 560 if (word >= 0x0E00 && word <= 0x0E7F) 561 return THAI_CHARSET; 562 563 if ((word >= 0x0370 && word <= 0x03FF) || 564 (word >= 0x1F00 && word <= 0x1FFF)) 565 return GREEK_CHARSET; 566 567 if ((word >= 0x0600 && word <= 0x06FF) || 568 (word >= 0xFB50 && word <= 0xFEFC)) 569 return ARABIC_CHARSET; 570 571 if (word >= 0x0590 && word <= 0x05FF) 572 return HEBREW_CHARSET; 573 574 if (word >= 0x0400 && word <= 0x04FF) 575 return RUSSIAN_CHARSET; 576 577 if (word >= 0x0100 && word <= 0x024F) 578 return EASTEUROPE_CHARSET; 579 580 if (word >= 0x1E00 && word <= 0x1EFF) 581 return VIETNAMESE_CHARSET; 582 583 return ANSI_CHARSET; 584} 585 586/* ------------------------ CPWL_DocFontMap ------------------------ */ 587 588CPWL_DocFontMap::CPWL_DocFontMap(IFX_SystemHandler* pSystemHandler, CPDF_Document* pAttachedDoc) 589 : CPWL_FontMap(pSystemHandler), 590 m_pAttachedDoc(pAttachedDoc) 591{ 592} 593 594CPWL_DocFontMap::~CPWL_DocFontMap() 595{ 596} 597 598CPDF_Document* CPWL_DocFontMap::GetDocument() 599{ 600 return m_pAttachedDoc; 601} 602