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