Home | History | Annotate | Download | only in pdfwindow
      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 
     15 CPWL_FontMap::CPWL_FontMap(IFX_SystemHandler* pSystemHandler) :
     16 	m_pPDFDoc(NULL),
     17 	m_pSystemHandler(pSystemHandler)
     18 {
     19 	ASSERT(m_pSystemHandler != NULL);
     20 }
     21 
     22 CPWL_FontMap::~CPWL_FontMap()
     23 {
     24 	if (m_pPDFDoc)
     25 	{
     26 		delete m_pPDFDoc;
     27 		m_pPDFDoc = NULL;
     28 	}
     29 
     30 	Empty();
     31 }
     32 
     33 void CPWL_FontMap::SetSystemHandler(IFX_SystemHandler* pSystemHandler)
     34 {
     35 	m_pSystemHandler = pSystemHandler;
     36 }
     37 
     38 CPDF_Document* CPWL_FontMap::GetDocument()
     39 {
     40 	if (!m_pPDFDoc)
     41 	{
     42 		if (CPDF_ModuleMgr::Get())
     43 		{
     44 			m_pPDFDoc = FX_NEW CPDF_Document;
     45 			m_pPDFDoc->CreateNewDoc();
     46 		}
     47 	}
     48 
     49 	return m_pPDFDoc;
     50 }
     51 
     52 CPDF_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 
     65 CFX_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 
     78 FX_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 
     91 FX_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 
    133 FX_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 
    156 CFX_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 
    182 void 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 
    198 void 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 /*
    212 List of currently supported standard fonts:
    213 Courier, Courier-Bold, Courier-BoldOblique, Courier-Oblique
    214 Helvetica, Helvetica-Bold, Helvetica-BoldOblique, Helvetica-Oblique
    215 Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic
    216 Symbol, ZapfDingbats
    217 */
    218 
    219 const 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 
    224 FX_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 
    235 FX_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 
    252 FX_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 
    288 FX_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 #ifdef FOXIT_CHROME_BUILD
    316   CFX_ByteString sAlias = EncodeFontAlias("Arial_Chrome", nCharset);
    317 #else
    318 	CFX_ByteString sAlias = EncodeFontAlias("Arial_Foxit", nCharset);
    319 #endif
    320 	AddedFont(pNewFont, sAlias);
    321 
    322 	return AddFontData(pNewFont, sAlias, nCharset);
    323 }
    324 
    325 CPDF_Font* CPWL_FontMap::FindFontSameCharset(CFX_ByteString& sFontAlias, FX_INT32 nCharset)
    326 {
    327 	return NULL;
    328 }
    329 
    330 FX_INT32 CPWL_FontMap::AddFontData(CPDF_Font* pFont, const CFX_ByteString& sFontAlias, FX_INT32 nCharset)
    331 {
    332 	CPWL_FontMap_Data* pNewData = new CPWL_FontMap_Data;
    333 	pNewData->pFont = pFont;
    334 	pNewData->sFontName = sFontAlias;
    335 	pNewData->nCharset = nCharset;
    336 
    337 	m_aData.Add(pNewData);
    338 
    339 	return m_aData.GetSize() -1;
    340 }
    341 
    342 void CPWL_FontMap::AddedFont(CPDF_Font* pFont, const CFX_ByteString& sFontAlias)
    343 {
    344 }
    345 
    346 CFX_ByteString CPWL_FontMap::GetFontName(FX_INT32 nFontIndex)
    347 {
    348 	if (nFontIndex >=0 && nFontIndex < m_aData.GetSize())
    349 	{
    350 		if (CPWL_FontMap_Data* pData = m_aData.GetAt(nFontIndex))
    351 		{
    352 			return pData->sFontName;
    353 		}
    354 	}
    355 
    356 	return "";
    357 }
    358 
    359 CFX_ByteString CPWL_FontMap::GetNativeFont(FX_INT32 nCharset)
    360 {
    361 	CFX_ByteString sFontName;
    362 
    363 	if (nCharset == DEFAULT_CHARSET)
    364 		nCharset = GetNativeCharset();
    365 
    366 	sFontName = GetDefaultFontByCharset(nCharset);
    367 
    368 	if (m_pSystemHandler)
    369 	{
    370 		if (m_pSystemHandler->FindNativeTrueTypeFont(nCharset, sFontName))
    371 			return sFontName;
    372 
    373 		sFontName = m_pSystemHandler->GetNativeTrueTypeFont(nCharset);
    374 	}
    375 
    376 	return sFontName;
    377 }
    378 
    379 CPDF_Font* CPWL_FontMap::AddFontToDocument(CPDF_Document* pDoc, CFX_ByteString& sFontName, FX_BYTE nCharset)
    380 {
    381 	if (IsStandardFont(sFontName))
    382 		return AddStandardFont(pDoc, sFontName);
    383 	else
    384 		return AddSystemFont(pDoc, sFontName, nCharset);
    385 }
    386 
    387 CPDF_Font* CPWL_FontMap::AddStandardFont(CPDF_Document* pDoc, CFX_ByteString& sFontName)
    388 {
    389 	if (!pDoc) return NULL;
    390 
    391 	CPDF_Font* pFont = NULL;
    392 
    393 	if (sFontName == "ZapfDingbats")
    394 		pFont = pDoc->AddStandardFont(sFontName, NULL);
    395 	else
    396 	{
    397 		CPDF_FontEncoding fe(PDFFONT_ENCODING_WINANSI);
    398 		pFont = pDoc->AddStandardFont(sFontName, &fe);
    399 	}
    400 
    401 	return pFont;
    402 }
    403 
    404 CPDF_Font* CPWL_FontMap::AddSystemFont(CPDF_Document* pDoc, CFX_ByteString& sFontName, FX_BYTE nCharset)
    405 {
    406 	if (!pDoc) return NULL;
    407 
    408 	if (sFontName.IsEmpty()) sFontName = GetNativeFont(nCharset);
    409 	if (nCharset == DEFAULT_CHARSET) nCharset = GetNativeCharset();
    410 
    411 	if (m_pSystemHandler)
    412 		return m_pSystemHandler->AddNativeTrueTypeFontToPDF(pDoc, sFontName, nCharset);
    413 
    414 	return NULL;
    415 }
    416 
    417 CFX_ByteString CPWL_FontMap::EncodeFontAlias(const CFX_ByteString& sFontName, FX_INT32 nCharset)
    418 {
    419 	CFX_ByteString sPostfix;
    420 	sPostfix.Format("_%02X", nCharset);
    421 	return EncodeFontAlias(sFontName) + sPostfix;
    422 }
    423 
    424 CFX_ByteString CPWL_FontMap::EncodeFontAlias(const CFX_ByteString& sFontName)
    425 {
    426 	CFX_ByteString sRet = sFontName;
    427 	sRet.Remove(' ');
    428 	return sRet;
    429 }
    430 
    431 FX_INT32 CPWL_FontMap::GetFontMapCount() const
    432 {
    433 	return m_aData.GetSize();
    434 }
    435 
    436 const CPWL_FontMap_Data* CPWL_FontMap::GetFontMapData(FX_INT32 nIndex) const
    437 {
    438 	if (nIndex >=0 && nIndex < m_aData.GetSize())
    439 	{
    440 		return m_aData.GetAt(nIndex);
    441 	}
    442 
    443 	return NULL;
    444 }
    445 
    446 FX_INT32 CPWL_FontMap::GetNativeCharset()
    447 {
    448 	FX_BYTE nCharset = ANSI_CHARSET;
    449 	FX_INT32 iCodePage = FXSYS_GetACP();
    450 	switch (iCodePage)
    451 	{
    452 	case 932://Japan
    453 		nCharset = SHIFTJIS_CHARSET;
    454 		break;
    455 	case 936://Chinese (PRC, Singapore)
    456 		nCharset = GB2312_CHARSET;
    457 		break;
    458 	case 950://Chinese (Taiwan; Hong Kong SAR, PRC)
    459 		nCharset = GB2312_CHARSET;
    460 		break;
    461 	case 1252://Windows 3.1 Latin 1 (US, Western Europe)
    462 		nCharset = ANSI_CHARSET;
    463 		break;
    464 	case 874://Thai
    465 		nCharset = THAI_CHARSET;
    466 		break;
    467 	case 949://Korean
    468 		nCharset = HANGUL_CHARSET;
    469 		break;
    470 	case 1200://Unicode (BMP of ISO 10646)
    471 		nCharset = ANSI_CHARSET;
    472 		break;
    473 	case 1250://Windows 3.1 Eastern European
    474 		nCharset = EASTEUROPE_CHARSET;
    475 		break;
    476 	case 1251://Windows 3.1 Cyrillic
    477 		nCharset = RUSSIAN_CHARSET;
    478 		break;
    479 	case 1253://Windows 3.1 Greek
    480 		nCharset = GREEK_CHARSET;
    481 		break;
    482 	case 1254://Windows 3.1 Turkish
    483 		nCharset = TURKISH_CHARSET;
    484 		break;
    485 	case 1255://Hebrew
    486 		nCharset = HEBREW_CHARSET;
    487 		break;
    488 	case 1256://Arabic
    489 		nCharset = ARABIC_CHARSET;
    490 		break;
    491 	case 1257://Baltic
    492 		nCharset = BALTIC_CHARSET;
    493 		break;
    494 	case 1258://Vietnamese
    495 		nCharset = VIETNAMESE_CHARSET;
    496 		break;
    497 	case 1361://Korean(Johab)
    498 		nCharset = JOHAB_CHARSET;
    499 		break;
    500 	}
    501 	return nCharset;
    502 }
    503 
    504 const CPWL_FontMap::CharsetFontMap CPWL_FontMap::defaultTTFMap[] = {
    505 	{ ANSI_CHARSET, "Helvetica" },
    506 	{ GB2312_CHARSET, "SimSun" },
    507 	{ CHINESEBIG5_CHARSET, "MingLiU" },
    508 	{ SHIFTJIS_CHARSET, "MS Gothic" },
    509 	{ HANGUL_CHARSET, "Batang" },
    510 	{ RUSSIAN_CHARSET, "Arial" },
    511 	{ EASTEUROPE_CHARSET, "Tahoma" },
    512 	{ ARABIC_CHARSET, "Arial" },
    513 	{ -1, NULL }
    514 };
    515 
    516 CFX_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 
    527 FX_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 
    588 CPWL_DocFontMap::CPWL_DocFontMap(IFX_SystemHandler* pSystemHandler, CPDF_Document* pAttachedDoc)
    589 	: CPWL_FontMap(pSystemHandler),
    590 	m_pAttachedDoc(pAttachedDoc)
    591 {
    592 }
    593 
    594 CPWL_DocFontMap::~CPWL_DocFontMap()
    595 {
    596 }
    597 
    598 CPDF_Document* CPWL_DocFontMap::GetDocument()
    599 {
    600 	return m_pAttachedDoc;
    601 }
    602