Convert all line endings to LF.
[pdfium.git] / fpdfsdk / src / fpdfview.cpp
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
14 CPDF_CustomAccess::CPDF_CustomAccess(FPDF_FILEACCESS* pFileAccess)
15 {
16         m_FileAccess = *pFileAccess;
17         m_BufferOffset = (FX_DWORD)-1;
18 }
19
20 FX_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
36 FX_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
42 FX_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
53 static FX_DWORD foxit_sandbox_policy = 0xFFFFFFFF;
54
55 void 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
72 FPDF_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_
107 class CFontMapper : public IPDF_FontMapper
108 {
109 public:
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
127 CFontMapper* g_pFontMapper = NULL;
128 #endif          // #if _FX_OS_ == _FX_LINUX_EMBEDDED_
129
130 DLLEXPORT 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
212 DLLEXPORT 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
233 int g_LastError;
234 void SetLastError(int err)
235 {
236         g_LastError = err;
237 }
238
239 int GetLastError()
240 {
241         return g_LastError;
242 }
243 #endif
244
245 void 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
265 DLLEXPORT void  STDCALL FPDF_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable)
266 {
267         return FSDK_SetSandBoxPolicy(policy, enable);
268 }
269
270 DLLEXPORT 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
290 extern void CheckUnSupportError(CPDF_Document * pDoc, FX_DWORD err_code);
291
292 class CMemFile: public IFX_FileRead, public CFX_Object
293 {
294 public:
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         }
305 private:
306         FX_BYTE* m_pBuf;
307         FX_FILESIZE m_size;
308 };
309 DLLEXPORT 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
333 DLLEXPORT 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
357 DLLEXPORT 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).
370 DLLEXPORT 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
381 DLLEXPORT int STDCALL FPDF_GetPageCount(FPDF_DOCUMENT document)
382 {
383         if (document == NULL) return 0;
384         return ((CPDF_Document*)document)->GetPageCount();
385 }
386
387 DLLEXPORT 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
411 DLLEXPORT double STDCALL FPDF_GetPageWidth(FPDF_PAGE page)
412 {
413         if (!page)
414                 return 0.0;
415         return ((CPDF_Page*)page)->GetPageWidth();
416 }
417
418 DLLEXPORT double STDCALL FPDF_GetPageHeight(FPDF_PAGE page)
419 {
420         if (!page) return 0.0;
421         return ((CPDF_Page*)page)->GetPageHeight();
422 }
423
424 void DropContext(void* data)
425 {
426         delete (CRenderContext*)data;
427 }
428
429 void 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  );
431 void (*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)
439 DLLEXPORT 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
605 DLLEXPORT 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
642 DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page)
643 {
644         if (!page) return;
645         delete (CPDF_Page*)page;
646
647 }
648
649 DLLEXPORT 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
664 DLLEXPORT unsigned long STDCALL FPDF_GetLastError()
665 {
666         return GetLastError();
667 }
668
669 DLLEXPORT 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
687 DLLEXPORT 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
703 DLLEXPORT 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
710 DLLEXPORT 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
734 DLLEXPORT 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
749 DLLEXPORT void* STDCALL FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap)
750 {
751         if (bitmap == NULL) return NULL;
752         return ((CFX_DIBitmap*)bitmap)->GetBuffer();
753 }
754
755 DLLEXPORT int STDCALL FPDFBitmap_GetWidth(FPDF_BITMAP bitmap)
756 {
757         if (bitmap == NULL) return 0;
758         return ((CFX_DIBitmap*)bitmap)->GetWidth();
759 }
760
761 DLLEXPORT int STDCALL FPDFBitmap_GetHeight(FPDF_BITMAP bitmap)
762 {
763         if (bitmap == NULL) return 0;
764         return ((CFX_DIBitmap*)bitmap)->GetHeight();
765 }
766
767 DLLEXPORT int STDCALL FPDFBitmap_GetStride(FPDF_BITMAP bitmap)
768 {
769         if (bitmap == NULL) return 0;
770         return ((CFX_DIBitmap*)bitmap)->GetPitch();
771 }
772
773 DLLEXPORT void STDCALL FPDFBitmap_Destroy(FPDF_BITMAP bitmap)
774 {
775         if (bitmap == NULL) return;
776         delete (CFX_DIBitmap*)bitmap;
777 }
778
779 void 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
844 DLLEXPORT 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
861 DLLEXPORT 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
869 DLLEXPORT 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 }