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