blob: 18d6f94bc71589b4cbe1832047d2bfaf7c0945b5 [file] [log] [blame]
Dan Sinclair1770c022016-03-14 14:14:16 -04001// 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
Dan Sinclair80c48782017-03-23 12:11:20 -04007#include "xfa/fxfa/cxfa_ffwidget.h"
Dan Sinclair1770c022016-03-14 14:14:16 -04008
9#include <algorithm>
thestig39fbb7e2016-05-12 15:35:00 -070010#include <memory>
Dan Sinclair85c8e7f2016-11-21 13:50:32 -050011#include <vector>
Dan Sinclair1770c022016-03-14 14:14:16 -040012
dsinclair41872fa2016-10-04 11:29:35 -070013#include "core/fpdfapi/page/cpdf_pageobjectholder.h"
dsinclair8a4e2862016-09-29 13:43:30 -070014#include "core/fxcodec/codec/ccodec_progressivedecoder.h"
15#include "core/fxcodec/fx_codec.h"
tsepez1a1d7642016-12-06 06:29:28 -080016#include "core/fxcrt/cfx_maybe_owned.h"
dsinclair74a34fc2016-09-29 16:41:42 -070017#include "core/fxge/cfx_gemodule.h"
18#include "core/fxge/cfx_pathdata.h"
19#include "core/fxge/cfx_renderdevice.h"
Nicolas Penac3202a92017-04-04 13:38:29 -040020#include "core/fxge/dib/cfx_imagerenderer.h"
Nicolas Penabdbb0bd2017-03-31 15:39:44 -040021#include "core/fxge/dib/cfx_imagetransformer.h"
dsinclair447b1f32016-12-08 10:06:32 -080022#include "xfa/fwl/fwl_widgethit.h"
Dan Sinclair1f5d4982017-01-10 16:37:32 -050023#include "xfa/fxfa/app/cxfa_textlayout.h"
dsinclair5b493092016-09-29 20:20:24 -070024#include "xfa/fxfa/cxfa_eventparam.h"
Dan Sinclair80c48782017-03-23 12:11:20 -040025#include "xfa/fxfa/cxfa_ffapp.h"
26#include "xfa/fxfa/cxfa_ffdoc.h"
27#include "xfa/fxfa/cxfa_ffdocview.h"
28#include "xfa/fxfa/cxfa_ffpageview.h"
29#include "xfa/fxfa/cxfa_widgetacc.h"
dsinclair44d054c2016-04-06 10:23:46 -070030#include "xfa/fxfa/parser/cxfa_corner.h"
Dan Sinclairefcae5d2017-03-29 14:47:46 -040031#include "xfa/fxfa/parser/cxfa_node.h"
Dan Sinclair811b8a42016-03-17 08:59:42 -040032#include "xfa/fxgraphics/cfx_color.h"
dsinclair202ad722016-09-29 17:41:42 -070033#include "xfa/fxgraphics/cfx_graphics.h"
Dan Sinclair811b8a42016-03-17 08:59:42 -040034#include "xfa/fxgraphics/cfx_path.h"
35#include "xfa/fxgraphics/cfx_pattern.h"
36#include "xfa/fxgraphics/cfx_shading.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040037
dan sinclairaaf0bdc2017-02-04 10:16:21 -050038CXFA_FFWidget::CXFA_FFWidget(CXFA_WidgetAcc* pDataAcc)
Dan Sinclair1770c022016-03-14 14:14:16 -040039 : CXFA_ContentLayoutItem(pDataAcc->GetNode()),
dan sinclairaaf0bdc2017-02-04 10:16:21 -050040 m_pPageView(nullptr),
Dan Sinclairbba2a7c2017-02-07 16:36:39 -050041 m_pDataAcc(pDataAcc) {}
dan sinclairaaf0bdc2017-02-04 10:16:21 -050042
Dan Sinclair1770c022016-03-14 14:14:16 -040043CXFA_FFWidget::~CXFA_FFWidget() {}
dsinclair20855382016-10-31 07:29:34 -070044
dsinclair1a7534a2016-11-22 15:56:11 -080045const CFWL_App* CXFA_FFWidget::GetFWLApp() {
dsinclair20855382016-10-31 07:29:34 -070046 return GetPageView()->GetDocView()->GetDoc()->GetApp()->GetFWLApp();
47}
48
Lei Zhangafc8eb32017-03-28 14:32:13 -070049const CFX_RectF& CXFA_FFWidget::GetWidgetRect() const {
Dan Sinclairc2229072017-02-07 09:04:28 -050050 if ((m_dwStatus & XFA_WidgetStatus_RectCached) == 0)
51 RecacheWidgetRect();
Dan Sinclair1b08df12017-02-09 09:17:20 -050052 return m_rtWidget;
Dan Sinclair1770c022016-03-14 14:14:16 -040053}
Dan Sinclair1b08df12017-02-09 09:17:20 -050054
Lei Zhangafc8eb32017-03-28 14:32:13 -070055const CFX_RectF& CXFA_FFWidget::RecacheWidgetRect() const {
dsinclair935d8d52016-05-17 10:32:18 -070056 m_dwStatus |= XFA_WidgetStatus_RectCached;
Dan Sinclairc2229072017-02-07 09:04:28 -050057 m_rtWidget = GetRect(false);
Dan Sinclair1770c022016-03-14 14:14:16 -040058 return m_rtWidget;
59}
Dan Sinclair1b08df12017-02-09 09:17:20 -050060
61CFX_RectF CXFA_FFWidget::GetRectWithoutRotate() {
62 CFX_RectF rtWidget = GetWidgetRect();
Dan Sinclair05df0752017-03-14 14:43:42 -040063 float fValue = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -040064 switch (m_pDataAcc->GetRotate()) {
65 case 90:
66 rtWidget.top = rtWidget.bottom();
67 fValue = rtWidget.width;
68 rtWidget.width = rtWidget.height;
69 rtWidget.height = fValue;
70 break;
71 case 180:
72 rtWidget.left = rtWidget.right();
73 rtWidget.top = rtWidget.bottom();
74 break;
75 case 270:
76 rtWidget.left = rtWidget.right();
77 fValue = rtWidget.width;
78 rtWidget.width = rtWidget.height;
79 rtWidget.height = fValue;
80 break;
81 }
Dan Sinclair1b08df12017-02-09 09:17:20 -050082 return rtWidget;
Dan Sinclair1770c022016-03-14 14:14:16 -040083}
Dan Sinclair1b08df12017-02-09 09:17:20 -050084
tsepez736f28a2016-03-25 14:19:51 -070085uint32_t CXFA_FFWidget::GetStatus() {
Dan Sinclair1770c022016-03-14 14:14:16 -040086 return m_dwStatus;
87}
88
tsepez736f28a2016-03-25 14:19:51 -070089void CXFA_FFWidget::ModifyStatus(uint32_t dwAdded, uint32_t dwRemoved) {
Dan Sinclair1770c022016-03-14 14:14:16 -040090 m_dwStatus = (m_dwStatus & ~dwRemoved) | dwAdded;
91}
92
Dan Sinclair1b08df12017-02-09 09:17:20 -050093CFX_RectF CXFA_FFWidget::GetBBox(uint32_t dwStatus, bool bDrawFocus) {
94 if (bDrawFocus || !m_pPageView)
95 return CFX_RectF();
96 return m_pPageView->GetPageViewRect();
Dan Sinclair1770c022016-03-14 14:14:16 -040097}
98
99CXFA_WidgetAcc* CXFA_FFWidget::GetDataAcc() {
100 return m_pDataAcc;
101}
weili47bcd4c2016-06-16 08:00:06 -0700102
tsepezd19e9122016-11-02 15:43:18 -0700103bool CXFA_FFWidget::GetToolTip(CFX_WideString& wsToolTip) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400104 if (CXFA_Assist assist = m_pDataAcc->GetAssist()) {
105 if (CXFA_ToolTip toolTip = assist.GetToolTip()) {
106 return toolTip.GetTip(wsToolTip);
107 }
108 }
109 return GetCaptionText(wsToolTip);
110}
Dan Sinclair1b08df12017-02-09 09:17:20 -0500111
Dan Sinclair1770c022016-03-14 14:14:16 -0400112void CXFA_FFWidget::RenderWidget(CFX_Graphics* pGS,
113 CFX_Matrix* pMatrix,
dsinclair9d6ca992016-06-16 10:51:56 -0700114 uint32_t dwStatus) {
Dan Sinclair1b08df12017-02-09 09:17:20 -0500115 if (!IsMatchVisibleStatus(dwStatus))
Dan Sinclair1770c022016-03-14 14:14:16 -0400116 return;
Dan Sinclair1b08df12017-02-09 09:17:20 -0500117
Dan Sinclair1770c022016-03-14 14:14:16 -0400118 CXFA_Border border = m_pDataAcc->GetBorder();
Dan Sinclair1b08df12017-02-09 09:17:20 -0500119 if (!border)
120 return;
121
122 CFX_RectF rtBorder = GetRectWithoutRotate();
123 CXFA_Margin margin = border.GetMargin();
124 if (margin)
125 XFA_RectWidthoutMargin(rtBorder, margin);
126
127 rtBorder.Normalize();
128 DrawBorder(pGS, border, rtBorder, pMatrix);
Dan Sinclair1770c022016-03-14 14:14:16 -0400129}
Dan Sinclair1b08df12017-02-09 09:17:20 -0500130
tsepezd19e9122016-11-02 15:43:18 -0700131bool CXFA_FFWidget::IsLoaded() {
dsinclair85d1f2c2016-06-23 12:40:16 -0700132 return !!m_pPageView;
Dan Sinclair1770c022016-03-14 14:14:16 -0400133}
tsepezd19e9122016-11-02 15:43:18 -0700134bool CXFA_FFWidget::LoadWidget() {
Dan Sinclair1770c022016-03-14 14:14:16 -0400135 PerformLayout();
tsepezd19e9122016-11-02 15:43:18 -0700136 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400137}
138void CXFA_FFWidget::UnloadWidget() {}
tsepezd19e9122016-11-02 15:43:18 -0700139bool CXFA_FFWidget::PerformLayout() {
Dan Sinclairc2229072017-02-07 09:04:28 -0500140 RecacheWidgetRect();
tsepezd19e9122016-11-02 15:43:18 -0700141 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400142}
tsepezd19e9122016-11-02 15:43:18 -0700143bool CXFA_FFWidget::UpdateFWLData() {
144 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400145}
146void CXFA_FFWidget::UpdateWidgetProperty() {}
147void CXFA_FFWidget::DrawBorder(CFX_Graphics* pGS,
148 CXFA_Box box,
149 const CFX_RectF& rtBorder,
150 CFX_Matrix* pMatrix,
tsepez736f28a2016-03-25 14:19:51 -0700151 uint32_t dwFlags) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400152 XFA_DrawBox(box, pGS, rtBorder, pMatrix, dwFlags);
153}
Dan Sinclair1b08df12017-02-09 09:17:20 -0500154
Dan Sinclair1770c022016-03-14 14:14:16 -0400155void CXFA_FFWidget::InvalidateWidget(const CFX_RectF* pRect) {
Dan Sinclair1b08df12017-02-09 09:17:20 -0500156 if (pRect) {
Dan Sinclaire3978d02017-03-23 09:12:10 -0400157 GetDoc()->GetDocEnvironment()->InvalidateRect(m_pPageView, *pRect);
Dan Sinclair1b08df12017-02-09 09:17:20 -0500158 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400159 }
Dan Sinclair1b08df12017-02-09 09:17:20 -0500160
161 CFX_RectF rtWidget = GetBBox(XFA_WidgetStatus_Focused);
162 rtWidget.Inflate(2, 2);
Dan Sinclaire3978d02017-03-23 09:12:10 -0400163 GetDoc()->GetDocEnvironment()->InvalidateRect(m_pPageView, rtWidget);
Dan Sinclair1770c022016-03-14 14:14:16 -0400164}
Dan Sinclair1b08df12017-02-09 09:17:20 -0500165
Dan Sinclair1770c022016-03-14 14:14:16 -0400166void CXFA_FFWidget::AddInvalidateRect(const CFX_RectF* pRect) {
167 CFX_RectF rtWidget;
168 if (pRect) {
169 rtWidget = *pRect;
170 } else {
Dan Sinclair1b08df12017-02-09 09:17:20 -0500171 rtWidget = GetBBox(XFA_WidgetStatus_Focused);
Dan Sinclair1770c022016-03-14 14:14:16 -0400172 rtWidget.Inflate(2, 2);
173 }
174 m_pDocView->AddInvalidateRect(m_pPageView, rtWidget);
175}
Dan Sinclair1b08df12017-02-09 09:17:20 -0500176
tsepezd19e9122016-11-02 15:43:18 -0700177bool CXFA_FFWidget::GetCaptionText(CFX_WideString& wsCap) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400178 CXFA_TextLayout* pCapTextlayout = m_pDataAcc->GetCaptionTextLayout();
179 if (!pCapTextlayout) {
tsepezd19e9122016-11-02 15:43:18 -0700180 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400181 }
182 pCapTextlayout->GetText(wsCap);
tsepezd19e9122016-11-02 15:43:18 -0700183 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400184}
tsepez7d89e722016-05-04 13:38:11 -0700185
186bool CXFA_FFWidget::IsFocused() {
dsinclair935d8d52016-05-17 10:32:18 -0700187 return !!(m_dwStatus & XFA_WidgetStatus_Focused);
Dan Sinclair1770c022016-03-14 14:14:16 -0400188}
tsepez7d89e722016-05-04 13:38:11 -0700189
tsepezd19e9122016-11-02 15:43:18 -0700190bool CXFA_FFWidget::OnMouseEnter() {
191 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400192}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500193
tsepezd19e9122016-11-02 15:43:18 -0700194bool CXFA_FFWidget::OnMouseExit() {
195 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400196}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500197
198bool CXFA_FFWidget::OnLButtonDown(uint32_t dwFlags, const CFX_PointF& point) {
tsepezd19e9122016-11-02 15:43:18 -0700199 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400200}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500201
202bool CXFA_FFWidget::OnLButtonUp(uint32_t dwFlags, const CFX_PointF& point) {
tsepezd19e9122016-11-02 15:43:18 -0700203 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400204}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500205
206bool CXFA_FFWidget::OnLButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) {
tsepezd19e9122016-11-02 15:43:18 -0700207 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400208}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500209
210bool CXFA_FFWidget::OnMouseMove(uint32_t dwFlags, const CFX_PointF& point) {
tsepezd19e9122016-11-02 15:43:18 -0700211 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400212}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500213
tsepezd19e9122016-11-02 15:43:18 -0700214bool CXFA_FFWidget::OnMouseWheel(uint32_t dwFlags,
215 int16_t zDelta,
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500216 const CFX_PointF& point) {
tsepezd19e9122016-11-02 15:43:18 -0700217 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400218}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500219
220bool CXFA_FFWidget::OnRButtonDown(uint32_t dwFlags, const CFX_PointF& point) {
tsepezd19e9122016-11-02 15:43:18 -0700221 return false;
222}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500223
224bool CXFA_FFWidget::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) {
tsepezd19e9122016-11-02 15:43:18 -0700225 return false;
226}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500227
228bool CXFA_FFWidget::OnRButtonDblClk(uint32_t dwFlags, const CFX_PointF& point) {
tsepezd19e9122016-11-02 15:43:18 -0700229 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400230}
231
tsepezd19e9122016-11-02 15:43:18 -0700232bool CXFA_FFWidget::OnSetFocus(CXFA_FFWidget* pOldWidget) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400233 CXFA_FFWidget* pParent = GetParent();
234 if (pParent && !pParent->IsAncestorOf(pOldWidget)) {
235 pParent->OnSetFocus(pOldWidget);
236 }
dsinclair935d8d52016-05-17 10:32:18 -0700237 m_dwStatus |= XFA_WidgetStatus_Focused;
Dan Sinclair1770c022016-03-14 14:14:16 -0400238 CXFA_EventParam eParam;
239 eParam.m_eType = XFA_EVENT_Enter;
240 eParam.m_pTarget = m_pDataAcc;
241 m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Enter, &eParam);
tsepezd19e9122016-11-02 15:43:18 -0700242 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400243}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500244
tsepezd19e9122016-11-02 15:43:18 -0700245bool CXFA_FFWidget::OnKillFocus(CXFA_FFWidget* pNewWidget) {
dsinclair935d8d52016-05-17 10:32:18 -0700246 m_dwStatus &= ~XFA_WidgetStatus_Focused;
Dan Sinclair1770c022016-03-14 14:14:16 -0400247 EventKillFocus();
248 if (pNewWidget) {
249 CXFA_FFWidget* pParent = GetParent();
250 if (pParent && !pParent->IsAncestorOf(pNewWidget)) {
251 pParent->OnKillFocus(pNewWidget);
252 }
253 }
tsepezd19e9122016-11-02 15:43:18 -0700254 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400255}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500256
tsepezd19e9122016-11-02 15:43:18 -0700257bool CXFA_FFWidget::OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) {
258 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400259}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500260
tsepezd19e9122016-11-02 15:43:18 -0700261bool CXFA_FFWidget::OnKeyUp(uint32_t dwKeyCode, uint32_t dwFlags) {
262 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400263}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500264
tsepezd19e9122016-11-02 15:43:18 -0700265bool CXFA_FFWidget::OnChar(uint32_t dwChar, uint32_t dwFlags) {
266 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400267}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500268
269FWL_WidgetHit CXFA_FFWidget::OnHitTest(const CFX_PointF& point) {
dsinclair89fcde82016-05-03 13:00:25 -0700270 return FWL_WidgetHit::Unknown;
Dan Sinclair1770c022016-03-14 14:14:16 -0400271}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500272
273bool CXFA_FFWidget::OnSetCursor(const CFX_PointF& point) {
tsepezd19e9122016-11-02 15:43:18 -0700274 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400275}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500276
tsepezd19e9122016-11-02 15:43:18 -0700277bool CXFA_FFWidget::CanUndo() {
278 return false;
weili47bcd4c2016-06-16 08:00:06 -0700279}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500280
tsepezd19e9122016-11-02 15:43:18 -0700281bool CXFA_FFWidget::CanRedo() {
282 return false;
weili47bcd4c2016-06-16 08:00:06 -0700283}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500284
tsepezd19e9122016-11-02 15:43:18 -0700285bool CXFA_FFWidget::Undo() {
286 return false;
weili47bcd4c2016-06-16 08:00:06 -0700287}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500288
tsepezd19e9122016-11-02 15:43:18 -0700289bool CXFA_FFWidget::Redo() {
290 return false;
weili47bcd4c2016-06-16 08:00:06 -0700291}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500292
tsepezd19e9122016-11-02 15:43:18 -0700293bool CXFA_FFWidget::CanCopy() {
294 return false;
weili47bcd4c2016-06-16 08:00:06 -0700295}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500296
tsepezd19e9122016-11-02 15:43:18 -0700297bool CXFA_FFWidget::CanCut() {
298 return false;
weili47bcd4c2016-06-16 08:00:06 -0700299}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500300
tsepezd19e9122016-11-02 15:43:18 -0700301bool CXFA_FFWidget::CanPaste() {
302 return false;
weili47bcd4c2016-06-16 08:00:06 -0700303}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500304
tsepezd19e9122016-11-02 15:43:18 -0700305bool CXFA_FFWidget::CanSelectAll() {
306 return false;
weili47bcd4c2016-06-16 08:00:06 -0700307}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500308
tsepezd19e9122016-11-02 15:43:18 -0700309bool CXFA_FFWidget::CanDelete() {
weili47bcd4c2016-06-16 08:00:06 -0700310 return CanCut();
311}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500312
tsepezd19e9122016-11-02 15:43:18 -0700313bool CXFA_FFWidget::CanDeSelect() {
weili47bcd4c2016-06-16 08:00:06 -0700314 return CanCopy();
315}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500316
tsepezd19e9122016-11-02 15:43:18 -0700317bool CXFA_FFWidget::Copy(CFX_WideString& wsCopy) {
318 return false;
weili47bcd4c2016-06-16 08:00:06 -0700319}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500320
tsepezd19e9122016-11-02 15:43:18 -0700321bool CXFA_FFWidget::Cut(CFX_WideString& wsCut) {
322 return false;
weili47bcd4c2016-06-16 08:00:06 -0700323}
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500324
tsepezd19e9122016-11-02 15:43:18 -0700325bool CXFA_FFWidget::Paste(const CFX_WideString& wsPaste) {
326 return false;
weili47bcd4c2016-06-16 08:00:06 -0700327}
dsinclair14a60c52016-11-16 12:15:27 -0800328
329void CXFA_FFWidget::SelectAll() {}
330
331void CXFA_FFWidget::Delete() {}
332
333void CXFA_FFWidget::DeSelect() {}
334
tsepezd19e9122016-11-02 15:43:18 -0700335bool CXFA_FFWidget::GetSuggestWords(CFX_PointF pointf,
336 std::vector<CFX_ByteString>& sSuggest) {
337 return false;
weili47bcd4c2016-06-16 08:00:06 -0700338}
tsepezd19e9122016-11-02 15:43:18 -0700339bool CXFA_FFWidget::ReplaceSpellCheckWord(CFX_PointF pointf,
340 const CFX_ByteStringC& bsReplace) {
341 return false;
weili47bcd4c2016-06-16 08:00:06 -0700342}
Dan Sinclair1f403ce2017-02-21 12:56:24 -0500343
344CFX_PointF CXFA_FFWidget::Rotate2Normal(const CFX_PointF& point) {
Dan Sinclair1b08df12017-02-09 09:17:20 -0500345 CFX_Matrix mt = GetRotateMatrix();
Dan Sinclair1f403ce2017-02-21 12:56:24 -0500346 if (mt.IsIdentity())
347 return point;
348
Dan Sinclair1770c022016-03-14 14:14:16 -0400349 CFX_Matrix mtReverse;
350 mtReverse.SetReverse(mt);
Dan Sinclair1f403ce2017-02-21 12:56:24 -0500351 return mtReverse.Transform(point);
Dan Sinclair1770c022016-03-14 14:14:16 -0400352}
Dan Sinclair1f403ce2017-02-21 12:56:24 -0500353
Dan Sinclair1770c022016-03-14 14:14:16 -0400354static void XFA_GetMatrix(CFX_Matrix& m,
355 int32_t iRotate,
weili038aa532016-05-20 15:38:29 -0700356 XFA_ATTRIBUTEENUM at,
Dan Sinclair1770c022016-03-14 14:14:16 -0400357 const CFX_RectF& rt) {
358 if (!iRotate) {
359 return;
360 }
Dan Sinclair05df0752017-03-14 14:43:42 -0400361 float fAnchorX = 0;
362 float fAnchorY = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400363 switch (at) {
364 case XFA_ATTRIBUTEENUM_TopLeft:
365 fAnchorX = rt.left, fAnchorY = rt.top;
366 break;
367 case XFA_ATTRIBUTEENUM_TopCenter:
368 fAnchorX = (rt.left + rt.right()) / 2, fAnchorY = rt.top;
369 break;
370 case XFA_ATTRIBUTEENUM_TopRight:
371 fAnchorX = rt.right(), fAnchorY = rt.top;
372 break;
373 case XFA_ATTRIBUTEENUM_MiddleLeft:
374 fAnchorX = rt.left, fAnchorY = (rt.top + rt.bottom()) / 2;
375 break;
376 case XFA_ATTRIBUTEENUM_MiddleCenter:
377 fAnchorX = (rt.left + rt.right()) / 2,
378 fAnchorY = (rt.top + rt.bottom()) / 2;
379 break;
380 case XFA_ATTRIBUTEENUM_MiddleRight:
381 fAnchorX = rt.right(), fAnchorY = (rt.top + rt.bottom()) / 2;
382 break;
383 case XFA_ATTRIBUTEENUM_BottomLeft:
384 fAnchorX = rt.left, fAnchorY = rt.bottom();
385 break;
386 case XFA_ATTRIBUTEENUM_BottomCenter:
387 fAnchorX = (rt.left + rt.right()) / 2, fAnchorY = rt.bottom();
388 break;
389 case XFA_ATTRIBUTEENUM_BottomRight:
390 fAnchorX = rt.right(), fAnchorY = rt.bottom();
391 break;
weili038aa532016-05-20 15:38:29 -0700392 default:
393 break;
Dan Sinclair1770c022016-03-14 14:14:16 -0400394 }
395 switch (iRotate) {
396 case 90:
397 m.a = 0, m.b = -1, m.c = 1, m.d = 0, m.e = fAnchorX - fAnchorY,
398 m.f = fAnchorX + fAnchorY;
399 break;
400 case 180:
401 m.a = -1, m.b = 0, m.c = 0, m.d = -1, m.e = fAnchorX * 2,
402 m.f = fAnchorY * 2;
403 break;
404 case 270:
405 m.a = 0, m.b = 1, m.c = -1, m.d = 0, m.e = fAnchorX + fAnchorY,
406 m.f = fAnchorY - fAnchorX;
407 break;
408 }
409}
Dan Sinclair1b08df12017-02-09 09:17:20 -0500410
411CFX_Matrix CXFA_FFWidget::GetRotateMatrix() {
412 CFX_Matrix mt;
Dan Sinclair1770c022016-03-14 14:14:16 -0400413 int32_t iRotate = m_pDataAcc->GetRotate();
Dan Sinclair1b08df12017-02-09 09:17:20 -0500414 if (!iRotate)
415 return mt;
416
417 CFX_RectF rcWidget = GetRectWithoutRotate();
Dan Sinclair1770c022016-03-14 14:14:16 -0400418 XFA_ATTRIBUTEENUM at = XFA_ATTRIBUTEENUM_TopLeft;
419 XFA_GetMatrix(mt, iRotate, at, rcWidget);
Dan Sinclair1b08df12017-02-09 09:17:20 -0500420
421 return mt;
Dan Sinclair1770c022016-03-14 14:14:16 -0400422}
Dan Sinclair1b08df12017-02-09 09:17:20 -0500423
tsepezd19e9122016-11-02 15:43:18 -0700424bool CXFA_FFWidget::IsLayoutRectEmpty() {
Dan Sinclair1b08df12017-02-09 09:17:20 -0500425 CFX_RectF rtLayout = GetRectWithoutRotate();
Dan Sinclair1770c022016-03-14 14:14:16 -0400426 return rtLayout.width < 0.1f && rtLayout.height < 0.1f;
427}
428CXFA_FFWidget* CXFA_FFWidget::GetParent() {
429 CXFA_Node* pParentNode =
430 m_pDataAcc->GetNode()->GetNodeItem(XFA_NODEITEM_Parent);
431 if (pParentNode) {
432 CXFA_WidgetAcc* pParentWidgetAcc =
tsepez20d6b762016-06-09 11:46:16 -0700433 static_cast<CXFA_WidgetAcc*>(pParentNode->GetWidgetData());
Dan Sinclair1770c022016-03-14 14:14:16 -0400434 if (pParentWidgetAcc) {
dsinclair85d1f2c2016-06-23 12:40:16 -0700435 return pParentWidgetAcc->GetNextWidget(nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -0400436 }
437 }
dsinclair85d1f2c2016-06-23 12:40:16 -0700438 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400439}
Dan Sinclair1b08df12017-02-09 09:17:20 -0500440
tsepezd19e9122016-11-02 15:43:18 -0700441bool CXFA_FFWidget::IsAncestorOf(CXFA_FFWidget* pWidget) {
Dan Sinclair1b08df12017-02-09 09:17:20 -0500442 if (!pWidget)
tsepezd19e9122016-11-02 15:43:18 -0700443 return false;
Dan Sinclair1b08df12017-02-09 09:17:20 -0500444
Dan Sinclair1770c022016-03-14 14:14:16 -0400445 CXFA_Node* pNode = m_pDataAcc->GetNode();
446 CXFA_Node* pChildNode = pWidget->GetDataAcc()->GetNode();
447 while (pChildNode) {
Dan Sinclair1b08df12017-02-09 09:17:20 -0500448 if (pChildNode == pNode)
tsepezd19e9122016-11-02 15:43:18 -0700449 return true;
Dan Sinclair1b08df12017-02-09 09:17:20 -0500450
Dan Sinclair1770c022016-03-14 14:14:16 -0400451 pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_Parent);
452 }
tsepezd19e9122016-11-02 15:43:18 -0700453 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400454}
Dan Sinclair1b08df12017-02-09 09:17:20 -0500455
Dan Sinclairb45ea1f2017-02-21 14:27:59 -0500456bool CXFA_FFWidget::PtInActiveRect(const CFX_PointF& point) {
457 return GetWidgetRect().Contains(point);
Dan Sinclair1770c022016-03-14 14:14:16 -0400458}
Dan Sinclair1b08df12017-02-09 09:17:20 -0500459
Dan Sinclair1770c022016-03-14 14:14:16 -0400460CXFA_FFDocView* CXFA_FFWidget::GetDocView() {
461 return m_pDocView;
462}
Dan Sinclair1b08df12017-02-09 09:17:20 -0500463
weili47bcd4c2016-06-16 08:00:06 -0700464void CXFA_FFWidget::SetDocView(CXFA_FFDocView* pDocView) {
465 m_pDocView = pDocView;
466}
Dan Sinclair1b08df12017-02-09 09:17:20 -0500467
Dan Sinclair1770c022016-03-14 14:14:16 -0400468CXFA_FFDoc* CXFA_FFWidget::GetDoc() {
tsepez20d6b762016-06-09 11:46:16 -0700469 return m_pDocView->GetDoc();
Dan Sinclair1770c022016-03-14 14:14:16 -0400470}
Dan Sinclair1b08df12017-02-09 09:17:20 -0500471
Dan Sinclair1770c022016-03-14 14:14:16 -0400472CXFA_FFApp* CXFA_FFWidget::GetApp() {
473 return GetDoc()->GetApp();
474}
Dan Sinclair1b08df12017-02-09 09:17:20 -0500475
Dan Sinclair1770c022016-03-14 14:14:16 -0400476IXFA_AppProvider* CXFA_FFWidget::GetAppProvider() {
477 return GetApp()->GetAppProvider();
478}
tsepez7d89e722016-05-04 13:38:11 -0700479
480bool CXFA_FFWidget::IsMatchVisibleStatus(uint32_t dwStatus) {
dsinclair935d8d52016-05-17 10:32:18 -0700481 return !!(m_dwStatus & XFA_WidgetStatus_Visible);
Dan Sinclair1770c022016-03-14 14:14:16 -0400482}
tsepez7d89e722016-05-04 13:38:11 -0700483
Dan Sinclair1770c022016-03-14 14:14:16 -0400484void CXFA_FFWidget::EventKillFocus() {
dsinclair935d8d52016-05-17 10:32:18 -0700485 if (m_dwStatus & XFA_WidgetStatus_Access) {
486 m_dwStatus &= ~XFA_WidgetStatus_Access;
Dan Sinclair1770c022016-03-14 14:14:16 -0400487 return;
488 }
489 CXFA_EventParam eParam;
490 eParam.m_eType = XFA_EVENT_Exit;
491 eParam.m_pTarget = m_pDataAcc;
492 m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Exit, &eParam);
493}
tsepezd19e9122016-11-02 15:43:18 -0700494bool CXFA_FFWidget::IsButtonDown() {
dsinclair935d8d52016-05-17 10:32:18 -0700495 return (m_dwStatus & XFA_WidgetStatus_ButtonDown) != 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400496}
tsepezd19e9122016-11-02 15:43:18 -0700497void CXFA_FFWidget::SetButtonDown(bool bSet) {
dsinclair935d8d52016-05-17 10:32:18 -0700498 bSet ? m_dwStatus |= XFA_WidgetStatus_ButtonDown
499 : m_dwStatus &= ~XFA_WidgetStatus_ButtonDown;
Dan Sinclair1770c022016-03-14 14:14:16 -0400500}
501int32_t XFA_StrokeTypeSetLineDash(CFX_Graphics* pGraphics,
502 int32_t iStrokeType,
503 int32_t iCapType) {
504 switch (iStrokeType) {
505 case XFA_ATTRIBUTEENUM_DashDot: {
Dan Sinclair05df0752017-03-14 14:43:42 -0400506 float dashArray[] = {4, 1, 2, 1};
Dan Sinclair1770c022016-03-14 14:14:16 -0400507 if (iCapType != XFA_ATTRIBUTEENUM_Butt) {
508 dashArray[1] = 2;
509 dashArray[3] = 2;
510 }
511 pGraphics->SetLineDash(0, dashArray, 4);
512 return FX_DASHSTYLE_DashDot;
513 }
514 case XFA_ATTRIBUTEENUM_DashDotDot: {
Dan Sinclair05df0752017-03-14 14:43:42 -0400515 float dashArray[] = {4, 1, 2, 1, 2, 1};
Dan Sinclair1770c022016-03-14 14:14:16 -0400516 if (iCapType != XFA_ATTRIBUTEENUM_Butt) {
517 dashArray[1] = 2;
518 dashArray[3] = 2;
519 dashArray[5] = 2;
520 }
521 pGraphics->SetLineDash(0, dashArray, 6);
522 return FX_DASHSTYLE_DashDotDot;
523 }
524 case XFA_ATTRIBUTEENUM_Dashed: {
Dan Sinclair05df0752017-03-14 14:43:42 -0400525 float dashArray[] = {5, 1};
Dan Sinclair1770c022016-03-14 14:14:16 -0400526 if (iCapType != XFA_ATTRIBUTEENUM_Butt) {
527 dashArray[1] = 2;
528 }
529 pGraphics->SetLineDash(0, dashArray, 2);
530 return FX_DASHSTYLE_Dash;
531 }
532 case XFA_ATTRIBUTEENUM_Dotted: {
Dan Sinclair05df0752017-03-14 14:43:42 -0400533 float dashArray[] = {2, 1};
Dan Sinclair1770c022016-03-14 14:14:16 -0400534 if (iCapType != XFA_ATTRIBUTEENUM_Butt) {
535 dashArray[1] = 2;
536 }
537 pGraphics->SetLineDash(0, dashArray, 2);
538 return FX_DASHSTYLE_Dot;
539 }
540 default:
541 break;
542 }
543 pGraphics->SetLineDash(FX_DASHSTYLE_Solid);
544 return FX_DASHSTYLE_Solid;
545}
546CFX_GraphStateData::LineCap XFA_LineCapToFXGE(int32_t iLineCap) {
547 switch (iLineCap) {
548 case XFA_ATTRIBUTEENUM_Round:
549 return CFX_GraphStateData::LineCapRound;
550 case XFA_ATTRIBUTEENUM_Butt:
551 return CFX_GraphStateData::LineCapButt;
552 default:
553 break;
554 }
555 return CFX_GraphStateData::LineCapSquare;
556}
thestig39fbb7e2016-05-12 15:35:00 -0700557
Dan Sinclair1770c022016-03-14 14:14:16 -0400558class CXFA_ImageRenderer {
559 public:
560 CXFA_ImageRenderer();
561 ~CXFA_ImageRenderer();
thestig39fbb7e2016-05-12 15:35:00 -0700562
tsepezd19e9122016-11-02 15:43:18 -0700563 bool Start(CFX_RenderDevice* pDevice,
Tom Sepezf0799fe2017-03-28 09:31:32 -0700564 const CFX_RetainPtr<CFX_DIBSource>& pDIBSource,
tsepezd19e9122016-11-02 15:43:18 -0700565 FX_ARGB bitmap_argb,
566 int bitmap_alpha,
567 const CFX_Matrix* pImage2Device,
568 uint32_t flags,
569 int blendType = FXDIB_BLEND_NORMAL);
570 bool Continue(IFX_Pause* pPause);
Dan Sinclair1770c022016-03-14 14:14:16 -0400571
572 protected:
tsepezd19e9122016-11-02 15:43:18 -0700573 bool StartDIBSource();
Tom Sepezf0799fe2017-03-28 09:31:32 -0700574 void CompositeDIBitmap(const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap,
Dan Sinclair1770c022016-03-14 14:14:16 -0400575 int left,
576 int top,
577 FX_ARGB mask_argb,
578 int bitmap_alpha,
579 int blend_mode,
580 int Transparency);
weilib4d1b572016-08-10 14:50:48 -0700581
582 CFX_RenderDevice* m_pDevice;
583 int m_Status;
584 CFX_Matrix m_ImageMatrix;
Tom Sepezf0799fe2017-03-28 09:31:32 -0700585 CFX_RetainPtr<CFX_DIBSource> m_pDIBSource;
586 CFX_RetainPtr<CFX_DIBitmap> m_pCloneConvert;
weilib4d1b572016-08-10 14:50:48 -0700587 int m_BitmapAlpha;
588 FX_ARGB m_FillArgb;
589 uint32_t m_Flags;
590 std::unique_ptr<CFX_ImageTransformer> m_pTransformer;
Nicolas Penac3202a92017-04-04 13:38:29 -0400591 std::unique_ptr<CFX_ImageRenderer> m_DeviceHandle;
weilib4d1b572016-08-10 14:50:48 -0700592 int32_t m_BlendType;
tsepezd19e9122016-11-02 15:43:18 -0700593 bool m_Result;
594 bool m_bPrint;
Dan Sinclair1770c022016-03-14 14:14:16 -0400595};
weilib4d1b572016-08-10 14:50:48 -0700596
597CXFA_ImageRenderer::CXFA_ImageRenderer()
598 : m_pDevice(nullptr),
599 m_Status(0),
weilib4d1b572016-08-10 14:50:48 -0700600 m_BitmapAlpha(255),
601 m_FillArgb(0),
602 m_Flags(0),
603 m_DeviceHandle(nullptr),
604 m_BlendType(FXDIB_BLEND_NORMAL),
tsepezd19e9122016-11-02 15:43:18 -0700605 m_Result(true),
606 m_bPrint(false) {}
thestig495bda12016-04-28 17:29:19 -0700607
Nicolas Penac3202a92017-04-04 13:38:29 -0400608CXFA_ImageRenderer::~CXFA_ImageRenderer() {}
thestig495bda12016-04-28 17:29:19 -0700609
tsepezd19e9122016-11-02 15:43:18 -0700610bool CXFA_ImageRenderer::Start(CFX_RenderDevice* pDevice,
Tom Sepezf0799fe2017-03-28 09:31:32 -0700611 const CFX_RetainPtr<CFX_DIBSource>& pDIBSource,
tsepezd19e9122016-11-02 15:43:18 -0700612 FX_ARGB bitmap_argb,
613 int bitmap_alpha,
614 const CFX_Matrix* pImage2Device,
615 uint32_t flags,
616 int blendType) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400617 m_pDevice = pDevice;
618 m_pDIBSource = pDIBSource;
619 m_FillArgb = bitmap_argb;
620 m_BitmapAlpha = bitmap_alpha;
621 m_ImageMatrix = *pImage2Device;
622 m_Flags = flags;
623 m_BlendType = blendType;
624 return StartDIBSource();
625}
thestigd3e354a2016-05-26 11:04:40 -0700626
tsepezd19e9122016-11-02 15:43:18 -0700627bool CXFA_ImageRenderer::StartDIBSource() {
thestigd3e354a2016-05-26 11:04:40 -0700628 if (m_pDevice->StartDIBitsWithBlend(m_pDIBSource, m_BitmapAlpha, m_FillArgb,
Nicolas Penac3202a92017-04-04 13:38:29 -0400629 &m_ImageMatrix, m_Flags, &m_DeviceHandle,
thestigd3e354a2016-05-26 11:04:40 -0700630 m_BlendType)) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400631 if (m_DeviceHandle) {
632 m_Status = 3;
tsepezd19e9122016-11-02 15:43:18 -0700633 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400634 }
tsepezd19e9122016-11-02 15:43:18 -0700635 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400636 }
637 CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect();
thestigad5ac752016-08-09 12:09:22 -0700638 FX_RECT image_rect = image_rect_f.GetOuterRect();
Dan Sinclair1770c022016-03-14 14:14:16 -0400639 int dest_width = image_rect.Width();
640 int dest_height = image_rect.Height();
Dan Sinclair669a4182017-04-03 14:51:45 -0400641 if ((fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) ||
642 (fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400643 if (m_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) {
tsepezd19e9122016-11-02 15:43:18 -0700644 m_Result = false;
645 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400646 }
Tom Sepezf0799fe2017-03-28 09:31:32 -0700647 CFX_RetainPtr<CFX_DIBSource> pDib = m_pDIBSource;
Dan Sinclair1770c022016-03-14 14:14:16 -0400648 if (m_pDIBSource->HasAlpha() &&
649 !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE) &&
650 !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) {
tsepez1a1d7642016-12-06 06:29:28 -0800651 m_pCloneConvert = m_pDIBSource->CloneConvert(FXDIB_Rgb);
Dan Sinclair1770c022016-03-14 14:14:16 -0400652 if (!m_pCloneConvert) {
tsepezd19e9122016-11-02 15:43:18 -0700653 m_Result = false;
654 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400655 }
Tom Sepezf0799fe2017-03-28 09:31:32 -0700656 pDib = m_pCloneConvert;
Dan Sinclair1770c022016-03-14 14:14:16 -0400657 }
658 FX_RECT clip_box = m_pDevice->GetClipBox();
659 clip_box.Intersect(image_rect);
660 m_Status = 2;
Tom Sepezf0799fe2017-03-28 09:31:32 -0700661 m_pTransformer = pdfium::MakeUnique<CFX_ImageTransformer>(
662 pDib, &m_ImageMatrix, m_Flags, &clip_box);
thestig39fbb7e2016-05-12 15:35:00 -0700663 m_pTransformer->Start();
tsepezd19e9122016-11-02 15:43:18 -0700664 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400665 }
666 if (m_ImageMatrix.a < 0) {
667 dest_width = -dest_width;
668 }
669 if (m_ImageMatrix.d > 0) {
670 dest_height = -dest_height;
671 }
672 int dest_left, dest_top;
673 dest_left = dest_width > 0 ? image_rect.left : image_rect.right;
674 dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom;
675 if (m_pDIBSource->IsOpaqueImage() && m_BitmapAlpha == 255) {
thestigd3e354a2016-05-26 11:04:40 -0700676 if (m_pDevice->StretchDIBitsWithFlagsAndBlend(
677 m_pDIBSource, dest_left, dest_top, dest_width, dest_height, m_Flags,
678 m_BlendType)) {
tsepezd19e9122016-11-02 15:43:18 -0700679 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400680 }
681 }
682 if (m_pDIBSource->IsAlphaMask()) {
683 if (m_BitmapAlpha != 255) {
684 m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha);
685 }
thestigd3e354a2016-05-26 11:04:40 -0700686 if (m_pDevice->StretchBitMaskWithFlags(m_pDIBSource, dest_left, dest_top,
687 dest_width, dest_height, m_FillArgb,
688 m_Flags)) {
tsepezd19e9122016-11-02 15:43:18 -0700689 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400690 }
691 }
692 if (m_bPrint && !(m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) {
tsepezd19e9122016-11-02 15:43:18 -0700693 m_Result = false;
694 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400695 }
696 FX_RECT clip_box = m_pDevice->GetClipBox();
697 FX_RECT dest_rect = clip_box;
698 dest_rect.Intersect(image_rect);
699 FX_RECT dest_clip(
700 dest_rect.left - image_rect.left, dest_rect.top - image_rect.top,
701 dest_rect.right - image_rect.left, dest_rect.bottom - image_rect.top);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700702 CFX_RetainPtr<CFX_DIBitmap> pStretched =
703 m_pDIBSource->StretchTo(dest_width, dest_height, m_Flags, &dest_clip);
Dan Sinclair1770c022016-03-14 14:14:16 -0400704 if (pStretched) {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700705 CompositeDIBitmap(pStretched, dest_rect.left, dest_rect.top, m_FillArgb,
706 m_BitmapAlpha, m_BlendType, false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400707 }
tsepezd19e9122016-11-02 15:43:18 -0700708 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400709}
thestig39fbb7e2016-05-12 15:35:00 -0700710
tsepezd19e9122016-11-02 15:43:18 -0700711bool CXFA_ImageRenderer::Continue(IFX_Pause* pPause) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400712 if (m_Status == 2) {
thestig39fbb7e2016-05-12 15:35:00 -0700713 if (m_pTransformer->Continue(pPause))
tsepezd19e9122016-11-02 15:43:18 -0700714 return true;
thestig39fbb7e2016-05-12 15:35:00 -0700715
Tom Sepezf0799fe2017-03-28 09:31:32 -0700716 CFX_RetainPtr<CFX_DIBitmap> pBitmap = m_pTransformer->DetachBitmap();
thestig39fbb7e2016-05-12 15:35:00 -0700717 if (!pBitmap)
tsepezd19e9122016-11-02 15:43:18 -0700718 return false;
thestig39fbb7e2016-05-12 15:35:00 -0700719
Dan Sinclair1770c022016-03-14 14:14:16 -0400720 if (pBitmap->IsAlphaMask()) {
thestig39fbb7e2016-05-12 15:35:00 -0700721 if (m_BitmapAlpha != 255)
Dan Sinclair1770c022016-03-14 14:14:16 -0400722 m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha);
thestig39fbb7e2016-05-12 15:35:00 -0700723 m_Result =
Tom Sepezf0799fe2017-03-28 09:31:32 -0700724 m_pDevice->SetBitMask(pBitmap, m_pTransformer->result().left,
thestig39fbb7e2016-05-12 15:35:00 -0700725 m_pTransformer->result().top, m_FillArgb);
Dan Sinclair1770c022016-03-14 14:14:16 -0400726 } else {
thestig39fbb7e2016-05-12 15:35:00 -0700727 if (m_BitmapAlpha != 255)
Dan Sinclair1770c022016-03-14 14:14:16 -0400728 pBitmap->MultiplyAlpha(m_BitmapAlpha);
thestigd3e354a2016-05-26 11:04:40 -0700729 m_Result = m_pDevice->SetDIBitsWithBlend(
Tom Sepezf0799fe2017-03-28 09:31:32 -0700730 pBitmap, m_pTransformer->result().left, m_pTransformer->result().top,
731 m_BlendType);
Dan Sinclair1770c022016-03-14 14:14:16 -0400732 }
tsepezd19e9122016-11-02 15:43:18 -0700733 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400734 }
thestig39fbb7e2016-05-12 15:35:00 -0700735 if (m_Status == 3)
Nicolas Penac3202a92017-04-04 13:38:29 -0400736 return m_pDevice->ContinueDIBits(m_DeviceHandle.get(), pPause);
thestig39fbb7e2016-05-12 15:35:00 -0700737
tsepezd19e9122016-11-02 15:43:18 -0700738 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400739}
thestig39fbb7e2016-05-12 15:35:00 -0700740
Tom Sepezf0799fe2017-03-28 09:31:32 -0700741void CXFA_ImageRenderer::CompositeDIBitmap(
742 const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap,
743 int left,
744 int top,
745 FX_ARGB mask_argb,
746 int bitmap_alpha,
747 int blend_mode,
748 int Transparency) {
dsinclair85d1f2c2016-06-23 12:40:16 -0700749 if (!pDIBitmap) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400750 return;
751 }
tsepez7d89e722016-05-04 13:38:11 -0700752 bool bIsolated = !!(Transparency & PDFTRANS_ISOLATED);
753 bool bGroup = !!(Transparency & PDFTRANS_GROUP);
Dan Sinclair1770c022016-03-14 14:14:16 -0400754 if (blend_mode == FXDIB_BLEND_NORMAL) {
755 if (!pDIBitmap->IsAlphaMask()) {
756 if (bitmap_alpha < 255) {
757 pDIBitmap->MultiplyAlpha(bitmap_alpha);
758 }
759 if (m_pDevice->SetDIBits(pDIBitmap, left, top)) {
760 return;
761 }
762 } else {
tsepez736f28a2016-03-25 14:19:51 -0700763 uint32_t fill_argb = (mask_argb);
Dan Sinclair1770c022016-03-14 14:14:16 -0400764 if (bitmap_alpha < 255) {
765 ((uint8_t*)&fill_argb)[3] =
766 ((uint8_t*)&fill_argb)[3] * bitmap_alpha / 255;
767 }
768 if (m_pDevice->SetBitMask(pDIBitmap, left, top, fill_argb)) {
769 return;
770 }
771 }
772 }
tsepezd19e9122016-11-02 15:43:18 -0700773 bool bBackAlphaRequired = blend_mode && bIsolated;
774 bool bGetBackGround =
Dan Sinclair1770c022016-03-14 14:14:16 -0400775 ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) ||
776 (!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) &&
777 (m_pDevice->GetRenderCaps() & FXRC_GET_BITS) && !bBackAlphaRequired);
778 if (bGetBackGround) {
779 if (bIsolated || !bGroup) {
780 if (pDIBitmap->IsAlphaMask()) {
781 return;
782 }
thestigd3e354a2016-05-26 11:04:40 -0700783 m_pDevice->SetDIBitsWithBlend(pDIBitmap, left, top, blend_mode);
Dan Sinclair1770c022016-03-14 14:14:16 -0400784 } else {
785 FX_RECT rect(left, top, left + pDIBitmap->GetWidth(),
786 top + pDIBitmap->GetHeight());
787 rect.Intersect(m_pDevice->GetClipBox());
Tom Sepezf0799fe2017-03-28 09:31:32 -0700788 CFX_RetainPtr<CFX_DIBitmap> pClone;
Dan Sinclair1770c022016-03-14 14:14:16 -0400789 if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400790 pClone = m_pDevice->GetBackDrop()->Clone(&rect);
Tom Sepezf0799fe2017-03-28 09:31:32 -0700791 CFX_RetainPtr<CFX_DIBitmap> pForeBitmap = m_pDevice->GetBitmap();
Dan Sinclair1770c022016-03-14 14:14:16 -0400792 pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(),
793 pForeBitmap, rect.left, rect.top);
794 left = left >= 0 ? 0 : left;
795 top = top >= 0 ? 0 : top;
796 if (!pDIBitmap->IsAlphaMask())
797 pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(),
798 pDIBitmap, left, top, blend_mode);
799 else
800 pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(),
801 pDIBitmap, mask_argb, left, top, blend_mode);
802 } else {
803 pClone = pDIBitmap;
804 }
805 if (m_pDevice->GetBackDrop()) {
Tom Sepezf0799fe2017-03-28 09:31:32 -0700806 m_pDevice->SetDIBits(pClone, rect.left, rect.top);
Dan Sinclair1770c022016-03-14 14:14:16 -0400807 } else {
thestigd3e354a2016-05-26 11:04:40 -0700808 if (pDIBitmap->IsAlphaMask())
Dan Sinclair1770c022016-03-14 14:14:16 -0400809 return;
thestigd3e354a2016-05-26 11:04:40 -0700810 m_pDevice->SetDIBitsWithBlend(pDIBitmap, rect.left, rect.top,
811 blend_mode);
Dan Sinclair1770c022016-03-14 14:14:16 -0400812 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400813 }
814 return;
815 }
tsepez1a1d7642016-12-06 06:29:28 -0800816 if (!pDIBitmap->HasAlpha() ||
817 (m_pDevice->GetRenderCaps() & FXRC_ALPHA_IMAGE)) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400818 return;
819 }
Tom Sepezf0799fe2017-03-28 09:31:32 -0700820 CFX_RetainPtr<CFX_DIBitmap> pCloneConvert =
tsepez1a1d7642016-12-06 06:29:28 -0800821 pDIBitmap->CloneConvert(FXDIB_Rgb);
822 if (!pCloneConvert)
823 return;
824
825 CXFA_ImageRenderer imageRender;
Tom Sepezf0799fe2017-03-28 09:31:32 -0700826 if (!imageRender.Start(m_pDevice, pCloneConvert, m_FillArgb, m_BitmapAlpha,
827 &m_ImageMatrix, m_Flags)) {
tsepez1a1d7642016-12-06 06:29:28 -0800828 return;
829 }
830 while (imageRender.Continue(nullptr))
831 continue;
Dan Sinclair1770c022016-03-14 14:14:16 -0400832}
tsepez1a1d7642016-12-06 06:29:28 -0800833
Dan Sinclair1770c022016-03-14 14:14:16 -0400834void XFA_DrawImage(CFX_Graphics* pGS,
835 const CFX_RectF& rtImage,
836 CFX_Matrix* pMatrix,
Tom Sepezf0799fe2017-03-28 09:31:32 -0700837 const CFX_RetainPtr<CFX_DIBitmap>& pDIBitmap,
Dan Sinclair1770c022016-03-14 14:14:16 -0400838 int32_t iAspect,
839 int32_t iImageXDpi,
840 int32_t iImageYDpi,
841 int32_t iHorzAlign,
842 int32_t iVertAlign) {
Dan Sinclairbba2a7c2017-02-07 16:36:39 -0500843 if (rtImage.IsEmpty())
Dan Sinclair1770c022016-03-14 14:14:16 -0400844 return;
Dan Sinclairbba2a7c2017-02-07 16:36:39 -0500845 if (!pDIBitmap || !pDIBitmap->GetBuffer())
Dan Sinclair1770c022016-03-14 14:14:16 -0400846 return;
Dan Sinclairbba2a7c2017-02-07 16:36:39 -0500847
848 CFX_RectF rtFit(
849 rtImage.TopLeft(),
Dan Sinclair05df0752017-03-14 14:43:42 -0400850 XFA_UnitPx2Pt((float)pDIBitmap->GetWidth(), (float)iImageXDpi),
851 XFA_UnitPx2Pt((float)pDIBitmap->GetHeight(), (float)iImageYDpi));
Dan Sinclair1770c022016-03-14 14:14:16 -0400852 switch (iAspect) {
853 case XFA_ATTRIBUTEENUM_Fit: {
Dan Sinclair05df0752017-03-14 14:43:42 -0400854 float f1 = rtImage.height / rtFit.height;
855 float f2 = rtImage.width / rtFit.width;
Dan Sinclair1770c022016-03-14 14:14:16 -0400856 f1 = std::min(f1, f2);
857 rtFit.height = rtFit.height * f1;
858 rtFit.width = rtFit.width * f1;
859 } break;
860 case XFA_ATTRIBUTEENUM_Actual:
861 break;
862 case XFA_ATTRIBUTEENUM_Height: {
Dan Sinclair05df0752017-03-14 14:43:42 -0400863 float f1 = rtImage.height / rtFit.height;
Dan Sinclair1770c022016-03-14 14:14:16 -0400864 rtFit.height = rtImage.height;
865 rtFit.width = f1 * rtFit.width;
866 } break;
867 case XFA_ATTRIBUTEENUM_None:
868 rtFit.height = rtImage.height;
869 rtFit.width = rtImage.width;
870 break;
871 case XFA_ATTRIBUTEENUM_Width: {
Dan Sinclair05df0752017-03-14 14:43:42 -0400872 float f1 = rtImage.width / rtFit.width;
Dan Sinclair1770c022016-03-14 14:14:16 -0400873 rtFit.width = rtImage.width;
874 rtFit.height = rtFit.height * f1;
875 } break;
876 }
877 if (iHorzAlign == XFA_ATTRIBUTEENUM_Center) {
878 rtFit.left += (rtImage.width - rtFit.width) / 2;
879 } else if (iHorzAlign == XFA_ATTRIBUTEENUM_Right) {
880 rtFit.left = rtImage.right() - rtFit.width;
881 }
882 if (iVertAlign == XFA_ATTRIBUTEENUM_Middle) {
883 rtFit.top += (rtImage.height - rtFit.height) / 2;
884 } else if (iVertAlign == XFA_ATTRIBUTEENUM_Bottom) {
885 rtFit.top = rtImage.bottom() - rtImage.height;
886 }
887 CFX_RenderDevice* pRenderDevice = pGS->GetRenderDevice();
888 pRenderDevice->SaveState();
dan sinclair071d7862017-02-07 20:46:32 -0500889
Dan Sinclair1770c022016-03-14 14:14:16 -0400890 CFX_PathData path;
891 path.AppendRect(rtImage.left, rtImage.bottom(), rtImage.right(), rtImage.top);
892 pRenderDevice->SetClip_PathFill(&path, pMatrix, FXFILL_WINDING);
dan sinclair071d7862017-02-07 20:46:32 -0500893
Dan Sinclair1770c022016-03-14 14:14:16 -0400894 CFX_Matrix mtImage(1, 0, 0, -1, 0, 1);
dan sinclair071d7862017-02-07 20:46:32 -0500895 mtImage.Concat(
896 CFX_Matrix(rtFit.width, 0, 0, rtFit.height, rtFit.left, rtFit.top));
Dan Sinclair1770c022016-03-14 14:14:16 -0400897 mtImage.Concat(*pMatrix);
dan sinclair071d7862017-02-07 20:46:32 -0500898
Dan Sinclair1770c022016-03-14 14:14:16 -0400899 CXFA_ImageRenderer imageRender;
tsepezd19e9122016-11-02 15:43:18 -0700900 bool bRet = imageRender.Start(pRenderDevice, pDIBitmap, 0, 255, &mtImage,
901 FXDIB_INTERPOL);
dan sinclair071d7862017-02-07 20:46:32 -0500902 while (bRet)
dsinclair85d1f2c2016-06-23 12:40:16 -0700903 bRet = imageRender.Continue(nullptr);
dan sinclair071d7862017-02-07 20:46:32 -0500904
thestig41846a02016-05-26 10:45:30 -0700905 pRenderDevice->RestoreState(false);
Dan Sinclair1770c022016-03-14 14:14:16 -0400906}
907
908static const uint8_t g_inv_base64[128] = {
909 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
910 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
911 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255,
912 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
913 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
914 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
915 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33,
916 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
917 49, 50, 51, 255, 255, 255, 255, 255,
918};
919
920static uint8_t* XFA_RemoveBase64Whitespace(const uint8_t* pStr, int32_t iLen) {
921 uint8_t* pCP;
922 int32_t i = 0, j = 0;
923 if (iLen == 0) {
Dan Sinclair812e96c2017-03-13 16:43:37 -0400924 iLen = FXSYS_strlen((char*)pStr);
Dan Sinclair1770c022016-03-14 14:14:16 -0400925 }
926 pCP = FX_Alloc(uint8_t, iLen + 1);
927 for (; i < iLen; i++) {
928 if ((pStr[i] & 128) == 0) {
929 if (g_inv_base64[pStr[i]] != 0xFF || pStr[i] == '=') {
930 pCP[j++] = pStr[i];
931 }
932 }
933 }
934 pCP[j] = '\0';
935 return pCP;
936}
Dan Sinclair812e96c2017-03-13 16:43:37 -0400937static int32_t XFA_Base64Decode(const char* pStr, uint8_t* pOutBuffer) {
dsinclair85d1f2c2016-06-23 12:40:16 -0700938 if (!pStr) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400939 return 0;
940 }
941 uint8_t* pBuffer =
Dan Sinclair812e96c2017-03-13 16:43:37 -0400942 XFA_RemoveBase64Whitespace((uint8_t*)pStr, FXSYS_strlen((char*)pStr));
dsinclair85d1f2c2016-06-23 12:40:16 -0700943 if (!pBuffer) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400944 return 0;
945 }
Dan Sinclair812e96c2017-03-13 16:43:37 -0400946 int32_t iLen = FXSYS_strlen((char*)pBuffer);
Dan Sinclair1770c022016-03-14 14:14:16 -0400947 int32_t i = 0, j = 0;
tsepez736f28a2016-03-25 14:19:51 -0700948 uint32_t dwLimb = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -0400949 for (; i + 3 < iLen; i += 4) {
950 if (pBuffer[i] == '=' || pBuffer[i + 1] == '=' || pBuffer[i + 2] == '=' ||
951 pBuffer[i + 3] == '=') {
952 if (pBuffer[i] == '=' || pBuffer[i + 1] == '=') {
953 break;
954 }
955 if (pBuffer[i + 2] == '=') {
tsepez736f28a2016-03-25 14:19:51 -0700956 dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 6) |
957 ((uint32_t)g_inv_base64[pBuffer[i + 1]]);
Dan Sinclair1770c022016-03-14 14:14:16 -0400958 pOutBuffer[j] = (uint8_t)(dwLimb >> 4) & 0xFF;
959 j++;
960 } else {
tsepez736f28a2016-03-25 14:19:51 -0700961 dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 12) |
962 ((uint32_t)g_inv_base64[pBuffer[i + 1]] << 6) |
963 ((uint32_t)g_inv_base64[pBuffer[i + 2]]);
Dan Sinclair1770c022016-03-14 14:14:16 -0400964 pOutBuffer[j] = (uint8_t)(dwLimb >> 10) & 0xFF;
965 pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 2) & 0xFF;
966 j += 2;
967 }
968 } else {
tsepez736f28a2016-03-25 14:19:51 -0700969 dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 18) |
970 ((uint32_t)g_inv_base64[pBuffer[i + 1]] << 12) |
971 ((uint32_t)g_inv_base64[pBuffer[i + 2]] << 6) |
972 ((uint32_t)g_inv_base64[pBuffer[i + 3]]);
Dan Sinclair1770c022016-03-14 14:14:16 -0400973 pOutBuffer[j] = (uint8_t)(dwLimb >> 16) & 0xff;
974 pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 8) & 0xff;
975 pOutBuffer[j + 2] = (uint8_t)(dwLimb)&0xff;
976 j += 3;
977 }
978 }
979 FX_Free(pBuffer);
980 return j;
981}
Tom Sepez4161c5c2016-03-21 12:26:54 -0700982
Dan Sinclair812e96c2017-03-13 16:43:37 -0400983static const char g_base64_chars[] =
Dan Sinclair1770c022016-03-14 14:14:16 -0400984 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
Tom Sepez4161c5c2016-03-21 12:26:54 -0700985
Dan Sinclair812e96c2017-03-13 16:43:37 -0400986char* XFA_Base64Encode(const uint8_t* buf, int32_t buf_len) {
987 char* out = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400988 int i, j;
tsepez736f28a2016-03-25 14:19:51 -0700989 uint32_t limb;
Dan Sinclair812e96c2017-03-13 16:43:37 -0400990 out = FX_Alloc(char, ((buf_len * 8 + 5) / 6) + 5);
Dan Sinclair1770c022016-03-14 14:14:16 -0400991 for (i = 0, j = 0, limb = 0; i + 2 < buf_len; i += 3, j += 4) {
tsepez736f28a2016-03-25 14:19:51 -0700992 limb = ((uint32_t)buf[i] << 16) | ((uint32_t)buf[i + 1] << 8) |
993 ((uint32_t)buf[i + 2]);
Dan Sinclair1770c022016-03-14 14:14:16 -0400994 out[j] = g_base64_chars[(limb >> 18) & 63];
995 out[j + 1] = g_base64_chars[(limb >> 12) & 63];
996 out[j + 2] = g_base64_chars[(limb >> 6) & 63];
997 out[j + 3] = g_base64_chars[(limb)&63];
998 }
999 switch (buf_len - i) {
1000 case 0:
1001 break;
1002 case 1:
tsepez736f28a2016-03-25 14:19:51 -07001003 limb = ((uint32_t)buf[i]);
Dan Sinclair1770c022016-03-14 14:14:16 -04001004 out[j++] = g_base64_chars[(limb >> 2) & 63];
1005 out[j++] = g_base64_chars[(limb << 4) & 63];
1006 out[j++] = '=';
1007 out[j++] = '=';
1008 break;
1009 case 2:
tsepez736f28a2016-03-25 14:19:51 -07001010 limb = ((uint32_t)buf[i] << 8) | ((uint32_t)buf[i + 1]);
Dan Sinclair1770c022016-03-14 14:14:16 -04001011 out[j++] = g_base64_chars[(limb >> 10) & 63];
1012 out[j++] = g_base64_chars[(limb >> 4) & 63];
1013 out[j++] = g_base64_chars[(limb << 2) & 63];
1014 out[j++] = '=';
1015 break;
1016 default:
1017 break;
1018 }
1019 out[j] = '\0';
1020 return out;
1021}
tsepezfc58ad12016-04-05 12:22:15 -07001022FXCODEC_IMAGE_TYPE XFA_GetImageType(const CFX_WideString& wsType) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001023 CFX_WideString wsContentType(wsType);
1024 wsContentType.MakeLower();
dan sinclair65c7c232017-02-02 14:05:30 -08001025 if (wsContentType == L"image/jpg")
Dan Sinclair1770c022016-03-14 14:14:16 -04001026 return FXCODEC_IMAGE_JPG;
dan sinclair65c7c232017-02-02 14:05:30 -08001027 if (wsContentType == L"image/png")
Dan Sinclair1770c022016-03-14 14:14:16 -04001028 return FXCODEC_IMAGE_PNG;
dan sinclair65c7c232017-02-02 14:05:30 -08001029 if (wsContentType == L"image/gif")
Dan Sinclair1770c022016-03-14 14:14:16 -04001030 return FXCODEC_IMAGE_GIF;
dan sinclair65c7c232017-02-02 14:05:30 -08001031 if (wsContentType == L"image/bmp")
Dan Sinclair1770c022016-03-14 14:14:16 -04001032 return FXCODEC_IMAGE_BMP;
dan sinclair65c7c232017-02-02 14:05:30 -08001033 if (wsContentType == L"image/tif")
Dan Sinclair1770c022016-03-14 14:14:16 -04001034 return FXCODEC_IMAGE_TIF;
Dan Sinclair1770c022016-03-14 14:14:16 -04001035 return FXCODEC_IMAGE_UNKNOWN;
1036}
Tom Sepezf0799fe2017-03-28 09:31:32 -07001037
1038CFX_RetainPtr<CFX_DIBitmap> XFA_LoadImageData(CXFA_FFDoc* pDoc,
1039 CXFA_Image* pImage,
1040 bool& bNameImage,
1041 int32_t& iImageXDpi,
1042 int32_t& iImageYDpi) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001043 CFX_WideString wsHref;
dsinclair31b08d42017-03-28 15:47:47 +00001044 CFX_WideString wsImage;
Tom Sepezf0799fe2017-03-28 09:31:32 -07001045 pImage->GetHref(wsHref);
Dan Sinclair1770c022016-03-14 14:14:16 -04001046 pImage->GetContent(wsImage);
Tom Sepezf0799fe2017-03-28 09:31:32 -07001047 if (wsHref.IsEmpty() && wsImage.IsEmpty())
dsinclair85d1f2c2016-06-23 12:40:16 -07001048 return nullptr;
Tom Sepezf0799fe2017-03-28 09:31:32 -07001049
Dan Sinclair1770c022016-03-14 14:14:16 -04001050 CFX_WideString wsContentType;
1051 pImage->GetContentType(wsContentType);
1052 FXCODEC_IMAGE_TYPE type = XFA_GetImageType(wsContentType);
1053 CFX_ByteString bsContent;
dsinclair85d1f2c2016-06-23 12:40:16 -07001054 uint8_t* pImageBuffer = nullptr;
tsepez833619b2016-12-07 09:21:17 -08001055 CFX_RetainPtr<IFX_SeekableReadStream> pImageFileRead;
Dan Sinclair1770c022016-03-14 14:14:16 -04001056 if (wsImage.GetLength() > 0) {
1057 XFA_ATTRIBUTEENUM iEncoding =
1058 (XFA_ATTRIBUTEENUM)pImage->GetTransferEncoding();
1059 if (iEncoding == XFA_ATTRIBUTEENUM_Base64) {
1060 CFX_ByteString bsData = wsImage.UTF8Encode();
1061 int32_t iLength = bsData.GetLength();
1062 pImageBuffer = FX_Alloc(uint8_t, iLength);
tsepezb4c9f3f2016-04-13 15:41:21 -07001063 int32_t iRead = XFA_Base64Decode(bsData.c_str(), pImageBuffer);
Dan Sinclair1770c022016-03-14 14:14:16 -04001064 if (iRead > 0) {
tsepez345d4892016-11-30 15:10:55 -08001065 pImageFileRead = IFX_MemoryStream::Create(pImageBuffer, iRead);
Dan Sinclair1770c022016-03-14 14:14:16 -04001066 }
1067 } else {
1068 bsContent = CFX_ByteString::FromUnicode(wsImage);
tsepez345d4892016-11-30 15:10:55 -08001069 pImageFileRead = IFX_MemoryStream::Create(
tsepezcfd4d572016-04-08 14:38:54 -07001070 const_cast<uint8_t*>(bsContent.raw_str()), bsContent.GetLength());
Dan Sinclair1770c022016-03-14 14:14:16 -04001071 }
1072 } else {
1073 CFX_WideString wsURL = wsHref;
dan sinclair65c7c232017-02-02 14:05:30 -08001074 if (wsURL.Left(7) != L"http://" && wsURL.Left(6) != L"ftp://") {
Tom Sepezf0799fe2017-03-28 09:31:32 -07001075 CFX_RetainPtr<CFX_DIBitmap> pBitmap =
tsepez4c3debb2016-04-08 12:20:38 -07001076 pDoc->GetPDFNamedImage(wsURL.AsStringC(), iImageXDpi, iImageYDpi);
Dan Sinclair1770c022016-03-14 14:14:16 -04001077 if (pBitmap) {
tsepezd19e9122016-11-02 15:43:18 -07001078 bNameImage = true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001079 return pBitmap;
1080 }
1081 }
dsinclaira440bb32016-09-14 07:01:54 -07001082 pImageFileRead = pDoc->GetDocEnvironment()->OpenLinkedFile(pDoc, wsURL);
Dan Sinclair1770c022016-03-14 14:14:16 -04001083 }
1084 if (!pImageFileRead) {
1085 FX_Free(pImageBuffer);
dsinclair85d1f2c2016-06-23 12:40:16 -07001086 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001087 }
tsepezd19e9122016-11-02 15:43:18 -07001088 bNameImage = false;
Tom Sepezf0799fe2017-03-28 09:31:32 -07001089 CFX_RetainPtr<CFX_DIBitmap> pBitmap =
Dan Sinclair1770c022016-03-14 14:14:16 -04001090 XFA_LoadImageFromBuffer(pImageFileRead, type, iImageXDpi, iImageYDpi);
1091 FX_Free(pImageBuffer);
Dan Sinclair1770c022016-03-14 14:14:16 -04001092 return pBitmap;
1093}
1094static FXDIB_Format XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type,
1095 int32_t iComponents,
1096 int32_t iBitsPerComponent) {
1097 FXDIB_Format dibFormat = FXDIB_Argb;
1098 switch (type) {
1099 case FXCODEC_IMAGE_BMP:
1100 case FXCODEC_IMAGE_JPG:
1101 case FXCODEC_IMAGE_TIF: {
1102 dibFormat = FXDIB_Rgb32;
1103 int32_t bpp = iComponents * iBitsPerComponent;
1104 if (bpp <= 24) {
1105 dibFormat = FXDIB_Rgb;
1106 }
1107 } break;
1108 case FXCODEC_IMAGE_PNG:
1109 default:
1110 break;
1111 }
1112 return dibFormat;
1113}
tsepez833619b2016-12-07 09:21:17 -08001114
Tom Sepezf0799fe2017-03-28 09:31:32 -07001115CFX_RetainPtr<CFX_DIBitmap> XFA_LoadImageFromBuffer(
tsepez833619b2016-12-07 09:21:17 -08001116 const CFX_RetainPtr<IFX_SeekableReadStream>& pImageFileRead,
1117 FXCODEC_IMAGE_TYPE type,
1118 int32_t& iImageXDpi,
1119 int32_t& iImageYDpi) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001120 CFX_GEModule* pGeModule = CFX_GEModule::Get();
tsepez833619b2016-12-07 09:21:17 -08001121 if (!pGeModule)
dsinclair85d1f2c2016-06-23 12:40:16 -07001122 return nullptr;
tsepez833619b2016-12-07 09:21:17 -08001123
Dan Sinclair1770c022016-03-14 14:14:16 -04001124 CCodec_ModuleMgr* pCodecMgr = pGeModule->GetCodecModule();
tsepez833619b2016-12-07 09:21:17 -08001125 if (!pCodecMgr)
dsinclair85d1f2c2016-06-23 12:40:16 -07001126 return nullptr;
tsepez833619b2016-12-07 09:21:17 -08001127
Dan Sinclair1770c022016-03-14 14:14:16 -04001128 CFX_DIBAttribute dibAttr;
Tom Sepezf0799fe2017-03-28 09:31:32 -07001129 CFX_RetainPtr<CFX_DIBitmap> pBitmap;
Tom Sepezb4a26182017-03-01 12:15:00 -08001130 std::unique_ptr<CCodec_ProgressiveDecoder> pProgressiveDecoder =
Dan Sinclair1770c022016-03-14 14:14:16 -04001131 pCodecMgr->CreateProgressiveDecoder();
dsinclair82e24b12016-06-13 13:46:49 -07001132 pProgressiveDecoder->LoadImageInfo(pImageFileRead, type, &dibAttr, false);
Dan Sinclair1770c022016-03-14 14:14:16 -04001133 switch (dibAttr.m_wDPIUnit) {
1134 case FXCODEC_RESUNIT_CENTIMETER:
1135 dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI * 2.54f);
1136 dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI * 2.54f);
1137 break;
1138 case FXCODEC_RESUNIT_METER:
Dan Sinclair05df0752017-03-14 14:43:42 -04001139 dibAttr.m_nXDPI = (int32_t)(dibAttr.m_nXDPI / (float)100 * 2.54f);
1140 dibAttr.m_nYDPI = (int32_t)(dibAttr.m_nYDPI / (float)100 * 2.54f);
Dan Sinclair1770c022016-03-14 14:14:16 -04001141 break;
1142 default:
1143 break;
1144 }
1145 iImageXDpi = dibAttr.m_nXDPI > 1 ? dibAttr.m_nXDPI : (96);
1146 iImageYDpi = dibAttr.m_nYDPI > 1 ? dibAttr.m_nYDPI : (96);
1147 if (pProgressiveDecoder->GetWidth() > 0 &&
1148 pProgressiveDecoder->GetHeight() > 0) {
1149 type = pProgressiveDecoder->GetType();
1150 int32_t iComponents = pProgressiveDecoder->GetNumComponents();
1151 int32_t iBpc = pProgressiveDecoder->GetBPC();
1152 FXDIB_Format dibFormat = XFA_GetDIBFormat(type, iComponents, iBpc);
Tom Sepezf0799fe2017-03-28 09:31:32 -07001153 pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
Dan Sinclair1770c022016-03-14 14:14:16 -04001154 pBitmap->Create(pProgressiveDecoder->GetWidth(),
1155 pProgressiveDecoder->GetHeight(), dibFormat);
1156 pBitmap->Clear(0xffffffff);
1157 int32_t nFrames;
1158 if ((pProgressiveDecoder->GetFrames(nFrames) ==
1159 FXCODEC_STATUS_DECODE_READY) &&
1160 (nFrames > 0)) {
1161 pProgressiveDecoder->StartDecode(pBitmap, 0, 0, pBitmap->GetWidth(),
1162 pBitmap->GetHeight());
1163 pProgressiveDecoder->ContinueDecode();
1164 }
1165 }
Dan Sinclair1770c022016-03-14 14:14:16 -04001166 return pBitmap;
1167}
Tom Sepezb4a26182017-03-01 12:15:00 -08001168
tsepezd19e9122016-11-02 15:43:18 -07001169void XFA_RectWidthoutMargin(CFX_RectF& rt, const CXFA_Margin& mg, bool bUI) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001170 if (!mg) {
1171 return;
1172 }
Dan Sinclair05df0752017-03-14 14:43:42 -04001173 float fLeftInset, fTopInset, fRightInset, fBottomInset;
Dan Sinclair1770c022016-03-14 14:14:16 -04001174 mg.GetLeftInset(fLeftInset);
1175 mg.GetTopInset(fTopInset);
1176 mg.GetRightInset(fRightInset);
1177 mg.GetBottomInset(fBottomInset);
1178 rt.Deflate(fLeftInset, fTopInset, fRightInset, fBottomInset);
1179}
1180CXFA_FFWidget* XFA_GetWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) {
dsinclair41cb62e2016-06-23 09:20:32 -07001181 if (XFA_IsCreateWidget(pLayoutItem->GetFormNode()->GetElementType()))
Dan Sinclair1770c022016-03-14 14:14:16 -04001182 return static_cast<CXFA_FFWidget*>(pLayoutItem);
Dan Sinclair1770c022016-03-14 14:14:16 -04001183 return nullptr;
1184}
tsepezd19e9122016-11-02 15:43:18 -07001185bool XFA_IsCreateWidget(XFA_Element eType) {
dsinclair41cb62e2016-06-23 09:20:32 -07001186 return eType == XFA_Element::Field || eType == XFA_Element::Draw ||
1187 eType == XFA_Element::Subform || eType == XFA_Element::ExclGroup;
Dan Sinclair1770c022016-03-14 14:14:16 -04001188}
1189static void XFA_BOX_GetPath_Arc(CXFA_Box box,
1190 CFX_RectF rtDraw,
1191 CFX_Path& fillPath,
tsepez736f28a2016-03-25 14:19:51 -07001192 uint32_t dwFlags) {
Dan Sinclair05df0752017-03-14 14:43:42 -04001193 float a, b;
Dan Sinclair1770c022016-03-14 14:14:16 -04001194 a = rtDraw.width / 2.0f;
1195 b = rtDraw.height / 2.0f;
1196 if (box.IsCircular() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) {
1197 a = b = std::min(a, b);
1198 }
1199 CFX_PointF center = rtDraw.Center();
1200 rtDraw.left = center.x - a;
1201 rtDraw.top = center.y - b;
1202 rtDraw.width = a + a;
1203 rtDraw.height = b + b;
Dan Sinclair05df0752017-03-14 14:43:42 -04001204 float startAngle = 0, sweepAngle = 360;
tsepezd19e9122016-11-02 15:43:18 -07001205 bool bStart = box.GetStartAngle(startAngle);
1206 bool bEnd = box.GetSweepAngle(sweepAngle);
Dan Sinclair1770c022016-03-14 14:14:16 -04001207 if (!bStart && !bEnd) {
1208 fillPath.AddEllipse(rtDraw);
1209 return;
1210 }
1211 startAngle = -startAngle * FX_PI / 180.0f;
1212 sweepAngle = -sweepAngle * FX_PI / 180.0f;
dan sinclairb147e072017-02-22 19:56:15 -05001213 fillPath.AddArc(rtDraw.TopLeft(), rtDraw.Size(), startAngle, sweepAngle);
Dan Sinclair1770c022016-03-14 14:14:16 -04001214}
dan sinclairb147e072017-02-22 19:56:15 -05001215
Dan Sinclair1770c022016-03-14 14:14:16 -04001216static void XFA_BOX_GetPath(CXFA_Box box,
tsepeza0b2d232017-01-23 11:32:36 -08001217 const std::vector<CXFA_Stroke>& strokes,
Dan Sinclair1770c022016-03-14 14:14:16 -04001218 CFX_RectF rtWidget,
1219 CFX_Path& path,
1220 int32_t nIndex,
tsepezd19e9122016-11-02 15:43:18 -07001221 bool bStart,
1222 bool bCorner) {
dsinclair43854a52016-04-27 12:26:00 -07001223 ASSERT(nIndex >= 0 && nIndex < 8);
Dan Sinclair1770c022016-03-14 14:14:16 -04001224 int32_t n = (nIndex & 1) ? nIndex - 1 : nIndex;
1225 CXFA_Corner corner1(strokes[n].GetNode());
1226 CXFA_Corner corner2(strokes[(n + 2) % 8].GetNode());
Dan Sinclair05df0752017-03-14 14:43:42 -04001227 float fRadius1 = bCorner ? corner1.GetRadius() : 0.0f;
1228 float fRadius2 = bCorner ? corner2.GetRadius() : 0.0f;
tsepezd19e9122016-11-02 15:43:18 -07001229 bool bInverted = corner1.IsInverted();
Dan Sinclair05df0752017-03-14 14:43:42 -04001230 float offsetY = 0.0f;
1231 float offsetX = 0.0f;
tsepezd19e9122016-11-02 15:43:18 -07001232 bool bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round;
Dan Sinclair05df0752017-03-14 14:43:42 -04001233 float halfAfter = 0.0f;
1234 float halfBefore = 0.0f;
Dan Sinclair1770c022016-03-14 14:14:16 -04001235 CXFA_Stroke stroke = strokes[nIndex];
1236 if (stroke.IsCorner()) {
1237 CXFA_Stroke edgeBefore = strokes[(nIndex + 1 * 8 - 1) % 8];
1238 CXFA_Stroke edgeAfter = strokes[nIndex + 1];
1239 if (stroke.IsInverted()) {
1240 if (!stroke.SameStyles(edgeBefore)) {
1241 halfBefore = edgeBefore.GetThickness() / 2;
1242 }
1243 if (!stroke.SameStyles(edgeAfter)) {
1244 halfAfter = edgeAfter.GetThickness() / 2;
1245 }
1246 }
1247 } else {
1248 CXFA_Stroke edgeBefore = strokes[(nIndex + 8 - 2) % 8];
1249 CXFA_Stroke edgeAfter = strokes[(nIndex + 2) % 8];
1250 if (!bRound && !bInverted) {
weili038aa532016-05-20 15:38:29 -07001251 halfBefore = edgeBefore.GetThickness() / 2;
1252 halfAfter = edgeAfter.GetThickness() / 2;
Dan Sinclair1770c022016-03-14 14:14:16 -04001253 }
1254 }
Dan Sinclair05df0752017-03-14 14:43:42 -04001255 float offsetEX = 0.0f;
1256 float offsetEY = 0.0f;
1257 float sx = 0.0f;
1258 float sy = 0.0f;
1259 float vx = 1.0f;
1260 float vy = 1.0f;
1261 float nx = 1.0f;
1262 float ny = 1.0f;
weili038aa532016-05-20 15:38:29 -07001263 CFX_PointF cpStart;
1264 CFX_PointF cp1;
1265 CFX_PointF cp2;
Dan Sinclair1770c022016-03-14 14:14:16 -04001266 if (bRound) {
1267 sy = FX_PI / 2;
1268 }
1269 switch (nIndex) {
1270 case 0:
1271 case 1:
1272 cp1 = rtWidget.TopLeft();
1273 cp2 = rtWidget.TopRight();
1274 if (nIndex == 0) {
1275 cpStart.x = cp1.x - halfBefore;
1276 cpStart.y = cp1.y + fRadius1, offsetY = -halfAfter;
1277 } else {
1278 cpStart.x = cp1.x + fRadius1 - halfBefore, cpStart.y = cp1.y,
1279 offsetEX = halfAfter;
1280 }
1281 vx = 1, vy = 1;
1282 nx = -1, ny = 0;
1283 if (bRound) {
1284 sx = bInverted ? FX_PI / 2 : FX_PI;
1285 } else {
1286 sx = 1, sy = 0;
1287 }
1288 break;
1289 case 2:
1290 case 3:
1291 cp1 = rtWidget.TopRight();
1292 cp2 = rtWidget.BottomRight();
1293 if (nIndex == 2) {
1294 cpStart.x = cp1.x - fRadius1, cpStart.y = cp1.y - halfBefore,
1295 offsetX = halfAfter;
1296 } else {
1297 cpStart.x = cp1.x, cpStart.y = cp1.y + fRadius1 - halfBefore,
1298 offsetEY = halfAfter;
1299 }
1300 vx = -1, vy = 1;
1301 nx = 0, ny = -1;
1302 if (bRound) {
1303 sx = bInverted ? FX_PI : FX_PI * 3 / 2;
1304 } else {
1305 sx = 0, sy = 1;
1306 }
1307 break;
1308 case 4:
1309 case 5:
1310 cp1 = rtWidget.BottomRight();
1311 cp2 = rtWidget.BottomLeft();
1312 if (nIndex == 4) {
1313 cpStart.x = cp1.x + halfBefore, cpStart.y = cp1.y - fRadius1,
1314 offsetY = halfAfter;
1315 } else {
1316 cpStart.x = cp1.x - fRadius1 + halfBefore, cpStart.y = cp1.y,
1317 offsetEX = -halfAfter;
1318 }
1319 vx = -1, vy = -1;
1320 nx = 1, ny = 0;
1321 if (bRound) {
1322 sx = bInverted ? FX_PI * 3 / 2 : 0;
1323 } else {
1324 sx = -1, sy = 0;
1325 }
1326 break;
1327 case 6:
1328 case 7:
1329 cp1 = rtWidget.BottomLeft();
1330 cp2 = rtWidget.TopLeft();
1331 if (nIndex == 6) {
1332 cpStart.x = cp1.x + fRadius1, cpStart.y = cp1.y + halfBefore,
1333 offsetX = -halfAfter;
1334 } else {
1335 cpStart.x = cp1.x, cpStart.y = cp1.y - fRadius1 + halfBefore,
1336 offsetEY = -halfAfter;
1337 }
dan sinclairb147e072017-02-22 19:56:15 -05001338 vx = 1;
1339 vy = -1;
1340 nx = 0;
1341 ny = 1;
Dan Sinclair1770c022016-03-14 14:14:16 -04001342 if (bRound) {
1343 sx = bInverted ? 0 : FX_PI / 2;
1344 } else {
dan sinclairb147e072017-02-22 19:56:15 -05001345 sx = 0;
1346 sy = -1;
Dan Sinclair1770c022016-03-14 14:14:16 -04001347 }
1348 break;
1349 }
1350 if (bStart) {
dan sinclairb147e072017-02-22 19:56:15 -05001351 path.MoveTo(cpStart);
Dan Sinclair1770c022016-03-14 14:14:16 -04001352 }
1353 if (nIndex & 1) {
dan sinclairb147e072017-02-22 19:56:15 -05001354 path.LineTo(CFX_PointF(cp2.x + fRadius2 * nx + offsetEX,
1355 cp2.y + fRadius2 * ny + offsetEY));
Dan Sinclair1770c022016-03-14 14:14:16 -04001356 return;
1357 }
1358 if (bRound) {
dan sinclairb147e072017-02-22 19:56:15 -05001359 if (fRadius1 < 0)
Dan Sinclair1770c022016-03-14 14:14:16 -04001360 sx -= FX_PI;
dan sinclairb147e072017-02-22 19:56:15 -05001361 if (bInverted)
Dan Sinclair1770c022016-03-14 14:14:16 -04001362 sy *= -1;
dan sinclairb147e072017-02-22 19:56:15 -05001363
Dan Sinclairbba2a7c2017-02-07 16:36:39 -05001364 CFX_RectF rtRadius(cp1.x + offsetX * 2, cp1.y + offsetY * 2,
1365 fRadius1 * 2 * vx - offsetX * 2,
1366 fRadius1 * 2 * vy - offsetY * 2);
Dan Sinclair1770c022016-03-14 14:14:16 -04001367 rtRadius.Normalize();
dan sinclairb147e072017-02-22 19:56:15 -05001368 if (bInverted)
Dan Sinclair1770c022016-03-14 14:14:16 -04001369 rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy);
dan sinclairb147e072017-02-22 19:56:15 -05001370
1371 path.ArcTo(rtRadius.TopLeft(), rtRadius.Size(), sx, sy);
Dan Sinclair1770c022016-03-14 14:14:16 -04001372 } else {
weili038aa532016-05-20 15:38:29 -07001373 CFX_PointF cp;
Dan Sinclair1770c022016-03-14 14:14:16 -04001374 if (bInverted) {
dan sinclairb147e072017-02-22 19:56:15 -05001375 cp.x = cp1.x + fRadius1 * vx;
1376 cp.y = cp1.y + fRadius1 * vy;
Dan Sinclair1770c022016-03-14 14:14:16 -04001377 } else {
1378 cp = cp1;
1379 }
dan sinclairb147e072017-02-22 19:56:15 -05001380 path.LineTo(cp);
1381 path.LineTo(CFX_PointF(cp1.x + fRadius1 * sx + offsetX,
1382 cp1.y + fRadius1 * sy + offsetY));
Dan Sinclair1770c022016-03-14 14:14:16 -04001383 }
1384}
1385static void XFA_BOX_GetFillPath(CXFA_Box box,
tsepeza0b2d232017-01-23 11:32:36 -08001386 const std::vector<CXFA_Stroke>& strokes,
Dan Sinclair1770c022016-03-14 14:14:16 -04001387 CFX_RectF rtWidget,
1388 CFX_Path& fillPath,
Tom Sepez62a70f92016-03-21 15:00:20 -07001389 uint16_t dwFlags) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001390 if (box.IsArc() || (dwFlags & XFA_DRAWBOX_ForceRound) != 0) {
1391 CXFA_Edge edge = box.GetEdge(0);
Dan Sinclair05df0752017-03-14 14:43:42 -04001392 float fThickness = edge.GetThickness();
Dan Sinclair1770c022016-03-14 14:14:16 -04001393 if (fThickness < 0) {
1394 fThickness = 0;
1395 }
Dan Sinclair05df0752017-03-14 14:43:42 -04001396 float fHalf = fThickness / 2;
Dan Sinclair1770c022016-03-14 14:14:16 -04001397 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 }
tsepezd19e9122016-11-02 15:43:18 -07001406 bool bSameStyles = true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001407 CXFA_Stroke stroke1 = strokes[0];
weilidb444d22016-06-02 15:48:15 -07001408 for (int32_t i = 1; i < 8; i++) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001409 CXFA_Stroke stroke2 = strokes[i];
1410 if (!stroke1.SameStyles(stroke2)) {
tsepezd19e9122016-11-02 15:43:18 -07001411 bSameStyles = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001412 break;
1413 }
1414 stroke1 = stroke2;
1415 }
1416 if (bSameStyles) {
1417 stroke1 = strokes[0];
weilidb444d22016-06-02 15:48:15 -07001418 for (int32_t i = 2; i < 8; i += 2) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001419 CXFA_Stroke stroke2 = strokes[i];
1420 if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence |
1421 XFA_STROKE_SAMESTYLE_Corner)) {
tsepezd19e9122016-11-02 15:43:18 -07001422 bSameStyles = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001423 break;
1424 }
1425 stroke1 = stroke2;
1426 }
1427 if (bSameStyles) {
1428 stroke1 = strokes[0];
1429 if (stroke1.IsInverted()) {
tsepezd19e9122016-11-02 15:43:18 -07001430 bSameStyles = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001431 }
1432 if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square) {
tsepezd19e9122016-11-02 15:43:18 -07001433 bSameStyles = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001434 }
1435 }
1436 }
1437 if (bSameStyles) {
1438 fillPath.AddRectangle(rtWidget.left, rtWidget.top, rtWidget.width,
1439 rtWidget.height);
1440 return;
1441 }
weili038aa532016-05-20 15:38:29 -07001442
Dan Sinclair1770c022016-03-14 14:14:16 -04001443 for (int32_t i = 0; i < 8; i += 2) {
Dan Sinclair05df0752017-03-14 14:43:42 -04001444 float sx = 0.0f;
1445 float sy = 0.0f;
1446 float vx = 1.0f;
1447 float vy = 1.0f;
1448 float nx = 1.0f;
1449 float ny = 1.0f;
weili038aa532016-05-20 15:38:29 -07001450 CFX_PointF cp1, cp2;
Dan Sinclair1770c022016-03-14 14:14:16 -04001451 CXFA_Corner corner1(strokes[i].GetNode());
1452 CXFA_Corner corner2(strokes[(i + 2) % 8].GetNode());
Dan Sinclair05df0752017-03-14 14:43:42 -04001453 float fRadius1 = corner1.GetRadius();
1454 float fRadius2 = corner2.GetRadius();
tsepezd19e9122016-11-02 15:43:18 -07001455 bool bInverted = corner1.IsInverted();
1456 bool bRound = corner1.GetJoinType() == XFA_ATTRIBUTEENUM_Round;
Dan Sinclair1770c022016-03-14 14:14:16 -04001457 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 {
dan sinclairb147e072017-02-22 19:56:15 -05001502 sx = 0;
1503 sy = -1;
Dan Sinclair1770c022016-03-14 14:14:16 -04001504 }
1505 break;
1506 }
dan sinclairb147e072017-02-22 19:56:15 -05001507 if (i == 0)
1508 fillPath.MoveTo(CFX_PointF(cp1.x, cp1.y + fRadius1));
1509
Dan Sinclair1770c022016-03-14 14:14:16 -04001510 if (bRound) {
dan sinclairb147e072017-02-22 19:56:15 -05001511 if (fRadius1 < 0)
Dan Sinclair1770c022016-03-14 14:14:16 -04001512 sx -= FX_PI;
dan sinclairb147e072017-02-22 19:56:15 -05001513 if (bInverted)
Dan Sinclair1770c022016-03-14 14:14:16 -04001514 sy *= -1;
dan sinclairb147e072017-02-22 19:56:15 -05001515
Dan Sinclairbba2a7c2017-02-07 16:36:39 -05001516 CFX_RectF rtRadius(cp1.x, cp1.y, fRadius1 * 2 * vx, fRadius1 * 2 * vy);
Dan Sinclair1770c022016-03-14 14:14:16 -04001517 rtRadius.Normalize();
dan sinclairb147e072017-02-22 19:56:15 -05001518 if (bInverted)
Dan Sinclair1770c022016-03-14 14:14:16 -04001519 rtRadius.Offset(-fRadius1 * vx, -fRadius1 * vy);
dan sinclairb147e072017-02-22 19:56:15 -05001520
1521 fillPath.ArcTo(rtRadius.TopLeft(), rtRadius.Size(), sx, sy);
Dan Sinclair1770c022016-03-14 14:14:16 -04001522 } else {
weili038aa532016-05-20 15:38:29 -07001523 CFX_PointF cp;
Dan Sinclair1770c022016-03-14 14:14:16 -04001524 if (bInverted) {
dan sinclairb147e072017-02-22 19:56:15 -05001525 cp.x = cp1.x + fRadius1 * vx;
1526 cp.y = cp1.y + fRadius1 * vy;
Dan Sinclair1770c022016-03-14 14:14:16 -04001527 } else {
1528 cp = cp1;
1529 }
dan sinclairb147e072017-02-22 19:56:15 -05001530 fillPath.LineTo(cp);
1531 fillPath.LineTo(CFX_PointF(cp1.x + fRadius1 * sx, cp1.y + fRadius1 * sy));
Dan Sinclair1770c022016-03-14 14:14:16 -04001532 }
dan sinclairb147e072017-02-22 19:56:15 -05001533 fillPath.LineTo(CFX_PointF(cp2.x + fRadius2 * nx, cp2.y + fRadius2 * ny));
Dan Sinclair1770c022016-03-14 14:14:16 -04001534 }
1535}
1536static void XFA_BOX_Fill_Radial(CXFA_Box box,
1537 CFX_Graphics* pGS,
1538 CFX_Path& fillPath,
1539 CFX_RectF rtFill,
1540 CFX_Matrix* pMatrix) {
1541 CXFA_Fill fill = box.GetFill();
1542 FX_ARGB crStart, crEnd;
1543 crStart = fill.GetColor();
1544 int32_t iType = fill.GetRadial(crEnd);
Dan Sinclair1770c022016-03-14 14:14:16 -04001545 if (iType != XFA_ATTRIBUTEENUM_ToEdge) {
1546 FX_ARGB temp = crEnd;
1547 crEnd = crStart;
1548 crStart = temp;
1549 }
Dan Sinclair811b8a42016-03-17 08:59:42 -04001550 CFX_Shading shading(rtFill.Center(), rtFill.Center(), 0,
Dan Sinclair669a4182017-04-03 14:51:45 -04001551 sqrt(rtFill.Width() * rtFill.Width() +
1552 rtFill.Height() * rtFill.Height()) /
Dan Sinclair811b8a42016-03-17 08:59:42 -04001553 2,
tsepezd19e9122016-11-02 15:43:18 -07001554 true, true, crStart, crEnd);
Dan Sinclair1770c022016-03-14 14:14:16 -04001555 CFX_Color cr(&shading);
1556 pGS->SetFillColor(&cr);
1557 pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
1558}
1559static void XFA_BOX_Fill_Pattern(CXFA_Box box,
1560 CFX_Graphics* pGS,
1561 CFX_Path& fillPath,
1562 CFX_RectF rtFill,
1563 CFX_Matrix* pMatrix) {
1564 CXFA_Fill fill = box.GetFill();
1565 FX_ARGB crStart, crEnd;
1566 crStart = fill.GetColor();
1567 int32_t iType = fill.GetPattern(crEnd);
Dan Sinclairb9c69ab2017-02-23 13:30:34 -05001568 FX_HatchStyle iHatch = FX_HatchStyle::Cross;
Dan Sinclair1770c022016-03-14 14:14:16 -04001569 switch (iType) {
1570 case XFA_ATTRIBUTEENUM_CrossDiagonal:
Dan Sinclairb9c69ab2017-02-23 13:30:34 -05001571 iHatch = FX_HatchStyle::DiagonalCross;
Dan Sinclair1770c022016-03-14 14:14:16 -04001572 break;
1573 case XFA_ATTRIBUTEENUM_DiagonalLeft:
Dan Sinclairb9c69ab2017-02-23 13:30:34 -05001574 iHatch = FX_HatchStyle::ForwardDiagonal;
Dan Sinclair1770c022016-03-14 14:14:16 -04001575 break;
1576 case XFA_ATTRIBUTEENUM_DiagonalRight:
Dan Sinclairb9c69ab2017-02-23 13:30:34 -05001577 iHatch = FX_HatchStyle::BackwardDiagonal;
Dan Sinclair1770c022016-03-14 14:14:16 -04001578 break;
1579 case XFA_ATTRIBUTEENUM_Horizontal:
Dan Sinclairb9c69ab2017-02-23 13:30:34 -05001580 iHatch = FX_HatchStyle::Horizontal;
Dan Sinclair1770c022016-03-14 14:14:16 -04001581 break;
1582 case XFA_ATTRIBUTEENUM_Vertical:
Dan Sinclairb9c69ab2017-02-23 13:30:34 -05001583 iHatch = FX_HatchStyle::Vertical;
Dan Sinclair1770c022016-03-14 14:14:16 -04001584 break;
1585 default:
1586 break;
1587 }
Dan Sinclair811b8a42016-03-17 08:59:42 -04001588
1589 CFX_Pattern pattern(iHatch, crEnd, crStart);
weili9b99ebf2016-08-22 13:37:04 -07001590 CFX_Color cr(&pattern, 0x0);
Dan Sinclair1770c022016-03-14 14:14:16 -04001591 pGS->SetFillColor(&cr);
1592 pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
1593}
1594static void XFA_BOX_Fill_Linear(CXFA_Box box,
1595 CFX_Graphics* pGS,
1596 CFX_Path& fillPath,
1597 CFX_RectF rtFill,
1598 CFX_Matrix* pMatrix) {
1599 CXFA_Fill fill = box.GetFill();
1600 FX_ARGB crStart = fill.GetColor();
1601 FX_ARGB crEnd;
1602 int32_t iType = fill.GetLinear(crEnd);
1603 CFX_PointF ptStart;
1604 CFX_PointF ptEnd;
1605 switch (iType) {
1606 case XFA_ATTRIBUTEENUM_ToRight:
1607 ptStart = CFX_PointF(rtFill.left, rtFill.top);
1608 ptEnd = CFX_PointF(rtFill.right(), rtFill.top);
1609 break;
1610 case XFA_ATTRIBUTEENUM_ToBottom:
1611 ptStart = CFX_PointF(rtFill.left, rtFill.top);
1612 ptEnd = CFX_PointF(rtFill.left, rtFill.bottom());
1613 break;
1614 case XFA_ATTRIBUTEENUM_ToLeft:
1615 ptStart = CFX_PointF(rtFill.right(), rtFill.top);
1616 ptEnd = CFX_PointF(rtFill.left, rtFill.top);
1617 break;
1618 case XFA_ATTRIBUTEENUM_ToTop:
1619 ptStart = CFX_PointF(rtFill.left, rtFill.bottom());
1620 ptEnd = CFX_PointF(rtFill.left, rtFill.top);
1621 break;
1622 default:
1623 break;
1624 }
tsepezd19e9122016-11-02 15:43:18 -07001625 CFX_Shading shading(ptStart, ptEnd, false, false, crStart, crEnd);
Dan Sinclair1770c022016-03-14 14:14:16 -04001626 CFX_Color cr(&shading);
1627 pGS->SetFillColor(&cr);
1628 pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
1629}
1630static void XFA_BOX_Fill(CXFA_Box box,
tsepeza0b2d232017-01-23 11:32:36 -08001631 const std::vector<CXFA_Stroke>& strokes,
Dan Sinclair1770c022016-03-14 14:14:16 -04001632 CFX_Graphics* pGS,
1633 const CFX_RectF& rtWidget,
1634 CFX_Matrix* pMatrix,
tsepez736f28a2016-03-25 14:19:51 -07001635 uint32_t dwFlags) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001636 CXFA_Fill fill = box.GetFill();
Dan Sinclairefcf3622017-02-23 13:29:56 -05001637 if (!fill || fill.GetPresence() != XFA_ATTRIBUTEENUM_Visible)
Dan Sinclair1770c022016-03-14 14:14:16 -04001638 return;
Dan Sinclairefcf3622017-02-23 13:29:56 -05001639
Dan Sinclair1770c022016-03-14 14:14:16 -04001640 pGS->SaveGraphState();
1641 CFX_Path fillPath;
Dan Sinclair1770c022016-03-14 14:14:16 -04001642 XFA_BOX_GetFillPath(box, strokes, rtWidget, fillPath,
1643 (dwFlags & XFA_DRAWBOX_ForceRound) != 0);
1644 fillPath.Close();
dsinclair56a8b192016-06-21 14:15:25 -07001645 XFA_Element eType = fill.GetFillType();
Dan Sinclair1770c022016-03-14 14:14:16 -04001646 switch (eType) {
dsinclair56a8b192016-06-21 14:15:25 -07001647 case XFA_Element::Radial:
Dan Sinclair1770c022016-03-14 14:14:16 -04001648 XFA_BOX_Fill_Radial(box, pGS, fillPath, rtWidget, pMatrix);
1649 break;
dsinclair56a8b192016-06-21 14:15:25 -07001650 case XFA_Element::Pattern:
Dan Sinclair1770c022016-03-14 14:14:16 -04001651 XFA_BOX_Fill_Pattern(box, pGS, fillPath, rtWidget, pMatrix);
1652 break;
dsinclair56a8b192016-06-21 14:15:25 -07001653 case XFA_Element::Linear:
Dan Sinclair1770c022016-03-14 14:14:16 -04001654 XFA_BOX_Fill_Linear(box, pGS, fillPath, rtWidget, pMatrix);
1655 break;
1656 default: {
1657 FX_ARGB cr;
dsinclair56a8b192016-06-21 14:15:25 -07001658 if (eType == XFA_Element::Stipple) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001659 int32_t iRate = fill.GetStipple(cr);
1660 if (iRate == 0) {
1661 iRate = 100;
1662 }
1663 int32_t a = 0;
1664 FX_COLORREF rgb;
1665 ArgbDecode(cr, a, rgb);
1666 cr = ArgbEncode(iRate * a / 100, rgb);
1667 } else {
1668 cr = fill.GetColor();
1669 }
1670 CFX_Color fillColor(cr);
1671 pGS->SetFillColor(&fillColor);
1672 pGS->FillPath(&fillPath, FXFILL_WINDING, pMatrix);
1673 } break;
1674 }
1675 pGS->RestoreGraphState();
1676}
1677static void XFA_BOX_StrokePath(CXFA_Stroke stroke,
1678 CFX_Path* pPath,
1679 CFX_Graphics* pGS,
1680 CFX_Matrix* pMatrix) {
1681 if (!stroke || !stroke.IsVisible()) {
1682 return;
1683 }
Dan Sinclair05df0752017-03-14 14:43:42 -04001684 float fThickness = stroke.GetThickness();
Dan Sinclair1770c022016-03-14 14:14:16 -04001685 if (fThickness < 0.001f) {
1686 return;
1687 }
1688 pGS->SaveGraphState();
1689 if (stroke.IsCorner() && fThickness > 2 * stroke.GetRadius()) {
1690 fThickness = 2 * stroke.GetRadius();
1691 }
tsepezd19e9122016-11-02 15:43:18 -07001692 pGS->SetLineWidth(fThickness, true);
Dan Sinclair1770c022016-03-14 14:14:16 -04001693 pGS->SetLineCap(CFX_GraphStateData::LineCapButt);
1694 XFA_StrokeTypeSetLineDash(pGS, stroke.GetStrokeType(),
1695 XFA_ATTRIBUTEENUM_Butt);
1696 CFX_Color fxColor(stroke.GetColor());
1697 pGS->SetStrokeColor(&fxColor);
1698 pGS->StrokePath(pPath, pMatrix);
1699 pGS->RestoreGraphState();
1700}
1701static void XFA_BOX_StrokeArc(CXFA_Box box,
1702 CFX_Graphics* pGS,
1703 CFX_RectF rtWidget,
1704 CFX_Matrix* pMatrix,
tsepez736f28a2016-03-25 14:19:51 -07001705 uint32_t dwFlags) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001706 CXFA_Edge edge = box.GetEdge(0);
1707 if (!edge || !edge.IsVisible()) {
1708 return;
1709 }
tsepezd19e9122016-11-02 15:43:18 -07001710 bool bVisible = false;
Dan Sinclair05df0752017-03-14 14:43:42 -04001711 float fThickness = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001712 int32_t i3DType = box.Get3DStyle(bVisible, fThickness);
1713 if (i3DType) {
1714 if (bVisible && fThickness >= 0.001f) {
1715 dwFlags |= XFA_DRAWBOX_Lowered3D;
1716 }
1717 }
Dan Sinclair05df0752017-03-14 14:43:42 -04001718 float fHalf = edge.GetThickness() / 2;
Dan Sinclair1770c022016-03-14 14:14:16 -04001719 if (fHalf < 0) {
1720 fHalf = 0;
1721 }
1722 int32_t iHand = box.GetHand();
1723 if (iHand == XFA_ATTRIBUTEENUM_Left) {
1724 rtWidget.Inflate(fHalf, fHalf);
1725 } else if (iHand == XFA_ATTRIBUTEENUM_Right) {
1726 rtWidget.Deflate(fHalf, fHalf);
1727 }
1728 if ((dwFlags & XFA_DRAWBOX_ForceRound) == 0 ||
1729 (dwFlags & XFA_DRAWBOX_Lowered3D) == 0) {
Dan Sinclairefcf3622017-02-23 13:29:56 -05001730 if (fHalf < 0.001f)
Dan Sinclair1770c022016-03-14 14:14:16 -04001731 return;
Dan Sinclairefcf3622017-02-23 13:29:56 -05001732
Dan Sinclair1770c022016-03-14 14:14:16 -04001733 CFX_Path arcPath;
Dan Sinclair1770c022016-03-14 14:14:16 -04001734 XFA_BOX_GetPath_Arc(box, rtWidget, arcPath, dwFlags);
1735 XFA_BOX_StrokePath(edge, &arcPath, pGS, pMatrix);
1736 return;
1737 }
1738 pGS->SaveGraphState();
1739 pGS->SetLineWidth(fHalf);
dan sinclairb147e072017-02-22 19:56:15 -05001740
Dan Sinclair05df0752017-03-14 14:43:42 -04001741 float a, b;
Dan Sinclair1770c022016-03-14 14:14:16 -04001742 a = rtWidget.width / 2.0f;
1743 b = rtWidget.height / 2.0f;
1744 if (dwFlags & XFA_DRAWBOX_ForceRound) {
dan sinclairb147e072017-02-22 19:56:15 -05001745 a = std::min(a, b);
1746 b = a;
Dan Sinclair1770c022016-03-14 14:14:16 -04001747 }
dan sinclairb147e072017-02-22 19:56:15 -05001748
Dan Sinclair1770c022016-03-14 14:14:16 -04001749 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;
dan sinclairb147e072017-02-22 19:56:15 -05001754
Dan Sinclair05df0752017-03-14 14:43:42 -04001755 float startAngle = 0, sweepAngle = 360;
Dan Sinclair1770c022016-03-14 14:14:16 -04001756 startAngle = startAngle * FX_PI / 180.0f;
1757 sweepAngle = -sweepAngle * FX_PI / 180.0f;
dan sinclairb147e072017-02-22 19:56:15 -05001758
Dan Sinclair1770c022016-03-14 14:14:16 -04001759 CFX_Path arcPath;
dan sinclairb147e072017-02-22 19:56:15 -05001760 arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), 3.0f * FX_PI / 4.0f,
1761 FX_PI);
1762
Dan Sinclair1770c022016-03-14 14:14:16 -04001763 CFX_Color cr(0xFF808080);
1764 pGS->SetStrokeColor(&cr);
1765 pGS->StrokePath(&arcPath, pMatrix);
1766 arcPath.Clear();
dan sinclairb147e072017-02-22 19:56:15 -05001767 arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), -1.0f * FX_PI / 4.0f,
1768 FX_PI);
1769
Dan Sinclair1770c022016-03-14 14:14:16 -04001770 cr.Set(0xFFFFFFFF);
1771 pGS->SetStrokeColor(&cr);
1772 pGS->StrokePath(&arcPath, pMatrix);
1773 rtWidget.Deflate(fHalf, fHalf);
1774 arcPath.Clear();
dan sinclairb147e072017-02-22 19:56:15 -05001775 arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), 3.0f * FX_PI / 4.0f,
1776 FX_PI);
1777
Dan Sinclair1770c022016-03-14 14:14:16 -04001778 cr.Set(0xFF404040);
1779 pGS->SetStrokeColor(&cr);
1780 pGS->StrokePath(&arcPath, pMatrix);
1781 arcPath.Clear();
dan sinclairb147e072017-02-22 19:56:15 -05001782 arcPath.AddArc(rtWidget.TopLeft(), rtWidget.Size(), -1.0f * FX_PI / 4.0f,
1783 FX_PI);
1784
Dan Sinclair1770c022016-03-14 14:14:16 -04001785 cr.Set(0xFFC0C0C0);
1786 pGS->SetStrokeColor(&cr);
1787 pGS->StrokePath(&arcPath, pMatrix);
1788 pGS->RestoreGraphState();
1789}
1790static void XFA_Draw3DRect(CFX_Graphics* pGraphic,
1791 const CFX_RectF& rt,
Dan Sinclair05df0752017-03-14 14:43:42 -04001792 float fLineWidth,
Dan Sinclair1770c022016-03-14 14:14:16 -04001793 CFX_Matrix* pMatrix,
1794 FX_ARGB argbTopLeft,
1795 FX_ARGB argbBottomRight) {
1796 CFX_Color crLT(argbTopLeft);
1797 pGraphic->SetFillColor(&crLT);
Dan Sinclair05df0752017-03-14 14:43:42 -04001798 float fBottom = rt.bottom();
1799 float fRight = rt.right();
Dan Sinclair1770c022016-03-14 14:14:16 -04001800 CFX_Path pathLT;
dan sinclairb147e072017-02-22 19:56:15 -05001801 pathLT.MoveTo(CFX_PointF(rt.left, fBottom));
1802 pathLT.LineTo(CFX_PointF(rt.left, rt.top));
1803 pathLT.LineTo(CFX_PointF(fRight, rt.top));
1804 pathLT.LineTo(CFX_PointF(fRight - fLineWidth, rt.top + fLineWidth));
1805 pathLT.LineTo(CFX_PointF(rt.left + fLineWidth, rt.top + fLineWidth));
1806 pathLT.LineTo(CFX_PointF(rt.left + fLineWidth, fBottom - fLineWidth));
1807 pathLT.LineTo(CFX_PointF(rt.left, fBottom));
Dan Sinclair1770c022016-03-14 14:14:16 -04001808 pGraphic->FillPath(&pathLT, FXFILL_WINDING, pMatrix);
dan sinclairb147e072017-02-22 19:56:15 -05001809
Dan Sinclair1770c022016-03-14 14:14:16 -04001810 CFX_Color crRB(argbBottomRight);
1811 pGraphic->SetFillColor(&crRB);
dan sinclairb147e072017-02-22 19:56:15 -05001812
Dan Sinclair1770c022016-03-14 14:14:16 -04001813 CFX_Path pathRB;
dan sinclairb147e072017-02-22 19:56:15 -05001814 pathRB.MoveTo(CFX_PointF(fRight, rt.top));
1815 pathRB.LineTo(CFX_PointF(fRight, fBottom));
1816 pathRB.LineTo(CFX_PointF(rt.left, fBottom));
1817 pathRB.LineTo(CFX_PointF(rt.left + fLineWidth, fBottom - fLineWidth));
1818 pathRB.LineTo(CFX_PointF(fRight - fLineWidth, fBottom - fLineWidth));
1819 pathRB.LineTo(CFX_PointF(fRight - fLineWidth, rt.top + fLineWidth));
1820 pathRB.LineTo(CFX_PointF(fRight, rt.top));
Dan Sinclair1770c022016-03-14 14:14:16 -04001821 pGraphic->FillPath(&pathRB, FXFILL_WINDING, pMatrix);
1822}
1823static void XFA_BOX_Stroke_3DRect_Lowered(CFX_Graphics* pGS,
1824 CFX_RectF rt,
Dan Sinclair05df0752017-03-14 14:43:42 -04001825 float fThickness,
Dan Sinclair1770c022016-03-14 14:14:16 -04001826 CFX_Matrix* pMatrix) {
Dan Sinclair05df0752017-03-14 14:43:42 -04001827 float fHalfWidth = fThickness / 2.0f;
Dan Sinclair1770c022016-03-14 14:14:16 -04001828 CFX_RectF rtInner(rt);
1829 rtInner.Deflate(fHalfWidth, fHalfWidth);
1830 CFX_Color cr(0xFF000000);
1831 pGS->SetFillColor(&cr);
1832 CFX_Path path;
Dan Sinclair1770c022016-03-14 14:14:16 -04001833 path.AddRectangle(rt.left, rt.top, rt.width, rt.height);
1834 path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height);
1835 pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix);
1836 XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF808080, 0xFFC0C0C0);
1837}
1838static void XFA_BOX_Stroke_3DRect_Raised(CFX_Graphics* pGS,
1839 CFX_RectF rt,
Dan Sinclair05df0752017-03-14 14:43:42 -04001840 float fThickness,
Dan Sinclair1770c022016-03-14 14:14:16 -04001841 CFX_Matrix* pMatrix) {
Dan Sinclair05df0752017-03-14 14:43:42 -04001842 float fHalfWidth = fThickness / 2.0f;
Dan Sinclair1770c022016-03-14 14:14:16 -04001843 CFX_RectF rtInner(rt);
1844 rtInner.Deflate(fHalfWidth, fHalfWidth);
1845 CFX_Color cr(0xFF000000);
1846 pGS->SetFillColor(&cr);
1847 CFX_Path path;
Dan Sinclair1770c022016-03-14 14:14:16 -04001848 path.AddRectangle(rt.left, rt.top, rt.width, rt.height);
1849 path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height);
1850 pGS->FillPath(&path, FXFILL_ALTERNATE, pMatrix);
1851 XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080);
1852}
1853static void XFA_BOX_Stroke_3DRect_Etched(CFX_Graphics* pGS,
1854 CFX_RectF rt,
Dan Sinclair05df0752017-03-14 14:43:42 -04001855 float fThickness,
Dan Sinclair1770c022016-03-14 14:14:16 -04001856 CFX_Matrix* pMatrix) {
Dan Sinclair05df0752017-03-14 14:43:42 -04001857 float fHalfWidth = fThickness / 2.0f;
Dan Sinclair1770c022016-03-14 14:14:16 -04001858 XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFFFFFFFF);
1859 CFX_RectF rtInner(rt);
1860 rtInner.Deflate(fHalfWidth, fHalfWidth);
1861 XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFFFFFFFF, 0xFF808080);
1862}
1863static void XFA_BOX_Stroke_3DRect_Embossed(CFX_Graphics* pGS,
1864 CFX_RectF rt,
Dan Sinclair05df0752017-03-14 14:43:42 -04001865 float fThickness,
Dan Sinclair1770c022016-03-14 14:14:16 -04001866 CFX_Matrix* pMatrix) {
Dan Sinclair05df0752017-03-14 14:43:42 -04001867 float fHalfWidth = fThickness / 2.0f;
Dan Sinclair1770c022016-03-14 14:14:16 -04001868 XFA_Draw3DRect(pGS, rt, fThickness, pMatrix, 0xFF808080, 0xFF000000);
1869 CFX_RectF rtInner(rt);
1870 rtInner.Deflate(fHalfWidth, fHalfWidth);
1871 XFA_Draw3DRect(pGS, rtInner, fHalfWidth, pMatrix, 0xFF000000, 0xFF808080);
1872}
1873static void XFA_BOX_Stroke_Rect(CXFA_Box box,
tsepeza0b2d232017-01-23 11:32:36 -08001874 const std::vector<CXFA_Stroke>& strokes,
Dan Sinclair1770c022016-03-14 14:14:16 -04001875 CFX_Graphics* pGS,
1876 CFX_RectF rtWidget,
1877 CFX_Matrix* pMatrix) {
tsepezd19e9122016-11-02 15:43:18 -07001878 bool bVisible = false;
Dan Sinclair05df0752017-03-14 14:43:42 -04001879 float fThickness = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001880 int32_t i3DType = box.Get3DStyle(bVisible, fThickness);
1881 if (i3DType) {
1882 if (!bVisible || fThickness < 0.001f) {
1883 return;
1884 }
1885 switch (i3DType) {
1886 case XFA_ATTRIBUTEENUM_Lowered:
1887 XFA_BOX_Stroke_3DRect_Lowered(pGS, rtWidget, fThickness, pMatrix);
1888 break;
1889 case XFA_ATTRIBUTEENUM_Raised:
1890 XFA_BOX_Stroke_3DRect_Raised(pGS, rtWidget, fThickness, pMatrix);
1891 break;
1892 case XFA_ATTRIBUTEENUM_Etched:
1893 XFA_BOX_Stroke_3DRect_Etched(pGS, rtWidget, fThickness, pMatrix);
1894 break;
1895 case XFA_ATTRIBUTEENUM_Embossed:
1896 XFA_BOX_Stroke_3DRect_Embossed(pGS, rtWidget, fThickness, pMatrix);
1897 break;
1898 }
1899 return;
1900 }
tsepezd19e9122016-11-02 15:43:18 -07001901 bool bClose = false;
1902 bool bSameStyles = true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001903 CXFA_Stroke stroke1 = strokes[0];
weilidb444d22016-06-02 15:48:15 -07001904 for (int32_t i = 1; i < 8; i++) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001905 CXFA_Stroke stroke2 = strokes[i];
1906 if (!stroke1.SameStyles(stroke2)) {
tsepezd19e9122016-11-02 15:43:18 -07001907 bSameStyles = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001908 break;
1909 }
1910 stroke1 = stroke2;
1911 }
1912 if (bSameStyles) {
1913 stroke1 = strokes[0];
tsepezd19e9122016-11-02 15:43:18 -07001914 bClose = true;
weilidb444d22016-06-02 15:48:15 -07001915 for (int32_t i = 2; i < 8; i += 2) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001916 CXFA_Stroke stroke2 = strokes[i];
1917 if (!stroke1.SameStyles(stroke2, XFA_STROKE_SAMESTYLE_NoPresence |
1918 XFA_STROKE_SAMESTYLE_Corner)) {
tsepezd19e9122016-11-02 15:43:18 -07001919 bSameStyles = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001920 break;
1921 }
1922 stroke1 = stroke2;
1923 }
1924 if (bSameStyles) {
1925 stroke1 = strokes[0];
Dan Sinclairefcf3622017-02-23 13:29:56 -05001926 if (stroke1.IsInverted())
tsepezd19e9122016-11-02 15:43:18 -07001927 bSameStyles = false;
Dan Sinclairefcf3622017-02-23 13:29:56 -05001928 if (stroke1.GetJoinType() != XFA_ATTRIBUTEENUM_Square)
tsepezd19e9122016-11-02 15:43:18 -07001929 bSameStyles = false;
Dan Sinclair1770c022016-03-14 14:14:16 -04001930 }
1931 }
tsepezd19e9122016-11-02 15:43:18 -07001932 bool bStart = true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001933 CFX_Path path;
weilidb444d22016-06-02 15:48:15 -07001934 for (int32_t i = 0; i < 8; i++) {
1935 CXFA_Stroke stroke = strokes[i];
1936 if ((i % 1) == 0 && stroke.GetRadius() < 0) {
tsepezd19e9122016-11-02 15:43:18 -07001937 bool bEmpty = path.IsEmpty();
Dan Sinclair1770c022016-03-14 14:14:16 -04001938 if (!bEmpty) {
weilidb444d22016-06-02 15:48:15 -07001939 XFA_BOX_StrokePath(stroke, &path, pGS, pMatrix);
Dan Sinclair1770c022016-03-14 14:14:16 -04001940 path.Clear();
1941 }
tsepezd19e9122016-11-02 15:43:18 -07001942 bStart = true;
Dan Sinclair1770c022016-03-14 14:14:16 -04001943 continue;
1944 }
1945 XFA_BOX_GetPath(box, strokes, rtWidget, path, i, bStart, !bSameStyles);
1946 CXFA_Stroke stroke2 = strokes[(i + 1) % 8];
weilidb444d22016-06-02 15:48:15 -07001947 bStart = !stroke.SameStyles(stroke2);
Dan Sinclair1770c022016-03-14 14:14:16 -04001948 if (bStart) {
weilidb444d22016-06-02 15:48:15 -07001949 XFA_BOX_StrokePath(stroke, &path, pGS, pMatrix);
Dan Sinclair1770c022016-03-14 14:14:16 -04001950 path.Clear();
1951 }
1952 }
tsepezd19e9122016-11-02 15:43:18 -07001953 bool bEmpty = path.IsEmpty();
Dan Sinclair1770c022016-03-14 14:14:16 -04001954 if (!bEmpty) {
1955 if (bClose) {
1956 path.Close();
1957 }
1958 XFA_BOX_StrokePath(strokes[7], &path, pGS, pMatrix);
1959 }
1960}
1961static void XFA_BOX_Stroke(CXFA_Box box,
tsepeza0b2d232017-01-23 11:32:36 -08001962 const std::vector<CXFA_Stroke>& strokes,
Dan Sinclair1770c022016-03-14 14:14:16 -04001963 CFX_Graphics* pGS,
1964 CFX_RectF rtWidget,
1965 CFX_Matrix* pMatrix,
tsepez736f28a2016-03-25 14:19:51 -07001966 uint32_t dwFlags) {
Dan Sinclair1770c022016-03-14 14:14:16 -04001967 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());
Dan Sinclair05df0752017-03-14 14:43:42 -04001983 float fThickness = edge.GetThickness();
Dan Sinclair1770c022016-03-14 14:14:16 -04001984 if (fThickness < 0) {
1985 fThickness = 0;
1986 }
Dan Sinclair05df0752017-03-14 14:43:42 -04001987 float fHalf = fThickness / 2;
Dan Sinclair1770c022016-03-14 14:14:16 -04001988 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}
2026void XFA_DrawBox(CXFA_Box box,
2027 CFX_Graphics* pGS,
2028 const CFX_RectF& rtWidget,
2029 CFX_Matrix* pMatrix,
tsepez736f28a2016-03-25 14:19:51 -07002030 uint32_t dwFlags) {
dsinclair56a8b192016-06-21 14:15:25 -07002031 if (!box || box.GetPresence() != XFA_ATTRIBUTEENUM_Visible)
Dan Sinclair1770c022016-03-14 14:14:16 -04002032 return;
dsinclair56a8b192016-06-21 14:15:25 -07002033
dsinclair41cb62e2016-06-23 09:20:32 -07002034 XFA_Element eType = box.GetElementType();
2035 if (eType != XFA_Element::Arc && eType != XFA_Element::Border &&
2036 eType != XFA_Element::Rectangle) {
Dan Sinclair1770c022016-03-14 14:14:16 -04002037 return;
2038 }
tsepeza0b2d232017-01-23 11:32:36 -08002039 std::vector<CXFA_Stroke> strokes;
2040 if (!(dwFlags & XFA_DRAWBOX_ForceRound) && eType != XFA_Element::Arc)
2041 box.GetStrokes(&strokes);
2042
Dan Sinclair1770c022016-03-14 14:14:16 -04002043 XFA_BOX_Fill(box, strokes, pGS, rtWidget, pMatrix, dwFlags);
2044 XFA_BOX_Stroke(box, strokes, pGS, rtWidget, pMatrix, dwFlags);
2045}
weili47bcd4c2016-06-16 08:00:06 -07002046
2047CXFA_CalcData::CXFA_CalcData() : m_iRefCount(0) {}
2048
Tom Sepez51d02b32017-01-30 14:49:24 -08002049CXFA_CalcData::~CXFA_CalcData() {}