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 = 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 	CFX_ByteString sAlias = EncodeFontAlias("Arial_Chrome", nCharset);
    316 	AddedFont(pNewFont, sAlias);
    317 
    318 	return AddFontData(pNewFont, sAlias, nCharset);
    319 }
    320 
    321 CPDF_Font* CPWL_FontMap::FindFontSameCharset(CFX_ByteString& sFontAlias, FX_INT32 nCharset)
    322 {
    323 	return NULL;
    324 }
    325 
    326 FX_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 
    338 void CPWL_FontMap::AddedFont(CPDF_Font* pFont, const CFX_ByteString& sFontAlias)
    339 {
    340 }
    341 
    342 CFX_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 
    355 CFX_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 
    375 CPDF_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 
    383 CPDF_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 
    400 CPDF_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 
    413 CFX_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 
    420 CFX_ByteString CPWL_FontMap::EncodeFontAlias(const CFX_ByteString& sFontName)
    421 {
    422 	CFX_ByteString sRet = sFontName;
    423 	sRet.Remove(' ');
    424 	return sRet;
    425 }
    426 
    427 FX_INT32 CPWL_FontMap::GetFontMapCount() const
    428 {
    429 	return m_aData.GetSize();
    430 }
    431 
    432 const 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 
    442 FX_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 
    500 const 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 
    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