1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2014 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker
5*3ac0a46fSAndroid Build Coastguard Worker // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6*3ac0a46fSAndroid Build Coastguard Worker
7*3ac0a46fSAndroid Build Coastguard Worker #include "fpdfsdk/pwl/cpwl_caret.h"
8*3ac0a46fSAndroid Build Coastguard Worker
9*3ac0a46fSAndroid Build Coastguard Worker #include <sstream>
10*3ac0a46fSAndroid Build Coastguard Worker #include <utility>
11*3ac0a46fSAndroid Build Coastguard Worker
12*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxge/cfx_fillrenderoptions.h"
13*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxge/cfx_graphstatedata.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxge/cfx_path.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "core/fxge/cfx_renderdevice.h"
16*3ac0a46fSAndroid Build Coastguard Worker
CPWL_Caret(const CreateParams & cp,std::unique_ptr<IPWL_FillerNotify::PerWindowData> pAttachedData)17*3ac0a46fSAndroid Build Coastguard Worker CPWL_Caret::CPWL_Caret(
18*3ac0a46fSAndroid Build Coastguard Worker const CreateParams& cp,
19*3ac0a46fSAndroid Build Coastguard Worker std::unique_ptr<IPWL_FillerNotify::PerWindowData> pAttachedData)
20*3ac0a46fSAndroid Build Coastguard Worker : CPWL_Wnd(cp, std::move(pAttachedData)) {}
21*3ac0a46fSAndroid Build Coastguard Worker
22*3ac0a46fSAndroid Build Coastguard Worker CPWL_Caret::~CPWL_Caret() = default;
23*3ac0a46fSAndroid Build Coastguard Worker
DrawThisAppearance(CFX_RenderDevice * pDevice,const CFX_Matrix & mtUser2Device)24*3ac0a46fSAndroid Build Coastguard Worker void CPWL_Caret::DrawThisAppearance(CFX_RenderDevice* pDevice,
25*3ac0a46fSAndroid Build Coastguard Worker const CFX_Matrix& mtUser2Device) {
26*3ac0a46fSAndroid Build Coastguard Worker if (!IsVisible() || !m_bFlash)
27*3ac0a46fSAndroid Build Coastguard Worker return;
28*3ac0a46fSAndroid Build Coastguard Worker
29*3ac0a46fSAndroid Build Coastguard Worker CFX_FloatRect rcRect = GetCaretRect();
30*3ac0a46fSAndroid Build Coastguard Worker CFX_FloatRect rcClip = GetClipRect();
31*3ac0a46fSAndroid Build Coastguard Worker
32*3ac0a46fSAndroid Build Coastguard Worker float fCaretX = rcRect.left + m_fWidth * 0.5f;
33*3ac0a46fSAndroid Build Coastguard Worker float fCaretTop = rcRect.top;
34*3ac0a46fSAndroid Build Coastguard Worker float fCaretBottom = rcRect.bottom;
35*3ac0a46fSAndroid Build Coastguard Worker if (!rcClip.IsEmpty()) {
36*3ac0a46fSAndroid Build Coastguard Worker rcRect.Intersect(rcClip);
37*3ac0a46fSAndroid Build Coastguard Worker if (rcRect.IsEmpty())
38*3ac0a46fSAndroid Build Coastguard Worker return;
39*3ac0a46fSAndroid Build Coastguard Worker
40*3ac0a46fSAndroid Build Coastguard Worker fCaretTop = rcRect.top;
41*3ac0a46fSAndroid Build Coastguard Worker fCaretBottom = rcRect.bottom;
42*3ac0a46fSAndroid Build Coastguard Worker }
43*3ac0a46fSAndroid Build Coastguard Worker
44*3ac0a46fSAndroid Build Coastguard Worker CFX_Path path;
45*3ac0a46fSAndroid Build Coastguard Worker path.AppendPoint(CFX_PointF(fCaretX, fCaretBottom),
46*3ac0a46fSAndroid Build Coastguard Worker CFX_Path::Point::Type::kMove);
47*3ac0a46fSAndroid Build Coastguard Worker path.AppendPoint(CFX_PointF(fCaretX, fCaretTop),
48*3ac0a46fSAndroid Build Coastguard Worker CFX_Path::Point::Type::kLine);
49*3ac0a46fSAndroid Build Coastguard Worker
50*3ac0a46fSAndroid Build Coastguard Worker CFX_GraphStateData gsd;
51*3ac0a46fSAndroid Build Coastguard Worker gsd.m_LineWidth = m_fWidth;
52*3ac0a46fSAndroid Build Coastguard Worker pDevice->DrawPath(path, &mtUser2Device, &gsd, 0, ArgbEncode(255, 0, 0, 0),
53*3ac0a46fSAndroid Build Coastguard Worker CFX_FillRenderOptions::EvenOddOptions());
54*3ac0a46fSAndroid Build Coastguard Worker }
55*3ac0a46fSAndroid Build Coastguard Worker
OnTimerFired()56*3ac0a46fSAndroid Build Coastguard Worker void CPWL_Caret::OnTimerFired() {
57*3ac0a46fSAndroid Build Coastguard Worker m_bFlash = !m_bFlash;
58*3ac0a46fSAndroid Build Coastguard Worker InvalidateRect(nullptr);
59*3ac0a46fSAndroid Build Coastguard Worker // Note, |this| may no longer be viable at this point. If more work needs
60*3ac0a46fSAndroid Build Coastguard Worker // to be done, add an observer.
61*3ac0a46fSAndroid Build Coastguard Worker }
62*3ac0a46fSAndroid Build Coastguard Worker
GetCaretRect() const63*3ac0a46fSAndroid Build Coastguard Worker CFX_FloatRect CPWL_Caret::GetCaretRect() const {
64*3ac0a46fSAndroid Build Coastguard Worker return CFX_FloatRect(m_ptFoot.x, m_ptFoot.y, m_ptHead.x + m_fWidth,
65*3ac0a46fSAndroid Build Coastguard Worker m_ptHead.y);
66*3ac0a46fSAndroid Build Coastguard Worker }
67*3ac0a46fSAndroid Build Coastguard Worker
SetCaret(bool bVisible,const CFX_PointF & ptHead,const CFX_PointF & ptFoot)68*3ac0a46fSAndroid Build Coastguard Worker void CPWL_Caret::SetCaret(bool bVisible,
69*3ac0a46fSAndroid Build Coastguard Worker const CFX_PointF& ptHead,
70*3ac0a46fSAndroid Build Coastguard Worker const CFX_PointF& ptFoot) {
71*3ac0a46fSAndroid Build Coastguard Worker if (!bVisible) {
72*3ac0a46fSAndroid Build Coastguard Worker m_ptHead = CFX_PointF();
73*3ac0a46fSAndroid Build Coastguard Worker m_ptFoot = CFX_PointF();
74*3ac0a46fSAndroid Build Coastguard Worker m_bFlash = false;
75*3ac0a46fSAndroid Build Coastguard Worker if (!IsVisible())
76*3ac0a46fSAndroid Build Coastguard Worker return;
77*3ac0a46fSAndroid Build Coastguard Worker
78*3ac0a46fSAndroid Build Coastguard Worker m_pTimer.reset();
79*3ac0a46fSAndroid Build Coastguard Worker (void)CPWL_Wnd::SetVisible(false);
80*3ac0a46fSAndroid Build Coastguard Worker // Note, |this| may no longer be viable at this point. If more work needs
81*3ac0a46fSAndroid Build Coastguard Worker // to be done, check the return value of SetVisible().
82*3ac0a46fSAndroid Build Coastguard Worker return;
83*3ac0a46fSAndroid Build Coastguard Worker }
84*3ac0a46fSAndroid Build Coastguard Worker
85*3ac0a46fSAndroid Build Coastguard Worker if (!IsVisible()) {
86*3ac0a46fSAndroid Build Coastguard Worker static constexpr int32_t kCaretFlashIntervalMs = 500;
87*3ac0a46fSAndroid Build Coastguard Worker
88*3ac0a46fSAndroid Build Coastguard Worker m_ptHead = ptHead;
89*3ac0a46fSAndroid Build Coastguard Worker m_ptFoot = ptFoot;
90*3ac0a46fSAndroid Build Coastguard Worker m_pTimer = std::make_unique<CFX_Timer>(GetTimerHandler(), this,
91*3ac0a46fSAndroid Build Coastguard Worker kCaretFlashIntervalMs);
92*3ac0a46fSAndroid Build Coastguard Worker
93*3ac0a46fSAndroid Build Coastguard Worker if (!CPWL_Wnd::SetVisible(true))
94*3ac0a46fSAndroid Build Coastguard Worker return;
95*3ac0a46fSAndroid Build Coastguard Worker
96*3ac0a46fSAndroid Build Coastguard Worker m_bFlash = true;
97*3ac0a46fSAndroid Build Coastguard Worker Move(m_rcInvalid, false, true);
98*3ac0a46fSAndroid Build Coastguard Worker // Note, |this| may no longer be viable at this point. If more work needs
99*3ac0a46fSAndroid Build Coastguard Worker // to be done, check the return value of Move().
100*3ac0a46fSAndroid Build Coastguard Worker return;
101*3ac0a46fSAndroid Build Coastguard Worker }
102*3ac0a46fSAndroid Build Coastguard Worker
103*3ac0a46fSAndroid Build Coastguard Worker if (m_ptHead == ptHead && m_ptFoot == ptFoot)
104*3ac0a46fSAndroid Build Coastguard Worker return;
105*3ac0a46fSAndroid Build Coastguard Worker
106*3ac0a46fSAndroid Build Coastguard Worker m_ptHead = ptHead;
107*3ac0a46fSAndroid Build Coastguard Worker m_ptFoot = ptFoot;
108*3ac0a46fSAndroid Build Coastguard Worker m_bFlash = true;
109*3ac0a46fSAndroid Build Coastguard Worker Move(m_rcInvalid, false, true);
110*3ac0a46fSAndroid Build Coastguard Worker // Note, |this| may no longer be viable at this point. If more work
111*3ac0a46fSAndroid Build Coastguard Worker // needs to be done, check the return value of Move().
112*3ac0a46fSAndroid Build Coastguard Worker }
113*3ac0a46fSAndroid Build Coastguard Worker
InvalidateRect(const CFX_FloatRect * pRect)114*3ac0a46fSAndroid Build Coastguard Worker bool CPWL_Caret::InvalidateRect(const CFX_FloatRect* pRect) {
115*3ac0a46fSAndroid Build Coastguard Worker if (!pRect)
116*3ac0a46fSAndroid Build Coastguard Worker return CPWL_Wnd::InvalidateRect(nullptr);
117*3ac0a46fSAndroid Build Coastguard Worker
118*3ac0a46fSAndroid Build Coastguard Worker CFX_FloatRect rcRefresh = *pRect;
119*3ac0a46fSAndroid Build Coastguard Worker if (!rcRefresh.IsEmpty()) {
120*3ac0a46fSAndroid Build Coastguard Worker rcRefresh.Inflate(0.5f, 0.5f);
121*3ac0a46fSAndroid Build Coastguard Worker rcRefresh.Normalize();
122*3ac0a46fSAndroid Build Coastguard Worker }
123*3ac0a46fSAndroid Build Coastguard Worker rcRefresh.top += 1;
124*3ac0a46fSAndroid Build Coastguard Worker rcRefresh.bottom -= 1;
125*3ac0a46fSAndroid Build Coastguard Worker return CPWL_Wnd::InvalidateRect(&rcRefresh);
126*3ac0a46fSAndroid Build Coastguard Worker }
127*3ac0a46fSAndroid Build Coastguard Worker
SetVisible(bool bVisible)128*3ac0a46fSAndroid Build Coastguard Worker bool CPWL_Caret::SetVisible(bool bVisible) {
129*3ac0a46fSAndroid Build Coastguard Worker return true;
130*3ac0a46fSAndroid Build Coastguard Worker }
131