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