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