// Copyright 2014 PDFium Authors. All rights reserved. | |
// Use of this source code is governed by a BSD-style license that can be | |
// found in the LICENSE file. | |
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
#include "../../include/pdfwindow/PDFWindow.h" | |
#include "../../include/pdfwindow/PWL_Wnd.h" | |
#include "../../include/pdfwindow/PWL_Caret.h" | |
#include "../../include/pdfwindow/PWL_Utils.h" | |
#define PWL_CARET_FLASHINTERVAL 500 | |
////////////////////////////////////////////////////////////////////// | |
// Construction/Destruction | |
////////////////////////////////////////////////////////////////////// | |
CPWL_Caret::CPWL_Caret() : | |
m_bFlash(FALSE), | |
m_ptHead(0,0), | |
m_ptFoot(0,0), | |
m_fWidth(0.4f), | |
m_nDelay(0) | |
{ | |
} | |
CPWL_Caret::~CPWL_Caret() | |
{ | |
} | |
CFX_ByteString CPWL_Caret::GetClassName() const | |
{ | |
return "CPWL_Caret"; | |
} | |
void CPWL_Caret::GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream) | |
{ | |
GetCaretApp(sAppStream,CPDF_Point(0.0f,0.0f)); | |
} | |
void CPWL_Caret::DrawThisAppearance(CFX_RenderDevice* pDevice, CPDF_Matrix* pUser2Device) | |
{ | |
if (IsVisible() && m_bFlash) | |
{ | |
CPDF_Rect rcRect = GetCaretRect(); | |
CPDF_Rect rcClip = GetClipRect(); | |
CFX_PathData path; | |
path.SetPointCount(2); | |
FX_FLOAT fCaretX = rcRect.left + m_fWidth * 0.5f; | |
FX_FLOAT fCaretTop = rcRect.top; | |
FX_FLOAT fCaretBottom = rcRect.bottom; | |
if (!rcClip.IsEmpty()) | |
{ | |
rcRect.Intersect(rcClip); | |
if (!rcRect.IsEmpty()) | |
{ | |
fCaretTop = rcRect.top; | |
fCaretBottom = rcRect.bottom; | |
path.SetPoint(0, fCaretX, fCaretBottom, FXPT_MOVETO); | |
path.SetPoint(1, fCaretX, fCaretTop, FXPT_LINETO); | |
} | |
else | |
{ | |
return; | |
} | |
} | |
else | |
{ | |
path.SetPoint(0, fCaretX, fCaretBottom, FXPT_MOVETO); | |
path.SetPoint(1, fCaretX, fCaretTop, FXPT_LINETO); | |
} | |
CFX_GraphStateData gsd; | |
gsd.m_LineWidth = m_fWidth; | |
pDevice->DrawPath(&path, pUser2Device, &gsd,0, ArgbEncode(255,0,0,0), FXFILL_ALTERNATE); | |
} | |
} | |
void CPWL_Caret::GetCaretApp(CFX_ByteTextBuf & sAppStream,const CPDF_Point & ptOffset) | |
{ | |
if (IsVisible() && m_bFlash) | |
{ | |
CFX_ByteTextBuf sCaret; | |
CPDF_Rect rcRect = GetCaretRect(); | |
CPDF_Rect rcClip = GetClipRect(); | |
rcRect = CPWL_Utils::OffsetRect(rcRect,ptOffset.x,ptOffset.y); | |
rcClip = CPWL_Utils::OffsetRect(rcClip,ptOffset.x,ptOffset.y); | |
sCaret << "q\n"; | |
if (!rcClip.IsEmpty()) | |
{ | |
sCaret << rcClip.left << " " << rcClip.bottom + 2.5f << " " | |
<< rcClip.right - rcClip.left << " " << rcClip.top - rcClip.bottom - 4.5f << " re W n\n"; | |
} | |
sCaret << m_fWidth << " w\n0 G\n"; | |
sCaret << rcRect.left + m_fWidth/2 << " " << rcRect.bottom << " m\n"; | |
sCaret << rcRect.left + m_fWidth/2 << " " << rcRect.top << " l S\nQ\n"; | |
sAppStream << sCaret; | |
} | |
} | |
CFX_ByteString CPWL_Caret::GetCaretAppearanceStream(const CPDF_Point & ptOffset) | |
{ | |
CFX_ByteTextBuf sCaret; | |
GetCaretApp(sCaret,ptOffset); | |
return sCaret.GetByteString(); | |
} | |
void CPWL_Caret::TimerProc() | |
{ | |
if (m_nDelay > 0) | |
{ | |
m_nDelay--; | |
} | |
else | |
{ | |
m_bFlash = !m_bFlash; | |
InvalidateRect(); | |
} | |
} | |
CPDF_Rect CPWL_Caret::GetCaretRect() const | |
{ | |
return CPDF_Rect(m_ptFoot.x, | |
m_ptFoot.y, | |
m_ptHead.x + this->m_fWidth, | |
m_ptHead.y); | |
} | |
void CPWL_Caret::SetCaret(FX_BOOL bVisible, const CPDF_Point & ptHead, const CPDF_Point & ptFoot) | |
{ | |
if (bVisible) | |
{ | |
if (IsVisible()) | |
{ | |
if (m_ptHead.x != ptHead.x || m_ptHead.y != ptHead.y || | |
m_ptFoot.x != ptFoot.x || m_ptFoot.y != ptFoot.y) | |
{ | |
this->m_ptHead = ptHead; | |
this->m_ptFoot = ptFoot; | |
m_bFlash = TRUE; | |
//Move(GetCaretRect(),FALSE,TRUE); | |
Move(m_rcInvalid, FALSE, TRUE); | |
} | |
} | |
else | |
{ | |
this->m_ptHead = ptHead; | |
this->m_ptFoot = ptFoot; | |
EndTimer(); | |
BeginTimer(PWL_CARET_FLASHINTERVAL); | |
CPWL_Wnd::SetVisible(TRUE); | |
m_bFlash = TRUE; | |
//Move(GetCaretRect(),FALSE,TRUE); | |
Move(m_rcInvalid, FALSE, TRUE); | |
} | |
} | |
else | |
{ | |
this->m_ptHead = CPDF_Point(0,0); | |
this->m_ptFoot = CPDF_Point(0,0); | |
m_bFlash = FALSE; | |
if (IsVisible()) | |
{ | |
EndTimer(); | |
CPWL_Wnd::SetVisible(FALSE); | |
} | |
} | |
} | |
void CPWL_Caret::InvalidateRect(CPDF_Rect * pRect) | |
{ | |
if (pRect) | |
{ | |
CPDF_Rect rcRefresh = CPWL_Utils::InflateRect(*pRect,0.5f); | |
rcRefresh.top += 1; | |
rcRefresh.bottom -= 1; | |
CPWL_Wnd::InvalidateRect(&rcRefresh); | |
} | |
else | |
CPWL_Wnd::InvalidateRect(pRect); | |
} | |