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