cdc7d57a9bfa8f7184f618b9d482c42bb85172b5
[pdfium.git] / fpdfsdk / src / pdfwindow / PWL_Caret.cpp
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 "../../include/pdfwindow/PDFWindow.h"
8 #include "../../include/pdfwindow/PWL_Wnd.h"
9 #include "../../include/pdfwindow/PWL_Caret.h"
10 #include "../../include/pdfwindow/PWL_Utils.h"
11
12 #define PWL_CARET_FLASHINTERVAL         500
13
14 //////////////////////////////////////////////////////////////////////
15 // Construction/Destruction
16 //////////////////////////////////////////////////////////////////////
17
18 CPWL_Caret::CPWL_Caret() :
19         m_bFlash(FALSE),
20         m_ptHead(0,0),
21         m_ptFoot(0,0),
22         m_fWidth(0.4f),
23         m_nDelay(0)
24 {
25 }
26
27 CPWL_Caret::~CPWL_Caret()
28 {
29 }
30
31 CFX_ByteString CPWL_Caret::GetClassName() const
32 {
33         return "CPWL_Caret";
34 }
35
36 void CPWL_Caret::GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)
37 {
38         GetCaretApp(sAppStream,CPDF_Point(0.0f,0.0f));
39 }
40
41 void CPWL_Caret::DrawThisAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device)
42 {
43         if (IsVisible() && m_bFlash)
44         {
45                 CPDF_Rect rcRect = GetCaretRect();
46                 CPDF_Rect rcClip = GetClipRect();
47
48                 CFX_PathData path;
49
50                 path.SetPointCount(2);
51                 
52                 FX_FLOAT fCaretX = rcRect.left + m_fWidth * 0.5f;
53                 FX_FLOAT fCaretTop = rcRect.top;
54                 FX_FLOAT fCaretBottom = rcRect.bottom;
55
56                 if (!rcClip.IsEmpty())
57                 {
58                         rcRect.Intersect(rcClip);
59                         if (!rcRect.IsEmpty())
60                         {
61                                 fCaretTop = rcRect.top;
62                                 fCaretBottom = rcRect.bottom;
63                                 path.SetPoint(0, fCaretX, fCaretBottom, FXPT_MOVETO);
64                                 path.SetPoint(1, fCaretX, fCaretTop, FXPT_LINETO);
65                         }
66                         else
67                         {
68                                 return;
69                         }
70                 }
71                 else
72                 {
73                         path.SetPoint(0, fCaretX, fCaretBottom, FXPT_MOVETO);
74                         path.SetPoint(1, fCaretX, fCaretTop, FXPT_LINETO);
75                 }
76
77                 CFX_GraphStateData gsd;
78                 gsd.m_LineWidth = m_fWidth;
79
80                 pDevice->DrawPath(&path, pUser2Device, &gsd,0,  ArgbEncode(255,0,0,0), FXFILL_ALTERNATE);
81         }
82 }
83
84 void CPWL_Caret::GetCaretApp(CFX_ByteTextBuf & sAppStream,const CPDF_Point & ptOffset)
85 {
86         if (IsVisible() && m_bFlash)
87         {       
88                 CFX_ByteTextBuf sCaret;
89
90                 CPDF_Rect rcRect = GetCaretRect();
91                 CPDF_Rect rcClip = GetClipRect();
92
93                 rcRect = CPWL_Utils::OffsetRect(rcRect,ptOffset.x,ptOffset.y);
94                 rcClip = CPWL_Utils::OffsetRect(rcClip,ptOffset.x,ptOffset.y);
95
96                 sCaret << "q\n";
97                 if (!rcClip.IsEmpty())
98                 {
99                         sCaret << rcClip.left << " " << rcClip.bottom + 2.5f << " " 
100                                 << rcClip.right - rcClip.left << " " << rcClip.top - rcClip.bottom - 4.5f << " re W n\n";
101                 }
102                 sCaret << m_fWidth << " w\n0 G\n";
103                 sCaret << rcRect.left + m_fWidth/2 << " " << rcRect.bottom << " m\n";
104                 sCaret << rcRect.left + m_fWidth/2 << " " << rcRect.top << " l S\nQ\n"; 
105
106                 sAppStream << sCaret;   
107         }
108 }
109
110 CFX_ByteString CPWL_Caret::GetCaretAppearanceStream(const CPDF_Point & ptOffset)
111 {
112         CFX_ByteTextBuf sCaret;
113         GetCaretApp(sCaret,ptOffset);
114         return sCaret.GetByteString();
115 }
116
117 void CPWL_Caret::TimerProc()
118 {
119         if (m_nDelay > 0)
120         {
121                 m_nDelay--;     
122         }
123         else
124         {
125                 m_bFlash = !m_bFlash;
126                 InvalidateRect();
127         }
128 }
129
130 CPDF_Rect CPWL_Caret::GetCaretRect() const
131 {
132         return CPDF_Rect(m_ptFoot.x,
133                         m_ptFoot.y,
134                         m_ptHead.x + this->m_fWidth,
135                         m_ptHead.y);
136 }
137
138 void CPWL_Caret::SetCaret(FX_BOOL bVisible, const CPDF_Point & ptHead, const CPDF_Point & ptFoot)
139 {
140         if (bVisible)
141         {       
142                 if (IsVisible())
143                 {
144                         if (m_ptHead.x != ptHead.x || m_ptHead.y != ptHead.y || 
145                                         m_ptFoot.x != ptFoot.x || m_ptFoot.y != ptFoot.y)
146                         {
147                                 this->m_ptHead = ptHead;
148                                 this->m_ptFoot = ptFoot;
149
150                                 m_bFlash = TRUE;
151                                 //Move(GetCaretRect(),FALSE,TRUE);
152                                 Move(m_rcInvalid, FALSE, TRUE);
153                         }
154                 }
155                 else
156                 {
157                         this->m_ptHead = ptHead;
158                         this->m_ptFoot = ptFoot;
159
160                         EndTimer();
161                         BeginTimer(PWL_CARET_FLASHINTERVAL);
162                         
163                         CPWL_Wnd::SetVisible(TRUE);
164                         m_bFlash = TRUE;
165
166                         //Move(GetCaretRect(),FALSE,TRUE);      
167                         Move(m_rcInvalid, FALSE, TRUE);
168                 }               
169         }
170         else
171         {
172                 this->m_ptHead = CPDF_Point(0,0);
173                 this->m_ptFoot = CPDF_Point(0,0);
174
175                 m_bFlash = FALSE;
176                 if (IsVisible())
177                 {
178                         EndTimer();
179                         CPWL_Wnd::SetVisible(FALSE);
180                 }               
181         }
182 }
183
184 void CPWL_Caret::InvalidateRect(CPDF_Rect * pRect)
185 {
186         if (pRect)
187         {
188                 CPDF_Rect rcRefresh = CPWL_Utils::InflateRect(*pRect,0.5f);
189                 rcRefresh.top += 1;
190                 rcRefresh.bottom -= 1;  
191                 
192                 CPWL_Wnd::InvalidateRect(&rcRefresh);
193         }
194         else
195                 CPWL_Wnd::InvalidateRect(pRect);
196 }
197