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