• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "fpdfsdk/pwl/cpwl_caret.h"
8 
9 #include <sstream>
10 #include <utility>
11 
12 #include "core/fxge/cfx_graphstatedata.h"
13 #include "core/fxge/cfx_pathdata.h"
14 #include "core/fxge/cfx_renderdevice.h"
15 #include "third_party/base/ptr_util.h"
16 
CPWL_Caret(const CreateParams & cp,std::unique_ptr<IPWL_SystemHandler::PerWindowData> pAttachedData)17 CPWL_Caret::CPWL_Caret(
18     const CreateParams& cp,
19     std::unique_ptr<IPWL_SystemHandler::PerWindowData> pAttachedData)
20     : CPWL_Wnd(cp, std::move(pAttachedData)) {}
21 
22 CPWL_Caret::~CPWL_Caret() = default;
23 
DrawThisAppearance(CFX_RenderDevice * pDevice,const CFX_Matrix & mtUser2Device)24 void CPWL_Caret::DrawThisAppearance(CFX_RenderDevice* pDevice,
25                                     const CFX_Matrix& mtUser2Device) {
26   if (!IsVisible() || !m_bFlash)
27     return;
28 
29   CFX_FloatRect rcRect = GetCaretRect();
30   CFX_FloatRect rcClip = GetClipRect();
31   CFX_PathData path;
32 
33   float fCaretX = rcRect.left + m_fWidth * 0.5f;
34   float fCaretTop = rcRect.top;
35   float fCaretBottom = rcRect.bottom;
36   if (!rcClip.IsEmpty()) {
37     rcRect.Intersect(rcClip);
38     if (rcRect.IsEmpty())
39       return;
40 
41     fCaretTop = rcRect.top;
42     fCaretBottom = rcRect.bottom;
43   }
44 
45   path.AppendPoint(CFX_PointF(fCaretX, fCaretBottom), FXPT_TYPE::MoveTo, false);
46   path.AppendPoint(CFX_PointF(fCaretX, fCaretTop), FXPT_TYPE::LineTo, false);
47 
48   CFX_GraphStateData gsd;
49   gsd.m_LineWidth = m_fWidth;
50   pDevice->DrawPath(&path, &mtUser2Device, &gsd, 0, ArgbEncode(255, 0, 0, 0),
51                     FXFILL_ALTERNATE);
52 }
53 
OnTimerFired()54 void CPWL_Caret::OnTimerFired() {
55   m_bFlash = !m_bFlash;
56   InvalidateRect(nullptr);
57   // Note, |this| may no longer be viable at this point. If more work needs
58   // to be done, add an observer.
59 }
60 
GetCaretRect() const61 CFX_FloatRect CPWL_Caret::GetCaretRect() const {
62   return CFX_FloatRect(m_ptFoot.x, m_ptFoot.y, m_ptHead.x + m_fWidth,
63                        m_ptHead.y);
64 }
65 
SetCaret(bool bVisible,const CFX_PointF & ptHead,const CFX_PointF & ptFoot)66 void CPWL_Caret::SetCaret(bool bVisible,
67                           const CFX_PointF& ptHead,
68                           const CFX_PointF& ptFoot) {
69   if (!bVisible) {
70     m_ptHead = CFX_PointF();
71     m_ptFoot = CFX_PointF();
72     m_bFlash = false;
73     if (!IsVisible())
74       return;
75 
76     m_pTimer.reset();
77     CPWL_Wnd::SetVisible(false);
78     // Note, |this| may no longer be viable at this point. If more work needs
79     // to be done, check the return value of SetVisible().
80     return;
81   }
82 
83   if (!IsVisible()) {
84     static constexpr int32_t kCaretFlashIntervalMs = 500;
85 
86     m_ptHead = ptHead;
87     m_ptFoot = ptFoot;
88     m_pTimer = pdfium::MakeUnique<CFX_Timer>(GetTimerHandler(), this,
89                                              kCaretFlashIntervalMs);
90 
91     if (!CPWL_Wnd::SetVisible(true))
92       return;
93 
94     m_bFlash = true;
95     Move(m_rcInvalid, false, true);
96     // Note, |this| may no longer be viable at this point. If more work needs
97     // to be done, check the return value of Move().
98     return;
99   }
100 
101   if (m_ptHead == ptHead && m_ptFoot == ptFoot)
102     return;
103 
104   m_ptHead = ptHead;
105   m_ptFoot = ptFoot;
106   m_bFlash = true;
107   Move(m_rcInvalid, false, true);
108   // Note, |this| may no longer be viable at this point. If more work
109   // needs to be done, check the return value of Move().
110 }
111 
InvalidateRect(CFX_FloatRect * pRect)112 bool CPWL_Caret::InvalidateRect(CFX_FloatRect* pRect) {
113   if (!pRect) {
114     return CPWL_Wnd::InvalidateRect(nullptr);
115   }
116 
117   CFX_FloatRect rcRefresh = *pRect;
118   if (!rcRefresh.IsEmpty()) {
119     rcRefresh.Inflate(0.5f, 0.5f);
120     rcRefresh.Normalize();
121   }
122   rcRefresh.top += 1;
123   rcRefresh.bottom -= 1;
124   return CPWL_Wnd::InvalidateRect(&rcRefresh);
125 }
126 
SetVisible(bool bVisible)127 bool CPWL_Caret::SetVisible(bool bVisible) {
128   return true;
129 }
130