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/fwl/theme/cfwl_widgettp.h"
8 
9 #include <algorithm>
10 #include <utility>
11 
12 #include "core/fxge/render_defines.h"
13 #include "third_party/base/ptr_util.h"
14 #include "xfa/fde/cfde_textout.h"
15 #include "xfa/fgas/font/cfgas_fontmgr.h"
16 #include "xfa/fgas/font/cfgas_gefont.h"
17 #include "xfa/fwl/cfwl_themebackground.h"
18 #include "xfa/fwl/cfwl_themepart.h"
19 #include "xfa/fwl/cfwl_themetext.h"
20 #include "xfa/fwl/cfwl_widget.h"
21 #include "xfa/fwl/cfwl_widgetmgr.h"
22 #include "xfa/fwl/ifwl_themeprovider.h"
23 #include "xfa/fxgraphics/cxfa_gecolor.h"
24 #include "xfa/fxgraphics/cxfa_gepath.h"
25 #include "xfa/fxgraphics/cxfa_geshading.h"
26 
27 namespace {
28 
29 CFWL_FontManager* g_FontManager = nullptr;
30 
31 }  // namespace
32 
33 CFWL_WidgetTP::CFWL_WidgetTP() = default;
34 
35 CFWL_WidgetTP::~CFWL_WidgetTP() = default;
36 
DrawBackground(const CFWL_ThemeBackground & pParams)37 void CFWL_WidgetTP::DrawBackground(const CFWL_ThemeBackground& pParams) {}
38 
DrawText(const CFWL_ThemeText & pParams)39 void CFWL_WidgetTP::DrawText(const CFWL_ThemeText& pParams) {
40   EnsureTTOInitialized();
41   int32_t iLen = pParams.m_wsText.GetLength();
42   if (iLen <= 0)
43     return;
44 
45   CXFA_Graphics* pGraphics = pParams.m_pGraphics;
46   m_pTextOut->SetStyles(pParams.m_dwTTOStyles);
47   m_pTextOut->SetAlignment(pParams.m_iTTOAlign);
48 
49   CFX_Matrix matrix = pParams.m_matrix;
50   matrix.Concat(*pGraphics->GetMatrix());
51   m_pTextOut->SetMatrix(matrix);
52   m_pTextOut->DrawLogicText(pGraphics->GetRenderDevice(),
53                             WideStringView(pParams.m_wsText.c_str(), iLen),
54                             pParams.m_rtPart);
55 }
56 
GetFont() const57 const RetainPtr<CFGAS_GEFont>& CFWL_WidgetTP::GetFont() const {
58   return m_pFDEFont;
59 }
60 
InitializeArrowColorData()61 void CFWL_WidgetTP::InitializeArrowColorData() {
62   if (m_pColorData)
63     return;
64 
65   m_pColorData = pdfium::MakeUnique<CColorData>();
66   m_pColorData->clrBorder[0] = ArgbEncode(255, 202, 216, 249);
67   m_pColorData->clrBorder[1] = ArgbEncode(255, 171, 190, 233);
68   m_pColorData->clrBorder[2] = ArgbEncode(255, 135, 147, 219);
69   m_pColorData->clrBorder[3] = ArgbEncode(255, 172, 168, 153);
70   m_pColorData->clrStart[0] = ArgbEncode(255, 225, 234, 254);
71   m_pColorData->clrStart[1] = ArgbEncode(255, 253, 255, 255);
72   m_pColorData->clrStart[2] = ArgbEncode(255, 110, 142, 241);
73   m_pColorData->clrStart[3] = ArgbEncode(255, 254, 254, 251);
74   m_pColorData->clrEnd[0] = ArgbEncode(255, 175, 204, 251);
75   m_pColorData->clrEnd[1] = ArgbEncode(255, 185, 218, 251);
76   m_pColorData->clrEnd[2] = ArgbEncode(255, 210, 222, 235);
77   m_pColorData->clrEnd[3] = ArgbEncode(255, 243, 241, 236);
78   m_pColorData->clrSign[0] = ArgbEncode(255, 77, 97, 133);
79   m_pColorData->clrSign[1] = ArgbEncode(255, 77, 97, 133);
80   m_pColorData->clrSign[2] = ArgbEncode(255, 77, 97, 133);
81   m_pColorData->clrSign[3] = ArgbEncode(255, 128, 128, 128);
82 }
83 
EnsureTTOInitialized()84 void CFWL_WidgetTP::EnsureTTOInitialized() {
85   if (m_pTextOut)
86     return;
87 
88   m_pFDEFont = CFWL_FontManager::GetInstance()->FindFont(L"Helvetica", 0, 0);
89   m_pTextOut = pdfium::MakeUnique<CFDE_TextOut>();
90   m_pTextOut->SetFont(m_pFDEFont);
91   m_pTextOut->SetFontSize(FWLTHEME_CAPACITY_FontSize);
92   m_pTextOut->SetTextColor(FWLTHEME_CAPACITY_TextColor);
93 }
94 
DrawBorder(CXFA_Graphics * pGraphics,const CFX_RectF & rect,const CFX_Matrix & matrix)95 void CFWL_WidgetTP::DrawBorder(CXFA_Graphics* pGraphics,
96                                const CFX_RectF& rect,
97                                const CFX_Matrix& matrix) {
98   if (!pGraphics)
99     return;
100 
101   CXFA_GEPath path;
102   path.AddRectangle(rect.left, rect.top, rect.width, rect.height);
103   path.AddRectangle(rect.left + 1, rect.top + 1, rect.width - 2,
104                     rect.height - 2);
105   pGraphics->SaveGraphState();
106   pGraphics->SetFillColor(CXFA_GEColor(ArgbEncode(255, 0, 0, 0)));
107   pGraphics->FillPath(&path, FXFILL_ALTERNATE, &matrix);
108   pGraphics->RestoreGraphState();
109 }
110 
FillBackground(CXFA_Graphics * pGraphics,const CFX_RectF & rect,const CFX_Matrix & matrix)111 void CFWL_WidgetTP::FillBackground(CXFA_Graphics* pGraphics,
112                                    const CFX_RectF& rect,
113                                    const CFX_Matrix& matrix) {
114   FillSolidRect(pGraphics, FWLTHEME_COLOR_Background, rect, matrix);
115 }
116 
FillSolidRect(CXFA_Graphics * pGraphics,FX_ARGB fillColor,const CFX_RectF & rect,const CFX_Matrix & matrix)117 void CFWL_WidgetTP::FillSolidRect(CXFA_Graphics* pGraphics,
118                                   FX_ARGB fillColor,
119                                   const CFX_RectF& rect,
120                                   const CFX_Matrix& matrix) {
121   if (!pGraphics)
122     return;
123 
124   CXFA_GEPath path;
125   path.AddRectangle(rect.left, rect.top, rect.width, rect.height);
126   pGraphics->SaveGraphState();
127   pGraphics->SetFillColor(CXFA_GEColor(fillColor));
128   pGraphics->FillPath(&path, FXFILL_WINDING, &matrix);
129   pGraphics->RestoreGraphState();
130 }
131 
DrawFocus(CXFA_Graphics * pGraphics,const CFX_RectF & rect,const CFX_Matrix & matrix)132 void CFWL_WidgetTP::DrawFocus(CXFA_Graphics* pGraphics,
133                               const CFX_RectF& rect,
134                               const CFX_Matrix& matrix) {
135   if (!pGraphics)
136     return;
137 
138   CXFA_GEPath path;
139   path.AddRectangle(rect.left, rect.top, rect.width, rect.height);
140   pGraphics->SaveGraphState();
141   pGraphics->SetStrokeColor(CXFA_GEColor(0xFF000000));
142   static constexpr float kDashPattern[2] = {1, 1};
143   pGraphics->SetLineDash(0.0f, kDashPattern, FX_ArraySize(kDashPattern));
144   pGraphics->StrokePath(&path, &matrix);
145   pGraphics->RestoreGraphState();
146 }
147 
DrawArrow(CXFA_Graphics * pGraphics,const CFX_RectF & rect,FWLTHEME_DIRECTION eDict,FX_ARGB argSign,const CFX_Matrix & matrix)148 void CFWL_WidgetTP::DrawArrow(CXFA_Graphics* pGraphics,
149                               const CFX_RectF& rect,
150                               FWLTHEME_DIRECTION eDict,
151                               FX_ARGB argSign,
152                               const CFX_Matrix& matrix) {
153   bool bVert =
154       (eDict == FWLTHEME_DIRECTION_Up || eDict == FWLTHEME_DIRECTION_Down);
155   float fLeft = ((rect.width - (bVert ? 9 : 6)) / 2 + rect.left) + 0.5f;
156   float fTop = ((rect.height - (bVert ? 6 : 9)) / 2 + rect.top) + 0.5f;
157   CXFA_GEPath path;
158   switch (eDict) {
159     case FWLTHEME_DIRECTION_Down: {
160       path.MoveTo(CFX_PointF(fLeft, fTop + 1));
161       path.LineTo(CFX_PointF(fLeft + 4, fTop + 5));
162       path.LineTo(CFX_PointF(fLeft + 8, fTop + 1));
163       path.LineTo(CFX_PointF(fLeft + 7, fTop));
164       path.LineTo(CFX_PointF(fLeft + 4, fTop + 3));
165       path.LineTo(CFX_PointF(fLeft + 1, fTop));
166       break;
167     }
168     case FWLTHEME_DIRECTION_Up: {
169       path.MoveTo(CFX_PointF(fLeft, fTop + 4));
170       path.LineTo(CFX_PointF(fLeft + 4, fTop));
171       path.LineTo(CFX_PointF(fLeft + 8, fTop + 4));
172       path.LineTo(CFX_PointF(fLeft + 7, fTop + 5));
173       path.LineTo(CFX_PointF(fLeft + 4, fTop + 2));
174       path.LineTo(CFX_PointF(fLeft + 1, fTop + 5));
175       break;
176     }
177     case FWLTHEME_DIRECTION_Right: {
178       path.MoveTo(CFX_PointF(fLeft + 1, fTop));
179       path.LineTo(CFX_PointF(fLeft + 5, fTop + 4));
180       path.LineTo(CFX_PointF(fLeft + 1, fTop + 8));
181       path.LineTo(CFX_PointF(fLeft, fTop + 7));
182       path.LineTo(CFX_PointF(fLeft + 3, fTop + 4));
183       path.LineTo(CFX_PointF(fLeft, fTop + 1));
184       break;
185     }
186     case FWLTHEME_DIRECTION_Left: {
187       path.MoveTo(CFX_PointF(fLeft, fTop + 4));
188       path.LineTo(CFX_PointF(fLeft + 4, fTop));
189       path.LineTo(CFX_PointF(fLeft + 5, fTop + 1));
190       path.LineTo(CFX_PointF(fLeft + 2, fTop + 4));
191       path.LineTo(CFX_PointF(fLeft + 5, fTop + 7));
192       path.LineTo(CFX_PointF(fLeft + 4, fTop + 8));
193       break;
194     }
195   }
196   pGraphics->SetFillColor(CXFA_GEColor(argSign));
197   pGraphics->FillPath(&path, FXFILL_WINDING, &matrix);
198 }
199 
DrawBtn(CXFA_Graphics * pGraphics,const CFX_RectF & rect,FWLTHEME_STATE eState,const CFX_Matrix & matrix)200 void CFWL_WidgetTP::DrawBtn(CXFA_Graphics* pGraphics,
201                             const CFX_RectF& rect,
202                             FWLTHEME_STATE eState,
203                             const CFX_Matrix& matrix) {
204   InitializeArrowColorData();
205   FillSolidRect(pGraphics, m_pColorData->clrEnd[eState - 1], rect, matrix);
206 
207   CXFA_GEPath path;
208   path.AddRectangle(rect.left, rect.top, rect.width, rect.height);
209   pGraphics->SetStrokeColor(CXFA_GEColor(m_pColorData->clrBorder[eState - 1]));
210   pGraphics->StrokePath(&path, &matrix);
211 }
212 
DrawArrowBtn(CXFA_Graphics * pGraphics,const CFX_RectF & rect,FWLTHEME_DIRECTION eDict,FWLTHEME_STATE eState,const CFX_Matrix & matrix)213 void CFWL_WidgetTP::DrawArrowBtn(CXFA_Graphics* pGraphics,
214                                  const CFX_RectF& rect,
215                                  FWLTHEME_DIRECTION eDict,
216                                  FWLTHEME_STATE eState,
217                                  const CFX_Matrix& matrix) {
218   DrawBtn(pGraphics, rect, eState, matrix);
219   InitializeArrowColorData();
220   DrawArrow(pGraphics, rect, eDict, m_pColorData->clrSign[eState - 1], matrix);
221 }
222 
CFWL_FontData()223 CFWL_FontData::CFWL_FontData() : m_dwStyles(0), m_dwCodePage(0) {}
224 
~CFWL_FontData()225 CFWL_FontData::~CFWL_FontData() {}
226 
Equal(WideStringView wsFontFamily,uint32_t dwFontStyles,uint16_t wCodePage)227 bool CFWL_FontData::Equal(WideStringView wsFontFamily,
228                           uint32_t dwFontStyles,
229                           uint16_t wCodePage) {
230   return m_wsFamily == wsFontFamily && m_dwStyles == dwFontStyles &&
231          m_dwCodePage == wCodePage;
232 }
233 
LoadFont(WideStringView wsFontFamily,uint32_t dwFontStyles,uint16_t dwCodePage)234 bool CFWL_FontData::LoadFont(WideStringView wsFontFamily,
235                              uint32_t dwFontStyles,
236                              uint16_t dwCodePage) {
237   m_wsFamily = wsFontFamily;
238   m_dwStyles = dwFontStyles;
239   m_dwCodePage = dwCodePage;
240   if (!m_pFontMgr) {
241     m_pFontMgr = pdfium::MakeUnique<CFGAS_FontMgr>();
242     if (!m_pFontMgr->EnumFonts())
243       m_pFontMgr = nullptr;
244   }
245 
246   // TODO(tsepez): check usage of c_str() below.
247   m_pFont = CFGAS_GEFont::LoadFont(wsFontFamily.unterminated_c_str(),
248                                    dwFontStyles, dwCodePage, m_pFontMgr.get());
249   return !!m_pFont;
250 }
251 
GetFont() const252 RetainPtr<CFGAS_GEFont> CFWL_FontData::GetFont() const {
253   return m_pFont;
254 }
255 
GetInstance()256 CFWL_FontManager* CFWL_FontManager::GetInstance() {
257   if (!g_FontManager)
258     g_FontManager = new CFWL_FontManager;
259   return g_FontManager;
260 }
261 
DestroyInstance()262 void CFWL_FontManager::DestroyInstance() {
263   delete g_FontManager;
264   g_FontManager = nullptr;
265 }
266 
267 CFWL_FontManager::CFWL_FontManager() = default;
268 
269 CFWL_FontManager::~CFWL_FontManager() = default;
270 
FindFont(WideStringView wsFontFamily,uint32_t dwFontStyles,uint16_t wCodePage)271 RetainPtr<CFGAS_GEFont> CFWL_FontManager::FindFont(WideStringView wsFontFamily,
272                                                    uint32_t dwFontStyles,
273                                                    uint16_t wCodePage) {
274   for (const auto& pData : m_FontsArray) {
275     if (pData->Equal(wsFontFamily, dwFontStyles, wCodePage))
276       return pData->GetFont();
277   }
278   auto pFontData = pdfium::MakeUnique<CFWL_FontData>();
279   if (!pFontData->LoadFont(wsFontFamily, dwFontStyles, wCodePage))
280     return nullptr;
281 
282   m_FontsArray.push_back(std::move(pFontData));
283   return m_FontsArray.back()->GetFont();
284 }
285 
286