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 "third_party/base/ptr_util.h"
11 #include "xfa/fde/cfde_textout.h"
12 #include "xfa/fgas/font/cfgas_gefont.h"
13 #include "xfa/fwl/cfwl_barcode.h"
14 #include "xfa/fwl/cfwl_caret.h"
15 #include "xfa/fwl/cfwl_checkbox.h"
16 #include "xfa/fwl/cfwl_combobox.h"
17 #include "xfa/fwl/cfwl_datetimepicker.h"
18 #include "xfa/fwl/cfwl_edit.h"
19 #include "xfa/fwl/cfwl_listbox.h"
20 #include "xfa/fwl/cfwl_monthcalendar.h"
21 #include "xfa/fwl/cfwl_picturebox.h"
22 #include "xfa/fwl/cfwl_pushbutton.h"
23 #include "xfa/fwl/cfwl_scrollbar.h"
24 #include "xfa/fwl/cfwl_themebackground.h"
25 #include "xfa/fwl/cfwl_themetext.h"
26 #include "xfa/fwl/theme/cfwl_widgettp.h"
27 #include "xfa/fxfa/cxfa_ffapp.h"
28 #include "xfa/fxfa/cxfa_ffwidget.h"
29 #include "xfa/fxfa/parser/cxfa_para.h"
30 #include "xfa/fxgraphics/cxfa_gecolor.h"
31
32 namespace {
33
34 const wchar_t* const g_FWLTheme_CalFonts[] = {
35 L"Arial", L"Courier New", L"DejaVu Sans",
36 };
37
38 const float kLineHeight = 12.0f;
39
XFA_ThemeGetOuterWidget(CFWL_Widget * pWidget)40 CXFA_FFWidget* XFA_ThemeGetOuterWidget(CFWL_Widget* pWidget) {
41 CFWL_Widget* pOuter = pWidget ? pWidget->GetOutmost() : nullptr;
42 return pOuter ? static_cast<CXFA_FFWidget*>(pOuter->GetAdapterIface())
43 : nullptr;
44 }
45
46 } // namespace
47
CXFA_FWLTheme(CXFA_FFApp * pApp)48 CXFA_FWLTheme::CXFA_FWLTheme(CXFA_FFApp* pApp)
49 : m_pCheckBoxTP(pdfium::MakeUnique<CFWL_CheckBoxTP>()),
50 m_pListBoxTP(pdfium::MakeUnique<CFWL_ListBoxTP>()),
51 m_pPictureBoxTP(pdfium::MakeUnique<CFWL_PictureBoxTP>()),
52 m_pSrollBarTP(pdfium::MakeUnique<CFWL_ScrollBarTP>()),
53 m_pEditTP(pdfium::MakeUnique<CFWL_EditTP>()),
54 m_pComboBoxTP(pdfium::MakeUnique<CFWL_ComboBoxTP>()),
55 m_pMonthCalendarTP(pdfium::MakeUnique<CFWL_MonthCalendarTP>()),
56 m_pDateTimePickerTP(pdfium::MakeUnique<CFWL_DateTimePickerTP>()),
57 m_pPushButtonTP(pdfium::MakeUnique<CFWL_PushButtonTP>()),
58 m_pCaretTP(pdfium::MakeUnique<CFWL_CaretTP>()),
59 m_pBarcodeTP(pdfium::MakeUnique<CFWL_BarcodeTP>()),
60 m_pTextOut(pdfium::MakeUnique<CFDE_TextOut>()),
61 m_pApp(pApp) {
62 }
63
LoadCalendarFont(CXFA_FFDoc * doc)64 bool CXFA_FWLTheme::LoadCalendarFont(CXFA_FFDoc* doc) {
65 for (size_t i = 0; !m_pCalendarFont && i < FX_ArraySize(g_FWLTheme_CalFonts);
66 ++i) {
67 m_pCalendarFont =
68 m_pApp->GetXFAFontMgr()->GetFont(doc, g_FWLTheme_CalFonts[i], 0);
69 }
70
71 if (!m_pCalendarFont) {
72 CFGAS_FontMgr* font_mgr = m_pApp->GetFDEFontMgr();
73 if (font_mgr) {
74 m_pCalendarFont = font_mgr->GetFontByCodePage(
75 FX_CODEPAGE_MSWin_WesternEuropean, 0, nullptr);
76 }
77 }
78
79 return m_pCalendarFont != nullptr;
80 }
81
~CXFA_FWLTheme()82 CXFA_FWLTheme::~CXFA_FWLTheme() {
83 m_pTextOut.reset();
84 CFWL_FontManager::DestroyInstance();
85 }
86
DrawBackground(const CFWL_ThemeBackground & pParams)87 void CXFA_FWLTheme::DrawBackground(const CFWL_ThemeBackground& pParams) {
88 GetTheme(pParams.m_pWidget)->DrawBackground(pParams);
89 }
90
DrawText(const CFWL_ThemeText & pParams)91 void CXFA_FWLTheme::DrawText(const CFWL_ThemeText& pParams) {
92 if (pParams.m_wsText.IsEmpty())
93 return;
94
95 if (pParams.m_pWidget->GetClassID() == FWL_Type::MonthCalendar) {
96 CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams.m_pWidget);
97 if (!pWidget)
98 return;
99
100 m_pTextOut->SetStyles(pParams.m_dwTTOStyles);
101 m_pTextOut->SetAlignment(pParams.m_iTTOAlign);
102 m_pTextOut->SetFont(m_pCalendarFont);
103 m_pTextOut->SetFontSize(FWLTHEME_CAPACITY_FontSize);
104 m_pTextOut->SetTextColor(FWLTHEME_CAPACITY_TextColor);
105 if ((pParams.m_iPart == CFWL_Part::DatesIn) &&
106 !(pParams.m_dwStates & FWL_ITEMSTATE_MCD_Flag) &&
107 (pParams.m_dwStates &
108 (CFWL_PartState_Hovered | CFWL_PartState_Selected))) {
109 m_pTextOut->SetTextColor(0xFF888888);
110 }
111 if (pParams.m_iPart == CFWL_Part::Caption)
112 m_pTextOut->SetTextColor(ArgbEncode(0xff, 0, 153, 255));
113
114 CXFA_Graphics* pGraphics = pParams.m_pGraphics;
115 CFX_RenderDevice* pRenderDevice = pGraphics->GetRenderDevice();
116 CFX_Matrix mtPart = pParams.m_matrix;
117 const CFX_Matrix* pMatrix = pGraphics->GetMatrix();
118 if (pMatrix)
119 mtPart.Concat(*pMatrix);
120
121 m_pTextOut->SetMatrix(mtPart);
122 m_pTextOut->DrawLogicText(pRenderDevice, pParams.m_wsText.AsStringView(),
123 pParams.m_rtPart);
124 return;
125 }
126 CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams.m_pWidget);
127 if (!pWidget)
128 return;
129
130 CXFA_Node* pNode = pWidget->GetNode();
131 CXFA_Graphics* pGraphics = pParams.m_pGraphics;
132 CFX_RenderDevice* pRenderDevice = pGraphics->GetRenderDevice();
133 m_pTextOut->SetStyles(pParams.m_dwTTOStyles);
134 m_pTextOut->SetAlignment(pParams.m_iTTOAlign);
135 m_pTextOut->SetFont(pNode->GetFDEFont(pWidget->GetDoc()));
136 m_pTextOut->SetFontSize(pNode->GetFontSize());
137 m_pTextOut->SetTextColor(pNode->GetTextColor());
138 CFX_Matrix mtPart = pParams.m_matrix;
139 const CFX_Matrix* pMatrix = pGraphics->GetMatrix();
140 if (pMatrix)
141 mtPart.Concat(*pMatrix);
142
143 m_pTextOut->SetMatrix(mtPart);
144 m_pTextOut->DrawLogicText(pRenderDevice, pParams.m_wsText.AsStringView(),
145 pParams.m_rtPart);
146 }
147
GetUIMargin(const CFWL_ThemePart & pThemePart) const148 CFX_RectF CXFA_FWLTheme::GetUIMargin(const CFWL_ThemePart& pThemePart) const {
149 CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart.m_pWidget);
150 if (!pWidget)
151 return CFX_RectF();
152
153 CXFA_ContentLayoutItem* pItem = pWidget->GetLayoutItem();
154 CXFA_Node* pNode = pWidget->GetNode();
155 CFX_RectF rect = pNode->GetUIMargin();
156 CXFA_Para* para = pNode->GetParaIfExists();
157 if (para) {
158 rect.left += para->GetMarginLeft();
159 if (pNode->IsMultiLine())
160 rect.width += para->GetMarginRight();
161 }
162 if (!pItem->GetPrev()) {
163 if (pItem->GetNext())
164 rect.height = 0;
165 } else if (!pItem->GetNext()) {
166 rect.top = 0;
167 } else {
168 rect.top = 0;
169 rect.height = 0;
170 }
171 return rect;
172 }
173
GetCXBorderSize() const174 float CXFA_FWLTheme::GetCXBorderSize() const {
175 return 1.0f;
176 }
177
GetCYBorderSize() const178 float CXFA_FWLTheme::GetCYBorderSize() const {
179 return 1.0f;
180 }
181
GetFontSize(const CFWL_ThemePart & pThemePart) const182 float CXFA_FWLTheme::GetFontSize(const CFWL_ThemePart& pThemePart) const {
183 if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart.m_pWidget))
184 return pWidget->GetNode()->GetFontSize();
185 return FWLTHEME_CAPACITY_FontSize;
186 }
187
GetFont(const CFWL_ThemePart & pThemePart) const188 RetainPtr<CFGAS_GEFont> CXFA_FWLTheme::GetFont(
189 const CFWL_ThemePart& pThemePart) const {
190 if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart.m_pWidget))
191 return pWidget->GetNode()->GetFDEFont(pWidget->GetDoc());
192 return GetTheme(pThemePart.m_pWidget)->GetFont();
193 }
194
GetLineHeight(const CFWL_ThemePart & pThemePart) const195 float CXFA_FWLTheme::GetLineHeight(const CFWL_ThemePart& pThemePart) const {
196 if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart.m_pWidget))
197 return pWidget->GetNode()->GetLineHeight();
198 return kLineHeight;
199 }
200
GetScrollBarWidth() const201 float CXFA_FWLTheme::GetScrollBarWidth() const {
202 return 9.0f;
203 }
204
GetTextColor(const CFWL_ThemePart & pThemePart) const205 FX_COLORREF CXFA_FWLTheme::GetTextColor(
206 const CFWL_ThemePart& pThemePart) const {
207 if (CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pThemePart.m_pWidget))
208 return pWidget->GetNode()->GetTextColor();
209 return FWLTHEME_CAPACITY_TextColor;
210 }
211
GetSpaceAboveBelow(const CFWL_ThemePart & pThemePart) const212 CFX_SizeF CXFA_FWLTheme::GetSpaceAboveBelow(
213 const 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(const CFWL_ThemeText & pParams,CFX_RectF * pRect)225 void CXFA_FWLTheme::CalcTextRect(const CFWL_ThemeText& pParams,
226 CFX_RectF* pRect) {
227 if (!m_pTextOut)
228 return;
229
230 CXFA_FFWidget* pWidget = XFA_ThemeGetOuterWidget(pParams.m_pWidget);
231 if (!pWidget)
232 return;
233
234 if (pParams.m_pWidget->GetClassID() == FWL_Type::MonthCalendar) {
235 m_pTextOut->SetFont(m_pCalendarFont);
236 m_pTextOut->SetFontSize(FWLTHEME_CAPACITY_FontSize);
237 m_pTextOut->SetTextColor(FWLTHEME_CAPACITY_TextColor);
238 m_pTextOut->SetAlignment(pParams.m_iTTOAlign);
239 m_pTextOut->SetStyles(pParams.m_dwTTOStyles);
240 m_pTextOut->CalcLogicSize(pParams.m_wsText.AsStringView(), pRect);
241 return;
242 }
243
244 CXFA_Node* pNode = pWidget->GetNode();
245 m_pTextOut->SetFont(pNode->GetFDEFont(pWidget->GetDoc()));
246 m_pTextOut->SetFontSize(pNode->GetFontSize());
247 m_pTextOut->SetTextColor(pNode->GetTextColor());
248 m_pTextOut->SetAlignment(pParams.m_iTTOAlign);
249 m_pTextOut->SetStyles(pParams.m_dwTTOStyles);
250 m_pTextOut->CalcLogicSize(pParams.m_wsText.AsStringView(), pRect);
251 }
252
GetTheme(CFWL_Widget * pWidget) const253 CFWL_WidgetTP* CXFA_FWLTheme::GetTheme(CFWL_Widget* pWidget) const {
254 switch (pWidget->GetClassID()) {
255 case FWL_Type::CheckBox:
256 return m_pCheckBoxTP.get();
257 case FWL_Type::ListBox:
258 return m_pListBoxTP.get();
259 case FWL_Type::PictureBox:
260 return m_pPictureBoxTP.get();
261 case FWL_Type::ScrollBar:
262 return m_pSrollBarTP.get();
263 case FWL_Type::Edit:
264 return m_pEditTP.get();
265 case FWL_Type::ComboBox:
266 return m_pComboBoxTP.get();
267 case FWL_Type::MonthCalendar:
268 return m_pMonthCalendarTP.get();
269 case FWL_Type::DateTimePicker:
270 return m_pDateTimePickerTP.get();
271 case FWL_Type::PushButton:
272 return m_pPushButtonTP.get();
273 case FWL_Type::Caret:
274 return m_pCaretTP.get();
275 case FWL_Type::Barcode:
276 return m_pBarcodeTP.get();
277 default:
278 return nullptr;
279 }
280 }
281