Home | History | Annotate | Download | only in theme
      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 <algorithm>
      8 
      9 #include "xfa/src/foxitlib.h"
     10 static void FWL_SetChildThemeID(IFWL_Widget* pParent, FX_DWORD dwThemeID) {
     11   IFWL_WidgetMgr* pWidgetMgr = FWL_GetWidgetMgr();
     12   IFWL_Widget* pChild =
     13       pWidgetMgr->GetWidget(pParent, FWL_WGTRELATION_FirstChild);
     14   while (pChild) {
     15     IFWL_ThemeProvider* pTheme = pChild->GetThemeProvider();
     16     if (pTheme) {
     17       pTheme->SetThemeID(pChild, dwThemeID, FALSE);
     18     }
     19     FWL_SetChildThemeID(pChild, dwThemeID);
     20     pChild = pWidgetMgr->GetWidget(pChild, FWL_WGTRELATION_NextSibling);
     21   }
     22 }
     23 FX_BOOL CFWL_WidgetTP::IsValidWidget(IFWL_Widget* pWidget) {
     24   return FALSE;
     25 }
     26 FX_DWORD CFWL_WidgetTP::GetThemeID(IFWL_Widget* pWidget) {
     27   return m_dwThemeID;
     28 }
     29 FX_DWORD CFWL_WidgetTP::SetThemeID(IFWL_Widget* pWidget,
     30                                    FX_DWORD dwThemeID,
     31                                    FX_BOOL bChildren) {
     32   FX_DWORD dwOld = m_dwThemeID;
     33   m_dwThemeID = dwThemeID;
     34   if (CFWL_ArrowData::IsInstance()) {
     35     CFWL_ArrowData::GetInstance()->SetColorData(FWL_GetThemeColor(dwThemeID));
     36   }
     37   if (bChildren) {
     38     FWL_SetChildThemeID(pWidget, dwThemeID);
     39   }
     40   return dwOld;
     41 }
     42 FWL_ERR CFWL_WidgetTP::GetThemeMatrix(IFWL_Widget* pWidget,
     43                                       CFX_Matrix& matrix) {
     44   matrix.Set(_ctm.a, _ctm.b, _ctm.c, _ctm.d, _ctm.e, _ctm.f);
     45   return FWL_ERR_Succeeded;
     46 }
     47 FWL_ERR CFWL_WidgetTP::SetThemeMatrix(IFWL_Widget* pWidget,
     48                                       const CFX_Matrix& matrix) {
     49   _ctm.Set(matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f);
     50   return FWL_ERR_Succeeded;
     51 }
     52 FX_BOOL CFWL_WidgetTP::DrawBackground(CFWL_ThemeBackground* pParams) {
     53   return TRUE;
     54 }
     55 FX_BOOL CFWL_WidgetTP::DrawText(CFWL_ThemeText* pParams) {
     56   if (!m_pTextOut) {
     57     InitTTO();
     58   }
     59   int32_t iLen = pParams->m_wsText.GetLength();
     60   if (iLen <= 0)
     61     return FALSE;
     62   CFX_Graphics* pGraphics = pParams->m_pGraphics;
     63   m_pTextOut->SetRenderDevice(pGraphics->GetRenderDevice());
     64   m_pTextOut->SetStyles(pParams->m_dwTTOStyles);
     65   m_pTextOut->SetAlignment(pParams->m_iTTOAlign);
     66   CFX_Matrix* pMatrix = &pParams->m_matrix;
     67   pMatrix->Concat(*pGraphics->GetMatrix());
     68   m_pTextOut->SetMatrix(*pMatrix);
     69   m_pTextOut->DrawLogicText(pParams->m_wsText, iLen, pParams->m_rtPart);
     70   return TRUE;
     71 }
     72 void* CFWL_WidgetTP::GetCapacity(CFWL_ThemePart* pThemePart,
     73                                  FX_DWORD dwCapacity) {
     74   switch (dwCapacity) {
     75     case FWL_WGTCAPACITY_CXBorder: {
     76       m_fValue = FWLTHEME_CAPACITY_CXBorder;
     77       break;
     78     }
     79     case FWL_WGTCAPACITY_CYBorder: {
     80       m_fValue = FWLTHEME_CAPACITY_CYBorder;
     81       break;
     82     }
     83     case FWL_WGTCAPACITY_EdgeFlat: {
     84       m_fValue = FWLTHEME_CAPACITY_EdgeFlat;
     85       break;
     86     }
     87     case FWL_WGTCAPACITY_EdgeRaised: {
     88       m_fValue = FWLTHEME_CAPACITY_EdgeRaised;
     89       break;
     90     }
     91     case FWL_WGTCAPACITY_EdgeSunken: {
     92       m_fValue = FWLTHEME_CAPACITY_EdgeSunken;
     93       break;
     94     }
     95     case FWL_WGTCAPACITY_FontSize: {
     96       m_fValue = FWLTHEME_CAPACITY_FontSize;
     97       break;
     98     }
     99     case FWL_WGTCAPACITY_TextColor: {
    100       m_dwValue = FWLTHEME_CAPACITY_TextColor;
    101       return &m_dwValue;
    102     }
    103     case FWL_WGTCAPACITY_ScrollBarWidth: {
    104       m_fValue = FWLTHEME_CAPACITY_ScrollBarWidth;
    105       break;
    106     }
    107     case FWL_WGTCAPACITY_Font: {
    108       return m_pFDEFont;
    109     }
    110     case FWL_WGTCAPACITY_TextSelColor: {
    111       m_dwValue = (m_dwThemeID == 0) ? FWLTHEME_CAPACITY_TextSelColor
    112                                      : FWLTHEME_COLOR_Green_BKSelected;
    113       return &m_dwValue;
    114     }
    115     case FWL_WGTCAPACITY_LineHeight: {
    116       m_fValue = FWLTHEME_CAPACITY_LineHeight;
    117       break;
    118     }
    119     case FWL_WGTCAPACITY_UIMargin: {
    120       m_rtMargin.Set(0, 0, 0, 0);
    121       return &m_rtMargin;
    122     }
    123     default: { return NULL; }
    124   }
    125   return &m_fValue;
    126 }
    127 FX_BOOL CFWL_WidgetTP::IsCustomizedLayout(IFWL_Widget* pWidget) {
    128   return FWL_GetThemeLayout(m_dwThemeID);
    129 }
    130 FWL_ERR CFWL_WidgetTP::GetPartRect(CFWL_ThemePart* pThemePart,
    131                                    CFX_RectF& rect) {
    132   return FWL_ERR_Succeeded;
    133 }
    134 FX_BOOL CFWL_WidgetTP::IsInPart(CFWL_ThemePart* pThemePart,
    135                                 FX_FLOAT fx,
    136                                 FX_FLOAT fy) {
    137   return TRUE;
    138 }
    139 FX_BOOL CFWL_WidgetTP::CalcTextRect(CFWL_ThemeText* pParams, CFX_RectF& rect) {
    140   if (!pParams)
    141     return FALSE;
    142   if (!m_pTextOut)
    143     return FALSE;
    144   m_pTextOut->SetAlignment(pParams->m_iTTOAlign);
    145   m_pTextOut->SetStyles(pParams->m_dwTTOStyles | FDE_TTOSTYLE_ArabicContext);
    146   m_pTextOut->CalcLogicSize(pParams->m_wsText, pParams->m_wsText.GetLength(),
    147                             rect);
    148   return TRUE;
    149 }
    150 FWL_ERR CFWL_WidgetTP::Initialize() {
    151   m_dwThemeID = 0;
    152   _ctm.SetIdentity();
    153   return FWL_ERR_Succeeded;
    154 }
    155 FWL_ERR CFWL_WidgetTP::Finalize() {
    156   if (!m_pTextOut) {
    157     FinalizeTTO();
    158   }
    159   return FWL_ERR_Succeeded;
    160 }
    161 CFWL_WidgetTP::~CFWL_WidgetTP() {}
    162 FWL_ERR CFWL_WidgetTP::SetFont(IFWL_Widget* pWidget,
    163                                const FX_WCHAR* strFont,
    164                                FX_FLOAT fFontSize,
    165                                FX_ARGB rgbFont) {
    166   if (!m_pTextOut) {
    167     return FWL_ERR_Succeeded;
    168   }
    169   m_pFDEFont = FWL_GetFontManager()->FindFont(strFont, 0, 0);
    170   m_pTextOut->SetFont(m_pFDEFont);
    171   m_pTextOut->SetFontSize(fFontSize);
    172   m_pTextOut->SetTextColor(rgbFont);
    173   return FWL_ERR_Succeeded;
    174 }
    175 FWL_ERR CFWL_WidgetTP::SetFont(IFWL_Widget* pWidget,
    176                                IFX_Font* pFont,
    177                                FX_FLOAT fFontSize,
    178                                FX_ARGB rgbFont) {
    179   if (!m_pTextOut) {
    180     return FWL_ERR_Succeeded;
    181   }
    182   m_pTextOut->SetFont(pFont);
    183   m_pTextOut->SetFontSize(fFontSize);
    184   m_pTextOut->SetTextColor(rgbFont);
    185   return FWL_ERR_Succeeded;
    186 }
    187 IFX_Font* CFWL_WidgetTP::GetFont(IFWL_Widget* pWidget) {
    188   return m_pFDEFont;
    189 }
    190 CFWL_WidgetTP::CFWL_WidgetTP()
    191     : m_dwRefCount(1), m_pTextOut(NULL), m_pFDEFont(NULL), m_dwThemeID(0) {}
    192 FX_ERR CFWL_WidgetTP::InitTTO() {
    193   if (m_pTextOut) {
    194     return FWL_ERR_Succeeded;
    195   }
    196   m_pFDEFont = FWL_GetFontManager()->FindFont(FX_WSTRC(L"Helvetica"), 0, 0);
    197   m_pTextOut = IFDE_TextOut::Create();
    198   m_pTextOut->SetFont(m_pFDEFont);
    199   m_pTextOut->SetFontSize(FWLTHEME_CAPACITY_FontSize);
    200   m_pTextOut->SetTextColor(FWLTHEME_CAPACITY_TextColor);
    201   m_pTextOut->SetEllipsisString(L"...");
    202   return FWL_ERR_Succeeded;
    203 }
    204 FX_ERR CFWL_WidgetTP::FinalizeTTO() {
    205   if (m_pTextOut) {
    206     m_pTextOut->Release();
    207     m_pTextOut = NULL;
    208   }
    209   return FWL_ERR_Succeeded;
    210 }
    211 #ifdef THEME_XPSimilar
    212 void CFWL_WidgetTP::DrawEdge(CFX_Graphics* pGraphics,
    213                              FX_DWORD dwStyles,
    214                              const CFX_RectF* pRect,
    215                              CFX_Matrix* pMatrix) {
    216   if (!pGraphics)
    217     return;
    218   if (!pRect)
    219     return;
    220   pGraphics->SaveGraphState();
    221   CFX_Color crStroke(FWL_GetThemeColor(m_dwThemeID) == 0
    222                          ? ArgbEncode(255, 127, 157, 185)
    223                          : FWLTHEME_COLOR_Green_BKSelected);
    224   pGraphics->SetStrokeColor(&crStroke);
    225   CFX_Path path;
    226   path.Create();
    227   path.AddRectangle(pRect->left, pRect->top, pRect->width - 1,
    228                     pRect->height - 1);
    229   pGraphics->StrokePath(&path, pMatrix);
    230   path.Clear();
    231   crStroke = ArgbEncode(255, 255, 255, 255);
    232   pGraphics->SetStrokeColor(&crStroke);
    233   path.AddRectangle(pRect->left + 1, pRect->top + 1, pRect->width - 3,
    234                     pRect->height - 3);
    235   pGraphics->StrokePath(&path, pMatrix);
    236   pGraphics->RestoreGraphState();
    237 }
    238 #else
    239 void CFWL_WidgetTP::DrawEdge(CFX_Graphics* pGraphics,
    240                              FX_DWORD dwStyles,
    241                              const CFX_RectF* pRect,
    242                              CFX_Matrix* pMatrix) {
    243   if (!pGraphics)
    244     return;
    245   if (!pRect)
    246     return;
    247   FWLTHEME_EDGE eType;
    248   FX_FLOAT fWidth;
    249   switch (dwStyles & FWL_WGTSTYLE_EdgeMask) {
    250     case FWL_WGTSTYLE_EdgeRaised: {
    251       eType = FWLTHEME_EDGE_Raised, fWidth = FWLTHEME_CAPACITY_EdgeRaised;
    252       break;
    253     }
    254     case FWL_WGTSTYLE_EdgeSunken: {
    255       eType = FWLTHEME_EDGE_Sunken, fWidth = FWLTHEME_CAPACITY_EdgeSunken;
    256       break;
    257     }
    258     case FWL_WGTSTYLE_EdgeFlat:
    259     default: { return; }
    260   }
    261   Draw3DRect(pGraphics, eType, fWidth, pRect, FWLTHEME_COLOR_EDGELT1,
    262              FWLTHEME_COLOR_EDGELT2, FWLTHEME_COLOR_EDGERB1,
    263              FWLTHEME_COLOR_EDGERB2, pMatrix);
    264 }
    265 #endif
    266 void CFWL_WidgetTP::Draw3DRect(CFX_Graphics* pGraphics,
    267                                FWLTHEME_EDGE eType,
    268                                FX_FLOAT fWidth,
    269                                const CFX_RectF* pRect,
    270                                FX_ARGB cr1,
    271                                FX_ARGB cr2,
    272                                FX_ARGB cr3,
    273                                FX_ARGB cr4,
    274                                CFX_Matrix* pMatrix) {
    275   if (!pGraphics)
    276     return;
    277   if (!pRect)
    278     return;
    279   pGraphics->SaveGraphState();
    280   if (eType == FWLTHEME_EDGE_Flat) {
    281     CFX_Path path;
    282     path.Create();
    283     path.AddRectangle(pRect->left, pRect->top, pRect->width, pRect->height);
    284     path.AddRectangle(pRect->left + 1, pRect->top + 1, pRect->width - 2,
    285                       pRect->height - 2);
    286     CFX_Color cr(ArgbEncode(255, 100, 100, 100));
    287     pGraphics->SetFillColor(&cr);
    288     pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix);
    289     path.Clear();
    290     path.AddRectangle(pRect->left + 1, pRect->top + 1, pRect->width - 2,
    291                       pRect->height - 2);
    292     path.AddRectangle(pRect->left + 2, pRect->top + 2, pRect->width - 4,
    293                       pRect->height - 4);
    294     cr.Set(0xFFFFFFFF);
    295     pGraphics->SetFillColor(&cr);
    296     pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix);
    297   } else {
    298     FX_FLOAT fLeft = pRect->left;
    299     FX_FLOAT fRight = pRect->right();
    300     FX_FLOAT fTop = pRect->top;
    301     FX_FLOAT fBottom = pRect->bottom();
    302     FX_FLOAT fHalfWidth = fWidth / 2.0f;
    303     CFX_Color crLT(eType == FWLTHEME_EDGE_Raised ? cr4 : cr1);
    304     pGraphics->SetFillColor(&crLT);
    305     CFX_Path pathLT;
    306     pathLT.Create();
    307     pathLT.MoveTo(fLeft, fBottom - fHalfWidth);
    308     pathLT.LineTo(fLeft, fTop);
    309     pathLT.LineTo(fRight - fHalfWidth, fTop);
    310     pathLT.LineTo(fRight - fHalfWidth, fTop + fHalfWidth);
    311     pathLT.LineTo(fLeft + fHalfWidth, fTop + fHalfWidth);
    312     pathLT.LineTo(fLeft + fHalfWidth, fBottom - fHalfWidth);
    313     pathLT.LineTo(fLeft, fBottom - fHalfWidth);
    314     pGraphics->FillPath(&pathLT, FXFILL_WINDING, pMatrix);
    315     crLT = CFX_Color(eType == FWLTHEME_EDGE_Raised ? cr3 : cr2);
    316     pGraphics->SetFillColor(&crLT);
    317     pathLT.Clear();
    318     pathLT.MoveTo(fLeft + fHalfWidth, fBottom - fWidth);
    319     pathLT.LineTo(fLeft + fHalfWidth, fTop + fHalfWidth);
    320     pathLT.LineTo(fRight - fWidth, fTop + fHalfWidth);
    321     pathLT.LineTo(fRight - fWidth, fTop + fWidth);
    322     pathLT.LineTo(fLeft + fWidth, fTop + fWidth);
    323     pathLT.LineTo(fLeft + fWidth, fBottom - fWidth);
    324     pathLT.LineTo(fLeft + fHalfWidth, fBottom - fWidth);
    325     pGraphics->FillPath(&pathLT, FXFILL_WINDING, pMatrix);
    326     CFX_Color crRB(eType == FWLTHEME_EDGE_Raised ? cr1 : cr3);
    327     pGraphics->SetFillColor(&crRB);
    328     CFX_Path pathRB;
    329     pathRB.Create();
    330     pathRB.MoveTo(fRight - fHalfWidth, fTop + fHalfWidth);
    331     pathRB.LineTo(fRight - fHalfWidth, fBottom - fHalfWidth);
    332     pathRB.LineTo(fLeft + fHalfWidth, fBottom - fHalfWidth);
    333     pathRB.LineTo(fLeft + fHalfWidth, fBottom - fWidth);
    334     pathRB.LineTo(fRight - fWidth, fBottom - fWidth);
    335     pathRB.LineTo(fRight - fWidth, fTop + fHalfWidth);
    336     pathRB.LineTo(fRight - fHalfWidth, fTop + fHalfWidth);
    337     pGraphics->FillPath(&pathRB, FXFILL_WINDING, pMatrix);
    338     crRB = CFX_Color(eType == FWLTHEME_EDGE_Raised ? cr2 : cr4);
    339     pGraphics->SetFillColor(&crRB);
    340     pathRB.Clear();
    341     pathRB.MoveTo(fRight, fTop);
    342     pathRB.LineTo(fRight, fBottom);
    343     pathRB.LineTo(fLeft, fBottom);
    344     pathRB.LineTo(fLeft, fBottom - fHalfWidth);
    345     pathRB.LineTo(fRight - fHalfWidth, fBottom - fHalfWidth);
    346     pathRB.LineTo(fRight - fHalfWidth, fTop);
    347     pathRB.LineTo(fRight, fTop);
    348     pGraphics->FillPath(&pathRB, FXFILL_WINDING, pMatrix);
    349   }
    350   pGraphics->RestoreGraphState();
    351 }
    352 void CFWL_WidgetTP::Draw3DCircle(CFX_Graphics* pGraphics,
    353                                  FWLTHEME_EDGE eType,
    354                                  FX_FLOAT fWidth,
    355                                  const CFX_RectF* pRect,
    356                                  FX_ARGB cr1,
    357                                  FX_ARGB cr2,
    358                                  FX_ARGB cr3,
    359                                  FX_ARGB cr4,
    360                                  CFX_Matrix* pMatrix) {
    361   if (!pGraphics)
    362     return;
    363   if (!pRect)
    364     return;
    365   pGraphics->SaveGraphState();
    366   CFX_Path path;
    367   path.Create();
    368   path.AddArc(pRect->left, pRect->top, pRect->width, pRect->height,
    369               FWLTHEME_PI * 3 / 4, FWLTHEME_PI);
    370   CFX_Color crFill1(eType == FWLTHEME_EDGE_Raised ? cr4 : cr1);
    371   pGraphics->SetStrokeColor(&crFill1);
    372   pGraphics->StrokePath(&path, pMatrix);
    373   CFX_RectF rtInner(*pRect);
    374   rtInner.Deflate(pRect->width / 4, pRect->height / 4);
    375   path.Clear();
    376   path.AddArc(rtInner.left, rtInner.top, rtInner.width, rtInner.height,
    377               FWLTHEME_PI * 3 / 4, FWLTHEME_PI);
    378   CFX_Color crFill2(eType == FWLTHEME_EDGE_Raised ? cr3 : cr2);
    379   pGraphics->SetStrokeColor(&crFill2);
    380   pGraphics->StrokePath(&path, pMatrix);
    381   path.Clear();
    382   path.AddArc(pRect->left, pRect->top, pRect->width, pRect->height,
    383               FWLTHEME_PI * 7 / 4, FWLTHEME_PI);
    384   CFX_Color crFill3(eType == FWLTHEME_EDGE_Raised ? cr1 : cr3);
    385   pGraphics->SetStrokeColor(&crFill3);
    386   pGraphics->StrokePath(&path, pMatrix);
    387   path.AddArc(rtInner.left, rtInner.top, rtInner.width, rtInner.height,
    388               FWLTHEME_PI * 7 / 4, FWLTHEME_PI);
    389   CFX_Color crFill4(eType == FWLTHEME_EDGE_Raised ? cr2 : cr4);
    390   pGraphics->SetStrokeColor(&crFill4);
    391   pGraphics->StrokePath(&path, pMatrix);
    392   pGraphics->RestoreGraphState();
    393 }
    394 void CFWL_WidgetTP::DrawBorder(CFX_Graphics* pGraphics,
    395                                const CFX_RectF* pRect,
    396                                CFX_Matrix* pMatrix) {
    397   if (!pGraphics)
    398     return;
    399   if (!pRect)
    400     return;
    401   CFX_Path path;
    402   path.Create();
    403   path.AddRectangle(pRect->left, pRect->top, pRect->width, pRect->height);
    404   path.AddRectangle(pRect->left + 1, pRect->top + 1, pRect->width - 2,
    405                     pRect->height - 2);
    406   pGraphics->SaveGraphState();
    407   CFX_Color crFill(ArgbEncode(255, 0, 0, 0));
    408   pGraphics->SetFillColor(&crFill);
    409   pGraphics->FillPath(&path, FXFILL_ALTERNATE, pMatrix);
    410   pGraphics->RestoreGraphState();
    411 }
    412 void CFWL_WidgetTP::FillBackground(CFX_Graphics* pGraphics,
    413                                    const CFX_RectF* pRect,
    414                                    CFX_Matrix* pMatrix) {
    415   FillSoildRect(pGraphics, FWLTHEME_COLOR_Background, pRect, pMatrix);
    416 }
    417 void CFWL_WidgetTP::FillSoildRect(CFX_Graphics* pGraphics,
    418                                   FX_ARGB fillColor,
    419                                   const CFX_RectF* pRect,
    420                                   CFX_Matrix* pMatrix) {
    421   if (!pGraphics)
    422     return;
    423   if (!pRect)
    424     return;
    425   pGraphics->SaveGraphState();
    426   CFX_Color crFill(fillColor);
    427   pGraphics->SetFillColor(&crFill);
    428   CFX_Path path;
    429   path.Create();
    430   path.AddRectangle(pRect->left, pRect->top, pRect->width, pRect->height);
    431   pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix);
    432   pGraphics->RestoreGraphState();
    433 }
    434 void CFWL_WidgetTP::DrawAxialShading(CFX_Graphics* pGraphics,
    435                                      FX_FLOAT fx1,
    436                                      FX_FLOAT fy1,
    437                                      FX_FLOAT fx2,
    438                                      FX_FLOAT fy2,
    439                                      FX_ARGB beginColor,
    440                                      FX_ARGB endColor,
    441                                      CFX_Path* path,
    442                                      int32_t fillMode,
    443                                      CFX_Matrix* pMatrix) {
    444   if (!pGraphics)
    445     return;
    446   if (!path)
    447     return;
    448   CFX_PointF begPoint, endPoint;
    449   begPoint.Set(fx1, fy1);
    450   endPoint.Set(fx2, fy2);
    451   CFX_Shading shading;
    452   shading.CreateAxial(begPoint, endPoint, FALSE, FALSE, beginColor, endColor);
    453   pGraphics->SaveGraphState();
    454   CFX_Color color1(&shading);
    455   pGraphics->SetFillColor(&color1);
    456   pGraphics->FillPath(path, fillMode, pMatrix);
    457   pGraphics->RestoreGraphState();
    458 }
    459 void CFWL_WidgetTP::DrawAnnulusRect(CFX_Graphics* pGraphics,
    460                                     FX_ARGB fillColor,
    461                                     const CFX_RectF* pRect,
    462                                     FX_FLOAT fRingWidth,
    463                                     CFX_Matrix* pMatrix) {
    464   if (!pGraphics)
    465     return;
    466   if (!pRect)
    467     return;
    468   pGraphics->SaveGraphState();
    469   CFX_Color cr(fillColor);
    470   pGraphics->SetFillColor(&cr);
    471   CFX_Path path;
    472   path.Create();
    473   CFX_RectF rtInner(*pRect);
    474   rtInner.Deflate(fRingWidth, fRingWidth);
    475   path.AddRectangle(rtInner.left, rtInner.top, rtInner.width, rtInner.height);
    476   path.AddRectangle(pRect->left, pRect->top, pRect->width, pRect->height);
    477   pGraphics->FillPath(&path, FXFILL_ALTERNATE, pMatrix);
    478   pGraphics->RestoreGraphState();
    479 }
    480 void CFWL_WidgetTP::DrawAnnulusCircle(CFX_Graphics* pGraphics,
    481                                       FX_ARGB fillColor,
    482                                       const CFX_RectF* pRect,
    483                                       FX_FLOAT fWidth,
    484                                       CFX_Matrix* pMatrix) {
    485   if (!pGraphics)
    486     return;
    487   if (!pRect)
    488     return;
    489   if (fWidth > pRect->width / 2) {
    490     return;
    491   }
    492   pGraphics->SaveGraphState();
    493   CFX_Color cr(fillColor);
    494   pGraphics->SetFillColor(&cr);
    495   CFX_Path path;
    496   path.Create();
    497   path.AddEllipse(*pRect);
    498   CFX_RectF rtIn(*pRect);
    499   rtIn.Inflate(-fWidth, -fWidth);
    500   path.AddEllipse(rtIn);
    501   pGraphics->FillPath(&path, FXFILL_ALTERNATE, pMatrix);
    502   pGraphics->RestoreGraphState();
    503 }
    504 void CFWL_WidgetTP::DrawFocus(CFX_Graphics* pGraphics,
    505                               const CFX_RectF* pRect,
    506                               CFX_Matrix* pMatrix) {
    507   if (!pGraphics)
    508     return;
    509   if (!pRect)
    510     return;
    511   pGraphics->SaveGraphState();
    512   CFX_Color cr(0xFF000000);
    513   pGraphics->SetStrokeColor(&cr);
    514   FX_FLOAT DashPattern[2] = {1, 1};
    515   pGraphics->SetLineDash(0.0f, DashPattern, 2);
    516   CFX_Path path;
    517   path.Create();
    518   path.AddRectangle(pRect->left, pRect->top, pRect->width, pRect->height);
    519   pGraphics->StrokePath(&path, pMatrix);
    520   pGraphics->RestoreGraphState();
    521 }
    522 #define FWLTHEME_ARROW_Denominator 3
    523 void CFWL_WidgetTP::DrawArrow(CFX_Graphics* pGraphics,
    524                               const CFX_RectF* pRect,
    525                               FWLTHEME_DIRECTION eDict,
    526                               FX_ARGB argbFill,
    527                               FX_BOOL bPressed,
    528                               CFX_Matrix* pMatrix) {
    529   CFX_RectF rtArrow(*pRect);
    530   CFX_Path path;
    531   path.Create();
    532   FX_FLOAT fBtn =
    533       std::min(pRect->width, pRect->height) / FWLTHEME_ARROW_Denominator;
    534   rtArrow.left = pRect->left + (pRect->width - fBtn) / 2;
    535   rtArrow.top = pRect->top + (pRect->height - fBtn) / 2;
    536   rtArrow.width = fBtn;
    537   rtArrow.height = fBtn;
    538   if (bPressed) {
    539     rtArrow.Offset(1, 1);
    540   }
    541   switch (eDict) {
    542     case FWLTHEME_DIRECTION_Up: {
    543       path.MoveTo(rtArrow.left, rtArrow.bottom());
    544       path.LineTo(rtArrow.right(), rtArrow.bottom());
    545       path.LineTo(rtArrow.left + fBtn / 2, rtArrow.top);
    546       path.LineTo(rtArrow.left, rtArrow.bottom());
    547       break;
    548     }
    549     case FWLTHEME_DIRECTION_Left: {
    550       path.MoveTo(rtArrow.right(), rtArrow.top);
    551       path.LineTo(rtArrow.right(), rtArrow.bottom());
    552       path.LineTo(rtArrow.left, rtArrow.top + fBtn / 2);
    553       path.LineTo(rtArrow.right(), rtArrow.top);
    554       break;
    555     }
    556     case FWLTHEME_DIRECTION_Right: {
    557       path.MoveTo(rtArrow.left, rtArrow.top);
    558       path.LineTo(rtArrow.left, rtArrow.bottom());
    559       path.LineTo(rtArrow.right(), rtArrow.top + fBtn / 2);
    560       path.LineTo(rtArrow.left, rtArrow.top);
    561       break;
    562     }
    563     case FWLTHEME_DIRECTION_Down:
    564     default: {
    565       path.MoveTo(rtArrow.left, rtArrow.top);
    566       path.LineTo(rtArrow.right(), rtArrow.top);
    567       path.LineTo(rtArrow.left + fBtn / 2, rtArrow.bottom());
    568       path.LineTo(rtArrow.left, rtArrow.top);
    569     }
    570   }
    571   pGraphics->SaveGraphState();
    572   CFX_Color cr(argbFill);
    573   pGraphics->SetFillColor(&cr);
    574   pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix);
    575   pGraphics->RestoreGraphState();
    576 }
    577 void CFWL_WidgetTP::DrawArrow(CFX_Graphics* pGraphics,
    578                               const CFX_RectF* pRect,
    579                               FWLTHEME_DIRECTION eDict,
    580                               FX_ARGB argSign,
    581                               CFX_Matrix* pMatrix) {
    582   FX_BOOL bVert =
    583       (eDict == FWLTHEME_DIRECTION_Up || eDict == FWLTHEME_DIRECTION_Down);
    584   FX_FLOAT fLeft =
    585       (FX_FLOAT)(((pRect->width - (bVert ? 9 : 6)) / 2 + pRect->left) + 0.5);
    586   FX_FLOAT fTop =
    587       (FX_FLOAT)(((pRect->height - (bVert ? 6 : 9)) / 2 + pRect->top) + 0.5);
    588   CFX_Path path;
    589   path.Create();
    590   switch (eDict) {
    591     case FWLTHEME_DIRECTION_Down: {
    592       path.MoveTo(fLeft, fTop + 1);
    593       path.LineTo(fLeft + 4, fTop + 5);
    594       path.LineTo(fLeft + 8, fTop + 1);
    595       path.LineTo(fLeft + 7, fTop);
    596       path.LineTo(fLeft + 4, fTop + 3);
    597       path.LineTo(fLeft + 1, fTop);
    598       break;
    599     }
    600     case FWLTHEME_DIRECTION_Up: {
    601       path.MoveTo(fLeft, fTop + 4);
    602       path.LineTo(fLeft + 4, fTop);
    603       path.LineTo(fLeft + 8, fTop + 4);
    604       path.LineTo(fLeft + 7, fTop + 5);
    605       path.LineTo(fLeft + 4, fTop + 2);
    606       path.LineTo(fLeft + 1, fTop + 5);
    607       break;
    608     }
    609     case FWLTHEME_DIRECTION_Right: {
    610       path.MoveTo(fLeft + 1, fTop);
    611       path.LineTo(fLeft + 5, fTop + 4);
    612       path.LineTo(fLeft + 1, fTop + 8);
    613       path.LineTo(fLeft, fTop + 7);
    614       path.LineTo(fLeft + 3, fTop + 4);
    615       path.LineTo(fLeft, fTop + 1);
    616       break;
    617     }
    618     case FWLTHEME_DIRECTION_Left: {
    619       path.MoveTo(fLeft, fTop + 4);
    620       path.LineTo(fLeft + 4, fTop);
    621       path.LineTo(fLeft + 5, fTop + 1);
    622       path.LineTo(fLeft + 2, fTop + 4);
    623       path.LineTo(fLeft + 5, fTop + 7);
    624       path.LineTo(fLeft + 4, fTop + 8);
    625       break;
    626     }
    627   }
    628   CFX_Color cr(argSign);
    629   pGraphics->SetFillColor(&cr);
    630   pGraphics->FillPath(&path, FXFILL_WINDING, pMatrix);
    631 }
    632 void CFWL_WidgetTP::DrawBtn(CFX_Graphics* pGraphics,
    633                             const CFX_RectF* pRect,
    634                             FWLTHEME_STATE eState,
    635                             CFX_Matrix* pMatrix) {
    636   CFX_Path path;
    637   path.Create();
    638   if (!CFWL_ArrowData::IsInstance()) {
    639     CFWL_ArrowData::GetInstance()->SetColorData(FWL_GetThemeColor(m_dwThemeID));
    640   }
    641   CFWL_ArrowData::CColorData* pColorData =
    642       CFWL_ArrowData::GetInstance()->m_pColorData;
    643   FX_FLOAT fRight = pRect->right();
    644   FX_FLOAT fBottom = pRect->bottom();
    645   path.AddRectangle(pRect->left, pRect->top, pRect->width, pRect->height);
    646   DrawAxialShading(pGraphics, pRect->left, pRect->top, fRight, fBottom,
    647                    pColorData->clrStart[eState - 1],
    648                    pColorData->clrEnd[eState - 1], &path, FXFILL_WINDING,
    649                    pMatrix);
    650   CFX_Color rcStroke;
    651   rcStroke.Set(pColorData->clrBorder[eState - 1]);
    652   pGraphics->SetStrokeColor(&rcStroke);
    653   pGraphics->StrokePath(&path, pMatrix);
    654 }
    655 void CFWL_WidgetTP::DrawArrowBtn(CFX_Graphics* pGraphics,
    656                                  const CFX_RectF* pRect,
    657                                  FWLTHEME_DIRECTION eDict,
    658                                  FWLTHEME_STATE eState,
    659                                  CFX_Matrix* pMatrix) {
    660   DrawBtn(pGraphics, pRect, eState, pMatrix);
    661   if (!CFWL_ArrowData::IsInstance()) {
    662     CFWL_ArrowData::GetInstance()->SetColorData(FWL_GetThemeColor(m_dwThemeID));
    663   }
    664   CFWL_ArrowData::CColorData* pColorData =
    665       CFWL_ArrowData::GetInstance()->m_pColorData;
    666   DrawArrow(pGraphics, pRect, eDict, pColorData->clrSign[eState - 1], pMatrix);
    667 }
    668 FWLCOLOR CFWL_WidgetTP::BlendColor(FWLCOLOR srcColor,
    669                                    FWLCOLOR renderColor,
    670                                    uint8_t scale) {
    671   FWLCOLOR dstColor;
    672   uint8_t n = 255 - scale;
    673   dstColor.a = (uint8_t)(
    674       ((FX_WORD)srcColor.a * n + (FX_WORD)renderColor.a * scale) >> 8);
    675   dstColor.r = (uint8_t)(
    676       ((FX_WORD)srcColor.r * n + (FX_WORD)renderColor.r * scale) >> 8);
    677   dstColor.g = (uint8_t)(
    678       ((FX_WORD)srcColor.g * n + (FX_WORD)renderColor.g * scale) >> 8);
    679   dstColor.b = (uint8_t)(
    680       ((FX_WORD)srcColor.b * n + (FX_WORD)renderColor.b * scale) >> 8);
    681   return dstColor;
    682 }
    683 CFWL_ArrowData::CFWL_ArrowData() : m_pColorData(NULL) {
    684   SetColorData(0);
    685 }
    686 CFWL_FontManager* FWL_GetFontManager() {
    687   static CFWL_FontManager* _fontManager = NULL;
    688   if (_fontManager == NULL) {
    689     _fontManager = new CFWL_FontManager;
    690   }
    691   return _fontManager;
    692 }
    693 void FWL_ReleaseFontManager() {
    694   CFWL_FontManager* fontManager = FWL_GetFontManager();
    695   delete fontManager;
    696 }
    697 CFWL_FontData::CFWL_FontData()
    698     : m_dwStyles(0),
    699       m_dwCodePage(0),
    700       m_pFont(0),
    701       m_pFontMgr(NULL)
    702 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
    703       ,
    704       m_pFontSource(NULL)
    705 #endif
    706 {
    707 }
    708 CFWL_FontData::~CFWL_FontData() {
    709   if (m_pFont) {
    710     m_pFont->Release();
    711   }
    712   if (m_pFontMgr) {
    713     m_pFontMgr->Release();
    714   }
    715 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
    716   if (m_pFontSource != NULL) {
    717     m_pFontSource->Release();
    718   }
    719 #endif
    720 }
    721 FX_BOOL CFWL_FontData::Equal(const CFX_WideStringC& wsFontFamily,
    722                              FX_DWORD dwFontStyles,
    723                              FX_WORD wCodePage) {
    724   return m_wsFamily == wsFontFamily && m_dwStyles == dwFontStyles &&
    725          m_dwCodePage == wCodePage;
    726 }
    727 FX_BOOL CFWL_FontData::LoadFont(const CFX_WideStringC& wsFontFamily,
    728                                 FX_DWORD dwFontStyles,
    729                                 FX_WORD dwCodePage) {
    730   m_wsFamily = wsFontFamily;
    731   m_dwStyles = dwFontStyles;
    732   m_dwCodePage = dwCodePage;
    733   if (!m_pFontMgr) {
    734 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    735     m_pFontMgr = IFX_FontMgr::Create(FX_GetDefFontEnumerator());
    736 #else
    737     m_pFontSource = FX_CreateDefaultFontSourceEnum();
    738     m_pFontMgr = IFX_FontMgr::Create(m_pFontSource);
    739 #endif
    740   }
    741   m_pFont = IFX_Font::LoadFont(wsFontFamily.GetPtr(), dwFontStyles, dwCodePage,
    742                                m_pFontMgr);
    743   return m_pFont != NULL;
    744 }
    745 CFWL_FontManager::CFWL_FontManager() {}
    746 CFWL_FontManager::~CFWL_FontManager() {
    747   for (int32_t i = 0; i < m_arrFonts.GetSize(); i++) {
    748     delete static_cast<CFWL_FontData*>(m_arrFonts[i]);
    749   }
    750   m_arrFonts.RemoveAll();
    751 }
    752 IFX_Font* CFWL_FontManager::FindFont(const CFX_WideStringC& wsFontFamily,
    753                                      FX_DWORD dwFontStyles,
    754                                      FX_WORD wCodePage) {
    755   for (int32_t i = 0; i < m_arrFonts.GetSize(); i++) {
    756     CFWL_FontData* data = static_cast<CFWL_FontData*>(m_arrFonts[i]);
    757     if (data->Equal(wsFontFamily, dwFontStyles, wCodePage)) {
    758       return data->GetFont();
    759     }
    760   }
    761   CFWL_FontData* fontData = new CFWL_FontData;
    762   if (!fontData->LoadFont(wsFontFamily, dwFontStyles, wCodePage)) {
    763     delete fontData;
    764     return NULL;
    765   }
    766   m_arrFonts.Add(fontData);
    767   return fontData->GetFont();
    768 }
    769 FX_BOOL FWLTHEME_Init() {
    770   return TRUE;
    771 }
    772 void FWLTHEME_Release() {
    773   CFWL_ArrowData::DestroyInstance();
    774   FWL_ReleaseFontManager();
    775 }
    776 FX_DWORD FWL_GetThemeLayout(FX_DWORD dwThemeID) {
    777   return 0xffff0000 & dwThemeID;
    778 }
    779 FX_DWORD FWL_GetThemeColor(FX_DWORD dwThemeID) {
    780   return 0x0000ffff & dwThemeID;
    781 }
    782 FX_DWORD FWL_MakeThemeID(FX_DWORD dwLayout, FX_DWORD dwColor) {
    783   return (dwLayout << 16) | (0x0000FFFF & dwColor);
    784 }
    785 CFWL_ArrowData* CFWL_ArrowData::m_pInstance = NULL;
    786 CFWL_ArrowData* CFWL_ArrowData::GetInstance() {
    787   if (!m_pInstance) {
    788     m_pInstance = new CFWL_ArrowData;
    789   }
    790   return m_pInstance;
    791 }
    792 FX_BOOL CFWL_ArrowData::IsInstance() {
    793   return (m_pInstance != NULL);
    794 }
    795 void CFWL_ArrowData::DestroyInstance() {
    796   if (m_pInstance) {
    797     delete m_pInstance;
    798     m_pInstance = NULL;
    799   }
    800 }
    801 CFWL_ArrowData::~CFWL_ArrowData() {
    802   if (m_pColorData) {
    803     delete m_pColorData;
    804     m_pColorData = NULL;
    805   }
    806 }
    807 void CFWL_ArrowData::SetColorData(FX_DWORD dwID) {
    808   if (!m_pColorData) {
    809     m_pColorData = new CColorData;
    810   }
    811   if (dwID) {
    812     m_pColorData->clrBorder[0] = ArgbEncode(255, 142, 153, 125);
    813     m_pColorData->clrBorder[1] = ArgbEncode(255, 157, 171, 119);
    814     m_pColorData->clrBorder[2] = ArgbEncode(255, 118, 131, 97);
    815     m_pColorData->clrBorder[3] = ArgbEncode(255, 172, 168, 153);
    816     m_pColorData->clrStart[0] = ArgbEncode(255, 203, 215, 186);
    817     m_pColorData->clrStart[1] = ArgbEncode(255, 218, 232, 185);
    818     m_pColorData->clrStart[2] = ArgbEncode(255, 203, 215, 186);
    819     m_pColorData->clrStart[3] = ArgbEncode(255, 254, 254, 251);
    820     m_pColorData->clrEnd[0] = ArgbEncode(255, 149, 167, 117);
    821     m_pColorData->clrEnd[1] = ArgbEncode(255, 198, 211, 155);
    822     m_pColorData->clrEnd[2] = ArgbEncode(255, 149, 167, 117);
    823     m_pColorData->clrEnd[3] = ArgbEncode(255, 243, 241, 236);
    824     m_pColorData->clrSign[0] = ArgbEncode(255, 255, 255, 255);
    825     m_pColorData->clrSign[1] = ArgbEncode(255, 255, 255, 255);
    826     m_pColorData->clrSign[2] = ArgbEncode(255, 255, 255, 255);
    827     m_pColorData->clrSign[3] = ArgbEncode(255, 128, 128, 128);
    828   } else {
    829     m_pColorData->clrBorder[0] = ArgbEncode(255, 202, 216, 249);
    830     m_pColorData->clrBorder[1] = ArgbEncode(255, 171, 190, 233);
    831     m_pColorData->clrBorder[2] = ArgbEncode(255, 135, 147, 219);
    832     m_pColorData->clrBorder[3] = ArgbEncode(255, 172, 168, 153);
    833     m_pColorData->clrStart[0] = ArgbEncode(255, 225, 234, 254);
    834     m_pColorData->clrStart[1] = ArgbEncode(255, 253, 255, 255);
    835     m_pColorData->clrStart[2] = ArgbEncode(255, 110, 142, 241);
    836     m_pColorData->clrStart[3] = ArgbEncode(255, 254, 254, 251);
    837     m_pColorData->clrEnd[0] = ArgbEncode(255, 175, 204, 251);
    838     m_pColorData->clrEnd[1] = ArgbEncode(255, 185, 218, 251);
    839     m_pColorData->clrEnd[2] = ArgbEncode(255, 210, 222, 235);
    840     m_pColorData->clrEnd[3] = ArgbEncode(255, 243, 241, 236);
    841     m_pColorData->clrSign[0] = ArgbEncode(255, 77, 97, 133);
    842     m_pColorData->clrSign[1] = ArgbEncode(255, 77, 97, 133);
    843     m_pColorData->clrSign[2] = ArgbEncode(255, 77, 97, 133);
    844     m_pColorData->clrSign[3] = ArgbEncode(255, 128, 128, 128);
    845   }
    846 }
    847