1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "xfa/fxfa/cxfa_fwltheme.h"
8
9 #include "core/fxcrt/fx_codepage.h"
10 #include "xfa/fde/cfde_textout.h"
11 #include "xfa/fgas/font/cfgas_gefont.h"
12 #include "xfa/fwl/cfwl_barcode.h"
13 #include "xfa/fwl/cfwl_caret.h"
14 #include "xfa/fwl/cfwl_checkbox.h"
15 #include "xfa/fwl/cfwl_combobox.h"
16 #include "xfa/fwl/cfwl_datetimepicker.h"
17 #include "xfa/fwl/cfwl_edit.h"
18 #include "xfa/fwl/cfwl_listbox.h"
19 #include "xfa/fwl/cfwl_monthcalendar.h"
20 #include "xfa/fwl/cfwl_picturebox.h"
21 #include "xfa/fwl/cfwl_pushbutton.h"
22 #include "xfa/fwl/cfwl_scrollbar.h"
23 #include "xfa/fwl/cfwl_themebackground.h"
24 #include "xfa/fwl/cfwl_themetext.h"
25 #include "xfa/fxfa/cxfa_ffapp.h"
26 #include "xfa/fxfa/cxfa_ffwidget.h"
27 #include "xfa/fxfa/parser/cxfa_para.h"
28 #include "xfa/fxgraphics/cxfa_gecolor.h"
29
30 namespace {
31
32 const wchar_t* const g_FWLTheme_CalFonts[] = {
33 L"Arial", L"Courier New", L"DejaVu Sans",
34 };
35
36 const float kLineHeight = 12.0f;
37
38 } // namespace
39
XFA_ThemeGetOuterWidget(CFWL_Widget * pWidget)40 CXFA_FFWidget* XFA_ThemeGetOuterWidget(CFWL_Widget* pWidget) {
41 CFWL_Widget* pOuter = pWidget;
42 while (pOuter && pOuter->GetOuter())
43 pOuter = pOuter->GetOuter();
44 return pOuter ? pOuter->GetLayoutItem() : nullptr;
45 }
46
CXFA_FWLTheme(CXFA_FFApp * pApp)47 CXFA_FWLTheme::CXFA_FWLTheme(CXFA_FFApp* pApp)
48 : m_pCheckBoxTP(pdfium::MakeUnique<CFWL_CheckBoxTP>()),
49 m_pListBoxTP(pdfium::MakeUnique<CFWL_ListBoxTP>()),
50 m_pPictureBoxTP(pdfium::MakeUnique<CFWL_PictureBoxTP>()),
51 m_pSrollBarTP(pdfium::MakeUnique<CFWL_ScrollBarTP>()),
52 m_pEditTP(pdfium::MakeUnique<CFWL_EditTP>()),
53 m_pComboBoxTP(pdfium::MakeUnique<CFWL_ComboBoxTP>()),
54 m_pMonthCalendarTP(pdfium::MakeUnique<CFWL_MonthCalendarTP>()),
55 m_pDateTimePickerTP(pdfium::MakeUnique<CFWL_DateTimePickerTP>()),
56 m_pPushButtonTP(pdfium::MakeUnique<CFWL_PushButtonTP>()),
57 m_pCaretTP(pdfium::MakeUnique<CFWL_CaretTP>()),
58 m_pBarcodeTP(pdfium::MakeUnique<CFWL_BarcodeTP>()),
59 m_pTextOut(pdfium::MakeUnique<CFDE_TextOut>()),
60 m_pCalendarFont(nullptr),
61 m_pApp(pApp) {
62 m_Rect.Reset();
63
64 for (size_t i = 0; !m_pCalendarFont && i < FX_ArraySize(g_FWLTheme_CalFonts);
65 ++i) {
66 m_pCalendarFont = CFGAS_GEFont::LoadFont(g_FWLTheme_CalFonts[i], 0, 0,
67 m_pApp->GetFDEFontMgr());
68 }
69 if (!m_pCalendarFont) {
70 m_pCalendarFont = m_pApp->GetFDEFontMgr()->GetFontByCodePage(
71 FX_CODEPAGE_MSWin_WesternEuropean, 0, nullptr);
72 }
73
74 ASSERT(m_pCalendarFont);
75 }
76
~CXFA_FWLTheme()77 CXFA_FWLTheme::~CXFA_FWLTheme() {
78 m_pTextOut.reset();
79 FWLTHEME_Release();
80 }
81
DrawBackground(CFWL_ThemeBackground * pParams)82 void CXFA_FWLTheme::DrawBackground(CFWL_ThemeBackground* pParams) {
83 GetTheme(pParams->m_pWidget)->DrawBackground(pParams);
84 }
85
DrawText(CFWL_ThemeText * pParams)86 void CXFA_FWLTheme::DrawText(CFWL_ThemeText* pParams) {
87 if (pParams->m_wsText.IsEmpty())
88 return;
89
90 if (pParams->m_pWidget->GetClassID() == FWL_Type::MonthCalendar) {
91 CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget);
92 if (!pWidget)
93 return;
94
95 m_pTextOut->SetStyles(pParams->m_dwTTOStyles);
96 m_pTextOut->SetAlignment(pParams->m_iTTOAlign);
97 m_pTextOut->SetFont(m_pCalendarFont);
98 m_pTextOut->SetFontSize(FWLTHEME_CAPACITY_FontSize);
99 m_pTextOut->SetTextColor(FWLTHEME_CAPACITY_TextColor);
100 if ((pParams->m_iPart == CFWL_Part::DatesIn) &&
101 !(pParams->m_dwStates & FWL_ITEMSTATE_MCD_Flag) &&
102 (pParams->m_dwStates &
103 (CFWL_PartState_Hovered | CFWL_PartState_Selected))) {
104 m_pTextOut->SetTextColor(0xFFFFFFFF);
105 }
106 if (pParams->m_iPart == CFWL_Part::Caption)
107 m_pTextOut->SetTextColor(ArgbEncode(0xff, 0, 153, 255));
108
109 CXFA_Graphics* pGraphics = pParams->m_pGraphics;
110 CFX_RenderDevice* pRenderDevice = pGraphics->GetRenderDevice();
111 if (!pRenderDevice)
112 return;
113
114 CFX_Matrix mtPart = pParams->m_matrix;
115 const CFX_Matrix* pMatrix = pGraphics->GetMatrix();
116 if (pMatrix)
117 mtPart.Concat(*pMatrix);
118
119 m_pTextOut->SetMatrix(mtPart);
120 m_pTextOut->DrawLogicText(pRenderDevice, pParams->m_wsText.AsStringView(),
121 pParams->m_rtPart);
122 return;
123 }
124 CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget);
125 if (!pWidget)
126 return;
127
128 CXFA_Node* pNode = pWidget->GetNode();
129 CXFA_Graphics* pGraphics = pParams->m_pGraphics;
130 CFX_RenderDevice* pRenderDevice = pGraphics->GetRenderDevice();
131 if (!pRenderDevice)
132 return;
133
134 m_pTextOut->SetStyles(pParams->m_dwTTOStyles);
135 m_pTextOut->SetAlignment(pParams->m_iTTOAlign);
136 m_pTextOut->SetFont(pNode->GetWidgetAcc()->GetFDEFont(pWidget->GetDoc()));
137 m_pTextOut->SetFontSize(pNode->GetFontSize());
138 m_pTextOut->SetTextColor(pNode->GetTextColor());
139 CFX_Matrix mtPart = pParams->m_matrix;
140 const CFX_Matrix* pMatrix = pGraphics->GetMatrix();
141 if (pMatrix)
142 mtPart.Concat(*pMatrix);
143
144 m_pTextOut->SetMatrix(mtPart);
145 m_pTextOut->DrawLogicText(pRenderDevice, pParams->m_wsText.AsStringView(),
146 pParams->m_rtPart);
147 }
148
GetUIMargin(CFWL_ThemePart * pThemePart) const149 CFX_RectF CXFA_FWLTheme::GetUIMargin(CFWL_ThemePart* pThemePart) const {
150 CFX_RectF rect;
151 CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget);
152 if (!pWidget)
153 return rect;
154
155 CXFA_LayoutItem* pItem = pWidget;
156 CXFA_WidgetAcc* pWidgetAcc = pWidget->GetNode()->GetWidgetAcc();
157 rect = pWidgetAcc->GetUIMargin();
158 CXFA_Para* para = pWidgetAcc->GetNode()->GetParaIfExists();
159 if (para) {
160 rect.left += para->GetMarginLeft();
161 if (pWidgetAcc->IsMultiLine())
162 rect.width += para->GetMarginRight();
163 }
164 if (!pItem->GetPrev()) {
165 if (pItem->GetNext())
166 rect.height = 0;
167 } else if (!pItem->GetNext()) {
168 rect.top = 0;
169 } else {
170 rect.top = 0;
171 rect.height = 0;
172 }
173 return rect;
174 }
175
GetCXBorderSize() const176 float CXFA_FWLTheme::GetCXBorderSize() const {
177 return 1.0f;
178 }
179
GetCYBorderSize() const180 float CXFA_FWLTheme::GetCYBorderSize() const {
181 return 1.0f;
182 }
183
GetFontSize(CFWL_ThemePart * pThemePart) const184 float CXFA_FWLTheme::GetFontSize(CFWL_ThemePart* pThemePart) const {
185 if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget))
186 return pWidget->GetNode()->GetFontSize();
187 return FWLTHEME_CAPACITY_FontSize;
188 }
189
GetFont(CFWL_ThemePart * pThemePart) const190 RetainPtr<CFGAS_GEFont> CXFA_FWLTheme::GetFont(
191 CFWL_ThemePart* pThemePart) const {
192 if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget))
193 return pWidget->GetNode()->GetWidgetAcc()->GetFDEFont(pWidget->GetDoc());
194 return GetTheme(pThemePart->m_pWidget)->GetFont();
195 }
196
GetLineHeight(CFWL_ThemePart * pThemePart) const197 float CXFA_FWLTheme::GetLineHeight(CFWL_ThemePart* pThemePart) const {
198 if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget))
199 return pWidget->GetNode()->GetLineHeight();
200 return kLineHeight;
201 }
202
GetScrollBarWidth() const203 float CXFA_FWLTheme::GetScrollBarWidth() const {
204 return 9.0f;
205 }
206
GetTextColor(CFWL_ThemePart * pThemePart) const207 FX_COLORREF CXFA_FWLTheme::GetTextColor(CFWL_ThemePart* pThemePart) const {
208 if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget))
209 return pWidget->GetNode()->GetTextColor();
210 return FWLTHEME_CAPACITY_TextColor;
211 }
212
GetSpaceAboveBelow(CFWL_ThemePart * pThemePart) const213 CFX_SizeF CXFA_FWLTheme::GetSpaceAboveBelow(CFWL_ThemePart* pThemePart) const {
214 CFX_SizeF sizeAboveBelow;
215 if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart->m_pWidget)) {
216 CXFA_Para* para = pWidget->GetNode()->GetParaIfExists();
217 if (para) {
218 sizeAboveBelow.width = para->GetSpaceAbove();
219 sizeAboveBelow.height = para->GetSpaceBelow();
220 }
221 }
222 return sizeAboveBelow;
223 }
224
CalcTextRect(CFWL_ThemeText * pParams,CFX_RectF & rect)225 void CXFA_FWLTheme::CalcTextRect(CFWL_ThemeText* pParams, CFX_RectF& rect) {
226 if (pParams->m_pWidget->GetClassID() == FWL_Type::MonthCalendar) {
227 CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget);
228 if (!pWidget || !pParams || !m_pTextOut)
229 return;
230
231 m_pTextOut->SetFont(m_pCalendarFont);
232 m_pTextOut->SetFontSize(FWLTHEME_CAPACITY_FontSize);
233 m_pTextOut->SetTextColor(FWLTHEME_CAPACITY_TextColor);
234 m_pTextOut->SetAlignment(pParams->m_iTTOAlign);
235 m_pTextOut->SetStyles(pParams->m_dwTTOStyles);
236 m_pTextOut->CalcLogicSize(pParams->m_wsText, rect);
237 }
238
239 CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams->m_pWidget);
240 if (!pWidget)
241 return;
242
243 CXFA_Node* pNode = pWidget->GetNode();
244 m_pTextOut->SetFont(pNode->GetWidgetAcc()->GetFDEFont(pWidget->GetDoc()));
245 m_pTextOut->SetFontSize(pNode->GetFontSize());
246 m_pTextOut->SetTextColor(pNode->GetTextColor());
247 if (!pParams)
248 return;
249
250 m_pTextOut->SetAlignment(pParams->m_iTTOAlign);
251 m_pTextOut->SetStyles(pParams->m_dwTTOStyles);
252 m_pTextOut->CalcLogicSize(pParams->m_wsText, rect);
253 }
254
GetTheme(CFWL_Widget * pWidget) const255 CFWL_WidgetTP* CXFA_FWLTheme::GetTheme(CFWL_Widget* pWidget) const {
256 switch (pWidget->GetClassID()) {
257 case FWL_Type::CheckBox:
258 return m_pCheckBoxTP.get();
259 case FWL_Type::ListBox:
260 return m_pListBoxTP.get();
261 case FWL_Type::PictureBox:
262 return m_pPictureBoxTP.get();
263 case FWL_Type::ScrollBar:
264 return m_pSrollBarTP.get();
265 case FWL_Type::Edit:
266 return m_pEditTP.get();
267 case FWL_Type::ComboBox:
268 return m_pComboBoxTP.get();
269 case FWL_Type::MonthCalendar:
270 return m_pMonthCalendarTP.get();
271 case FWL_Type::DateTimePicker:
272 return m_pDateTimePickerTP.get();
273 case FWL_Type::PushButton:
274 return m_pPushButtonTP.get();
275 case FWL_Type::Caret:
276 return m_pCaretTP.get();
277 case FWL_Type::Barcode:
278 return m_pBarcodeTP.get();
279 default:
280 return nullptr;
281 }
282 }
283