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 "xfa/fxfa/include/xfa_ffwidget.h"
8 
9 #include <algorithm>
10 #include <memory>
11 
12 #include "core/fpdfapi/fpdf_page/include/cpdf_pageobjectholder.h"
13 #include "core/fxcodec/codec/include/ccodec_progressivedecoder.h"
14 #include "core/fxcodec/include/fx_codec.h"
15 #include "xfa/fxfa/app/xfa_textlayout.h"
16 #include "xfa/fxfa/include/fxfa_widget.h"
17 #include "xfa/fxfa/include/cxfa_eventparam.h"
18 #include "xfa/fxfa/include/xfa_ffapp.h"
19 #include "xfa/fxfa/include/xfa_ffdoc.h"
20 #include "xfa/fxfa/include/xfa_ffdocview.h"
21 #include "xfa/fxfa/include/xfa_ffpageview.h"
22 #include "xfa/fxfa/parser/cxfa_corner.h"
23 #include "xfa/fxgraphics/cfx_color.h"
24 #include "xfa/fxgraphics/cfx_path.h"
25 #include "xfa/fxgraphics/cfx_pattern.h"
26 #include "xfa/fxgraphics/cfx_shading.h"
27 #include "xfa/fxgraphics/include/cfx_graphics.h"
28 
CXFA_FFWidget(CXFA_FFPageView * pPageView,CXFA_WidgetAcc * pDataAcc)29 CXFA_FFWidget::CXFA_FFWidget(CXFA_FFPageView* pPageView,
30                              CXFA_WidgetAcc* pDataAcc)
31     : CXFA_ContentLayoutItem(pDataAcc->GetNode()),
32       m_pPageView(pPageView),
33       m_pDataAcc(pDataAcc) {
34   m_rtWidget.Set(0, 0, 0, 0);
35 }
~CXFA_FFWidget()36 CXFA_FFWidget::~CXFA_FFWidget() {}
GetPageView()37 CXFA_FFPageView* CXFA_FFWidget::GetPageView() {
38   return m_pPageView;
39 }
SetPageView(CXFA_FFPageView * pPageView)40 void CXFA_FFWidget::SetPageView(CXFA_FFPageView* pPageView) {
41   m_pPageView = pPageView;
42 }
GetWidgetRect(CFX_RectF & rtWidget)43 void CXFA_FFWidget::GetWidgetRect(CFX_RectF& rtWidget) {
44   if ((m_dwStatus & XFA_WidgetStatus_RectCached) == 0) {
45     m_dwStatus |= XFA_WidgetStatus_RectCached;
46     GetRect(m_rtWidget);
47   }
48   rtWidget = m_rtWidget;
49 }
ReCacheWidgetRect()50 CFX_RectF CXFA_FFWidget::ReCacheWidgetRect() {
51   m_dwStatus |= XFA_WidgetStatus_RectCached;
52   GetRect(m_rtWidget);
53   return m_rtWidget;
54 }
GetRectWithoutRotate(CFX_RectF & rtWidget)55 void CXFA_FFWidget::GetRectWithoutRotate(CFX_RectF& rtWidget) {
56   GetWidgetRect(rtWidget);
57   FX_FLOAT fValue = 0;
58   switch (m_pDataAcc->GetRotate()) {
59     case 90:
60       rtWidget.top = rtWidget.bottom();
61       fValue = rtWidget.width;
62       rtWidget.width = rtWidget.height;
63       rtWidget.height = fValue;
64       break;
65     case 180:
66       rtWidget.left = rtWidget.right();
67       rtWidget.top = rtWidget.bottom();
68       break;
69     case 270:
70       rtWidget.left = rtWidget.right();
71       fValue = rtWidget.width;
72       rtWidget.width = rtWidget.height;
73       rtWidget.height = fValue;
74       break;
75   }
76 }
GetStatus()77 uint32_t CXFA_FFWidget::GetStatus() {
78   return m_dwStatus;
79 }
80 
ModifyStatus(uint32_t dwAdded,uint32_t dwRemoved)81 void CXFA_FFWidget::ModifyStatus(uint32_t dwAdded, uint32_t dwRemoved) {
82   m_dwStatus = (m_dwStatus & ~dwRemoved) | dwAdded;
83 }
84 
GetBBox(CFX_RectF & rtBox,uint32_t dwStatus,FX_BOOL bDrawFocus)85 FX_BOOL CXFA_FFWidget::GetBBox(CFX_RectF& rtBox,
86                                uint32_t dwStatus,
87                                FX_BOOL bDrawFocus) {
88   if (bDrawFocus)
89     return FALSE;
90   if (m_pPageView)
91     m_pPageView->GetPageViewRect(rtBox);
92   return TRUE;
93 }
94 
GetDataAcc()95 CXFA_WidgetAcc* CXFA_FFWidget::GetDataAcc() {
96   return m_pDataAcc;
97 }
98 
GetToolTip(CFX_WideString & wsToolTip)99 FX_BOOL CXFA_FFWidget::GetToolTip(CFX_WideString& wsToolTip) {
100   if (CXFA_Assist assist = m_pDataAcc->GetAssist()) {
101     if (CXFA_ToolTip toolTip = assist.GetToolTip()) {
102       return toolTip.GetTip(wsToolTip);
103     }
104   }
105   return GetCaptionText(wsToolTip);
106 }
RenderWidget(CFX_Graphics * pGS,CFX_Matrix * pMatrix,uint32_t dwStatus)107 void CXFA_FFWidget::RenderWidget(CFX_Graphics* pGS,
108                                  CFX_Matrix* pMatrix,
109                                  uint32_t dwStatus) {
110   if (!IsMatchVisibleStatus(dwStatus)) {
111     return;
112   }
113   CXFA_Border border = m_pDataAcc->GetBorder();
114   if (border) {
115     CFX_RectF rtBorder;
116     GetRectWithoutRotate(rtBorder);
117     CXFA_Margin margin = border.GetMargin();
118     if (margin) {
119       XFA_RectWidthoutMargin(rtBorder, margin);
120     }
121     rtBorder.Normalize();
122     DrawBorder(pGS, border, rtBorder, pMatrix);
123   }
124 }
IsLoaded()125 FX_BOOL CXFA_FFWidget::IsLoaded() {
126   return !!m_pPageView;
127 }
LoadWidget()128 FX_BOOL CXFA_FFWidget::LoadWidget() {
129   PerformLayout();
130   return TRUE;
131 }
UnloadWidget()132 void CXFA_FFWidget::UnloadWidget() {}
PerformLayout()133 FX_BOOL CXFA_FFWidget::PerformLayout() {
134   ReCacheWidgetRect();
135   return TRUE;
136 }
UpdateFWLData()137 FX_BOOL CXFA_FFWidget::UpdateFWLData() {
138   return FALSE;
139 }
UpdateWidgetProperty()140 void CXFA_FFWidget::UpdateWidgetProperty() {}
DrawBorder(CFX_Graphics * pGS,CXFA_Box box,const CFX_RectF & rtBorder,CFX_Matrix * pMatrix,uint32_t dwFlags)141 void CXFA_FFWidget::DrawBorder(CFX_Graphics* pGS,
142                                CXFA_Box box,
143                                const CFX_RectF& rtBorder,
144                                CFX_Matrix* pMatrix,
145                                uint32_t dwFlags) {
146   XFA_DrawBox(box, pGS, rtBorder, pMatrix, dwFlags);
147 }
InvalidateWidget(const CFX_RectF * pRect)148 void CXFA_FFWidget::InvalidateWidget(const CFX_RectF* pRect) {
149   if (!pRect) {
150     CFX_RectF rtWidget;
151     GetBBox(rtWidget, XFA_WidgetStatus_Focused);
152     rtWidget.Inflate(2, 2);
153     GetDoc()->GetDocProvider()->InvalidateRect(m_pPageView, rtWidget,
154                                                XFA_INVALIDATE_CurrentPage);
155   } else {
156     GetDoc()->GetDocProvider()->InvalidateRect(m_pPageView, *pRect,
157                                                XFA_INVALIDATE_CurrentPage);
158   }
159 }
AddInvalidateRect(const CFX_RectF * pRect)160 void CXFA_FFWidget::AddInvalidateRect(const CFX_RectF* pRect) {
161   CFX_RectF rtWidget;
162   if (pRect) {
163     rtWidget = *pRect;
164   } else {
165     GetBBox(rtWidget, XFA_WidgetStatus_Focused);
166     rtWidget.Inflate(2, 2);
167   }
168   m_pDocView->AddInvalidateRect(m_pPageView, rtWidget);
169 }
GetCaptionText(CFX_WideString & wsCap)170 FX_BOOL CXFA_FFWidget::GetCaptionText(CFX_WideString& wsCap) {
171   CXFA_TextLayout* pCapTextlayout = m_pDataAcc->GetCaptionTextLayout();
172   if (!pCapTextlayout) {
173     return FALSE;
174   }
175   pCapTextlayout->GetText(wsCap);
176   return TRUE;
177 }
178 
IsFocused()179 bool CXFA_FFWidget::IsFocused() {
180   return !!(m_dwStatus & XFA_WidgetStatus_Focused);
181 }
182 
OnMouseEnter()183 FX_BOOL CXFA_FFWidget::OnMouseEnter() {
184   return FALSE;
185 }
OnMouseExit()186 FX_BOOL CXFA_FFWidget::OnMouseExit() {
187   return FALSE;
188 }
OnLButtonDown(uint32_t dwFlags,FX_FLOAT fx,FX_FLOAT fy)189 FX_BOOL CXFA_FFWidget::OnLButtonDown(uint32_t dwFlags,
190                                      FX_FLOAT fx,
191                                      FX_FLOAT fy) {
192   return FALSE;
193 }
OnLButtonUp(uint32_t dwFlags,FX_FLOAT fx,FX_FLOAT fy)194 FX_BOOL CXFA_FFWidget::OnLButtonUp(uint32_t dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
195   return FALSE;
196 }
OnLButtonDblClk(uint32_t dwFlags,FX_FLOAT fx,FX_FLOAT fy)197 FX_BOOL CXFA_FFWidget::OnLButtonDblClk(uint32_t dwFlags,
198                                        FX_FLOAT fx,
199                                        FX_FLOAT fy) {
200   return FALSE;
201 }
OnMouseMove(uint32_t dwFlags,FX_FLOAT fx,FX_FLOAT fy)202 FX_BOOL CXFA_FFWidget::OnMouseMove(uint32_t dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
203   return FALSE;
204 }
OnMouseWheel(uint32_t dwFlags,int16_t zDelta,FX_FLOAT fx,FX_FLOAT fy)205 FX_BOOL CXFA_FFWidget::OnMouseWheel(uint32_t dwFlags,
206                                     int16_t zDelta,
207                                     FX_FLOAT fx,
208                                     FX_FLOAT fy) {
209   return FALSE;
210 }
OnRButtonDown(uint32_t dwFlags,FX_FLOAT fx,FX_FLOAT fy)211 FX_BOOL CXFA_FFWidget::OnRButtonDown(uint32_t dwFlags,
212                                      FX_FLOAT fx,
213                                      FX_FLOAT fy) {
214   return FALSE;
215 }
OnRButtonUp(uint32_t dwFlags,FX_FLOAT fx,FX_FLOAT fy)216 FX_BOOL CXFA_FFWidget::OnRButtonUp(uint32_t dwFlags, FX_FLOAT fx, FX_FLOAT fy) {
217   return FALSE;
218 }
OnRButtonDblClk(uint32_t dwFlags,FX_FLOAT fx,FX_FLOAT fy)219 FX_BOOL CXFA_FFWidget::OnRButtonDblClk(uint32_t dwFlags,
220                                        FX_FLOAT fx,
221                                        FX_FLOAT fy) {
222   return FALSE;
223 }
224 
OnSetFocus(CXFA_FFWidget * pOldWidget)225 FX_BOOL CXFA_FFWidget::OnSetFocus(CXFA_FFWidget* pOldWidget) {
226   CXFA_FFWidget* pParent = GetParent();
227   if (pParent && !pParent->IsAncestorOf(pOldWidget)) {
228     pParent->OnSetFocus(pOldWidget);
229   }
230   m_dwStatus |= XFA_WidgetStatus_Focused;
231   CXFA_EventParam eParam;
232   eParam.m_eType = XFA_EVENT_Enter;
233   eParam.m_pTarget = m_pDataAcc;
234   m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Enter, &eParam);
235   return TRUE;
236 }
OnKillFocus(CXFA_FFWidget * pNewWidget)237 FX_BOOL CXFA_FFWidget::OnKillFocus(CXFA_FFWidget* pNewWidget) {
238   m_dwStatus &= ~XFA_WidgetStatus_Focused;
239   EventKillFocus();
240   if (pNewWidget) {
241     CXFA_FFWidget* pParent = GetParent();
242     if (pParent && !pParent->IsAncestorOf(pNewWidget)) {
243       pParent->OnKillFocus(pNewWidget);
244     }
245   }
246   return TRUE;
247 }
OnKeyDown(uint32_t dwKeyCode,uint32_t dwFlags)248 FX_BOOL CXFA_FFWidget::OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) {
249   return FALSE;
250 }
OnKeyUp(uint32_t dwKeyCode,uint32_t dwFlags)251 FX_BOOL CXFA_FFWidget::OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) {
252   return FALSE;
253 }
OnChar(uint32_t dwChar,uint32_t dwFlags)254 FX_BOOL CXFA_FFWidget::OnChar(uint32_t dwChar, uint32_t dwFlags) {
255   return FALSE;
256 }
OnHitTest(FX_FLOAT fx,FX_FLOAT fy)257 FWL_WidgetHit CXFA_FFWidget::OnHitTest(FX_FLOAT fx, FX_FLOAT fy) {
258   return FWL_WidgetHit::Unknown;
259 }
OnSetCursor(FX_FLOAT fx,FX_FLOAT fy)260 FX_BOOL CXFA_FFWidget::OnSetCursor(FX_FLOAT fx, FX_FLOAT fy) {
261   return FALSE;
262 }
CanUndo()263 FX_BOOL CXFA_FFWidget::CanUndo() {
264   return FALSE;
265 }
CanRedo()266 FX_BOOL CXFA_FFWidget::CanRedo() {
267   return FALSE;
268 }
Undo()269 FX_BOOL CXFA_FFWidget::Undo() {
270   return FALSE;
271 }
Redo()272 FX_BOOL CXFA_FFWidget::Redo() {
273   return FALSE;
274 }
CanCopy()275 FX_BOOL CXFA_FFWidget::CanCopy() {
276   return FALSE;
277 }
CanCut()278 FX_BOOL CXFA_FFWidget::CanCut() {
279   return FALSE;
280 }
CanPaste()281 FX_BOOL CXFA_FFWidget::CanPaste() {
282   return FALSE;
283 }
CanSelectAll()284 FX_BOOL CXFA_FFWidget::CanSelectAll() {
285   return FALSE;
286 }
CanDelete()287 FX_BOOL CXFA_FFWidget::CanDelete() {
288   return CanCut();
289 }
CanDeSelect()290 FX_BOOL CXFA_FFWidget::CanDeSelect() {
291   return CanCopy();
292 }
Copy(CFX_WideString & wsCopy)293 FX_BOOL CXFA_FFWidget::Copy(CFX_WideString& wsCopy) {
294   return FALSE;
295 }
Cut(CFX_WideString & wsCut)296 FX_BOOL CXFA_FFWidget::Cut(CFX_WideString& wsCut) {
297   return FALSE;
298 }
Paste(const CFX_WideString & wsPaste)299 FX_BOOL CXFA_FFWidget::Paste(const CFX_WideString& wsPaste) {
300   return FALSE;
301 }
SelectAll()302 FX_BOOL CXFA_FFWidget::SelectAll() {
303   return FALSE;
304 }
Delete()305 FX_BOOL CXFA_FFWidget::Delete() {
306   return FALSE;
307 }
DeSelect()308 FX_BOOL CXFA_FFWidget::DeSelect() {
309   return FALSE;
310 }
GetSuggestWords(CFX_PointF pointf,std::vector<CFX_ByteString> & sSuggest)311 FX_BOOL CXFA_FFWidget::GetSuggestWords(CFX_PointF pointf,
312                                        std::vector<CFX_ByteString>& sSuggest) {
313   return FALSE;
314 }
ReplaceSpellCheckWord(CFX_PointF pointf,const CFX_ByteStringC & bsReplace)315 FX_BOOL CXFA_FFWidget::ReplaceSpellCheckWord(CFX_PointF pointf,
316                                              const CFX_ByteStringC& bsReplace) {
317   return FALSE;
318 }
Rotate2Normal(FX_FLOAT & fx,FX_FLOAT & fy)319 void CXFA_FFWidget::Rotate2Normal(FX_FLOAT& fx, FX_FLOAT& fy) {
320   CFX_Matrix mt;
321   GetRotateMatrix(mt);
322   if (mt.IsIdentity()) {
323     return;
324   }
325   CFX_Matrix mtReverse;
326   mtReverse.SetReverse(mt);
327   mtReverse.TransformPoint(fx, fy);
328 }
XFA_GetMatrix(CFX_Matrix & m,int32_t iRotate,XFA_ATTRIBUTEENUM at,const CFX_RectF & rt)329 static void XFA_GetMatrix(CFX_Matrix& m,
330                           int32_t iRotate,
331                           XFA_ATTRIBUTEENUM at,
332                           const CFX_RectF& rt) {
333   if (!iRotate) {
334     return;
335   }
336   FX_FLOAT fAnchorX = 0;
337   FX_FLOAT fAnchorY = 0;
338   switch (at) {
339     case XFA_ATTRIBUTEENUM_TopLeft:
340       fAnchorX = rt.left, fAnchorY = rt.top;
341       break;
342     case XFA_ATTRIBUTEENUM_TopCenter:
343       fAnchorX = (rt.left + rt.right()) / 2, fAnchorY = rt.top;
344       break;
345     case XFA_ATTRIBUTEENUM_TopRight:
346       fAnchorX = rt.right(), fAnchorY = rt.top;
347       break;
348     case XFA_ATTRIBUTEENUM_MiddleLeft:
349       fAnchorX = rt.left, fAnchorY = (rt.top + rt.bottom()) / 2;
350       break;
351     case XFA_ATTRIBUTEENUM_MiddleCenter:
352       fAnchorX = (rt.left + rt.right()) / 2,
353       fAnchorY = (rt.top + rt.bottom()) / 2;
354       break;
355     case XFA_ATTRIBUTEENUM_MiddleRight:
356       fAnchorX = rt.right(), fAnchorY = (rt.top + rt.bottom()) / 2;
357       break;
358     case XFA_ATTRIBUTEENUM_BottomLeft:
359       fAnchorX = rt.left, fAnchorY = rt.bottom();
360       break;
361     case XFA_ATTRIBUTEENUM_BottomCenter:
362       fAnchorX = (rt.left + rt.right()) / 2, fAnchorY = rt.bottom();
363       break;
364     case XFA_ATTRIBUTEENUM_BottomRight:
365       fAnchorX = rt.right(), fAnchorY = rt.bottom();
366       break;
367     default:
368       break;
369   }
370   switch (iRotate) {
371     case 90:
372       m.a = 0, m.b = -1, m.c = 1, m.d = 0, m.e = fAnchorX - fAnchorY,
373       m.f = fAnchorX + fAnchorY;
374       break;
375     case 180:
376       m.a = -1, m.b = 0, m.c = 0, m.d = -1, m.e = fAnchorX * 2,
377       m.f = fAnchorY * 2;
378       break;
379     case 270:
380       m.a = 0, m.b = 1, m.c = -1, m.d = 0, m.e = fAnchorX + fAnchorY,
381       m.f = fAnchorY - fAnchorX;
382       break;
383   }
384 }
GetRotateMatrix(CFX_Matrix & mt)385 void CXFA_FFWidget::GetRotateMatrix(CFX_Matrix& mt) {
386   mt.Set(1, 0, 0, 1, 0, 0);
387   int32_t iRotate = m_pDataAcc->GetRotate();
388   if (!iRotate) {
389     return;
390   }
391   CFX_RectF rcWidget;
392   GetRectWithoutRotate(rcWidget);
393   XFA_ATTRIBUTEENUM at = XFA_ATTRIBUTEENUM_TopLeft;
394   XFA_GetMatrix(mt, iRotate, at, rcWidget);
395 }
IsLayoutRectEmpty()396 FX_BOOL CXFA_FFWidget::IsLayoutRectEmpty() {
397   CFX_RectF rtLayout;
398   GetRectWithoutRotate(rtLayout);
399   return rtLayout.width < 0.1f && rtLayout.height < 0.1f;
400 }
GetParent()401 CXFA_FFWidget* CXFA_FFWidget::GetParent() {
402   CXFA_Node* pParentNode =
403       m_pDataAcc->GetNode()->GetNodeItem(XFA_NODEITEM_Parent);
404   if (pParentNode) {
405     CXFA_WidgetAcc* pParentWidgetAcc =
406         static_cast<CXFA_WidgetAcc*>(pParentNode->GetWidgetData());
407     if (pParentWidgetAcc) {
408       return pParentWidgetAcc->GetNextWidget(nullptr);
409     }
410   }
411   return nullptr;
412 }
IsAncestorOf(CXFA_FFWidget * pWidget)413 FX_BOOL CXFA_FFWidget::IsAncestorOf(CXFA_FFWidget* pWidget) {
414   if (!pWidget) {
415     return FALSE;
416   }
417   CXFA_Node* pNode = m_pDataAcc->GetNode();
418   CXFA_Node* pChildNode = pWidget->GetDataAcc()->GetNode();
419   while (pChildNode) {
420     if (pChildNode == pNode) {
421       return TRUE;
422     }
423     pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_Parent);
424   }
425   return FALSE;
426 }
PtInActiveRect(FX_FLOAT fx,FX_FLOAT fy)427 FX_BOOL CXFA_FFWidget::PtInActiveRect(FX_FLOAT fx, FX_FLOAT fy) {
428   CFX_RectF rtWidget;
429   GetWidgetRect(rtWidget);
430   if (rtWidget.Contains(fx, fy)) {
431     return TRUE;
432   }
433   return FALSE;
434 }
GetDocView()435 CXFA_FFDocView* CXFA_FFWidget::GetDocView() {
436   return m_pDocView;
437 }
SetDocView(CXFA_FFDocView * pDocView)438 void CXFA_FFWidget::SetDocView(CXFA_FFDocView* pDocView) {
439   m_pDocView = pDocView;
440 }
GetDoc()441 CXFA_FFDoc* CXFA_FFWidget::GetDoc() {
442   return m_pDocView->GetDoc();
443 }
GetApp()444 CXFA_FFApp* CXFA_FFWidget::GetApp() {
445   return GetDoc()->GetApp();
446 }
GetAppProvider()447 IXFA_AppProvider* CXFA_FFWidget::GetAppProvider() {
448   return GetApp()->GetAppProvider();
449 }
GetMinMaxWidth(FX_FLOAT fMinWidth,FX_FLOAT fMaxWidth)450 void CXFA_FFWidget::GetMinMaxWidth(FX_FLOAT fMinWidth, FX_FLOAT fMaxWidth) {
451   fMinWidth = fMaxWidth = 0;
452   FX_FLOAT fWidth = 0;
453   if (m_pDataAcc->GetWidth(fWidth)) {
454     fMinWidth = fMaxWidth = fWidth;
455   } else {
456     m_pDataAcc->GetMinWidth(fMinWidth);
457     m_pDataAcc->GetMaxWidth(fMaxWidth);
458   }
459 }
GetMinMaxHeight(FX_FLOAT fMinHeight,FX_FLOAT fMaxHeight)460 void CXFA_FFWidget::GetMinMaxHeight(FX_FLOAT fMinHeight, FX_FLOAT fMaxHeight) {
461   fMinHeight = fMaxHeight = 0;
462   FX_FLOAT fHeight = 0;
463   if (m_pDataAcc->GetHeight(fHeight)) {
464     fMinHeight = fMaxHeight = fHeight;
465   } else {
466     m_pDataAcc->GetMinHeight(fMinHeight);
467     m_pDataAcc->GetMaxHeight(fMaxHeight);
468   }
469 }
470 
IsMatchVisibleStatus(uint32_t dwStatus)471 bool CXFA_FFWidget::IsMatchVisibleStatus(uint32_t dwStatus) {
472   return !!(m_dwStatus & XFA_WidgetStatus_Visible);
473 }
474 
EventKillFocus()475 void CXFA_FFWidget::EventKillFocus() {
476   if (m_dwStatus & XFA_WidgetStatus_Access) {
477     m_dwStatus &= ~XFA_WidgetStatus_Access;
478     return;
479   }
480   CXFA_EventParam eParam;
481   eParam.m_eType = XFA_EVENT_Exit;
482   eParam.m_pTarget = m_pDataAcc;
483   m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Exit, &eParam);
484 }
IsButtonDown()485 FX_BOOL CXFA_FFWidget::IsButtonDown() {
486   return (m_dwStatus & XFA_WidgetStatus_ButtonDown) != 0;
487 }
SetButtonDown(FX_BOOL bSet)488 void CXFA_FFWidget::SetButtonDown(FX_BOOL bSet) {
489   bSet ? m_dwStatus |= XFA_WidgetStatus_ButtonDown
490        : m_dwStatus &= ~XFA_WidgetStatus_ButtonDown;
491 }
XFA_StrokeTypeSetLineDash(CFX_Graphics * pGraphics,int32_t iStrokeType,int32_t iCapType)492 int32_t XFA_StrokeTypeSetLineDash(CFX_Graphics* pGraphics,
493                                   int32_t iStrokeType,
494                                   int32_t iCapType) {
495   switch (iStrokeType) {
496     case XFA_ATTRIBUTEENUM_DashDot: {
497       FX_FLOAT dashArray[] = {4, 1, 2, 1};
498       if (iCapType != XFA_ATTRIBUTEENUM_Butt) {
499         dashArray[1] = 2;
500         dashArray[3] = 2;
501       }
502       pGraphics->SetLineDash(0, dashArray, 4);
503       return FX_DASHSTYLE_DashDot;
504     }
505     case XFA_ATTRIBUTEENUM_DashDotDot: {
506       FX_FLOAT dashArray[] = {4, 1, 2, 1, 2, 1};
507       if (iCapType != XFA_ATTRIBUTEENUM_Butt) {
508         dashArray[1] = 2;
509         dashArray[3] = 2;
510         dashArray[5] = 2;
511       }
512       pGraphics->SetLineDash(0, dashArray, 6);
513       return FX_DASHSTYLE_DashDotDot;
514     }
515     case XFA_ATTRIBUTEENUM_Dashed: {
516       FX_FLOAT dashArray[] = {5, 1};
517       if (iCapType != XFA_ATTRIBUTEENUM_Butt) {
518         dashArray[1] = 2;
519       }
520       pGraphics->SetLineDash(0, dashArray, 2);
521       return FX_DASHSTYLE_Dash;
522     }
523     case XFA_ATTRIBUTEENUM_Dotted: {
524       FX_FLOAT dashArray[] = {2, 1};
525       if (iCapType != XFA_ATTRIBUTEENUM_Butt) {
526         dashArray[1] = 2;
527       }
528       pGraphics->SetLineDash(0, dashArray, 2);
529       return FX_DASHSTYLE_Dot;
530     }
531     default:
532       break;
533   }
534   pGraphics->SetLineDash(FX_DASHSTYLE_Solid);
535   return FX_DASHSTYLE_Solid;
536 }
XFA_LineCapToFXGE(int32_t iLineCap)537 CFX_GraphStateData::LineCap XFA_LineCapToFXGE(int32_t iLineCap) {
538   switch (iLineCap) {
539     case XFA_ATTRIBUTEENUM_Round:
540       return CFX_GraphStateData::LineCapRound;
541     case XFA_ATTRIBUTEENUM_Butt:
542       return CFX_GraphStateData::LineCapButt;
543     default:
544       break;
545   }
546   return CFX_GraphStateData::LineCapSquare;
547 }
548 
549 class CXFA_ImageRenderer {
550  public:
551   CXFA_ImageRenderer();
552   ~CXFA_ImageRenderer();
553 
554   FX_BOOL Start(CFX_RenderDevice* pDevice,
555                 CFX_DIBSource* pDIBSource,
556                 FX_ARGB bitmap_argb,
557                 int bitmap_alpha,
558                 const CFX_Matrix* pImage2Device,
559                 uint32_t flags,
560                 int blendType = FXDIB_BLEND_NORMAL);
561   FX_BOOL Continue(IFX_Pause* pPause);
562 
563  protected:
564   CFX_RenderDevice* m_pDevice;
565   int m_Status;
566   CFX_Matrix m_ImageMatrix;
567   CFX_DIBSource* m_pDIBSource;
568   CFX_DIBitmap* m_pCloneConvert;
569   int m_BitmapAlpha;
570   FX_ARGB m_FillArgb;
571   uint32_t m_Flags;
572   std::unique_ptr<CFX_ImageTransformer> m_pTransformer;
573   void* m_DeviceHandle;
574   int32_t m_BlendType;
575   FX_BOOL m_Result;
576   FX_BOOL m_bPrint;
577   FX_BOOL StartDIBSource();
578   void CompositeDIBitmap(CFX_DIBitmap* pDIBitmap,
579                          int left,
580                          int top,
581                          FX_ARGB mask_argb,
582                          int bitmap_alpha,
583                          int blend_mode,
584                          int Transparency);
585 };
CXFA_ImageRenderer()586 CXFA_ImageRenderer::CXFA_ImageRenderer() {
587   m_pDevice = nullptr;
588   m_Status = 0;
589   m_pDIBSource = nullptr;
590   m_pCloneConvert = nullptr;
591   m_BitmapAlpha = 255;
592   m_FillArgb = 0;
593   m_Flags = 0;
594   m_DeviceHandle = nullptr;
595   m_BlendType = FXDIB_BLEND_NORMAL;
596   m_Result = TRUE;
597   m_bPrint = FALSE;
598 }
599 
~CXFA_ImageRenderer()600 CXFA_ImageRenderer::~CXFA_ImageRenderer() {
601   delete m_pCloneConvert;
602   if (m_DeviceHandle)
603     m_pDevice->CancelDIBits(m_DeviceHandle);
604 }
605 
Start(CFX_RenderDevice * pDevice,CFX_DIBSource * pDIBSource,FX_ARGB bitmap_argb,int bitmap_alpha,const CFX_Matrix * pImage2Device,uint32_t flags,int blendType)606 FX_BOOL CXFA_ImageRenderer::Start(CFX_RenderDevice* pDevice,
607                                   CFX_DIBSource* pDIBSource,
608                                   FX_ARGB bitmap_argb,
609                                   int bitmap_alpha,
610                                   const CFX_Matrix* pImage2Device,
611                                   uint32_t flags,
612                                   int blendType) {
613   m_pDevice = pDevice;
614   m_pDIBSource = pDIBSource;
615   m_FillArgb = bitmap_argb;
616   m_BitmapAlpha = bitmap_alpha;
617   m_ImageMatrix = *pImage2Device;
618   m_Flags = flags;
619   m_BlendType = blendType;
620   return StartDIBSource();
621 }
622 
StartDIBSource()623 FX_BOOL CXFA_ImageRenderer::StartDIBSource() {
624   if (m_pDevice->StartDIBitsWithBlend(m_pDIBSource, m_BitmapAlpha, m_FillArgb,
625                                       &m_ImageMatrix, m_Flags, m_DeviceHandle,
626                                       m_BlendType)) {
627     if (m_DeviceHandle) {
628       m_Status = 3;
629       return TRUE;
630     }
631     return FALSE;
632   }
633   CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect();
634   FX_RECT image_rect = image_rect_f.GetOutterRect();
635   int dest_width = image_rect.Width();
636   int dest_height = image_rect.Height();
637   if ((FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) ||
638       (FXSYS_fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) {
639     if (m_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) {
640       m_Result = FALSE;
641       return FALSE;
642     }
643     CFX_DIBSource* pDib = m_pDIBSource;
644     if (m_pDIBSource->HasAlpha() &&
645         !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE) &&
646         !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) {
647       m_pCloneConvert = m_pDIBSource->CloneConvert(FXDIB_Rgb);
648       if (!m_pCloneConvert) {
649         m_Result = FALSE;
650         return FALSE;
651       }
652       pDib = m_pCloneConvert;
653     }
654     FX_RECT clip_box = m_pDevice->GetClipBox();
655     clip_box.Intersect(image_rect);
656     m_Status = 2;
657     m_pTransformer.reset(
658         new CFX_ImageTransformer(pDib, &m_ImageMatrix, m_Flags, &clip_box));
659     m_pTransformer->Start();
660     return TRUE;
661   }
662   if (m_ImageMatrix.a < 0) {
663     dest_width = -dest_width;
664   }
665   if (m_ImageMatrix.d > 0) {
666     dest_height = -dest_height;
667   }
668   int dest_left, dest_top;
669   dest_left = dest_width > 0 ? image_rect.left : image_rect.right;
670   dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom;
671   if (m_pDIBSource->IsOpaqueImage() && m_BitmapAlpha == 255) {
672     if (m_pDevice->StretchDIBitsWithFlagsAndBlend(
673             m_pDIBSource, dest_left, dest_top, dest_width, dest_height, m_Flags,
674             m_BlendType)) {
675       return FALSE;
676     }
677   }
678   if (m_pDIBSource->IsAlphaMask()) {
679     if (m_BitmapAlpha != 255) {
680       m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha);
681     }
682     if (m_pDevice->StretchBitMaskWithFlags(m_pDIBSource, dest_left, dest_top,
683                                            dest_width, dest_height, m_FillArgb,
684                                            m_Flags)) {
685       return FALSE;
686     }
687   }
688   if (m_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) {
689     m_Result = FALSE;
690     return TRUE;
691   }
692   FX_RECT clip_box = m_pDevice->GetClipBox();
693   FX_RECT dest_rect = clip_box;
694   dest_rect.Intersect(image_rect);
695   FX_RECT dest_clip(
696       dest_rect.left - image_rect.left, dest_rect.top - image_rect.top,
697       dest_rect.right - image_rect.left, dest_rect.bottom - image_rect.top);
698   std::unique_ptr<CFX_DIBitmap> pStretched(
699       m_pDIBSource->StretchTo(dest_width, dest_height, m_Flags, &dest_clip));
700   if (pStretched) {
701     CompositeDIBitmap(pStretched.get(), dest_rect.left, dest_rect.top,
702                       m_FillArgb, m_BitmapAlpha, m_BlendType, FALSE);
703   }
704   return FALSE;
705 }
706 
Continue(IFX_Pause * pPause)707 FX_BOOL CXFA_ImageRenderer::Continue(IFX_Pause* pPause) {
708   if (m_Status == 2) {
709     if (m_pTransformer->Continue(pPause))
710       return TRUE;
711 
712     std::unique_ptr<CFX_DIBitmap> pBitmap(m_pTransformer->DetachBitmap());
713     if (!pBitmap)
714       return FALSE;
715 
716     if (pBitmap->IsAlphaMask()) {
717       if (m_BitmapAlpha != 255)
718         m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha);
719       m_Result =
720           m_pDevice->SetBitMask(pBitmap.get(), m_pTransformer->result().left,
721                                 m_pTransformer->result().top, m_FillArgb);
722     } else {
723       if (m_BitmapAlpha != 255)
724         pBitmap->MultiplyAlpha(m_BitmapAlpha);
725       m_Result = m_pDevice->SetDIBitsWithBlend(
726           pBitmap.get(), m_pTransformer->result().left,
727           m_pTransformer->result().top, m_BlendType);
728     }
729     return FALSE;
730   }
731   if (m_Status == 3)
732     return m_pDevice->ContinueDIBits(m_DeviceHandle, pPause);
733 
734   return FALSE;
735 }
736 
CompositeDIBitmap(CFX_DIBitmap * pDIBitmap,int left,int top,FX_ARGB mask_argb,int bitmap_alpha,int blend_mode,int Transparency)737 void CXFA_ImageRenderer::CompositeDIBitmap(CFX_DIBitmap* pDIBitmap,
738                                            int left,
739                                            int top,
740                                            FX_ARGB mask_argb,
741                                            int bitmap_alpha,
742                                            int blend_mode,
743                                            int Transparency) {
744   if (!pDIBitmap) {
745     return;
746   }
747   bool bIsolated = !!(Transparency & PDFTRANS_ISOLATED);
748   bool bGroup = !!(Transparency & PDFTRANS_GROUP);
749   if (blend_mode == FXDIB_BLEND_NORMAL) {
750     if (!pDIBitmap->IsAlphaMask()) {
751       if (bitmap_alpha < 255) {
752         pDIBitmap->MultiplyAlpha(bitmap_alpha);
753       }
754       if (m_pDevice->SetDIBits(pDIBitmap, left, top)) {
755         return;
756       }
757     } else {
758       uint32_t fill_argb = (mask_argb);
759       if (bitmap_alpha < 255) {
760         ((uint8_t*)&fill_argb)[3] =
761             ((uint8_t*)&fill_argb)[3] * bitmap_alpha / 255;
762       }
763       if (m_pDevice->SetBitMask(pDIBitmap, left, top, fill_argb)) {
764         return;
765       }
766     }
767   }
768   FX_BOOL bBackAlphaRequired = blend_mode && bIsolated;
769   FX_BOOL bGetBackGround =
770       ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) ||
771       (!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) &&
772        (m_pDevice->GetRenderCaps() & FXRC_GET_BITS) && !bBackAlphaRequired);
773   if (bGetBackGround) {
774     if (bIsolated || !bGroup) {
775       if (pDIBitmap->IsAlphaMask()) {
776         return;
777       }
778       m_pDevice->SetDIBitsWithBlend(pDIBitmap, left, top, blend_mode);
779     } else {
780       FX_RECT rect(left, top, left + pDIBitmap->GetWidth(),
781                    top + pDIBitmap->GetHeight());
782       rect.Intersect(m_pDevice->GetClipBox());
783       CFX_DIBitmap* pClone = nullptr;
784       FX_BOOL bClone = FALSE;
785       if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) {
786         bClone = TRUE;
787         pClone = m_pDevice->GetBackDrop()->Clone(&rect);
788         CFX_DIBitmap* pForeBitmap = m_pDevice->GetBitmap();
789         pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(),
790                                 pForeBitmap, rect.left, rect.top);
791         left = left >= 0 ? 0 : left;
792         top = top >= 0 ? 0 : top;
793         if (!pDIBitmap->IsAlphaMask())
794           pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(),
795                                   pDIBitmap, left, top, blend_mode);
796         else
797           pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(),
798                                 pDIBitmap, mask_argb, left, top, blend_mode);
799       } else {
800         pClone = pDIBitmap;
801       }
802       if (m_pDevice->GetBackDrop()) {
803         m_pDevice->SetDIBits(pClone, rect.left, rect.top);
804       } else {
805         if (pDIBitmap->IsAlphaMask())
806           return;
807         m_pDevice->SetDIBitsWithBlend(pDIBitmap, rect.left, rect.top,
808                                       blend_mode);
809       }
810       if (bClone) {
811         delete pClone;
812       }
813     }
814     return;
815   }
816   if (pDIBitmap->HasAlpha() &&
817       !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE)) {
818     CFX_DIBitmap* pCloneConvert = pDIBitmap->CloneConvert(FXDIB_Rgb);
819     if (!pCloneConvert) {
820       return;
821     }
822     CXFA_ImageRenderer imageRender;
823     FX_BOOL bRet = imageRender.Start(m_pDevice, pCloneConvert, m_FillArgb,
824                                      m_BitmapAlpha, &m_ImageMatrix, m_Flags);
825     while (bRet) {
826       bRet = imageRender.Continue(nullptr);
827     }
828     delete pCloneConvert;
829     return;
830   }
831 }
XFA_DrawImage(CFX_Graphics * pGS,const CFX_RectF & rtImage,CFX_Matrix * pMatrix,CFX_DIBitmap * pDIBitmap,int32_t iAspect,int32_t iImageXDpi,int32_t iImageYDpi,int32_t iHorzAlign,int32_t iVertAlign)832 void XFA_DrawImage(CFX_Graphics* pGS,
833                    const CFX_RectF& rtImage,
834                    CFX_Matrix* pMatrix,
835                    CFX_DIBitmap* pDIBitmap,
836                    int32_t iAspect,
837                    int32_t iImageXDpi,
838                    int32_t iImageYDpi,
839                    int32_t iHorzAlign,
840                    int32_t iVertAlign) {
841   if (rtImage.IsEmpty()) {
842     return;
843   }
844   if (!pDIBitmap || !pDIBitmap->GetBuffer()) {
845     return;
846   }
847   FX_FLOAT fWidth =
848       XFA_UnitPx2Pt((FX_FLOAT)pDIBitmap->GetWidth(), (FX_FLOAT)iImageXDpi);
849   FX_FLOAT fHeight =
850       XFA_UnitPx2Pt((FX_FLOAT)pDIBitmap->GetHeight(), (FX_FLOAT)iImageYDpi);
851   CFX_RectF rtFit;
852   rtFit.Set(rtImage.left, rtImage.top, fWidth, fHeight);
853   switch (iAspect) {
854     case XFA_ATTRIBUTEENUM_Fit: {
855       FX_FLOAT f1 = rtImage.height / rtFit.height;
856       FX_FLOAT f2 = rtImage.width / rtFit.width;
857       f1 = std::min(f1, f2);
858       rtFit.height = rtFit.height * f1;
859       rtFit.width = rtFit.width * f1;
860     } break;
861     case XFA_ATTRIBUTEENUM_Actual:
862       break;
863     case XFA_ATTRIBUTEENUM_Height: {
864       FX_FLOAT f1 = rtImage.height / rtFit.height;
865       rtFit.height = rtImage.height;
866       rtFit.width = f1 * rtFit.width;
867     } break;
868     case XFA_ATTRIBUTEENUM_None:
869       rtFit.height = rtImage.height;
870       rtFit.width = rtImage.width;
871       break;
872     case XFA_ATTRIBUTEENUM_Width: {
873       FX_FLOAT f1 = rtImage.width / rtFit.width;
874       rtFit.width = rtImage.width;
875       rtFit.height = rtFit.height * f1;
876     } break;
877   }
878   if (iHorzAlign == XFA_ATTRIBUTEENUM_Center) {
879     rtFit.left += (rtImage.width - rtFit.width) / 2;
880   } else if (iHorzAlign == XFA_ATTRIBUTEENUM_Right) {
881     rtFit.left = rtImage.right() - rtFit.width;
882   }
883   if (iVertAlign == XFA_ATTRIBUTEENUM_Middle) {
884     rtFit.top += (rtImage.height - rtFit.height) / 2;
885   } else if (iVertAlign == XFA_ATTRIBUTEENUM_Bottom) {
886     rtFit.top = rtImage.bottom() - rtImage.height;
887   }
888   CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
889   pRenderDevice->SaveState();
890   CFX_PathData path;
891   path.AppendRect(rtImage.left, rtImage.bottom(), rtImage.right(), rtImage.top);
892   pRenderDevice->SetClip_PathFill(&path, pMatrix, FXFILL_WINDING);
893   CFX_Matrix mtImage(1, 0, 0, -1, 0, 1);
894   mtImage.Concat(rtFit.width, 0, 0, rtFit.height, rtFit.left, rtFit.top);
895   mtImage.Concat(*pMatrix);
896   CXFA_ImageRenderer imageRender;
897   FX_BOOL bRet = imageRender.Start(pRenderDevice, pDIBitmap, 0, 255, &mtImage,
898                                    FXDIB_INTERPOL);
899   while (bRet) {
900     bRet = imageRender.Continue(nullptr);
901   }
902   pRenderDevice->RestoreState(false);
903 }
904 
905 static const uint8_t g_inv_base64[128] = {
906     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
907     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
908     255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62,  255,
909     255, 255, 63,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  255, 255,
910     255, 255, 255, 255, 255, 0,   1,   2,   3,   4,   5,   6,   7,   8,   9,
911     10,  11,  12,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
912     25,  255, 255, 255, 255, 255, 255, 26,  27,  28,  29,  30,  31,  32,  33,
913     34,  35,  36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
914     49,  50,  51,  255, 255, 255, 255, 255,
915 };
916 
XFA_RemoveBase64Whitespace(const uint8_t * pStr,int32_t iLen)917 static uint8_t* XFA_RemoveBase64Whitespace(const uint8_t* pStr, int32_t iLen) {
918   uint8_t* pCP;
919   int32_t i = 0, j = 0;
920   if (iLen == 0) {
921     iLen = FXSYS_strlen((FX_CHAR*)pStr);
922   }
923   pCP = FX_Alloc(uint8_t, iLen + 1);
924   for (; i < iLen; i++) {
925     if ((pStr[i] & 128) == 0) {
926       if (g_inv_base64[pStr[i]] != 0xFF || pStr[i] == '=') {
927         pCP[j++] = pStr[i];
928       }
929     }
930   }
931   pCP[j] = '\0';
932   return pCP;
933 }
XFA_Base64Decode(const FX_CHAR * pStr,uint8_t * pOutBuffer)934 static int32_t XFA_Base64Decode(const FX_CHAR* pStr, uint8_t* pOutBuffer) {
935   if (!pStr) {
936     return 0;
937   }
938   uint8_t* pBuffer =
939       XFA_RemoveBase64Whitespace((uint8_t*)pStr, FXSYS_strlen((FX_CHAR*)pStr));
940   if (!pBuffer) {
941     return 0;
942   }
943   int32_t iLen = FXSYS_strlen((FX_CHAR*)pBuffer);
944   int32_t i = 0, j = 0;
945   uint32_t dwLimb = 0;
946   for (; i + 3 < iLen; i += 4) {
947     if (pBuffer[i] == '=' || pBuffer[i + 1] == '=' || pBuffer[i + 2] == '=' ||
948         pBuffer[i + 3] == '=') {
949       if (pBuffer[i] == '=' || pBuffer[i + 1] == '=') {
950         break;
951       }
952       if (pBuffer[i + 2] == '=') {
953         dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 6) |
954                  ((uint32_t)g_inv_base64[pBuffer[i + 1]]);
955         pOutBuffer[j] = (uint8_t)(dwLimb >> 4) & 0xFF;
956         j++;
957       } else {
958         dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 12) |
959                  ((uint32_t)g_inv_base64[pBuffer[i + 1]] << 6) |
960                  ((uint32_t)g_inv_base64[pBuffer[i + 2]]);
961         pOutBuffer[j] = (uint8_t)(dwLimb >> 10) & 0xFF;
962         pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 2) & 0xFF;
963         j += 2;
964       }
965     } else {
966       dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 18) |
967                ((uint32_t)g_inv_base64[pBuffer[i + 1]] << 12) |
968                ((uint32_t)g_inv_base64[pBuffer[i + 2]] << 6) |
969                ((uint32_t)g_inv_base64[pBuffer[i + 3]]);
970       pOutBuffer[j] = (uint8_t)(dwLimb >> 16) & 0xff;
971       pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 8) & 0xff;
972       pOutBuffer[j + 2] = (uint8_t)(dwLimb)&0xff;
973       j += 3;
974     }
975   }
976   FX_Free(pBuffer);
977   return j;
978 }
979 
980 static const FX_CHAR g_base64_chars[] =
981     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
982 
XFA_Base64Encode(const uint8_t * buf,int32_t buf_len)983 FX_CHAR* XFA_Base64Encode(const uint8_t* buf, int32_t buf_len) {
984   FX_CHAR* out = nullptr;
985   int i, j;
986   uint32_t limb;
987   out = FX_Alloc(FX_CHAR, ((buf_len * 8 + 5) / 6) + 5);
988   for (i = 0, j = 0, limb = 0; i + 2 < buf_len; i += 3, j += 4) {
989     limb = ((uint32_t)buf[i] << 16) | ((uint32_t)buf[i + 1] << 8) |
990            ((uint32_t)buf[i + 2]);
991     out[j] = g_base64_chars[(limb >> 18) & 63];
992     out[j + 1] = g_base64_chars[(limb >> 12) & 63];
993     out[j + 2] = g_base64_chars[(limb >> 6) & 63];
994     out[j + 3] = g_base64_chars[(limb)&63];
995   }
996   switch (buf_len - i) {
997     case 0:
998       break;
999     case 1:
1000       limb = ((uint32_t)buf[i]);
1001       out[j++] = g_base64_chars[(limb >> 2) & 63];
1002       out[j++] = g_base64_chars[(limb << 4) & 63];
1003       out[j++] = '=';
1004       out[j++] = '=';
1005       break;
1006     case 2:
1007       limb = ((uint32_t)buf[i] << 8) | ((uint32_t)buf[i + 1]);
1008       out[j++] = g_base64_chars[(limb >> 10) & 63];
1009       out[j++] = g_base64_chars[(limb >> 4) & 63];
1010       out[j++] = g_base64_chars[(limb << 2) & 63];
1011       out[j++] = '=';
1012       break;
1013     default:
1014       break;
1015   }
1016   out[j] = '\0';
1017   return out;
1018 }
XFA_GetImageType(const CFX_WideString & wsType)1019 FXCODEC_IMAGE_TYPE XFA_GetImageType(const CFX_WideString& wsType) {
1020   CFX_WideString wsContentType(wsType);
1021   wsContentType.MakeLower();
1022   if (wsContentType == FX_WSTRC(L"image/jpg")) {
1023     return FXCODEC_IMAGE_JPG;
1024   }
1025   if (wsContentType == FX_WSTRC(L"image/png")) {
1026     return FXCODEC_IMAGE_PNG;
1027   }
1028   if (wsContentType == FX_WSTRC(L"image/gif")) {
1029     return FXCODEC_IMAGE_GIF;
1030   }
1031   if (wsContentType == FX_WSTRC(L"image/bmp")) {
1032     return FXCODEC_IMAGE_BMP;
1033   }
1034   if (wsContentType == FX_WSTRC(L"image/tif")) {
1035     return FXCODEC_IMAGE_TIF;
1036   }
1037   return FXCODEC_IMAGE_UNKNOWN;
1038 }
XFA_LoadImageData(CXFA_FFDoc * pDoc,CXFA_Image * pImage,FX_BOOL & bNameImage,int32_t & iImageXDpi,int32_t & iImageYDpi)1039 CFX_DIBitmap* XFA_LoadImageData(CXFA_FFDoc* pDoc,
1040                                 CXFA_Image* pImage,
1041                                 FX_BOOL& bNameImage,
1042                                 int32_t& iImageXDpi,
1043                                 int32_t& iImageYDpi) {
1044   CFX_WideString wsHref;
1045   pImage->GetHref(wsHref);
1046   CFX_WideString wsImage;
1047   pImage->GetContent(wsImage);
1048   if (wsHref.IsEmpty() && wsImage.IsEmpty()) {
1049     return nullptr;
1050   }
1051   CFX_WideString wsContentType;
1052   pImage->GetContentType(wsContentType);
1053   FXCODEC_IMAGE_TYPE type = XFA_GetImageType(wsContentType);
1054   CFX_ByteString bsContent;
1055   uint8_t* pImageBuffer = nullptr;
1056   IFX_FileRead* pImageFileRead = nullptr;
1057   if (wsImage.GetLength() > 0) {
1058     XFA_ATTRIBUTEENUM iEncoding =
1059         (XFA_ATTRIBUTEENUM)pImage->GetTransferEncoding();
1060     if (iEncoding == XFA_ATTRIBUTEENUM_Base64) {
1061       CFX_ByteString bsData = wsImage.UTF8Encode();
1062       int32_t iLength = bsData.GetLength();
1063       pImageBuffer = FX_Alloc(uint8_t, iLength);
1064       int32_t iRead = XFA_Base64Decode(bsData.c_str(), pImageBuffer);
1065       if (iRead > 0) {
1066         pImageFileRead = FX_CreateMemoryStream(pImageBuffer, iRead);
1067       }
1068     } else {
1069       bsContent = CFX_ByteString::FromUnicode(wsImage);
1070       pImageFileRead = FX_CreateMemoryStream(
1071           const_cast<uint8_t*>(bsContent.raw_str()), bsContent.GetLength());
1072     }
1073   } else {
1074     CFX_WideString wsURL = wsHref;
1075     if (wsURL.Left(7) != FX_WSTRC(L"http://") &&
1076         wsURL.Left(6) != FX_WSTRC(L"ftp://")) {
1077       CFX_DIBitmap* pBitmap =
1078           pDoc->GetPDFNamedImage(wsURL.AsStringC(), iImageXDpi, iImageYDpi);
1079       if (pBitmap) {
1080         bNameImage = TRUE;
1081         return pBitmap;
1082       }
1083     }
1084     pImageFileRead = pDoc->GetDocProvider()->OpenLinkedFile(pDoc, wsURL);
1085   }
1086   if (!pImageFileRead) {
1087     FX_Free(pImageBuffer);
1088     return nullptr;
1089   }
1090   bNameImage = FALSE;
1091   CFX_DIBitmap* pBitmap =
1092       XFA_LoadImageFromBuffer(pImageFileRead, type, iImageXDpi, iImageYDpi);
1093   FX_Free(pImageBuffer);
1094   pImageFileRead->Release();
1095   return pBitmap;
1096 }
XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type,int32_t iComponents,int32_t iBitsPerComponent)1097 static FXDIB_Format XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type,
1098                                      int32_t iComponents,
1099                                      int32_t iBitsPerComponent) {
1100   FXDIB_Format dibFormat = FXDIB_Argb;
1101   switch (type) {
1102     case FXCODEC_IMAGE_BMP:
1103     case FXCODEC_IMAGE_JPG:
1104     case FXCODEC_IMAGE_TIF: {
1105       dibFormat = FXDIB_Rgb32;
1106       int32_t bpp = iComponents * iBitsPerComponent;
1107       if (bpp <= 24) {
1108         dibFormat = FXDIB_Rgb;
1109       }
1110     } break;
1111     case FXCODEC_IMAGE_PNG:
1112     default:
1113       break;
1114   }
1115   return dibFormat;
1116 }
XFA_LoadImageFromBuffer(IFX_FileRead * pImageFileRead,FXCODEC_IMAGE_TYPE type,int32_t & iImageXDpi,int32_t & iImageYDpi)1117 CFX_DIBitmap* XFA_LoadImageFromBuffer(IFX_FileRead* pImageFileRead,
1118                                       FXCODEC_IMAGE_TYPE type,
1119                                       int32_t& iImageXDpi,
1120                                       int32_t& iImageYDpi) {
1121   CFX_GEModule* pGeModule = CFX_GEModule::Get();
1122   if (!pGeModule) {
1123     return nullptr;
1124   }
1125   CCodec_ModuleMgr* pCodecMgr = pGeModule->GetCodecModule();
1126   if (!pCodecMgr) {
1127     return nullptr;
1128   }
1129   CFX_DIBAttribute dibAttr;
1130   CFX_DIBitmap* pBitmap = nullptr;
1131   CCodec_ProgressiveDecoder* pProgressiveDecoder =
1132       pCodecMgr->CreateProgressiveDecoder();
1133   pProgressiveDecoder->LoadImageInfo(pImageFileRead, type, &dibAttr, false);
1134   switch (dibAttr.m_wDPIUnit) {
1135     case FXCODEC_RESUNIT_CENTIMETER:
1136       dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI * 2.54f);
1137       dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI * 2.54f);
1138       break;
1139     case FXCODEC_RESUNIT_METER:
1140       dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI / (FX_FLOAT)100 * 2.54f);
1141       dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI / (FX_FLOAT)100 * 2.54f);
1142       break;
1143     default:
1144       break;
1145   }
1146   iImageXDpi = dibAttr.m_nXDPI > 1 ? dibAttr.m_nXDPI : (96);
1147   iImageYDpi = dibAttr.m_nYDPI > 1 ? dibAttr.m_nYDPI : (96);
1148   if (pProgressiveDecoder->GetWidth() > 0 &&
1149       pProgressiveDecoder->GetHeight() > 0) {
1150     type = pProgressiveDecoder->GetType();
1151     int32_t iComponents = pProgressiveDecoder->GetNumComponents();
1152     int32_t iBpc = pProgressiveDecoder->GetBPC();
1153     FXDIB_Format dibFormat = XFA_GetDIBFormat(type, iComponents, iBpc);
1154     pBitmap = new CFX_DIBitmap();
1155     pBitmap->Create(pProgressiveDecoder->GetWidth(),
1156                     pProgressiveDecoder->GetHeight(), dibFormat);
1157     pBitmap->Clear(0xffffffff);
1158     int32_t nFrames;
1159     if ((pProgressiveDecoder->GetFrames(nFrames) ==
1160          FXCODEC_STATUS_DECODE_READY) &&
1161         (nFrames > 0)) {
1162       pProgressiveDecoder->StartDecode(pBitmap, 0, 0, pBitmap->GetWidth(),
1163                                        pBitmap->GetHeight());
1164       pProgressiveDecoder->ContinueDecode();
1165     }
1166   }
1167   delete pProgressiveDecoder;
1168   return pBitmap;
1169 }
XFA_RectWidthoutMargin(CFX_RectF & rt,const CXFA_Margin & mg,FX_BOOL bUI)1170 void XFA_RectWidthoutMargin(CFX_RectF& rt, const CXFA_Margin& mg, FX_BOOL bUI) {
1171   if (!mg) {
1172     return;
1173   }
1174   FX_FLOAT fLeftInset, fTopInset, fRightInset, fBottomInset;
1175   mg.GetLeftInset(fLeftInset);
1176   mg.GetTopInset(fTopInset);
1177   mg.GetRightInset(fRightInset);
1178   mg.GetBottomInset(fBottomInset);
1179   rt.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset);
1180 }
XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem * pLayoutItem)1181 CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) {
1182   if (XFA_IsCreateWidget(pLayoutItem->GetFormNode()->GetElementType()))
1183     return static_cast<CXFA_FFWidget*>(pLayoutItem);
1184   return nullptr;
1185 }
XFA_IsCreateWidget(XFA_Element eType)1186 FX_BOOL XFA_IsCreateWidget(XFA_Element eType) {
1187   return eType == XFA_Element::Field || eType == XFA_Element::Draw ||
1188          eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup;
1189 }
XFA_BOX_GetPath_Arc(CXFA_Box box,CFX_RectF rtDraw,CFX_Path & fillPath,uint32_t dwFlags)1190 static void XFA_BOX_GetPath_Arc(CXFA_Box box,
1191                                 CFX_RectF rtDraw,
1192                                 CFX_Path& fillPath,
1193                                 uint32_t dwFlags) {
1194   FX_FLOAT a, b;
1195   a = rtDraw.width / 2.0f;
1196   b = rtDraw.height / 2.0f;
1197   if (box.IsCircular() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) {
1198     a = b = std::min(a, b);
1199   }
1200   CFX_PointF center = rtDraw.Center();
1201   rtDraw.left = center.x - a;
1202   rtDraw.top = center.y - b;
1203   rtDraw.width = a + a;
1204   rtDraw.height = b + b;
1205   FX_FLOAT startAngle = 0, sweepAngle = 360;
1206   FX_BOOL bStart = box.GetStartAngle(startAngle);
1207   FX_BOOL bEnd = box.GetSweepAngle(sweepAngle);
1208   if (!bStart && !bEnd) {
1209     fillPath.AddEllipse(rtDraw);
1210     return;
1211   }
1212   startAngle = -startAngle * FX_PI / 180.0f;
1213   sweepAngle = -sweepAngle * FX_PI / 180.0f;
1214   fillPath.AddArc(rtDraw.left, rtDraw.top, rtDraw.width, rtDraw.height,
1215                   startAngle, sweepAngle);
1216 }
XFA_BOX_GetPath(CXFA_Box box,const CXFA_StrokeArray & strokes,CFX_RectF rtWidget,CFX_Path & path,int32_t nIndex,FX_BOOL bStart,FX_BOOL bCorner)1217 static void XFA_BOX_GetPath(CXFA_Box box,
1218                             const CXFA_StrokeArray& strokes,
1219                             CFX_RectF rtWidget,
1220                             CFX_Path& path,
1221                             int32_t nIndex,
1222                             FX_BOOL bStart,
1223                             FX_BOOL bCorner) {
1224   ASSERT(nIndex >= 0 && nIndex < 8);
1225   int32_t n = (nIndex & 1) ? nIndex - 1 : nIndex;
1226   CXFA_Corner corner1(strokes[n].GetNode());
1227   CXFA_Corner corner2(strokes[(n + 2) % 8].GetNode());
1228   FX_FLOAT fRadius1 = bCorner ? corner1.GetRadius() : 0.0f;
1229   FX_FLOAT fRadius2 = bCorner ? corner2.GetRadius() : 0.0f;
1230   FX_BOOL bInverted = corner1.IsInverted();
1231   FX_FLOAT offsetY = 0.0f;
1232   FX_FLOAT offsetX = 0.0f;
1233   FX_BOOL bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round;
1234   FX_FLOAT halfAfter = 0.0f;
1235   FX_FLOAT halfBefore = 0.0f;
1236   CXFA_Stroke stroke = strokes[nIndex];
1237   if (stroke.IsCorner()) {
1238     CXFA_Stroke edgeBefore = strokes[(nIndex + 1 * 8 - 1) % 8];
1239     CXFA_Stroke edgeAfter = strokes[nIndex + 1];
1240     if (stroke.IsInverted()) {
1241       if (!stroke.SameStyles(edgeBefore)) {
1242         halfBefore = edgeBefore.GetThickness() / 2;
1243       }
1244       if (!stroke.SameStyles(edgeAfter)) {
1245         halfAfter = edgeAfter.GetThickness() / 2;
1246       }
1247     }
1248   } else {
1249     CXFA_Stroke edgeBefore = strokes[(nIndex + 8 - 2) % 8];
1250     CXFA_Stroke edgeAfter = strokes[(nIndex + 2) % 8];
1251     if (!bRound && !bInverted) {
1252       halfBefore = edgeBefore.GetThickness() / 2;
1253       halfAfter = edgeAfter.GetThickness() / 2;
1254     }
1255   }
1256   FX_FLOAT offsetEX = 0.0f;
1257   FX_FLOAT offsetEY = 0.0f;
1258   FX_FLOAT sx = 0.0f;
1259   FX_FLOAT sy = 0.0f;
1260   FX_FLOAT vx = 1.0f;
1261   FX_FLOAT vy = 1.0f;
1262   FX_FLOAT nx = 1.0f;
1263   FX_FLOAT ny = 1.0f;
1264   CFX_PointF cpStart;
1265   CFX_PointF cp1;
1266   CFX_PointF cp2;
1267   if (bRound) {
1268     sy = FX_PI / 2;
1269   }
1270   switch (nIndex) {
1271     case 0:
1272     case 1:
1273       cp1 = rtWidget.TopLeft();
1274       cp2 = rtWidget.TopRight();
1275       if (nIndex == 0) {
1276         cpStart.x = cp1.x - halfBefore;
1277         cpStart.y = cp1.y + fRadius1, offsetY = -halfAfter;
1278       } else {
1279         cpStart.x = cp1.x + fRadius1 - halfBefore, cpStart.y = cp1.y,
1280         offsetEX = halfAfter;
1281       }
1282       vx = 1, vy = 1;
1283       nx = -1, ny = 0;
1284       if (bRound) {
1285         sx = bInverted ? FX_PI / 2 : FX_PI;
1286       } else {
1287         sx = 1, sy = 0;
1288       }
1289       break;
1290     case 2:
1291     case 3:
1292       cp1 = rtWidget.TopRight();
1293       cp2 = rtWidget.BottomRight();
1294       if (nIndex == 2) {
1295         cpStart.x = cp1.x - fRadius1, cpStart.y = cp1.y - halfBefore,
1296         offsetX = halfAfter;
1297       } else {
1298         cpStart.x = cp1.x, cpStart.y = cp1.y + fRadius1 - halfBefore,
1299         offsetEY = halfAfter;
1300       }
1301       vx = -1, vy = 1;
1302       nx = 0, ny = -1;
1303       if (bRound) {
1304         sx = bInverted ? FX_PI : FX_PI * 3 / 2;
1305       } else {
1306         sx = 0, sy = 1;
1307       }
1308       break;
1309     case 4:
1310     case 5:
1311       cp1 = rtWidget.BottomRight();
1312       cp2 = rtWidget.BottomLeft();
1313       if (nIndex == 4) {
1314         cpStart.x = cp1.x + halfBefore, cpStart.y = cp1.y - fRadius1,
1315         offsetY = halfAfter;
1316       } else {
1317         cpStart.x = cp1.x - fRadius1 + halfBefore, cpStart.y = cp1.y,
1318         offsetEX = -halfAfter;
1319       }
1320       vx = -1, vy = -1;
1321       nx = 1, ny = 0;
1322       if (bRound) {
1323         sx = bInverted ? FX_PI * 3 / 2 : 0;
1324       } else {
1325         sx = -1, sy = 0;
1326       }
1327       break;
1328     case 6:
1329     case 7:
1330       cp1 = rtWidget.BottomLeft();
1331       cp2 = rtWidget.TopLeft();
1332       if (nIndex == 6) {
1333         cpStart.x = cp1.x + fRadius1, cpStart.y = cp1.y + halfBefore,
1334         offsetX = -halfAfter;
1335       } else {
1336         cpStart.x = cp1.x, cpStart.y = cp1.y - fRadius1 + halfBefore,
1337         offsetEY = -halfAfter;
1338       }
1339       vx = 1, vy = -1;
1340       nx = 0, ny = 1;
1341       if (bRound) {
1342         sx = bInverted ? 0 : FX_PI / 2;
1343       } else {
1344         sx = 0, sy = -1;
1345       }
1346       break;
1347   }
1348   if (bStart) {
1349     path.MoveTo(cpStart.x, cpStart.y);
1350   }
1351   if (nIndex & 1) {
1352     path.LineTo(cp2.x + fRadius2 * nx + offsetEX,
1353                 cp2.y + fRadius2 * ny + offsetEY);
1354     return;
1355   }
1356   if (bRound) {
1357     if (fRadius1 < 0) {
1358       sx -= FX_PI;
1359     }
1360     if (bInverted) {
1361       sy *= -1;
1362     }
1363     CFX_RectF rtRadius;
1364     rtRadius.Set(cp1.x + offsetX * 2, cp1.y + offsetY * 2,
1365                  fRadius1 * 2 * vx - offsetX * 2,
1366                  fRadius1 * 2 * vy - offsetY * 2);
1367     rtRadius.Normalize();
1368     if (bInverted) {
1369       rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy);
1370     }
1371     path.ArcTo(rtRadius.left, rtRadius.top, rtRadius.width, rtRadius.height, sx,
1372                sy);
1373   } else {
1374     CFX_PointF cp;
1375     if (bInverted) {
1376       cp.x = cp1.x + fRadius1 * vx, cp.y = cp1.y + fRadius1 * vy;
1377     } else {
1378       cp = cp1;
1379     }
1380     path.LineTo(cp.x, cp.y);
1381     path.LineTo(cp1.x + fRadius1 * sx + offsetX,
1382                 cp1.y + fRadius1 * sy + offsetY);
1383   }
1384 }
XFA_BOX_GetFillPath(CXFA_Box box,const CXFA_StrokeArray & strokes,CFX_RectF rtWidget,CFX_Path & fillPath,uint16_t dwFlags)1385 static void XFA_BOX_GetFillPath(CXFA_Box box,
1386                                 const CXFA_StrokeArray& strokes,
1387                                 CFX_RectF rtWidget,
1388                                 CFX_Path& fillPath,
1389                                 uint16_t dwFlags) {
1390   if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) {
1391     CXFA_Edge edge = box.GetEdge(0);
1392     FX_FLOAT fThickness = edge.GetThickness();
1393     if (fThickness < 0) {
1394       fThickness = 0;
1395     }
1396     FX_FLOAT fHalf = fThickness / 2;
1397     int32_t iHand = box.GetHand();
1398     if (iHand == XFA_ATTRIBUTEENUM_Left) {
1399       rtWidget.Inflate(fHalf, fHalf);
1400     } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
1401       rtWidget.Deflate(fHalf, fHalf);
1402     }
1403     XFA_BOX_GetPath_Arc(box, rtWidget, fillPath, dwFlags);
1404     return;
1405   }
1406   FX_BOOL bSameStyles = TRUE;
1407   CXFA_Stroke stroke1 = strokes[0];
1408   for (int32_t i = 1; i < 8; i++) {
1409     CXFA_Stroke stroke2 = strokes[i];
1410     if (!stroke1.SameStyles(stroke2)) {
1411       bSameStyles = FALSE;
1412       break;
1413     }
1414     stroke1 = stroke2;
1415   }
1416   if (bSameStyles) {
1417     stroke1 = strokes[0];
1418     for (int32_t i = 2; i < 8; i += 2) {
1419       CXFA_Stroke stroke2 = strokes[i];
1420       if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence |
1421                                            XFA_STROKE_SAMESTYLE_Corner)) {
1422         bSameStyles = FALSE;
1423         break;
1424       }
1425       stroke1 = stroke2;
1426     }
1427     if (bSameStyles) {
1428       stroke1 = strokes[0];
1429       if (stroke1.IsInverted()) {
1430         bSameStyles = FALSE;
1431       }
1432       if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square) {
1433         bSameStyles = FALSE;
1434       }
1435     }
1436   }
1437   if (bSameStyles) {
1438     fillPath.AddRectangle(rtWidget.left, rtWidget.top, rtWidget.width,
1439                           rtWidget.height);
1440     return;
1441   }
1442 
1443   for (int32_t i = 0; i < 8; i += 2) {
1444     FX_FLOAT sx = 0.0f;
1445     FX_FLOAT sy = 0.0f;
1446     FX_FLOAT vx = 1.0f;
1447     FX_FLOAT vy = 1.0f;
1448     FX_FLOAT nx = 1.0f;
1449     FX_FLOAT ny = 1.0f;
1450     CFX_PointF cp1, cp2;
1451     CXFA_Corner corner1(strokes[i].GetNode());
1452     CXFA_Corner corner2(strokes[(i + 2) % 8].GetNode());
1453     FX_FLOAT fRadius1 = corner1.GetRadius();
1454     FX_FLOAT fRadius2 = corner2.GetRadius();
1455     FX_BOOL bInverted = corner1.IsInverted();
1456     FX_BOOL bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round;
1457     if (bRound) {
1458       sy = FX_PI / 2;
1459     }
1460     switch (i) {
1461       case 0:
1462         cp1 = rtWidget.TopLeft();
1463         cp2 = rtWidget.TopRight();
1464         vx = 1, vy = 1;
1465         nx = -1, ny = 0;
1466         if (bRound) {
1467           sx = bInverted ? FX_PI / 2 : FX_PI;
1468         } else {
1469           sx = 1, sy = 0;
1470         }
1471         break;
1472       case 2:
1473         cp1 = rtWidget.TopRight();
1474         cp2 = rtWidget.BottomRight();
1475         vx = -1, vy = 1;
1476         nx = 0, ny = -1;
1477         if (bRound) {
1478           sx = bInverted ? FX_PI : FX_PI * 3 / 2;
1479         } else {
1480           sx = 0, sy = 1;
1481         }
1482         break;
1483       case 4:
1484         cp1 = rtWidget.BottomRight();
1485         cp2 = rtWidget.BottomLeft();
1486         vx = -1, vy = -1;
1487         nx = 1, ny = 0;
1488         if (bRound) {
1489           sx = bInverted ? FX_PI * 3 / 2 : 0;
1490         } else {
1491           sx = -1, sy = 0;
1492         }
1493         break;
1494       case 6:
1495         cp1 = rtWidget.BottomLeft();
1496         cp2 = rtWidget.TopLeft();
1497         vx = 1, vy = -1;
1498         nx = 0, ny = 1;
1499         if (bRound) {
1500           sx = bInverted ? 0 : FX_PI / 2;
1501         } else {
1502           sx = 0, sy = -1;
1503         }
1504         break;
1505     }
1506     if (i == 0) {
1507       fillPath.MoveTo(cp1.x, cp1.y + fRadius1);
1508     }
1509     if (bRound) {
1510       if (fRadius1 < 0) {
1511         sx -= FX_PI;
1512       }
1513       if (bInverted) {
1514         sy *= -1;
1515       }
1516       CFX_RectF rtRadius;
1517       rtRadius.Set(cp1.x, cp1.y, fRadius1 * 2 * vx, fRadius1 * 2 * vy);
1518       rtRadius.Normalize();
1519       if (bInverted) {
1520         rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy);
1521       }
1522       fillPath.ArcTo(rtRadius.left, rtRadius.top, rtRadius.width,
1523                      rtRadius.height, sx, sy);
1524     } else {
1525       CFX_PointF cp;
1526       if (bInverted) {
1527         cp.x = cp1.x + fRadius1 * vx, cp.y = cp1.y + fRadius1 * vy;
1528       } else {
1529         cp = cp1;
1530       }
1531       fillPath.LineTo(cp.x, cp.y);
1532       fillPath.LineTo(cp1.x + fRadius1 * sx, cp1.y + fRadius1 * sy);
1533     }
1534     fillPath.LineTo(cp2.x + fRadius2 * nx, cp2.y + fRadius2 * ny);
1535   }
1536 }
XFA_BOX_Fill_Radial(CXFA_Box box,CFX_Graphics * pGS,CFX_Path & fillPath,CFX_RectF rtFill,CFX_Matrix * pMatrix)1537 static void XFA_BOX_Fill_Radial(CXFA_Box box,
1538                                 CFX_Graphics* pGS,
1539                                 CFX_Path& fillPath,
1540                                 CFX_RectF rtFill,
1541                                 CFX_Matrix* pMatrix) {
1542   CXFA_Fill fill = box.GetFill();
1543   FX_ARGB crStart, crEnd;
1544   crStart = fill.GetColor();
1545   int32_t iType = fill.GetRadial(crEnd);
1546   if (iType != XFA_ATTRIBUTEENUM_ToEdge) {
1547     FX_ARGB temp = crEnd;
1548     crEnd = crStart;
1549     crStart = temp;
1550   }
1551   CFX_Shading shading(rtFill.Center(), rtFill.Center(), 0,
1552                       FXSYS_sqrt(rtFill.Width() * rtFill.Width() +
1553                                  rtFill.Height() * rtFill.Height()) /
1554                           2,
1555                       TRUE, TRUE, crStart, crEnd);
1556   CFX_Color cr(&shading);
1557   pGS->SetFillColor(&cr);
1558   pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
1559 }
XFA_BOX_Fill_Pattern(CXFA_Box box,CFX_Graphics * pGS,CFX_Path & fillPath,CFX_RectF rtFill,CFX_Matrix * pMatrix)1560 static void XFA_BOX_Fill_Pattern(CXFA_Box box,
1561                                  CFX_Graphics* pGS,
1562                                  CFX_Path& fillPath,
1563                                  CFX_RectF rtFill,
1564                                  CFX_Matrix* pMatrix) {
1565   CXFA_Fill fill = box.GetFill();
1566   FX_ARGB crStart, crEnd;
1567   crStart = fill.GetColor();
1568   int32_t iType = fill.GetPattern(crEnd);
1569   FX_HatchStyle iHatch = FX_HATCHSTYLE_Cross;
1570   switch (iType) {
1571     case XFA_ATTRIBUTEENUM_CrossDiagonal:
1572       iHatch = FX_HATCHSTYLE_DiagonalCross;
1573       break;
1574     case XFA_ATTRIBUTEENUM_DiagonalLeft:
1575       iHatch = FX_HATCHSTYLE_ForwardDiagonal;
1576       break;
1577     case XFA_ATTRIBUTEENUM_DiagonalRight:
1578       iHatch = FX_HATCHSTYLE_BackwardDiagonal;
1579       break;
1580     case XFA_ATTRIBUTEENUM_Horizontal:
1581       iHatch = FX_HATCHSTYLE_Horizontal;
1582       break;
1583     case XFA_ATTRIBUTEENUM_Vertical:
1584       iHatch = FX_HATCHSTYLE_Vertical;
1585       break;
1586     default:
1587       break;
1588   }
1589 
1590   CFX_Pattern pattern(iHatch, crEnd, crStart);
1591   CFX_Color cr(&pattern);
1592   pGS->SetFillColor(&cr);
1593   pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
1594 }
XFA_BOX_Fill_Linear(CXFA_Box box,CFX_Graphics * pGS,CFX_Path & fillPath,CFX_RectF rtFill,CFX_Matrix * pMatrix)1595 static void XFA_BOX_Fill_Linear(CXFA_Box box,
1596                                 CFX_Graphics* pGS,
1597                                 CFX_Path& fillPath,
1598                                 CFX_RectF rtFill,
1599                                 CFX_Matrix* pMatrix) {
1600   CXFA_Fill fill = box.GetFill();
1601   FX_ARGB crStart = fill.GetColor();
1602   FX_ARGB crEnd;
1603   int32_t iType = fill.GetLinear(crEnd);
1604   CFX_PointF ptStart;
1605   CFX_PointF ptEnd;
1606   switch (iType) {
1607     case XFA_ATTRIBUTEENUM_ToRight:
1608       ptStart = CFX_PointF(rtFill.left, rtFill.top);
1609       ptEnd = CFX_PointF(rtFill.right(), rtFill.top);
1610       break;
1611     case XFA_ATTRIBUTEENUM_ToBottom:
1612       ptStart = CFX_PointF(rtFill.left, rtFill.top);
1613       ptEnd = CFX_PointF(rtFill.left, rtFill.bottom());
1614       break;
1615     case XFA_ATTRIBUTEENUM_ToLeft:
1616       ptStart = CFX_PointF(rtFill.right(), rtFill.top);
1617       ptEnd = CFX_PointF(rtFill.left, rtFill.top);
1618       break;
1619     case XFA_ATTRIBUTEENUM_ToTop:
1620       ptStart = CFX_PointF(rtFill.left, rtFill.bottom());
1621       ptEnd = CFX_PointF(rtFill.left, rtFill.top);
1622       break;
1623     default:
1624       break;
1625   }
1626   CFX_Shading shading(ptStart, ptEnd, FALSE, FALSE, crStart, crEnd);
1627   CFX_Color cr(&shading);
1628   pGS->SetFillColor(&cr);
1629   pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
1630 }
XFA_BOX_Fill(CXFA_Box box,const CXFA_StrokeArray & strokes,CFX_Graphics * pGS,const CFX_RectF & rtWidget,CFX_Matrix * pMatrix,uint32_t dwFlags)1631 static void XFA_BOX_Fill(CXFA_Box box,
1632                          const CXFA_StrokeArray& strokes,
1633                          CFX_Graphics* pGS,
1634                          const CFX_RectF& rtWidget,
1635                          CFX_Matrix* pMatrix,
1636                          uint32_t dwFlags) {
1637   CXFA_Fill fill = box.GetFill();
1638   if (!fill || fill.GetPresence() != XFA_ATTRIBUTEENUM_Visible) {
1639     return;
1640   }
1641   pGS->SaveGraphState();
1642   CFX_Path fillPath;
1643   fillPath.Create();
1644   XFA_BOX_GetFillPath(box, strokes, rtWidget, fillPath,
1645                       (dwFlags & XFA_DRAWBOX_ForceRound) != 0);
1646   fillPath.Close();
1647   XFA_Element eType = fill.GetFillType();
1648   switch (eType) {
1649     case XFA_Element::Radial:
1650       XFA_BOX_Fill_Radial(box, pGS, fillPath, rtWidget, pMatrix);
1651       break;
1652     case XFA_Element::Pattern:
1653       XFA_BOX_Fill_Pattern(box, pGS, fillPath, rtWidget, pMatrix);
1654       break;
1655     case XFA_Element::Linear:
1656       XFA_BOX_Fill_Linear(box, pGS, fillPath, rtWidget, pMatrix);
1657       break;
1658     default: {
1659       FX_ARGB cr;
1660       if (eType == XFA_Element::Stipple) {
1661         int32_t iRate = fill.GetStipple(cr);
1662         if (iRate == 0) {
1663           iRate = 100;
1664         }
1665         int32_t a = 0;
1666         FX_COLORREF rgb;
1667         ArgbDecode(cr, a, rgb);
1668         cr = ArgbEncode(iRate * a / 100, rgb);
1669       } else {
1670         cr = fill.GetColor();
1671       }
1672       CFX_Color fillColor(cr);
1673       pGS->SetFillColor(&fillColor);
1674       pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
1675     } break;
1676   }
1677   pGS->RestoreGraphState();
1678 }
XFA_BOX_StrokePath(CXFA_Stroke stroke,CFX_Path * pPath,CFX_Graphics * pGS,CFX_Matrix * pMatrix)1679 static void XFA_BOX_StrokePath(CXFA_Stroke stroke,
1680                                CFX_Path* pPath,
1681                                CFX_Graphics* pGS,
1682                                CFX_Matrix* pMatrix) {
1683   if (!stroke || !stroke.IsVisible()) {
1684     return;
1685   }
1686   FX_FLOAT fThickness = stroke.GetThickness();
1687   if (fThickness < 0.001f) {
1688     return;
1689   }
1690   pGS->SaveGraphState();
1691   if (stroke.IsCorner() && fThickness > 2 * stroke.GetRadius()) {
1692     fThickness = 2 * stroke.GetRadius();
1693   }
1694   pGS->SetLineWidth(fThickness, TRUE);
1695   pGS->SetLineCap(CFX_GraphStateData::LineCapButt);
1696   XFA_StrokeTypeSetLineDash(pGS, stroke.GetStrokeType(),
1697                             XFA_ATTRIBUTEENUM_Butt);
1698   CFX_Color fxColor(stroke.GetColor());
1699   pGS->SetStrokeColor(&fxColor);
1700   pGS->StrokePath(pPath, pMatrix);
1701   pGS->RestoreGraphState();
1702 }
XFA_BOX_StrokeArc(CXFA_Box box,CFX_Graphics * pGS,CFX_RectF rtWidget,CFX_Matrix * pMatrix,uint32_t dwFlags)1703 static void XFA_BOX_StrokeArc(CXFA_Box box,
1704                               CFX_Graphics* pGS,
1705                               CFX_RectF rtWidget,
1706                               CFX_Matrix* pMatrix,
1707                               uint32_t dwFlags) {
1708   CXFA_Edge edge = box.GetEdge(0);
1709   if (!edge || !edge.IsVisible()) {
1710     return;
1711   }
1712   FX_BOOL bVisible = FALSE;
1713   FX_FLOAT fThickness = 0;
1714   int32_t i3DType = box.Get3DStyle(bVisible, fThickness);
1715   if (i3DType) {
1716     if (bVisible && fThickness >= 0.001f) {
1717       dwFlags |= XFA_DRAWBOX_Lowered3D;
1718     }
1719   }
1720   FX_FLOAT fHalf = edge.GetThickness() / 2;
1721   if (fHalf < 0) {
1722     fHalf = 0;
1723   }
1724   int32_t iHand = box.GetHand();
1725   if (iHand == XFA_ATTRIBUTEENUM_Left) {
1726     rtWidget.Inflate(fHalf, fHalf);
1727   } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
1728     rtWidget.Deflate(fHalf, fHalf);
1729   }
1730   if ((dwFlags & XFA_DRAWBOX_ForceRound) == 0 ||
1731       (dwFlags & XFA_DRAWBOX_Lowered3D) == 0) {
1732     if (fHalf < 0.001f) {
1733       return;
1734     }
1735     CFX_Path arcPath;
1736     arcPath.Create();
1737     XFA_BOX_GetPath_Arc(box, rtWidget, arcPath, dwFlags);
1738     XFA_BOX_StrokePath(edge, &arcPath, pGS, pMatrix);
1739     return;
1740   }
1741   pGS->SaveGraphState();
1742   pGS->SetLineWidth(fHalf);
1743   FX_FLOAT a, b;
1744   a = rtWidget.width / 2.0f;
1745   b = rtWidget.height / 2.0f;
1746   if (dwFlags & XFA_DRAWBOX_ForceRound) {
1747     a = b = std::min(a, b);
1748   }
1749   CFX_PointF center = rtWidget.Center();
1750   rtWidget.left = center.x - a;
1751   rtWidget.top = center.y - b;
1752   rtWidget.width = a + a;
1753   rtWidget.height = b + b;
1754   FX_FLOAT startAngle = 0, sweepAngle = 360;
1755   startAngle = startAngle * FX_PI / 180.0f;
1756   sweepAngle = -sweepAngle * FX_PI / 180.0f;
1757   CFX_Path arcPath;
1758   arcPath.Create();
1759   arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height,
1760                  3.0f * FX_PI / 4.0f, FX_PI);
1761   CFX_Color cr(0xFF808080);
1762   pGS->SetStrokeColor(&cr);
1763   pGS->StrokePath(&arcPath, pMatrix);
1764   arcPath.Clear();
1765   arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height,
1766                  -1.0f * FX_PI / 4.0f, FX_PI);
1767   cr.Set(0xFFFFFFFF);
1768   pGS->SetStrokeColor(&cr);
1769   pGS->StrokePath(&arcPath, pMatrix);
1770   rtWidget.Deflate(fHalf, fHalf);
1771   arcPath.Clear();
1772   arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height,
1773                  3.0f * FX_PI / 4.0f, FX_PI);
1774   cr.Set(0xFF404040);
1775   pGS->SetStrokeColor(&cr);
1776   pGS->StrokePath(&arcPath, pMatrix);
1777   arcPath.Clear();
1778   arcPath.AddArc(rtWidget.left, rtWidget.top, rtWidget.width, rtWidget.height,
1779                  -1.0f * FX_PI / 4.0f, FX_PI);
1780   cr.Set(0xFFC0C0C0);
1781   pGS->SetStrokeColor(&cr);
1782   pGS->StrokePath(&arcPath, pMatrix);
1783   pGS->RestoreGraphState();
1784 }
XFA_Draw3DRect(CFX_Graphics * pGraphic,const CFX_RectF & rt,FX_FLOAT fLineWidth,CFX_Matrix * pMatrix,FX_ARGB argbTopLeft,FX_ARGB argbBottomRight)1785 static void XFA_Draw3DRect(CFX_Graphics* pGraphic,
1786                            const CFX_RectF& rt,
1787                            FX_FLOAT fLineWidth,
1788                            CFX_Matrix* pMatrix,
1789                            FX_ARGB argbTopLeft,
1790                            FX_ARGB argbBottomRight) {
1791   CFX_Color crLT(argbTopLeft);
1792   pGraphic->SetFillColor(&crLT);
1793   FX_FLOAT fBottom = rt.bottom();
1794   FX_FLOAT fRight = rt.right();
1795   CFX_Path pathLT;
1796   pathLT.Create();
1797   pathLT.MoveTo(rt.left, fBottom);
1798   pathLT.LineTo(rt.left, rt.top);
1799   pathLT.LineTo(fRight, rt.top);
1800   pathLT.LineTo(fRight - fLineWidth, rt.top + fLineWidth);
1801   pathLT.LineTo(rt.left + fLineWidth, rt.top + fLineWidth);
1802   pathLT.LineTo(rt.left + fLineWidth, fBottom - fLineWidth);
1803   pathLT.LineTo(rt.left, fBottom);
1804   pGraphic->FillPath(&pathLT, FXFILL_WINDING, pMatrix);
1805   CFX_Color crRB(argbBottomRight);
1806   pGraphic->SetFillColor(&crRB);
1807   CFX_Path pathRB;
1808   pathRB.Create();
1809   pathRB.MoveTo(fRight, rt.top);
1810   pathRB.LineTo(fRight, fBottom);
1811   pathRB.LineTo(rt.left, fBottom);
1812   pathRB.LineTo(rt.left + fLineWidth, fBottom - fLineWidth);
1813   pathRB.LineTo(fRight - fLineWidth, fBottom - fLineWidth);
1814   pathRB.LineTo(fRight - fLineWidth, rt.top + fLineWidth);
1815   pathRB.LineTo(fRight, rt.top);
1816   pGraphic->FillPath(&pathRB, FXFILL_WINDING, pMatrix);
1817 }
XFA_BOX_Stroke_3DRect_Lowered(CFX_Graphics * pGS,CFX_RectF rt,FX_FLOAT fThickness,CFX_Matrix * pMatrix)1818 static void XFA_BOX_Stroke_3DRect_Lowered(CFX_Graphics* pGS,
1819                                           CFX_RectF rt,
1820                                           FX_FLOAT fThickness,
1821                                           CFX_Matrix* pMatrix) {
1822   FX_FLOAT fHalfWidth = fThickness / 2.0f;
1823   CFX_RectF rtInner(rt);
1824   rtInner.Deflate(fHalfWidth, fHalfWidth);
1825   CFX_Color cr(0xFF000000);
1826   pGS->SetFillColor(&cr);
1827   CFX_Path path;
1828   path.Create();
1829   path.AddRectangle(rt.left, rt.top, rt.width, rt.height);
1830   path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height);
1831   pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix);
1832   XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF808080, 0xFFC0C0C0);
1833 }
XFA_BOX_Stroke_3DRect_Raised(CFX_Graphics * pGS,CFX_RectF rt,FX_FLOAT fThickness,CFX_Matrix * pMatrix)1834 static void XFA_BOX_Stroke_3DRect_Raised(CFX_Graphics* pGS,
1835                                          CFX_RectF rt,
1836                                          FX_FLOAT fThickness,
1837                                          CFX_Matrix* pMatrix) {
1838   FX_FLOAT fHalfWidth = fThickness / 2.0f;
1839   CFX_RectF rtInner(rt);
1840   rtInner.Deflate(fHalfWidth, fHalfWidth);
1841   CFX_Color cr(0xFF000000);
1842   pGS->SetFillColor(&cr);
1843   CFX_Path path;
1844   path.Create();
1845   path.AddRectangle(rt.left, rt.top, rt.width, rt.height);
1846   path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height);
1847   pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix);
1848   XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080);
1849 }
XFA_BOX_Stroke_3DRect_Etched(CFX_Graphics * pGS,CFX_RectF rt,FX_FLOAT fThickness,CFX_Matrix * pMatrix)1850 static void XFA_BOX_Stroke_3DRect_Etched(CFX_Graphics* pGS,
1851                                          CFX_RectF rt,
1852                                          FX_FLOAT fThickness,
1853                                          CFX_Matrix* pMatrix) {
1854   FX_FLOAT fHalfWidth = fThickness / 2.0f;
1855   XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFFFFFFFF);
1856   CFX_RectF rtInner(rt);
1857   rtInner.Deflate(fHalfWidth, fHalfWidth);
1858   XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080);
1859 }
XFA_BOX_Stroke_3DRect_Embossed(CFX_Graphics * pGS,CFX_RectF rt,FX_FLOAT fThickness,CFX_Matrix * pMatrix)1860 static void XFA_BOX_Stroke_3DRect_Embossed(CFX_Graphics* pGS,
1861                                            CFX_RectF rt,
1862                                            FX_FLOAT fThickness,
1863                                            CFX_Matrix* pMatrix) {
1864   FX_FLOAT fHalfWidth = fThickness / 2.0f;
1865   XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFF000000);
1866   CFX_RectF rtInner(rt);
1867   rtInner.Deflate(fHalfWidth, fHalfWidth);
1868   XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF000000, 0xFF808080);
1869 }
XFA_BOX_Stroke_Rect(CXFA_Box box,const CXFA_StrokeArray & strokes,CFX_Graphics * pGS,CFX_RectF rtWidget,CFX_Matrix * pMatrix)1870 static void XFA_BOX_Stroke_Rect(CXFA_Box box,
1871                                 const CXFA_StrokeArray& strokes,
1872                                 CFX_Graphics* pGS,
1873                                 CFX_RectF rtWidget,
1874                                 CFX_Matrix* pMatrix) {
1875   FX_BOOL bVisible = FALSE;
1876   FX_FLOAT fThickness = 0;
1877   int32_t i3DType = box.Get3DStyle(bVisible, fThickness);
1878   if (i3DType) {
1879     if (!bVisible || fThickness < 0.001f) {
1880       return;
1881     }
1882     switch (i3DType) {
1883       case XFA_ATTRIBUTEENUM_Lowered:
1884         XFA_BOX_Stroke_3DRect_Lowered(pGS, rtWidget, fThickness, pMatrix);
1885         break;
1886       case XFA_ATTRIBUTEENUM_Raised:
1887         XFA_BOX_Stroke_3DRect_Raised(pGS, rtWidget, fThickness, pMatrix);
1888         break;
1889       case XFA_ATTRIBUTEENUM_Etched:
1890         XFA_BOX_Stroke_3DRect_Etched(pGS, rtWidget, fThickness, pMatrix);
1891         break;
1892       case XFA_ATTRIBUTEENUM_Embossed:
1893         XFA_BOX_Stroke_3DRect_Embossed(pGS, rtWidget, fThickness, pMatrix);
1894         break;
1895     }
1896     return;
1897   }
1898   FX_BOOL bClose = FALSE;
1899   FX_BOOL bSameStyles = TRUE;
1900   CXFA_Stroke stroke1 = strokes[0];
1901   for (int32_t i = 1; i < 8; i++) {
1902     CXFA_Stroke stroke2 = strokes[i];
1903     if (!stroke1.SameStyles(stroke2)) {
1904       bSameStyles = FALSE;
1905       break;
1906     }
1907     stroke1 = stroke2;
1908   }
1909   if (bSameStyles) {
1910     stroke1 = strokes[0];
1911     bClose = TRUE;
1912     for (int32_t i = 2; i < 8; i += 2) {
1913       CXFA_Stroke stroke2 = strokes[i];
1914       if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence |
1915                                            XFA_STROKE_SAMESTYLE_Corner)) {
1916         bSameStyles = FALSE;
1917         break;
1918       }
1919       stroke1 = stroke2;
1920     }
1921     if (bSameStyles) {
1922       stroke1 = strokes[0];
1923       if (stroke1.IsInverted()) {
1924         bSameStyles = FALSE;
1925       }
1926       if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square) {
1927         bSameStyles = FALSE;
1928       }
1929     }
1930   }
1931   FX_BOOL bStart = TRUE;
1932   CFX_Path path;
1933   path.Create();
1934   for (int32_t i = 0; i < 8; i++) {
1935     CXFA_Stroke stroke = strokes[i];
1936     if ((i % 1) == 0 && stroke.GetRadius() < 0) {
1937       FX_BOOL bEmpty = path.IsEmpty();
1938       if (!bEmpty) {
1939         XFA_BOX_StrokePath(stroke, &path, pGS, pMatrix);
1940         path.Clear();
1941       }
1942       bStart = TRUE;
1943       continue;
1944     }
1945     XFA_BOX_GetPath(box, strokes, rtWidget, path, i, bStart, !bSameStyles);
1946     CXFA_Stroke stroke2 = strokes[(i + 1) % 8];
1947     bStart = !stroke.SameStyles(stroke2);
1948     if (bStart) {
1949       XFA_BOX_StrokePath(stroke, &path, pGS, pMatrix);
1950       path.Clear();
1951     }
1952   }
1953   FX_BOOL bEmpty = path.IsEmpty();
1954   if (!bEmpty) {
1955     if (bClose) {
1956       path.Close();
1957     }
1958     XFA_BOX_StrokePath(strokes[7], &path, pGS, pMatrix);
1959   }
1960 }
XFA_BOX_Stroke(CXFA_Box box,const CXFA_StrokeArray & strokes,CFX_Graphics * pGS,CFX_RectF rtWidget,CFX_Matrix * pMatrix,uint32_t dwFlags)1961 static void XFA_BOX_Stroke(CXFA_Box box,
1962                            const CXFA_StrokeArray& strokes,
1963                            CFX_Graphics* pGS,
1964                            CFX_RectF rtWidget,
1965                            CFX_Matrix* pMatrix,
1966                            uint32_t dwFlags) {
1967   if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) {
1968     XFA_BOX_StrokeArc(box, pGS, rtWidget, pMatrix, dwFlags);
1969     return;
1970   }
1971   bool bVisible = false;
1972   for (int32_t j = 0; j < 4; j++) {
1973     if (strokes[j * 2 + 1].IsVisible()) {
1974       bVisible = true;
1975       break;
1976     }
1977   }
1978   if (!bVisible) {
1979     return;
1980   }
1981   for (int32_t i = 1; i < 8; i += 2) {
1982     CXFA_Edge edge(strokes[i].GetNode());
1983     FX_FLOAT fThickness = edge.GetThickness();
1984     if (fThickness < 0) {
1985       fThickness = 0;
1986     }
1987     FX_FLOAT fHalf = fThickness / 2;
1988     int32_t iHand = box.GetHand();
1989     switch (i) {
1990       case 1:
1991         if (iHand == XFA_ATTRIBUTEENUM_Left) {
1992           rtWidget.top -= fHalf;
1993           rtWidget.height += fHalf;
1994         } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
1995           rtWidget.top += fHalf;
1996           rtWidget.height -= fHalf;
1997         }
1998         break;
1999       case 3:
2000         if (iHand == XFA_ATTRIBUTEENUM_Left) {
2001           rtWidget.width += fHalf;
2002         } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
2003           rtWidget.width -= fHalf;
2004         }
2005         break;
2006       case 5:
2007         if (iHand == XFA_ATTRIBUTEENUM_Left) {
2008           rtWidget.height += fHalf;
2009         } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
2010           rtWidget.height -= fHalf;
2011         }
2012         break;
2013       case 7:
2014         if (iHand == XFA_ATTRIBUTEENUM_Left) {
2015           rtWidget.left -= fHalf;
2016           rtWidget.width += fHalf;
2017         } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
2018           rtWidget.left += fHalf;
2019           rtWidget.width -= fHalf;
2020         }
2021         break;
2022     }
2023   }
2024   XFA_BOX_Stroke_Rect(box, strokes, pGS, rtWidget, pMatrix);
2025 }
XFA_DrawBox(CXFA_Box box,CFX_Graphics * pGS,const CFX_RectF & rtWidget,CFX_Matrix * pMatrix,uint32_t dwFlags)2026 void XFA_DrawBox(CXFA_Box box,
2027                  CFX_Graphics* pGS,
2028                  const CFX_RectF& rtWidget,
2029                  CFX_Matrix* pMatrix,
2030                  uint32_t dwFlags) {
2031   if (!box || box.GetPresence() != XFA_ATTRIBUTEENUM_Visible)
2032     return;
2033 
2034   XFA_Element eType = box.GetElementType();
2035   if (eType != XFA_Element::Arc && eType != XFA_Element::Border &&
2036       eType != XFA_Element::Rectangle) {
2037     return;
2038   }
2039   CXFA_StrokeArray strokes;
2040   if (!(dwFlags & XFA_DRAWBOX_ForceRound) && eType != XFA_Element::Arc) {
2041     box.GetStrokes(strokes);
2042   }
2043   XFA_BOX_Fill(box, strokes, pGS, rtWidget, pMatrix, dwFlags);
2044   XFA_BOX_Stroke(box, strokes, pGS, rtWidget, pMatrix, dwFlags);
2045 }
2046 
CXFA_CalcData()2047 CXFA_CalcData::CXFA_CalcData() : m_iRefCount(0) {}
2048 
~CXFA_CalcData()2049 CXFA_CalcData::~CXFA_CalcData() {
2050   m_Globals.RemoveAll();
2051 }
2052