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