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