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_checkboxtp.h" 8 9 #include "core/fxge/cfx_pathdata.h" 10 #include "third_party/base/ptr_util.h" 11 #include "xfa/fde/cfde_textout.h" 12 #include "xfa/fwl/cfwl_checkbox.h" 13 #include "xfa/fwl/cfwl_themebackground.h" 14 #include "xfa/fwl/cfwl_themetext.h" 15 #include "xfa/fwl/cfwl_widget.h" 16 #include "xfa/fxgraphics/cxfa_gecolor.h" 17 #include "xfa/fxgraphics/cxfa_gepath.h" 18 19 namespace { 20 21 const int kSignPath = 100; 22 23 CFX_PointF ScaleBezierPoint(const CFX_PointF& point) { 24 CFX_PointF scaled_point(point); 25 scaled_point.x *= FX_BEZIER; 26 scaled_point.y *= FX_BEZIER; 27 return scaled_point; 28 } 29 30 } // namespace 31 32 #define CHECKBOX_COLOR_BOXLT1 (ArgbEncode(255, 172, 168, 153)) 33 #define CHECKBOX_COLOR_BOXLT2 (ArgbEncode(255, 113, 111, 100)) 34 #define CHECKBOX_COLOR_BOXRB1 (ArgbEncode(255, 241, 239, 226)) 35 #define CHECKBOX_COLOR_BOXRB2 (ArgbEncode(255, 255, 255, 255)) 36 37 CFWL_CheckBoxTP::CFWL_CheckBoxTP() : m_pThemeData(new CKBThemeData) { 38 SetThemeData(); 39 } 40 41 CFWL_CheckBoxTP::~CFWL_CheckBoxTP() { 42 if (m_pCheckPath) 43 m_pCheckPath->Clear(); 44 } 45 46 void CFWL_CheckBoxTP::Initialize() { 47 CFWL_WidgetTP::Initialize(); 48 InitTTO(); 49 } 50 51 void CFWL_CheckBoxTP::Finalize() { 52 FinalizeTTO(); 53 CFWL_WidgetTP::Finalize(); 54 } 55 56 void CFWL_CheckBoxTP::DrawText(CFWL_ThemeText* pParams) { 57 if (!m_pTextOut) 58 return; 59 60 m_pTextOut->SetTextColor(pParams->m_dwStates & CFWL_PartState_Disabled 61 ? FWLTHEME_CAPACITY_TextDisColor 62 : FWLTHEME_CAPACITY_TextColor); 63 CFWL_WidgetTP::DrawText(pParams); 64 } 65 66 void CFWL_CheckBoxTP::DrawSignCheck(CXFA_Graphics* pGraphics, 67 const CFX_RectF* pRtSign, 68 FX_ARGB argbFill, 69 CFX_Matrix* pMatrix) { 70 if (!m_pCheckPath) 71 InitCheckPath(pRtSign->width); 72 73 CFX_Matrix mt; 74 mt.Translate(pRtSign->left, pRtSign->top); 75 mt.Concat(*pMatrix); 76 pGraphics->SaveGraphState(); 77 pGraphics->SetFillColor(CXFA_GEColor(argbFill)); 78 pGraphics->FillPath(m_pCheckPath.get(), FXFILL_WINDING, &mt); 79 pGraphics->RestoreGraphState(); 80 } 81 82 void CFWL_CheckBoxTP::DrawSignCircle(CXFA_Graphics* pGraphics, 83 const CFX_RectF* pRtSign, 84 FX_ARGB argbFill, 85 CFX_Matrix* pMatrix) { 86 CXFA_GEPath path; 87 path.AddEllipse(*pRtSign); 88 pGraphics->SaveGraphState(); 89 pGraphics->SetFillColor(CXFA_GEColor(argbFill)); 90 pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); 91 pGraphics->RestoreGraphState(); 92 } 93 94 void CFWL_CheckBoxTP::DrawSignCross(CXFA_Graphics* pGraphics, 95 const CFX_RectF* pRtSign, 96 FX_ARGB argbFill, 97 CFX_Matrix* pMatrix) { 98 CXFA_GEPath path; 99 float fRight = pRtSign->right(); 100 float fBottom = pRtSign->bottom(); 101 path.AddLine(pRtSign->TopLeft(), CFX_PointF(fRight, fBottom)); 102 path.AddLine(CFX_PointF(pRtSign->left, fBottom), 103 CFX_PointF(fRight, pRtSign->top)); 104 105 pGraphics->SaveGraphState(); 106 pGraphics->SetStrokeColor(CXFA_GEColor(argbFill)); 107 pGraphics->SetLineWidth(1.0f); 108 pGraphics->StrokePath(&path, pMatrix); 109 pGraphics->RestoreGraphState(); 110 } 111 112 void CFWL_CheckBoxTP::DrawSignDiamond(CXFA_Graphics* pGraphics, 113 const CFX_RectF* pRtSign, 114 FX_ARGB argbFill, 115 CFX_Matrix* pMatrix) { 116 CXFA_GEPath path; 117 float fWidth = pRtSign->width; 118 float fHeight = pRtSign->height; 119 float fBottom = pRtSign->bottom(); 120 path.MoveTo(CFX_PointF(pRtSign->left + fWidth / 2, pRtSign->top)); 121 path.LineTo(CFX_PointF(pRtSign->left, pRtSign->top + fHeight / 2)); 122 path.LineTo(CFX_PointF(pRtSign->left + fWidth / 2, fBottom)); 123 path.LineTo(CFX_PointF(pRtSign->right(), pRtSign->top + fHeight / 2)); 124 path.LineTo(CFX_PointF(pRtSign->left + fWidth / 2, pRtSign->top)); 125 126 pGraphics->SaveGraphState(); 127 pGraphics->SetFillColor(CXFA_GEColor(argbFill)); 128 pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); 129 pGraphics->RestoreGraphState(); 130 } 131 132 void CFWL_CheckBoxTP::DrawSignSquare(CXFA_Graphics* pGraphics, 133 const CFX_RectF* pRtSign, 134 FX_ARGB argbFill, 135 CFX_Matrix* pMatrix) { 136 CXFA_GEPath path; 137 path.AddRectangle(pRtSign->left, pRtSign->top, pRtSign->width, 138 pRtSign->height); 139 pGraphics->SaveGraphState(); 140 pGraphics->SetFillColor(CXFA_GEColor(argbFill)); 141 pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); 142 pGraphics->RestoreGraphState(); 143 } 144 145 void CFWL_CheckBoxTP::DrawSignStar(CXFA_Graphics* pGraphics, 146 const CFX_RectF* pRtSign, 147 FX_ARGB argbFill, 148 CFX_Matrix* pMatrix) { 149 CXFA_GEPath path; 150 float fBottom = pRtSign->bottom(); 151 float fRadius = 152 (pRtSign->top - fBottom) / (1 + static_cast<float>(cos(FX_PI / 5.0f))); 153 CFX_PointF ptCenter((pRtSign->left + pRtSign->right()) / 2.0f, 154 (pRtSign->top + fBottom) / 2.0f); 155 156 CFX_PointF points[5]; 157 float fAngel = FX_PI / 10.0f; 158 for (int32_t i = 0; i < 5; i++) { 159 points[i] = 160 ptCenter + CFX_PointF(fRadius * static_cast<float>(cos(fAngel)), 161 fRadius * static_cast<float>(sin(fAngel))); 162 fAngel += FX_PI * 2 / 5.0f; 163 } 164 165 path.MoveTo(points[0]); 166 int32_t nNext = 0; 167 for (int32_t j = 0; j < 5; j++) { 168 nNext += 2; 169 if (nNext >= 5) 170 nNext -= 5; 171 172 path.LineTo(points[nNext]); 173 } 174 pGraphics->SaveGraphState(); 175 pGraphics->SetFillColor(CXFA_GEColor(argbFill)); 176 pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); 177 pGraphics->RestoreGraphState(); 178 } 179 180 void CFWL_CheckBoxTP::SetThemeData() { 181 uint32_t* pData = (uint32_t*)&m_pThemeData->clrBoxBk; 182 183 *pData++ = 0; 184 *pData++ = 0; 185 *pData++ = ArgbEncode(255, 220, 220, 215), 186 *pData++ = ArgbEncode(255, 255, 255, 255), 187 *pData++ = ArgbEncode(255, 255, 240, 207), 188 *pData++ = ArgbEncode(255, 248, 179, 48), 189 *pData++ = ArgbEncode(255, 176, 176, 167), 190 *pData++ = ArgbEncode(255, 241, 239, 239), 191 *pData++ = ArgbEncode(255, 255, 255, 255), 192 *pData++ = ArgbEncode(255, 255, 255, 255), 193 *pData++ = ArgbEncode(255, 220, 220, 215), 194 *pData++ = ArgbEncode(255, 255, 255, 255), 195 *pData++ = ArgbEncode(255, 255, 240, 207), 196 *pData++ = ArgbEncode(255, 248, 179, 48), 197 *pData++ = ArgbEncode(255, 176, 176, 167), 198 *pData++ = ArgbEncode(255, 241, 239, 239), 199 *pData++ = ArgbEncode(255, 255, 255, 255), 200 *pData++ = ArgbEncode(255, 255, 255, 255), 201 *pData++ = ArgbEncode(255, 220, 220, 215), 202 *pData++ = ArgbEncode(255, 255, 255, 255), 203 *pData++ = ArgbEncode(255, 255, 240, 207), 204 *pData++ = ArgbEncode(255, 248, 179, 48), 205 *pData++ = ArgbEncode(255, 176, 176, 167), 206 *pData++ = ArgbEncode(255, 241, 239, 239), 207 *pData++ = ArgbEncode(255, 255, 255, 255), 208 *pData++ = ArgbEncode(255, 255, 255, 255); 209 m_pThemeData->clrSignBorderNormal = ArgbEncode(255, 28, 81, 128); 210 m_pThemeData->clrSignBorderDisable = ArgbEncode(255, 202, 200, 187); 211 m_pThemeData->clrSignCheck = ArgbEncode(255, 28, 81, 128); 212 m_pThemeData->clrSignNeutral = ArgbEncode(255, 28, 134, 26); 213 m_pThemeData->clrSignNeutralNormal = ArgbEncode(255, 114, 192, 113); 214 m_pThemeData->clrSignNeutralHover = ArgbEncode(255, 33, 161, 33); 215 m_pThemeData->clrSignNeutralPressed = ArgbEncode(255, 28, 134, 26); 216 } 217 218 void CFWL_CheckBoxTP::InitCheckPath(float fCheckLen) { 219 if (!m_pCheckPath) { 220 m_pCheckPath = pdfium::MakeUnique<CXFA_GEPath>(); 221 222 float fWidth = kSignPath; 223 float fHeight = -kSignPath; 224 float fBottom = kSignPath; 225 CFX_PointF pt1(fWidth / 15.0f, fBottom + fHeight * 2 / 5.0f); 226 CFX_PointF pt2(fWidth / 4.5f, fBottom + fHeight / 16.0f); 227 CFX_PointF pt3(fWidth / 3.0f, fBottom); 228 CFX_PointF pt4(fWidth * 14 / 15.0f, fBottom + fHeight * 15 / 16.0f); 229 CFX_PointF pt5(fWidth / 3.6f, fBottom + fHeight / 3.5f); 230 CFX_PointF pt12(fWidth / 7.0f, fBottom + fHeight * 2 / 7.0f); 231 CFX_PointF pt21(fWidth / 5.0f, fBottom + fHeight / 5.0f); 232 CFX_PointF pt23(fWidth / 4.4f, fBottom + fHeight * 0 / 16.0f); 233 CFX_PointF pt32(fWidth / 4.0f, fBottom); 234 CFX_PointF pt34(fWidth * (1 / 7.0f + 7 / 15.0f), 235 fBottom + fHeight * 4 / 5.0f); 236 CFX_PointF pt43(fWidth * (1 / 7.0f + 7 / 15.0f), 237 fBottom + fHeight * 4 / 5.0f); 238 CFX_PointF pt45(fWidth * 7 / 15.0f, fBottom + fHeight * 8 / 7.0f); 239 CFX_PointF pt54(fWidth / 3.4f, fBottom + fHeight / 3.5f); 240 CFX_PointF pt51(fWidth / 3.6f, fBottom + fHeight / 4.0f); 241 CFX_PointF pt15(fWidth / 3.5f, fBottom + fHeight * 3.5f / 5.0f); 242 m_pCheckPath->MoveTo(pt1); 243 244 CFX_PointF p1 = ScaleBezierPoint(pt12 - pt1); 245 CFX_PointF p2 = ScaleBezierPoint(pt21 - pt2); 246 m_pCheckPath->BezierTo(pt1 + p1, pt2 + p2, pt2); 247 248 p1 = ScaleBezierPoint(pt23 - pt2); 249 p2 = ScaleBezierPoint(pt32 - pt3); 250 m_pCheckPath->BezierTo(pt2 + p1, pt3 + p2, pt3); 251 252 p1 = ScaleBezierPoint(pt34 - pt3); 253 p2 = ScaleBezierPoint(pt43 - pt4); 254 m_pCheckPath->BezierTo(pt3 + p1, pt4 + p2, pt4); 255 256 p1 = ScaleBezierPoint(pt45 - pt4); 257 p2 = ScaleBezierPoint(pt54 - pt5); 258 m_pCheckPath->BezierTo(pt4 + p1, pt5 + p2, pt5); 259 260 p1 = ScaleBezierPoint(pt51 - pt5); 261 p2 = ScaleBezierPoint(pt15 - pt1); 262 m_pCheckPath->BezierTo(pt5 + p1, pt1 + p2, pt1); 263 264 float fScale = fCheckLen / kSignPath; 265 CFX_Matrix mt; 266 mt.Scale(fScale, fScale); 267 268 m_pCheckPath->TransformBy(mt); 269 } 270 } 271 272 void CFWL_CheckBoxTP::DrawBackground(CFWL_ThemeBackground* pParams) { 273 if (pParams->m_iPart != CFWL_Part::CheckBox) 274 return; 275 276 if ((pParams->m_dwStates & CFWL_PartState_Checked) || 277 (pParams->m_dwStates & CFWL_PartState_Neutral)) { 278 DrawCheckSign(pParams->m_pWidget, pParams->m_pGraphics, pParams->m_rtPart, 279 pParams->m_dwStates, &pParams->m_matrix); 280 } 281 } 282 283 void CFWL_CheckBoxTP::DrawCheckSign(CFWL_Widget* pWidget, 284 CXFA_Graphics* pGraphics, 285 const CFX_RectF& pRtBox, 286 int32_t iState, 287 CFX_Matrix* pMatrix) { 288 CFX_RectF rtSign(pRtBox); 289 uint32_t dwColor = iState & CFWL_PartState_Neutral ? 0xFFA9A9A9 : 0xFF000000; 290 291 uint32_t dwStyle = pWidget->GetStylesEx(); 292 rtSign.Deflate(rtSign.width / 4, rtSign.height / 4); 293 switch (dwStyle & FWL_STYLEEXT_CKB_SignShapeMask) { 294 case FWL_STYLEEXT_CKB_SignShapeCheck: 295 DrawSignCheck(pGraphics, &rtSign, dwColor, pMatrix); 296 break; 297 case FWL_STYLEEXT_CKB_SignShapeCircle: 298 DrawSignCircle(pGraphics, &rtSign, dwColor, pMatrix); 299 break; 300 case FWL_STYLEEXT_CKB_SignShapeCross: 301 DrawSignCross(pGraphics, &rtSign, dwColor, pMatrix); 302 break; 303 case FWL_STYLEEXT_CKB_SignShapeDiamond: 304 DrawSignDiamond(pGraphics, &rtSign, dwColor, pMatrix); 305 break; 306 case FWL_STYLEEXT_CKB_SignShapeSquare: 307 DrawSignSquare(pGraphics, &rtSign, dwColor, pMatrix); 308 break; 309 case FWL_STYLEEXT_CKB_SignShapeStar: 310 DrawSignStar(pGraphics, &rtSign, dwColor, pMatrix); 311 break; 312 default: 313 break; 314 } 315 } 316