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