// Copyright 2014 PDFium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "xfa/fwl/theme/cfwl_widgettp.h" #include <algorithm> #include <utility> #include "third_party/base/ptr_util.h" #include "xfa/fde/tto/fde_textout.h" #include "xfa/fgas/font/cfgas_fontmgr.h" #include "xfa/fgas/font/cfgas_gefont.h" #include "xfa/fwl/cfwl_themebackground.h" #include "xfa/fwl/cfwl_themepart.h" #include "xfa/fwl/cfwl_themetext.h" #include "xfa/fwl/cfwl_widget.h" #include "xfa/fwl/cfwl_widgetmgr.h" #include "xfa/fwl/ifwl_themeprovider.h" #include "xfa/fxgraphics/cfx_color.h" #include "xfa/fxgraphics/cfx_path.h" #include "xfa/fxgraphics/cfx_shading.h" CFWL_WidgetTP::CFWL_WidgetTP() : m_dwRefCount(1), m_pFDEFont(nullptr), m_pColorData(nullptr) {} CFWL_WidgetTP::~CFWL_WidgetTP() {} void CFWL_WidgetTP::Initialize() {} void CFWL_WidgetTP::Finalize() { if (m_pTextOut) FinalizeTTO(); } void CFWL_WidgetTP::DrawBackground(CFWL_ThemeBackground* pParams) {} void CFWL_WidgetTP::DrawText(CFWL_ThemeText* pParams) { if (!m_pTextOut) InitTTO(); int32_t iLen = pParams->m_wsText.GetLength(); if (iLen <= 0) return; CFX_Graphics* pGraphics = pParams->m_pGraphics; m_pTextOut->SetRenderDevice(pGraphics->GetRenderDevice()); m_pTextOut->SetStyles(pParams->m_dwTTOStyles); m_pTextOut->SetAlignment(pParams->m_iTTOAlign); CFX_Matrix* pMatrix = &pParams->m_matrix; pMatrix->Concat(*pGraphics->GetMatrix()); m_pTextOut->SetMatrix(*pMatrix); m_pTextOut->DrawLogicText(pParams->m_wsText.c_str(), iLen, pParams->m_rtPart); } void CFWL_WidgetTP::InitializeArrowColorData() { if (m_pColorData) return; m_pColorData = pdfium::MakeUnique<CColorData>(); m_pColorData->clrBorder[0] = ArgbEncode(255, 202, 216, 249); m_pColorData->clrBorder[1] = ArgbEncode(255, 171, 190, 233); m_pColorData->clrBorder[2] = ArgbEncode(255, 135, 147, 219); m_pColorData->clrBorder[3] = ArgbEncode(255, 172, 168, 153); m_pColorData->clrStart[0] = ArgbEncode(255, 225, 234, 254); m_pColorData->clrStart[1] = ArgbEncode(255, 253, 255, 255); m_pColorData->clrStart[2] = ArgbEncode(255, 110, 142, 241); m_pColorData->clrStart[3] = ArgbEncode(255, 254, 254, 251); m_pColorData->clrEnd[0] = ArgbEncode(255, 175, 204, 251); m_pColorData->clrEnd[1] = ArgbEncode(255, 185, 218, 251); m_pColorData->clrEnd[2] = ArgbEncode(255, 210, 222, 235); m_pColorData->clrEnd[3] = ArgbEncode(255, 243, 241, 236); m_pColorData->clrSign[0] = ArgbEncode(255, 77, 97, 133); m_pColorData->clrSign[1] = ArgbEncode(255, 77, 97, 133); m_pColorData->clrSign[2] = ArgbEncode(255, 77, 97, 133); m_pColorData->clrSign[3] = ArgbEncode(255, 128, 128, 128); } void CFWL_WidgetTP::InitTTO() { if (m_pTextOut) return; m_pFDEFont = CFWL_FontManager::GetInstance()->FindFont(L"Helvetica", 0, 0); m_pTextOut = pdfium::MakeUnique<CFDE_TextOut>(); m_pTextOut->SetFont(m_pFDEFont); m_pTextOut->SetFontSize(FWLTHEME_CAPACITY_FontSize); m_pTextOut->SetTextColor(FWLTHEME_CAPACITY_TextColor); m_pTextOut->SetEllipsisString(L"..."); } void CFWL_WidgetTP::FinalizeTTO() { m_pTextOut.reset(); } void CFWL_WidgetTP::DrawBorder(CFX_Graphics* pGraphics, const CFX_RectF* pRect, CFX_Matrix* pMatrix) { if (!pGraphics) return; if (!pRect) return; CFX_Path path; path.AddRectangle(pRect->left, pRect->top, pRect->width, pRect->height); path.AddRectangle(pRect->left + 1, pRect->top + 1, pRect->width - 2, pRect->height - 2); pGraphics->SaveGraphState(); CFX_Color crFill(ArgbEncode(255, 0, 0, 0)); pGraphics->SetFillColor(&crFill); pGraphics->FillPath(&path, FXFILL_ALTERNATE, pMatrix); pGraphics->RestoreGraphState(); } void CFWL_WidgetTP::FillBackground(CFX_Graphics* pGraphics, const CFX_RectF* pRect, CFX_Matrix* pMatrix) { FillSoildRect(pGraphics, FWLTHEME_COLOR_Background, pRect, pMatrix); } void CFWL_WidgetTP::FillSoildRect(CFX_Graphics* pGraphics, FX_ARGB fillColor, const CFX_RectF* pRect, CFX_Matrix* pMatrix) { if (!pGraphics) return; if (!pRect) return; pGraphics->SaveGraphState(); CFX_Color crFill(fillColor); pGraphics->SetFillColor(&crFill); CFX_Path path; path.AddRectangle(pRect->left, pRect->top, pRect->width, pRect->height); pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); pGraphics->RestoreGraphState(); } void CFWL_WidgetTP::DrawAxialShading(CFX_Graphics* pGraphics, FX_FLOAT fx1, FX_FLOAT fy1, FX_FLOAT fx2, FX_FLOAT fy2, FX_ARGB beginColor, FX_ARGB endColor, CFX_Path* path, int32_t fillMode, CFX_Matrix* pMatrix) { if (!pGraphics || !path) return; CFX_PointF begPoint(fx1, fy1); CFX_PointF endPoint(fx2, fy2); CFX_Shading shading(begPoint, endPoint, false, false, beginColor, endColor); pGraphics->SaveGraphState(); CFX_Color color1(&shading); pGraphics->SetFillColor(&color1); pGraphics->FillPath(path, fillMode, pMatrix); pGraphics->RestoreGraphState(); } void CFWL_WidgetTP::DrawFocus(CFX_Graphics* pGraphics, const CFX_RectF* pRect, CFX_Matrix* pMatrix) { if (!pGraphics) return; if (!pRect) return; pGraphics->SaveGraphState(); CFX_Color cr(0xFF000000); pGraphics->SetStrokeColor(&cr); FX_FLOAT DashPattern[2] = {1, 1}; pGraphics->SetLineDash(0.0f, DashPattern, 2); CFX_Path path; path.AddRectangle(pRect->left, pRect->top, pRect->width, pRect->height); pGraphics->StrokePath(&path, pMatrix); pGraphics->RestoreGraphState(); } void CFWL_WidgetTP::DrawArrow(CFX_Graphics* pGraphics, const CFX_RectF* pRect, FWLTHEME_DIRECTION eDict, FX_ARGB argSign, CFX_Matrix* pMatrix) { bool bVert = (eDict == FWLTHEME_DIRECTION_Up || eDict == FWLTHEME_DIRECTION_Down); FX_FLOAT fLeft = (FX_FLOAT)(((pRect->width - (bVert ? 9 : 6)) / 2 + pRect->left) + 0.5); FX_FLOAT fTop = (FX_FLOAT)(((pRect->height - (bVert ? 6 : 9)) / 2 + pRect->top) + 0.5); CFX_Path path; switch (eDict) { case FWLTHEME_DIRECTION_Down: { path.MoveTo(CFX_PointF(fLeft, fTop + 1)); path.LineTo(CFX_PointF(fLeft + 4, fTop + 5)); path.LineTo(CFX_PointF(fLeft + 8, fTop + 1)); path.LineTo(CFX_PointF(fLeft + 7, fTop)); path.LineTo(CFX_PointF(fLeft + 4, fTop + 3)); path.LineTo(CFX_PointF(fLeft + 1, fTop)); break; } case FWLTHEME_DIRECTION_Up: { path.MoveTo(CFX_PointF(fLeft, fTop + 4)); path.LineTo(CFX_PointF(fLeft + 4, fTop)); path.LineTo(CFX_PointF(fLeft + 8, fTop + 4)); path.LineTo(CFX_PointF(fLeft + 7, fTop + 5)); path.LineTo(CFX_PointF(fLeft + 4, fTop + 2)); path.LineTo(CFX_PointF(fLeft + 1, fTop + 5)); break; } case FWLTHEME_DIRECTION_Right: { path.MoveTo(CFX_PointF(fLeft + 1, fTop)); path.LineTo(CFX_PointF(fLeft + 5, fTop + 4)); path.LineTo(CFX_PointF(fLeft + 1, fTop + 8)); path.LineTo(CFX_PointF(fLeft, fTop + 7)); path.LineTo(CFX_PointF(fLeft + 3, fTop + 4)); path.LineTo(CFX_PointF(fLeft, fTop + 1)); break; } case FWLTHEME_DIRECTION_Left: { path.MoveTo(CFX_PointF(fLeft, fTop + 4)); path.LineTo(CFX_PointF(fLeft + 4, fTop)); path.LineTo(CFX_PointF(fLeft + 5, fTop + 1)); path.LineTo(CFX_PointF(fLeft + 2, fTop + 4)); path.LineTo(CFX_PointF(fLeft + 5, fTop + 7)); path.LineTo(CFX_PointF(fLeft + 4, fTop + 8)); break; } } CFX_Color cr(argSign); pGraphics->SetFillColor(&cr); pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix); } void CFWL_WidgetTP::DrawBtn(CFX_Graphics* pGraphics, const CFX_RectF* pRect, FWLTHEME_STATE eState, CFX_Matrix* pMatrix) { CFX_Path path; InitializeArrowColorData(); FX_FLOAT fRight = pRect->right(); FX_FLOAT fBottom = pRect->bottom(); path.AddRectangle(pRect->left, pRect->top, pRect->width, pRect->height); DrawAxialShading(pGraphics, pRect->left, pRect->top, fRight, fBottom, m_pColorData->clrStart[eState - 1], m_pColorData->clrEnd[eState - 1], &path, FXFILL_WINDING, pMatrix); CFX_Color rcStroke; rcStroke.Set(m_pColorData->clrBorder[eState - 1]); pGraphics->SetStrokeColor(&rcStroke); pGraphics->StrokePath(&path, pMatrix); } void CFWL_WidgetTP::DrawArrowBtn(CFX_Graphics* pGraphics, const CFX_RectF* pRect, FWLTHEME_DIRECTION eDict, FWLTHEME_STATE eState, CFX_Matrix* pMatrix) { DrawBtn(pGraphics, pRect, eState, pMatrix); InitializeArrowColorData(); DrawArrow(pGraphics, pRect, eDict, m_pColorData->clrSign[eState - 1], pMatrix); } CFWL_FontData::CFWL_FontData() : m_dwStyles(0), m_dwCodePage(0) {} CFWL_FontData::~CFWL_FontData() {} bool CFWL_FontData::Equal(const CFX_WideStringC& wsFontFamily, uint32_t dwFontStyles, uint16_t wCodePage) { return m_wsFamily == wsFontFamily && m_dwStyles == dwFontStyles && m_dwCodePage == wCodePage; } bool CFWL_FontData::LoadFont(const CFX_WideStringC& wsFontFamily, uint32_t dwFontStyles, uint16_t dwCodePage) { m_wsFamily = wsFontFamily; m_dwStyles = dwFontStyles; m_dwCodePage = dwCodePage; if (!m_pFontMgr) { #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ m_pFontMgr = CFGAS_FontMgr::Create(FX_GetDefFontEnumerator()); #else m_pFontSource = pdfium::MakeUnique<CFX_FontSourceEnum_File>(); m_pFontMgr = CFGAS_FontMgr::Create(m_pFontSource.get()); #endif } m_pFont = CFGAS_GEFont::LoadFont(wsFontFamily.c_str(), dwFontStyles, dwCodePage, m_pFontMgr.get()); return !!m_pFont; } CFWL_FontManager* CFWL_FontManager::s_FontManager = nullptr; CFWL_FontManager* CFWL_FontManager::GetInstance() { if (!s_FontManager) s_FontManager = new CFWL_FontManager; return s_FontManager; } void CFWL_FontManager::DestroyInstance() { delete s_FontManager; s_FontManager = nullptr; } CFWL_FontManager::CFWL_FontManager() {} CFWL_FontManager::~CFWL_FontManager() {} CFX_RetainPtr<CFGAS_GEFont> CFWL_FontManager::FindFont( const CFX_WideStringC& wsFontFamily, uint32_t dwFontStyles, uint16_t wCodePage) { for (const auto& pData : m_FontsArray) { if (pData->Equal(wsFontFamily, dwFontStyles, wCodePage)) return pData->GetFont(); } auto pFontData = pdfium::MakeUnique<CFWL_FontData>(); if (!pFontData->LoadFont(wsFontFamily, dwFontStyles, wCodePage)) return nullptr; m_FontsArray.push_back(std::move(pFontData)); return m_FontsArray.back()->GetFont(); } void FWLTHEME_Release() { CFWL_FontManager::DestroyInstance(); }