Revert "Revert "Add type cast definitions for CPDF_Dictionary.""
[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   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
28   if (!pPage)
29     return nullptr;
30
31   CPDFSDK_Document* pSDKDoc = FormHandleToSDKDoc(hHandle);
32   return pSDKDoc ? pSDKDoc->GetPageView(pPage, TRUE) : nullptr;
33 }
34
35 }  // namespace
36
37 DLLEXPORT int STDCALL FPDFPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle,
38                                                    FPDF_PAGE page,
39                                                    double page_x,
40                                                    double page_y) {
41   if (!hHandle)
42     return -1;
43   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
44   if (!pPage)
45     return -1;
46   CPDF_InterForm interform(pPage->m_pDocument, FALSE);
47   CPDF_FormControl* pFormCtrl = interform.GetControlAtPoint(
48       pPage, (FX_FLOAT)page_x, (FX_FLOAT)page_y, nullptr);
49   if (!pFormCtrl)
50     return -1;
51
52   CPDF_FormField* pFormField = pFormCtrl->GetField();
53   return pFormField ? pFormField->GetFieldType() : -1;
54 }
55
56 DLLEXPORT int STDCALL FPDPage_HasFormFieldAtPoint(FPDF_FORMHANDLE hHandle,
57                                                   FPDF_PAGE page,
58                                                   double page_x,
59                                                   double page_y) {
60   return FPDFPage_HasFormFieldAtPoint(hHandle, page, page_x, page_y);
61 }
62
63 DLLEXPORT int STDCALL FPDFPage_FormFieldZOrderAtPoint(FPDF_FORMHANDLE hHandle,
64                                                       FPDF_PAGE page,
65                                                       double page_x,
66                                                       double page_y) {
67   if (!hHandle)
68     return -1;
69   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
70   if (!pPage)
71     return -1;
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 = CPDFDocumentFromFPDFDocument(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)
196     return;
197
198   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
199   if (!pPage)
200     return;
201
202   CPDF_RenderOptions options;
203   if (flags & FPDF_LCD_TEXT)
204     options.m_Flags |= RENDER_CLEARTYPE;
205   else
206     options.m_Flags &= ~RENDER_CLEARTYPE;
207
208   // Grayscale output
209   if (flags & FPDF_GRAYSCALE) {
210     options.m_ColorMode = RENDER_COLOR_GRAY;
211     options.m_ForeColor = 0;
212     options.m_BackColor = 0xffffff;
213   }
214
215   options.m_AddFlags = flags >> 8;
216   options.m_pOCContext = new CPDF_OCContext(pPage->m_pDocument);
217
218   CFX_AffineMatrix matrix;
219   pPage->GetDisplayMatrix(matrix, start_x, start_y, size_x, size_y, rotate);
220
221   FX_RECT clip;
222   clip.left = start_x;
223   clip.right = start_x + size_x;
224   clip.top = start_y;
225   clip.bottom = start_y + size_y;
226
227 #ifdef _SKIA_SUPPORT_
228   nonstd::unique_ptr<CFX_SkiaDevice> pDevice(new CFX_SkiaDevice);
229 #else
230   nonstd::unique_ptr<CFX_FxgeDevice> pDevice(new CFX_FxgeDevice);
231 #endif
232   pDevice->Attach((CFX_DIBitmap*)bitmap);
233   pDevice->SaveState();
234   pDevice->SetClip_Rect(&clip);
235
236   if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, pPage))
237     pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options);
238
239   pDevice->RestoreState();
240   delete options.m_pOCContext;
241 }
242
243 DLLEXPORT void STDCALL FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle,
244                                                        int fieldType,
245                                                        unsigned long color) {
246   if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
247     pInterForm->SetHighlightColor(color, fieldType);
248 }
249
250 DLLEXPORT void STDCALL FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle,
251                                                        unsigned char alpha) {
252   if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
253     pInterForm->SetHighlightAlpha(alpha);
254 }
255
256 DLLEXPORT void STDCALL FPDF_RemoveFormFieldHighlight(FPDF_FORMHANDLE hHandle) {
257   if (CPDFSDK_InterForm* pInterForm = FormHandleToInterForm(hHandle))
258     pInterForm->RemoveAllHighLight();
259 }
260
261 DLLEXPORT void STDCALL FORM_OnAfterLoadPage(FPDF_PAGE page,
262                                             FPDF_FORMHANDLE hHandle) {
263   if (CPDFSDK_PageView* pPageView = FormHandleToPageView(hHandle, page))
264     pPageView->SetValid(TRUE);
265 }
266
267 DLLEXPORT void STDCALL FORM_OnBeforeClosePage(FPDF_PAGE page,
268                                               FPDF_FORMHANDLE hHandle) {
269   if (!hHandle)
270     return;
271
272   CPDFSDK_Document* pSDKDoc = ((CPDFDoc_Environment*)hHandle)->GetSDKDocument();
273   if (!pSDKDoc)
274     return;
275
276   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
277   if (!pPage)
278     return;
279
280   CPDFSDK_PageView* pPageView = pSDKDoc->GetPageView(pPage, FALSE);
281   if (pPageView) {
282     pPageView->SetValid(FALSE);
283     // ReMovePageView() takes care of the delete for us.
284     pSDKDoc->ReMovePageView(pPage);
285   }
286 }
287
288 DLLEXPORT void STDCALL FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle) {
289   CPDFSDK_Document* pSDKDoc = FormHandleToSDKDoc(hHandle);
290   if (pSDKDoc && ((CPDFDoc_Environment*)hHandle)->IsJSInitiated())
291     pSDKDoc->ProcJavascriptFun();
292 }
293
294 DLLEXPORT void STDCALL FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle) {
295   CPDFSDK_Document* pSDKDoc = FormHandleToSDKDoc(hHandle);
296   if (pSDKDoc && ((CPDFDoc_Environment*)hHandle)->IsJSInitiated())
297     pSDKDoc->ProcOpenAction();
298 }
299
300 DLLEXPORT void STDCALL FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle,
301                                               int aaType) {
302   CPDFSDK_Document* pSDKDoc = FormHandleToSDKDoc(hHandle);
303   if (!pSDKDoc)
304     return;
305
306   CPDF_Document* pDoc = pSDKDoc->GetDocument();
307   CPDF_Dictionary* pDic = pDoc->GetRoot();
308   if (!pDic)
309     return;
310
311   CPDF_AAction aa = pDic->GetDict(FX_BSTRC("AA"));
312   if (aa.ActionExist((CPDF_AAction::AActionType)aaType)) {
313     CPDF_Action action = aa.GetAction((CPDF_AAction::AActionType)aaType);
314     CPDFSDK_ActionHandler* pActionHandler =
315         ((CPDFDoc_Environment*)hHandle)->GetActionHander();
316     ASSERT(pActionHandler != NULL);
317     pActionHandler->DoAction_Document(action, (CPDF_AAction::AActionType)aaType,
318                                       pSDKDoc);
319   }
320 }
321
322 DLLEXPORT void STDCALL FORM_DoPageAAction(FPDF_PAGE page,
323                                           FPDF_FORMHANDLE hHandle,
324                                           int aaType) {
325   if (!hHandle)
326     return;
327   CPDFSDK_Document* pSDKDoc = ((CPDFDoc_Environment*)hHandle)->GetSDKDocument();
328   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
329   if (!pPage)
330     return;
331   CPDFSDK_PageView* pPageView = pSDKDoc->GetPageView(pPage, FALSE);
332   if (pPageView) {
333     CPDFDoc_Environment* pEnv = pSDKDoc->GetEnv();
334     CPDFSDK_ActionHandler* pActionHandler = pEnv->GetActionHander();
335     CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
336     CPDF_AAction aa = pPageDict->GetDict(FX_BSTRC("AA"));
337
338     FX_BOOL bExistOAAction = FALSE;
339     FX_BOOL bExistCAAction = FALSE;
340     if (FPDFPAGE_AACTION_OPEN == aaType) {
341       bExistOAAction = aa.ActionExist(CPDF_AAction::OpenPage);
342       if (bExistOAAction) {
343         CPDF_Action action = aa.GetAction(CPDF_AAction::OpenPage);
344         pActionHandler->DoAction_Page(action, CPDF_AAction::OpenPage, pSDKDoc);
345       }
346     } else {
347       bExistCAAction = aa.ActionExist(CPDF_AAction::ClosePage);
348       if (bExistCAAction) {
349         CPDF_Action action = aa.GetAction(CPDF_AAction::ClosePage);
350         pActionHandler->DoAction_Page(action, CPDF_AAction::ClosePage, pSDKDoc);
351       }
352     }
353   }
354 }