Fix segv above CPDFSDK_Document::GetPageView()
[pdfium.git] / fpdfsdk / src / fpdfformfill.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 "../../public/fpdf_formfill.h"
8 #include "../../public/fpdfview.h"
9 #include "../../third_party/base/nonstd_unique_ptr.h"
10 #include "../include/fsdk_define.h"
11 #include "../include/fsdk_mgr.h"
12 #include "../include/javascript/IJavaScript.h"
13
14 namespace {
15
16 CPDFSDK_Document* FormHandleToSDKDoc(FPDF_FORMHANDLE hHandle)
17 {
18     CPDFDoc_Environment* pEnv = (CPDFDoc_Environment*)hHandle;
19     return pEnv ? pEnv->GetSDKDocument() : nullptr;
20 }
21
22 CPDFSDK_InterForm* FormHandleToInterForm(FPDF_FORMHANDLE hHandle)
23 {
24     CPDFSDK_Document* pSDKDoc = FormHandleToSDKDoc(hHandle);
25     return pSDKDoc ? pSDKDoc->GetInterForm() : nullptr;
26 }
27
28 CPDFSDK_PageView* FormHandleToPageView(FPDF_FORMHANDLE hHandle, FPDF_PAGE page)
29 {
30     if (!page)
31         return nullptr;
32
33     CPDFSDK_Document* pSDKDoc = FormHandleToSDKDoc(hHandle);
34     return pSDKDoc ? pSDKDoc->GetPageView((CPDF_Page*)page, TRUE) : nullptr;
35 }
36
37 }  // namespace
38
39 DLLEXPORT int STDCALL FPDPage_HasFormFieldAtPoint(
40     FPDF_FORMHANDLE hHandle, FPDF_PAGE page, double page_x, double page_y)
41 {
42     if (!page || !hHandle)
43         return -1;
44     CPDF_Page* pPage = (CPDF_Page*) page;
45
46     nonstd::unique_ptr<CPDF_InterForm> pInterForm(
47         new CPDF_InterForm(pPage->m_pDocument, FALSE));
48     CPDF_FormControl* pFormCtrl = pInterForm->GetControlAtPoint(
49         pPage, (FX_FLOAT)page_x, (FX_FLOAT)page_y);
50     if (!pFormCtrl)
51         return -1;
52
53     CPDF_FormField* pFormField = pFormCtrl->GetField();
54     if(!pFormField)
55         return -1;
56
57     return pFormField->GetFieldType();
58 }
59
60 DLLEXPORT FPDF_FORMHANDLE STDCALL FPDFDOC_InitFormFillEnvironment(
61     FPDF_DOCUMENT document, FPDF_FORMFILLINFO* formInfo)
62 {
63     if (!document || !formInfo || formInfo->version != 1)
64         return nullptr;
65
66     CPDF_Document* pDocument = (CPDF_Document*)document;
67     CPDFDoc_Environment* pEnv = new CPDFDoc_Environment(pDocument, formInfo);
68     pEnv->SetSDKDocument(new CPDFSDK_Document(pDocument, pEnv));
69     return pEnv;
70 }
71
72 DLLEXPORT void STDCALL FPDFDOC_ExitFormFillEnvironment(FPDF_FORMHANDLE hHandle)
73 {
74     if (!hHandle)
75         return;
76
77     CPDFDoc_Environment* pEnv = (CPDFDoc_Environment*)hHandle;
78     if (CPDFSDK_Document* pSDKDoc = pEnv->GetSDKDocument())
79     {
80         pEnv->SetSDKDocument(NULL);
81         delete pSDKDoc;
82     }
83     delete pEnv;
84 }
85
86 DLLEXPORT FPDF_BOOL STDCALL FORM_OnMouseMove(FPDF_FORMHANDLE hHandle, FPDF_PAGE page, int modifier, double page_x, double page_y)
87 {
88     CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
89     if (!pPageView)
90         return FALSE;
91
92     CPDF_Point pt((FX_FLOAT)page_x, (FX_FLOAT)page_y);
93     return pPageView->OnMouseMove(pt, modifier);
94 }
95
96 DLLEXPORT FPDF_BOOL STDCALL FORM_OnLButtonDown(FPDF_FORMHANDLE hHandle, FPDF_PAGE page, int modifier, double page_x, double page_y)
97 {
98     CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
99     if (!pPageView)
100         return FALSE;
101
102     CPDF_Point pt((FX_FLOAT)page_x, (FX_FLOAT)page_y);
103     return pPageView->OnLButtonDown(pt, modifier);
104 }
105
106 DLLEXPORT FPDF_BOOL STDCALL FORM_OnLButtonUp(FPDF_FORMHANDLE hHandle, FPDF_PAGE page, int modifier, double page_x, double page_y)
107 {
108     CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
109     if (!pPageView)
110         return FALSE;
111
112     CPDF_Point pt((FX_FLOAT)page_x, (FX_FLOAT)page_y);
113     return pPageView->OnLButtonUp(pt, modifier);
114 }
115
116 DLLEXPORT FPDF_BOOL STDCALL FORM_OnKeyDown(FPDF_FORMHANDLE hHandle, FPDF_PAGE page, int nKeyCode, int modifier)
117 {
118     CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
119     if (!pPageView)
120         return FALSE;
121
122     return pPageView->OnKeyDown(nKeyCode, modifier);
123 }
124
125 DLLEXPORT FPDF_BOOL STDCALL FORM_OnKeyUp(FPDF_FORMHANDLE hHandle, FPDF_PAGE page, int nKeyCode, int modifier)
126 {
127     CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
128     if (!pPageView)
129         return FALSE;
130
131     return pPageView->OnKeyUp(nKeyCode, modifier);
132 }
133
134 DLLEXPORT FPDF_BOOL STDCALL FORM_OnChar(FPDF_FORMHANDLE hHandle, FPDF_PAGE page, int nChar,  int modifier)
135 {
136     CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page);
137     if (!pPageView)
138         return FALSE;
139
140     return pPageView->OnChar(nChar, modifier);
141 }
142
143 DLLEXPORT FPDF_BOOL STDCALL FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle)
144 {
145     CPDFSDK_Document* pSDKDoc = FormHandleToSDKDoc(hHandle);
146     if (!pSDKDoc)
147         return FALSE;
148
149     return pSDKDoc->KillFocusAnnot(0);
150 }
151
152 DLLEXPORT void STDCALL FPDF_FFLDraw(FPDF_FORMHANDLE hHandle, FPDF_BITMAP bitmap, FPDF_PAGE page,
153                                     int start_x, int start_y, int size_x, int size_y, int rotate, int flags)
154 {
155     if (!hHandle || !page)
156         return;
157
158     CPDF_Page* pPage = (CPDF_Page*)page;
159     CPDF_RenderOptions options;
160     if (flags & FPDF_LCD_TEXT)
161         options.m_Flags |= RENDER_CLEARTYPE;
162     else
163         options.m_Flags &= ~RENDER_CLEARTYPE;
164
165     //Grayscale output
166     if (flags & FPDF_GRAYSCALE)
167     {
168         options.m_ColorMode = RENDER_COLOR_GRAY;
169         options.m_ForeColor = 0;
170         options.m_BackColor = 0xffffff;
171     }
172
173     options.m_AddFlags = flags >> 8;
174     options.m_pOCContext = new CPDF_OCContext(pPage->m_pDocument);
175
176     CFX_AffineMatrix matrix;
177     pPage->GetDisplayMatrix(matrix, start_x, start_y, size_x, size_y, rotate);
178
179     FX_RECT clip;
180     clip.left = start_x;
181     clip.right = start_x + size_x;
182     clip.top = start_y;
183     clip.bottom = start_y + size_y;
184
185 #ifdef _SKIA_SUPPORT_
186     nonstd::unique_ptr<CFX_SkiaDevice> pDevice(new CFX_SkiaDevice);
187 #else
188     nonstd::unique_ptr<CFX_FxgeDevice> pDevice(new CFX_FxgeDevice);
189 #endif
190     pDevice->Attach((CFX_DIBitmap*)bitmap);
191     pDevice->SaveState();
192     pDevice->SetClip_Rect(&clip);
193
194     if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, pPage))
195         pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options);
196
197     pDevice->RestoreState();
198     delete options.m_pOCContext;
199 }
200
201 DLLEXPORT void STDCALL FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle, int fieldType, unsigned long color)
202 {
203     if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
204         pInterForm->SetHighlightColor(color, fieldType);
205 }
206
207 DLLEXPORT void STDCALL FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle, unsigned char alpha)
208 {
209     if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
210         pInterForm->SetHighlightAlpha(alpha);
211 }
212
213 DLLEXPORT void STDCALL FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle)
214 {
215     if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
216         pInterForm->RemoveAllHighLight();
217 }
218
219 DLLEXPORT void STDCALL FORM_OnAfterLoadPage(FPDF_PAGE page, FPDF_FORMHANDLE hHandle)
220 {
221     if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page))
222         pPageView->SetValid(TRUE);
223 }
224
225 DLLEXPORT void STDCALL FORM_OnBeforeClosePage(FPDF_PAGE page, FPDF_FORMHANDLE hHandle)
226 {
227     if (!hHandle || !page)
228         return;
229
230     CPDFSDK_Document* pSDKDoc = ((CPDFDoc_Environment*)hHandle)->GetSDKDocument();
231     if (!pSDKDoc)
232         return;
233
234     CPDF_Page* pPage = (CPDF_Page*)page;
235     CPDFSDK_PageView* pPageView = pSDKDoc->GetPageView(pPage, FALSE);
236     if (pPageView)
237     {
238         pPageView->SetValid(FALSE);
239         // ReMovePageView() takes care of the delete for us.
240         pSDKDoc->ReMovePageView(pPage);
241     }
242 }
243
244 DLLEXPORT void STDCALL FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle)
245 {
246     CPDFSDK_Document* pSDKDoc = FormHandleToSDKDoc(hHandle);
247     if (pSDKDoc && ((CPDFDoc_Environment*)hHandle)->IsJSInitiated())
248         pSDKDoc->ProcJavascriptFun();
249 }
250
251 DLLEXPORT void STDCALL FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle)
252 {
253     CPDFSDK_Document* pSDKDoc = FormHandleToSDKDoc(hHandle);
254     if (pSDKDoc && ((CPDFDoc_Environment*)hHandle)->IsJSInitiated())
255         pSDKDoc->ProcOpenAction();
256 }
257
258 DLLEXPORT void STDCALL FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle, int aaType)
259 {
260     CPDFSDK_Document* pSDKDoc = FormHandleToSDKDoc(hHandle);
261     if (!pSDKDoc)
262         return;
263
264     CPDF_Document* pDoc = pSDKDoc->GetDocument();
265     CPDF_Dictionary* pDic = pDoc->GetRoot();
266     if (!pDic)
267         return;
268
269     CPDF_AAction aa = pDic->GetDict(FX_BSTRC("AA"));
270     if (aa.ActionExist((CPDF_AAction::AActionType)aaType))
271     {
272         CPDF_Action action = aa.GetAction((CPDF_AAction::AActionType)aaType);
273         CPDFSDK_ActionHandler *pActionHandler = ((CPDFDoc_Environment*)hHandle)->GetActionHander();
274         ASSERT(pActionHandler != NULL);
275         pActionHandler->DoAction_Document(action, (CPDF_AAction::AActionType)aaType, pSDKDoc);
276     }
277 }
278
279 DLLEXPORT void STDCALL FORM_DoPageAAction(FPDF_PAGE page, FPDF_FORMHANDLE hHandle, int aaType)
280 {
281     if(!hHandle || !page)
282         return;
283     CPDFSDK_Document* pSDKDoc = ((CPDFDoc_Environment*)hHandle)->GetSDKDocument();
284     CPDF_Page* pPage = (CPDF_Page*)page;
285     CPDFSDK_PageView* pPageView = pSDKDoc->GetPageView(pPage, FALSE);
286     if(pPageView)
287     {
288         CPDFDoc_Environment *pEnv = pSDKDoc->GetEnv();
289         ASSERT(pEnv != NULL);
290
291         CPDFSDK_ActionHandler *pActionHandler = pEnv->GetActionHander();
292         ASSERT(pActionHandler != NULL);
293
294         CPDF_Dictionary *pPageDict = pPage->m_pFormDict;
295         ASSERT(pPageDict != NULL);
296
297         CPDF_AAction aa = pPageDict->GetDict(FX_BSTRC("AA"));
298
299         FX_BOOL bExistOAAction = FALSE;
300         FX_BOOL bExistCAAction = FALSE;
301         if (FPDFPAGE_AACTION_OPEN == aaType)
302         {
303             bExistOAAction = aa.ActionExist(CPDF_AAction::OpenPage);
304             if (bExistOAAction)
305             {
306                 CPDF_Action action = aa.GetAction(CPDF_AAction::OpenPage);
307                 pActionHandler->DoAction_Page(action, CPDF_AAction::OpenPage, pSDKDoc);
308             }
309         }
310         else
311         {
312             bExistCAAction = aa.ActionExist(CPDF_AAction::ClosePage);
313             if (bExistCAAction)
314             {
315                 CPDF_Action action = aa.GetAction(CPDF_AAction::ClosePage);
316                 pActionHandler->DoAction_Page(action, CPDF_AAction::ClosePage, pSDKDoc);
317             }
318         }
319     }
320 }