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
CPWL_Caret()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
~CPWL_Caret()27 CPWL_Caret::~CPWL_Caret()
28 {
29 }
30
GetClassName() const31 CFX_ByteString CPWL_Caret::GetClassName() const
32 {
33 return "CPWL_Caret";
34 }
35
GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)36 void CPWL_Caret::GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)
37 {
38 GetCaretApp(sAppStream,CPDF_Point(0.0f,0.0f));
39 }
40
DrawThisAppearance(CFX_RenderDevice * pDevice,CPDF_Matrix * pUser2Device)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
GetCaretApp(CFX_ByteTextBuf & sAppStream,const CPDF_Point & ptOffset)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
GetCaretAppearanceStream(const CPDF_Point & ptOffset)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
TimerProc()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
GetCaretRect() const130 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
SetCaret(FX_BOOL bVisible,const CPDF_Point & ptHead,const CPDF_Point & ptFoot)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
InvalidateRect(CPDF_Rect * pRect)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
198