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/fsdk_define.h"
8#include "../include/fpdfview.h"
9#include "../include/fsdk_rendercontext.h"
10#include "../include/fpdf_progressive.h"
11#include "../include/fpdf_ext.h"
12
13
14CPDF_CustomAccess::CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess)
15{
16	m_FileAccess = *pFileAccess;
17	m_BufferOffset = (FX_DWORD)-1;
18}
19
20FX_BOOL CPDF_CustomAccess::GetByte(FX_DWORD pos, FX_BYTE& ch)
21{
22	if (pos >= m_FileAccess.m_FileLen) return FALSE;
23	if (m_BufferOffset == (FX_DWORD)-1 || pos < m_BufferOffset || pos >= m_BufferOffset + 512) {
24		// Need to read from file access
25		m_BufferOffset = pos;
26		int size = 512;
27		if (pos + 512 > m_FileAccess.m_FileLen)
28			size = m_FileAccess.m_FileLen - pos;
29		if (!m_FileAccess.m_GetBlock(m_FileAccess.m_Param, m_BufferOffset, m_Buffer, size))
30			return FALSE;
31	}
32	ch = m_Buffer[pos - m_BufferOffset];
33	return TRUE;
34}
35
36FX_BOOL CPDF_CustomAccess::GetBlock(FX_DWORD pos, FX_LPBYTE pBuf, FX_DWORD size)
37{
38	if (pos + size > m_FileAccess.m_FileLen) return FALSE;
39	return m_FileAccess.m_GetBlock(m_FileAccess.m_Param, pos, pBuf, size);
40}
41
42FX_BOOL CPDF_CustomAccess::ReadBlock(void* buffer, FX_FILESIZE offset, size_t size)
43{
44	//	m_FileAccess = *pFileAccess;
45	//	m_BufferOffset = (FX_DWORD)-1;
46	if (offset + size > m_FileAccess.m_FileLen) return FALSE;
47	return m_FileAccess.m_GetBlock(m_FileAccess.m_Param, offset,(FX_LPBYTE) buffer, size);
48
49	//	return FALSE;
50}
51
52//0 bit: FPDF_POLICY_MACHINETIME_ACCESS
53static FX_DWORD foxit_sandbox_policy = 0xFFFFFFFF;
54
55void FSDK_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable)
56{
57	switch(policy)
58	{
59	case FPDF_POLICY_MACHINETIME_ACCESS:
60		{
61			if(enable)
62				foxit_sandbox_policy |= 0x01;
63			else
64				foxit_sandbox_policy &= 0xFFFFFFFE;
65		}
66		break;
67	default:
68		break;
69	}
70}
71
72FPDF_BOOL FSDK_IsSandBoxPolicyEnabled(FPDF_DWORD policy)
73{
74	switch(policy)
75	{
76	case FPDF_POLICY_MACHINETIME_ACCESS:
77		{
78			if(foxit_sandbox_policy&0x01)
79				return TRUE;
80			else
81				return FALSE;
82		}
83		break;
84	default:
85		break;
86	}
87	return FALSE;
88}
89
90
91#ifndef _T
92#define _T(x) x
93#endif
94
95#ifdef API5
96	CPDF_ModuleMgr*	g_pModuleMgr = NULL;
97#else
98	CCodec_ModuleMgr*	g_pCodecModule = NULL;
99#ifdef _FXSDK_OPENSOURCE_
100	FXMEM_FoxitMgr* g_pFoxitMgr = NULL;
101#endif
102#endif
103
104//extern CPDFSDK_FormFillApp* g_pFormFillApp;
105
106#if _FX_OS_ == _FX_LINUX_EMBEDDED_
107class CFontMapper : public IPDF_FontMapper
108{
109public:
110	CFontMapper();
111	virtual ~CFontMapper();
112
113	virtual FT_Face FindSubstFont(
114							CPDF_Document* pDoc,				// [IN] The PDF document
115							const CFX_ByteString& face_name,	// [IN] Original name
116							FX_BOOL bTrueType,					// [IN] TrueType or Type1
117							FX_DWORD flags,						// [IN] PDF font flags (see PDF Reference section 5.7.1)
118							int font_weight,					// [IN] original font weight. 0 for not specified
119							int CharsetCP,						// [IN] code page for charset (see Win32 GetACP())
120							FX_BOOL bVertical,
121							CPDF_SubstFont* pSubstFont			// [OUT] Subst font data
122						);
123
124	FT_Face m_SysFace;
125};
126
127CFontMapper* g_pFontMapper = NULL;
128#endif		// #if _FX_OS_ == _FX_LINUX_EMBEDDED_
129
130DLLEXPORT void STDCALL FPDF_InitLibrary(FX_LPVOID hInstance)
131{
132#ifdef API5
133	CPDF_ModuleMgr::Create();
134	g_pModuleMgr = CPDF_ModuleMgr::Get();
135	 #if _FX_OS_ == _FX_WIN32_MOBILE_ || _FX_OS_ == _FX_LINUX_EMBEDDED_
136	 	g_pModuleMgr->InitEmbedded();
137	 #ifdef _GB1_CMAPS_
138	 	g_pModuleMgr->LoadEmbeddedGB1CMaps();
139	 #endif
140	 #ifdef _GB1_CMAPS_4_
141	 	g_pModuleMgr->LoadEmbeddedGB1CMaps_4();
142	 #endif
143	 #ifdef _CNS1_CMAPS_
144	 	g_pModuleMgr->LoadEmbeddedCNS1CMaps();
145	 #endif
146	 #ifdef _JAPAN1_CMAPS_
147	 	g_pModuleMgr->LoadEmbeddedJapan1CMaps();
148	 #endif
149	 #ifdef _JAPAN1_CMAPS_6_
150	 	g_pModuleMgr->LoadEmbeddedJapan1CMaps_6();
151	 #endif
152	 #ifdef _KOREA1_CMAPS_
153	 	g_pModuleMgr->LoadEmbeddedKorea1CMaps();
154	 #endif
155	 #ifdef _JPX_DECODER_
156	 	g_pModuleMgr->InitJpxModule();
157	 	g_pModuleMgr->InitJbig2Module();
158	 //	g_pModuleMgr->InitIccModule();
159	 #endif
160	 #else
161	 	g_pModuleMgr->InitDesktop();
162	 #endif
163#else
164#ifdef _FXSDK_OPENSOURCE_
165	g_pFoxitMgr = FXMEM_CreateMemoryMgr(1024 * 1024 * 32, TRUE);
166#endif
167	g_pCodecModule = CCodec_ModuleMgr::Create();
168
169	CFX_GEModule::Create();
170	CFX_GEModule::Get()->SetCodecModule(g_pCodecModule);
171
172	CPDF_ModuleMgr::Create();
173	CPDF_ModuleMgr::Get()->SetCodecModule(g_pCodecModule);
174	CPDF_ModuleMgr::Get()->InitPageModule();
175	CPDF_ModuleMgr::Get()->InitRenderModule();
176#ifdef FOXIT_CHROME_BUILD
177	CPDF_ModuleMgr * pModuleMgr = CPDF_ModuleMgr::Get();
178	if ( pModuleMgr )
179	{
180		pModuleMgr->LoadEmbeddedGB1CMaps();
181		pModuleMgr->LoadEmbeddedJapan1CMaps();
182		pModuleMgr->LoadEmbeddedCNS1CMaps();
183		pModuleMgr->LoadEmbeddedKorea1CMaps();
184	}
185#endif
186#endif
187
188#ifdef _WIN32
189	// Get module path
190	TCHAR app_path[MAX_PATH];
191	::GetModuleFileName((HINSTANCE)hInstance, app_path, MAX_PATH);
192	size_t len = _tcslen(app_path);
193	for (size_t i = len; i >= 0; i --)
194		if (app_path[i] == '\\') {
195			app_path[i] = 0;
196			break;
197		}
198
199#ifdef _UNICODE
200		#ifndef _FXSDK_OPENSOURCE_
201		CPDF_ModuleMgr::Get()->SetModulePath(NULL, CFX_ByteString::FromUnicode(app_path));
202		#endif
203#else
204#ifndef _FXSDK_OPENSOURCE_
205		CPDF_ModuleMgr::Get()->SetModulePath(NULL, app_path);
206#endif
207#endif
208#endif
209}
210
211
212DLLEXPORT void STDCALL FPDF_DestroyLibrary()
213{
214
215#if _FX_OS_ == _FX_LINUX_EMBEDDED_
216	if (g_pFontMapper) delete g_pFontMapper;
217#endif
218#ifdef API5
219	g_pModuleMgr->Destroy();
220#else
221	CPDF_ModuleMgr::Destroy();
222	CFX_GEModule::Destroy();
223	g_pCodecModule->Destroy();
224#endif
225#ifndef _FXSDK_OPENSOURCE_
226	FXMEM_CollectAll(FXMEM_GetDefaultMgr());
227#else
228	FXMEM_DestroyFoxitMgr(g_pFoxitMgr);
229#endif
230}
231
232#ifndef _WIN32
233int g_LastError;
234void SetLastError(int err)
235{
236	g_LastError = err;
237}
238
239int GetLastError()
240{
241	return g_LastError;
242}
243#endif
244
245void ProcessParseError(FX_DWORD err_code)
246{
247	// Translate FPDFAPI error code to FPDFVIEW error code
248	switch (err_code) {
249		case PDFPARSE_ERROR_FILE:
250			err_code = FPDF_ERR_FILE;
251			break;
252		case PDFPARSE_ERROR_FORMAT:
253			err_code = FPDF_ERR_FORMAT;
254			break;
255		case PDFPARSE_ERROR_PASSWORD:
256			err_code = FPDF_ERR_PASSWORD;
257			break;
258		case PDFPARSE_ERROR_HANDLER:
259			err_code = FPDF_ERR_SECURITY;
260			break;
261	}
262	SetLastError(err_code);
263}
264
265DLLEXPORT void	STDCALL FPDF_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable)
266{
267	return FSDK_SetSandBoxPolicy(policy, enable);
268}
269
270DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadDocument(FPDF_STRING file_path, FPDF_BYTESTRING password)
271{
272	CPDF_Parser* pParser = FX_NEW CPDF_Parser;
273	pParser->SetPassword(password);
274	try {
275		FX_DWORD err_code = pParser->StartParse((FX_LPCSTR)file_path);
276		if (err_code) {
277			delete pParser;
278			ProcessParseError(err_code);
279			return NULL;
280		}
281	}
282	catch (...) {
283		delete pParser;
284		SetLastError(FPDF_ERR_UNKNOWN);
285		return NULL;
286	}
287	return pParser->GetDocument();
288}
289
290extern void CheckUnSupportError(CPDF_Document * pDoc, FX_DWORD err_code);
291
292class CMemFile: public IFX_FileRead, public CFX_Object
293{
294public:
295	CMemFile(FX_BYTE* pBuf, FX_FILESIZE size):m_pBuf(pBuf),m_size(size) {}
296
297	virtual void			Release() {delete this;}
298	virtual FX_FILESIZE		GetSize() {return m_size;}
299	virtual FX_BOOL			ReadBlock(void* buffer, FX_FILESIZE offset, size_t size)
300	{
301		if(offset+size > (FX_DWORD)m_size) return FALSE;
302		FXSYS_memcpy(buffer, m_pBuf+offset, size);
303		return TRUE;
304	}
305private:
306	FX_BYTE* m_pBuf;
307	FX_FILESIZE m_size;
308};
309DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadMemDocument(const void* data_buf, int size, FPDF_BYTESTRING password)
310{
311	CPDF_Parser* pParser = FX_NEW CPDF_Parser;
312	pParser->SetPassword(password);
313	try {
314		CMemFile* pMemFile = FX_NEW CMemFile((FX_BYTE*)data_buf, size);
315		FX_DWORD err_code = pParser->StartParse(pMemFile);
316		if (err_code) {
317			delete pParser;
318			ProcessParseError(err_code);
319			return NULL;
320		}
321		CPDF_Document * pDoc = NULL;
322		pDoc = pParser?pParser->GetDocument():NULL;
323		CheckUnSupportError(pDoc, err_code);
324	}
325	catch (...) {
326		delete pParser;
327		SetLastError(FPDF_ERR_UNKNOWN);
328		return NULL;
329	}
330	return pParser->GetDocument();
331}
332
333DLLEXPORT FPDF_DOCUMENT STDCALL FPDF_LoadCustomDocument(FPDF_FILEACCESS* pFileAccess, FPDF_BYTESTRING password)
334{
335	CPDF_Parser* pParser = FX_NEW CPDF_Parser;
336	pParser->SetPassword(password);
337	CPDF_CustomAccess* pFile = FX_NEW CPDF_CustomAccess(pFileAccess);
338	try {
339		FX_DWORD err_code = pParser->StartParse(pFile);
340		if (err_code) {
341			delete pParser;
342			ProcessParseError(err_code);
343			return NULL;
344		}
345		CPDF_Document * pDoc = NULL;
346		pDoc = pParser?pParser->GetDocument():NULL;
347		CheckUnSupportError(pDoc, err_code);
348	}
349	catch (...) {
350		delete pParser;
351		SetLastError(FPDF_ERR_UNKNOWN);
352		return NULL;
353	}
354	return pParser->GetDocument();
355}
356
357DLLEXPORT FPDF_BOOL STDCALL FPDF_GetFileVersion(FPDF_DOCUMENT doc, int* fileVersion)
358{
359	if(!doc||!fileVersion) return FALSE;
360	*fileVersion = 0;
361	CPDF_Document* pDoc = (CPDF_Document*)doc;
362	CPDF_Parser* pParser = (CPDF_Parser*)pDoc->GetParser();
363	if(!pParser)
364		return FALSE;
365	*fileVersion = pParser->GetFileVersion();
366	return TRUE;
367}
368
369// jabdelmalek: changed return type from FX_DWORD to build on Linux (and match header).
370DLLEXPORT unsigned long STDCALL FPDF_GetDocPermissions(FPDF_DOCUMENT document)
371{
372	if (document == NULL) return 0;
373	CPDF_Document*pDoc = (CPDF_Document*)document;
374	CPDF_Parser* pParser = 	(CPDF_Parser*)pDoc->GetParser();
375	CPDF_Dictionary* pDict = pParser->GetEncryptDict();
376	if (pDict == NULL) return (FX_DWORD)-1;
377
378	return pDict->GetInteger("P");
379}
380
381DLLEXPORT int STDCALL FPDF_GetPageCount(FPDF_DOCUMENT document)
382{
383	if (document == NULL) return 0;
384	return ((CPDF_Document*)document)->GetPageCount();
385}
386
387DLLEXPORT FPDF_PAGE STDCALL FPDF_LoadPage(FPDF_DOCUMENT document, int page_index)
388{
389	if (document == NULL) return NULL;
390	if (page_index < 0 || page_index >= FPDF_GetPageCount(document)) return NULL;
391//	CPDF_Parser* pParser = (CPDF_Parser*)document;
392	CPDF_Document* pDoc = (CPDF_Document*)document;
393	if (pDoc == NULL) return NULL;
394	CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
395	if (pDict == NULL) return NULL;
396	CPDF_Page* pPage = FX_NEW CPDF_Page;
397	pPage->Load(pDoc, pDict);
398	try {
399		pPage->ParseContent();
400	}
401	catch (...) {
402		delete pPage;
403		return NULL;
404	}
405
406//	CheckUnSupportError(pDoc, 0);
407
408	return pPage;
409}
410
411DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page)
412{
413	if (!page)
414		return 0.0;
415	return ((CPDF_Page*)page)->GetPageWidth();
416}
417
418DLLEXPORT double STDCALL FPDF_GetPageHeight(FPDF_PAGE page)
419{
420	if (!page) return 0.0;
421	return ((CPDF_Page*)page)->GetPageHeight();
422}
423
424void DropContext(void* data)
425{
426	delete (CRenderContext*)data;
427}
428
429void FPDF_RenderPage_Retail(CRenderContext* pContext, FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y,
430						int rotate, int flags,FX_BOOL bNeedToRestore, IFSDK_PAUSE_Adapter * pause  );
431void (*Func_RenderPage)(CRenderContext*, FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y,
432						int rotate, int flags,FX_BOOL bNeedToRestore, IFSDK_PAUSE_Adapter * pause  ) = FPDF_RenderPage_Retail;
433
434#if defined(_DEBUG) || defined(DEBUG)
435#define DEBUG_TRACE
436#endif
437
438#if defined(_WIN32)
439DLLEXPORT void STDCALL FPDF_RenderPage(HDC dc, FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y,
440						int rotate, int flags)
441{
442	if (page==NULL) return;
443	CPDF_Page* pPage = (CPDF_Page*)page;
444
445	CRenderContext* pContext = FX_NEW CRenderContext;
446	pPage->SetPrivateData((void*)1, pContext, DropContext);
447
448#ifndef _WIN32_WCE
449	CFX_DIBitmap* pBitmap = NULL;
450	FX_BOOL bBackgroundAlphaNeeded=FALSE;
451	bBackgroundAlphaNeeded = pPage->BackgroundAlphaNeeded();
452	if (bBackgroundAlphaNeeded)
453	{
454
455		pBitmap = FX_NEW CFX_DIBitmap;
456		pBitmap->Create(size_x, size_y, FXDIB_Argb);
457		pBitmap->Clear(0x00ffffff);
458#ifdef _SKIA_SUPPORT_
459		pContext->m_pDevice = FX_NEW CFX_SkiaDevice;
460		((CFX_SkiaDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)pBitmap);
461#else
462		pContext->m_pDevice = FX_NEW CFX_FxgeDevice;
463		((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)pBitmap);
464#endif
465	}
466	else
467	pContext->m_pDevice = FX_NEW CFX_WindowsDevice(dc);
468	if (flags & FPDF_NO_CATCH)
469		Func_RenderPage(pContext, page, start_x, start_y, size_x, size_y, rotate, flags,TRUE,NULL);
470	else {
471		try {
472			Func_RenderPage(pContext, page, start_x, start_y, size_x, size_y, rotate, flags,TRUE,NULL);
473		} catch (...) {
474		}
475	}
476	if (bBackgroundAlphaNeeded)
477	{
478		if (pBitmap)
479		{
480			CFX_WindowsDevice WinDC(dc);
481
482 			if (WinDC.GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER)
483 			{
484				CFX_DIBitmap* pDst = FX_NEW CFX_DIBitmap;
485				pDst->Create(pBitmap->GetWidth(), pBitmap->GetHeight(),FXDIB_Rgb32);
486				FXSYS_memcpy(pDst->GetBuffer(), pBitmap->GetBuffer(), pBitmap->GetPitch()*pBitmap->GetHeight());
487//				WinDC.SetDIBits(pDst,0,0);
488				WinDC.StretchDIBits(pDst,0,0,size_x*2,size_y*2);
489				delete pDst;
490 			}
491 			else
492 				WinDC.SetDIBits(pBitmap,0,0);
493
494		}
495	}
496#else
497	// get clip region
498	RECT rect, cliprect;
499	rect.left = start_x;
500	rect.top = start_y;
501	rect.right = start_x + size_x;
502	rect.bottom = start_y + size_y;
503	GetClipBox(dc, &cliprect);
504	IntersectRect(&rect, &rect, &cliprect);
505	int width = rect.right - rect.left;
506	int height = rect.bottom - rect.top;
507
508#ifdef DEBUG_TRACE
509	{
510		char str[128];
511		sprintf(str, "Rendering DIB %d x %d", width, height);
512		CPDF_ModuleMgr::Get()->ReportError(999, str);
513	}
514#endif
515
516	// Create a DIB section
517	LPVOID pBuffer;
518	BITMAPINFOHEADER bmih;
519	FXSYS_memset(&bmih, 0, sizeof bmih);
520	bmih.biSize = sizeof bmih;
521	bmih.biBitCount = 24;
522	bmih.biHeight = -height;
523	bmih.biPlanes = 1;
524	bmih.biWidth = width;
525	pContext->m_hBitmap = CreateDIBSection(dc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, &pBuffer, NULL, 0);
526	if (pContext->m_hBitmap == NULL) {
527#if defined(DEBUG) || defined(_DEBUG)
528		char str[128];
529		sprintf(str, "Error CreateDIBSection: %d x %d, error code = %d", width, height, GetLastError());
530		CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, str);
531#else
532		CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, NULL);
533#endif
534	}
535	FXSYS_memset(pBuffer, 0xff, height*((width*3+3)/4*4));
536
537#ifdef DEBUG_TRACE
538	{
539		CPDF_ModuleMgr::Get()->ReportError(999, "DIBSection created");
540	}
541#endif
542
543	// Create a device with this external buffer
544	pContext->m_pBitmap = FX_NEW CFX_DIBitmap;
545	pContext->m_pBitmap->Create(width, height, FXDIB_Rgb, (FX_LPBYTE)pBuffer);
546	pContext->m_pDevice = FX_NEW CPDF_FxgeDevice;
547	((CPDF_FxgeDevice*)pContext->m_pDevice)->Attach(pContext->m_pBitmap);
548
549#ifdef DEBUG_TRACE
550	CPDF_ModuleMgr::Get()->ReportError(999, "Ready for PDF rendering");
551#endif
552
553	// output to bitmap device
554	if (flags & FPDF_NO_CATCH)
555		Func_RenderPage(pContext, page, start_x - rect.left, start_y - rect.top, size_x, size_y, rotate, flags);
556	else {
557		try {
558			Func_RenderPage(pContext, page, start_x - rect.left, start_y - rect.top, size_x, size_y, rotate, flags);
559		} catch (...) {
560		}
561	}
562
563#ifdef DEBUG_TRACE
564	CPDF_ModuleMgr::Get()->ReportError(999, "Finished PDF rendering");
565#endif
566
567	// Now output to real device
568	HDC hMemDC = CreateCompatibleDC(dc);
569	if (hMemDC == NULL) {
570#if defined(DEBUG) || defined(_DEBUG)
571		char str[128];
572		sprintf(str, "Error CreateCompatibleDC. Error code = %d", GetLastError());
573		CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, str);
574#else
575		CPDF_ModuleMgr::Get()->ReportError(FPDFERR_OUT_OF_MEMORY, NULL);
576#endif
577	}
578
579	HGDIOBJ hOldBitmap = SelectObject(hMemDC, pContext->m_hBitmap);
580
581#ifdef DEBUG_TRACE
582	CPDF_ModuleMgr::Get()->ReportError(999, "Ready for screen rendering");
583#endif
584
585	BitBlt(dc, rect.left, rect.top, width, height, hMemDC, 0, 0, SRCCOPY);
586	SelectObject(hMemDC, hOldBitmap);
587	DeleteDC(hMemDC);
588
589#ifdef DEBUG_TRACE
590	CPDF_ModuleMgr::Get()->ReportError(999, "Finished screen rendering");
591#endif
592
593#endif
594	if (bBackgroundAlphaNeeded)
595	{
596		if (pBitmap)
597			delete pBitmap;
598		pBitmap = NULL;
599	}
600	delete pContext;
601	pPage->RemovePrivateData((void*)1);
602}
603#endif
604
605DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap, FPDF_PAGE page, int start_x, int start_y,
606						int size_x, int size_y, int rotate, int flags)
607{
608	if (bitmap == NULL || page == NULL) return;
609	CPDF_Page* pPage = (CPDF_Page*)page;
610
611
612	CRenderContext* pContext = FX_NEW CRenderContext;
613	pPage->SetPrivateData((void*)1, pContext, DropContext);
614#ifdef _SKIA_SUPPORT_
615	pContext->m_pDevice = FX_NEW CFX_SkiaDevice;
616
617	if (flags & FPDF_REVERSE_BYTE_ORDER)
618		((CFX_SkiaDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)bitmap,0,TRUE);
619	else
620		((CFX_SkiaDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)bitmap);
621#else
622	pContext->m_pDevice = FX_NEW CFX_FxgeDevice;
623
624	if (flags & FPDF_REVERSE_BYTE_ORDER)
625		((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)bitmap,0,TRUE);
626	else
627		((CFX_FxgeDevice*)pContext->m_pDevice)->Attach((CFX_DIBitmap*)bitmap);
628#endif
629	if (flags & FPDF_NO_CATCH)
630		Func_RenderPage(pContext, page, start_x, start_y, size_x, size_y, rotate, flags,TRUE,NULL);
631	else {
632		try {
633			Func_RenderPage(pContext, page, start_x, start_y, size_x, size_y, rotate, flags,TRUE,NULL);
634		} catch (...) {
635		}
636	}
637
638	delete pContext;
639	pPage->RemovePrivateData((void*)1);
640}
641
642DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page)
643{
644	if (!page) return;
645	delete (CPDF_Page*)page;
646
647}
648
649DLLEXPORT void STDCALL FPDF_CloseDocument(FPDF_DOCUMENT document)
650{
651	if (!document)
652		return;
653	CPDF_Document* pDoc = (CPDF_Document*)document;
654	CPDF_Parser* pParser = (CPDF_Parser*)pDoc->GetParser();
655	if (pParser == NULL)
656	{
657		delete pDoc;
658		return;
659	}
660	delete pParser;
661//	delete pDoc;
662}
663
664DLLEXPORT unsigned long STDCALL FPDF_GetLastError()
665{
666	return GetLastError();
667}
668
669DLLEXPORT void STDCALL FPDF_DeviceToPage(FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y,
670						int rotate, int device_x, int device_y, double* page_x, double* page_y)
671{
672	if (page == NULL || page_x == NULL || page_y == NULL) return;
673	CPDF_Page* pPage = (CPDF_Page*)page;
674
675	CPDF_Matrix page2device;
676	pPage->GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y, rotate);
677	CPDF_Matrix device2page;
678	device2page.SetReverse(page2device);
679
680	FX_FLOAT page_x_f, page_y_f;
681	device2page.Transform((FX_FLOAT)(device_x), (FX_FLOAT)(device_y), page_x_f, page_y_f);
682
683	*page_x = (page_x_f);
684	*page_y = (page_y_f);
685}
686
687DLLEXPORT void STDCALL FPDF_PageToDevice(FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y,
688						int rotate, double page_x, double page_y, int* device_x, int* device_y)
689{
690	if (page == NULL || device_x == NULL || device_y == NULL) return;
691	CPDF_Page* pPage = (CPDF_Page*)page;
692
693	CPDF_Matrix page2device;
694	pPage->GetDisplayMatrix(page2device, start_x, start_y, size_x, size_y, rotate);
695
696	FX_FLOAT device_x_f, device_y_f;
697	page2device.Transform(((FX_FLOAT)page_x), ((FX_FLOAT)page_y), device_x_f, device_y_f);
698
699	*device_x = FXSYS_round(device_x_f);
700	*device_y = FXSYS_round(device_y_f);
701}
702
703DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_Create(int width, int height, int alpha)
704{
705	CFX_DIBitmap* pBitmap = FX_NEW CFX_DIBitmap;
706	pBitmap->Create(width, height, alpha ? FXDIB_Argb : FXDIB_Rgb32);
707	return pBitmap;
708}
709
710DLLEXPORT FPDF_BITMAP STDCALL FPDFBitmap_CreateEx(int width, int height, int format, void* first_scan, int stride)
711{
712	FXDIB_Format fx_format;
713	switch (format) {
714		case FPDFBitmap_Gray:
715			fx_format = FXDIB_8bppRgb;
716			break;
717		case FPDFBitmap_BGR:
718			fx_format = FXDIB_Rgb;
719			break;
720		case FPDFBitmap_BGRx:
721			fx_format = FXDIB_Rgb32;
722			break;
723		case FPDFBitmap_BGRA:
724			fx_format = FXDIB_Argb;
725			break;
726		default:
727			return NULL;
728	}
729	CFX_DIBitmap* pBitmap = FX_NEW CFX_DIBitmap;
730	pBitmap->Create(width, height, fx_format, (FX_LPBYTE)first_scan, stride);
731	return pBitmap;
732}
733
734DLLEXPORT void STDCALL FPDFBitmap_FillRect(FPDF_BITMAP bitmap, int left, int top, int width, int height,
735									int red, int green, int blue, int alpha)
736{
737	if (bitmap == NULL) return;
738#ifdef _SKIA_SUPPORT_
739	CFX_SkiaDevice device;
740#else
741	CFX_FxgeDevice device;
742#endif
743	device.Attach((CFX_DIBitmap*)bitmap);
744	if (!((CFX_DIBitmap*)bitmap)->HasAlpha()) alpha = 255;
745	FX_RECT rect(left, top, left+width, top+height);
746	device.FillRect(&rect, FXARGB_MAKE(alpha, red, green, blue));
747}
748
749DLLEXPORT void* STDCALL FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap)
750{
751	if (bitmap == NULL) return NULL;
752	return ((CFX_DIBitmap*)bitmap)->GetBuffer();
753}
754
755DLLEXPORT int STDCALL FPDFBitmap_GetWidth(FPDF_BITMAP bitmap)
756{
757	if (bitmap == NULL) return 0;
758	return ((CFX_DIBitmap*)bitmap)->GetWidth();
759}
760
761DLLEXPORT int STDCALL FPDFBitmap_GetHeight(FPDF_BITMAP bitmap)
762{
763	if (bitmap == NULL) return 0;
764	return ((CFX_DIBitmap*)bitmap)->GetHeight();
765}
766
767DLLEXPORT int STDCALL FPDFBitmap_GetStride(FPDF_BITMAP bitmap)
768{
769	if (bitmap == NULL) return 0;
770	return ((CFX_DIBitmap*)bitmap)->GetPitch();
771}
772
773DLLEXPORT void STDCALL FPDFBitmap_Destroy(FPDF_BITMAP bitmap)
774{
775	if (bitmap == NULL) return;
776	delete (CFX_DIBitmap*)bitmap;
777}
778
779void FPDF_RenderPage_Retail(CRenderContext* pContext, FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y,
780						int rotate, int flags,FX_BOOL bNeedToRestore, IFSDK_PAUSE_Adapter * pause )
781{
782//#ifdef _LICENSED_BUILD_
783	CPDF_Page* pPage = (CPDF_Page*)page;
784	if (pPage == NULL) return;
785
786	if (!pContext->m_pOptions)
787		pContext->m_pOptions = new CPDF_RenderOptions;
788//	CPDF_RenderOptions options;
789	if (flags & FPDF_LCD_TEXT)
790		pContext->m_pOptions->m_Flags |= RENDER_CLEARTYPE;
791	else
792		pContext->m_pOptions->m_Flags &= ~RENDER_CLEARTYPE;
793	if (flags & FPDF_NO_NATIVETEXT)
794		pContext->m_pOptions->m_Flags |= RENDER_NO_NATIVETEXT;
795	if (flags & FPDF_RENDER_LIMITEDIMAGECACHE)
796		pContext->m_pOptions->m_Flags |= RENDER_LIMITEDIMAGECACHE;
797	if (flags & FPDF_RENDER_FORCEHALFTONE)
798		pContext->m_pOptions->m_Flags |= RENDER_FORCE_HALFTONE;
799	//Grayscale output
800	if (flags & FPDF_GRAYSCALE)
801	{
802		pContext->m_pOptions->m_ColorMode = RENDER_COLOR_GRAY;
803		pContext->m_pOptions->m_ForeColor = 0;
804		pContext->m_pOptions->m_BackColor = 0xffffff;
805	}
806	const CPDF_OCContext::UsageType usage = (flags & FPDF_PRINTING) ? CPDF_OCContext::Print : CPDF_OCContext::View;
807
808	pContext->m_pOptions->m_AddFlags = flags >> 8;
809
810	pContext->m_pOptions->m_pOCContext = new CPDF_OCContext(pPage->m_pDocument, usage);
811
812
813	CFX_AffineMatrix matrix;
814	pPage->GetDisplayMatrix(matrix, start_x, start_y, size_x, size_y, rotate);
815
816	FX_RECT clip;
817	clip.left = start_x;
818	clip.right = start_x + size_x;
819	clip.top = start_y;
820	clip.bottom = start_y + size_y;
821	pContext->m_pDevice->SaveState();
822	pContext->m_pDevice->SetClip_Rect(&clip);
823
824	pContext->m_pContext = FX_NEW CPDF_RenderContext;
825	pContext->m_pContext->Create(pPage);
826	pContext->m_pContext->AppendObjectList(pPage, &matrix);
827
828	if (flags & FPDF_ANNOT) {
829		pContext->m_pAnnots = FX_NEW CPDF_AnnotList(pPage);
830		FX_BOOL bPrinting = pContext->m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
831		pContext->m_pAnnots->DisplayAnnots(pPage, pContext->m_pContext, bPrinting, &matrix, TRUE, NULL);
832	}
833
834	pContext->m_pRenderer = FX_NEW CPDF_ProgressiveRenderer;
835	pContext->m_pRenderer->Start(pContext->m_pContext, pContext->m_pDevice, pContext->m_pOptions, pause);
836	if (bNeedToRestore)
837	{
838	  pContext->m_pDevice->RestoreState();
839	}
840
841//#endif
842}
843
844DLLEXPORT int STDCALL FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document, int page_index, double* width, double* height)
845{
846	CPDF_Document* pDoc = (CPDF_Document*)document;
847	if(pDoc == NULL)
848		return FALSE;
849
850	CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
851	if (pDict == NULL) return FALSE;
852
853	CPDF_Page page;
854	page.Load(pDoc, pDict);
855	*width = page.GetPageWidth();
856	*height = page.GetPageHeight();
857
858	return TRUE;
859}
860
861DLLEXPORT FPDF_BOOL STDCALL FPDF_VIEWERREF_GetPrintScaling(FPDF_DOCUMENT document)
862{
863	CPDF_Document* pDoc = (CPDF_Document*)document;
864	if (!pDoc) return TRUE;
865	CPDF_ViewerPreferences viewRef(pDoc);
866	return viewRef.PrintScaling();
867}
868
869DLLEXPORT FPDF_DEST STDCALL FPDF_GetNamedDestByName(FPDF_DOCUMENT document,FPDF_BYTESTRING name)
870{
871	if (document == NULL)
872		return NULL;
873	if (name == NULL || name[0] == 0)
874		return NULL;
875
876	CPDF_Document* pDoc = (CPDF_Document*)document;
877	CPDF_NameTree name_tree(pDoc, FX_BSTRC("Dests"));
878	return name_tree.LookupNamedDest(pDoc, name);
879}
880