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