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