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