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 "xfa/fde/fde_render.h"
8
9 #include "third_party/base/ptr_util.h"
10 #include "xfa/fde/fde_gedevice.h"
11 #include "xfa/fde/fde_object.h"
12
13 #define FDE_PATHRENDER_Stroke 1
14 #define FDE_PATHRENDER_Fill 2
15
CFDE_RenderContext()16 CFDE_RenderContext::CFDE_RenderContext()
17 : m_eStatus(FDE_RENDERSTATUS_Reset),
18 m_pRenderDevice(nullptr),
19 m_Transform() {
20 m_Transform.SetIdentity();
21 }
22
~CFDE_RenderContext()23 CFDE_RenderContext::~CFDE_RenderContext() {
24 StopRender();
25 }
26
StartRender(CFDE_RenderDevice * pRenderDevice,IFDE_CanvasSet * pCanvasSet,const CFX_Matrix & tmDoc2Device)27 bool CFDE_RenderContext::StartRender(CFDE_RenderDevice* pRenderDevice,
28 IFDE_CanvasSet* pCanvasSet,
29 const CFX_Matrix& tmDoc2Device) {
30 if (m_pRenderDevice)
31 return false;
32 if (!pRenderDevice)
33 return false;
34 if (!pCanvasSet)
35 return false;
36
37 m_eStatus = FDE_RENDERSTATUS_Paused;
38 m_pRenderDevice = pRenderDevice;
39 m_Transform = tmDoc2Device;
40 if (!m_pIterator)
41 m_pIterator = pdfium::MakeUnique<CFDE_VisualSetIterator>();
42
43 return m_pIterator->AttachCanvas(pCanvasSet) && m_pIterator->FilterObjects();
44 }
45
DoRender(IFX_Pause * pPause)46 FDE_RENDERSTATUS CFDE_RenderContext::DoRender(IFX_Pause* pPause) {
47 if (!m_pRenderDevice)
48 return FDE_RENDERSTATUS_Failed;
49 if (!m_pIterator)
50 return FDE_RENDERSTATUS_Failed;
51
52 FDE_RENDERSTATUS eStatus = FDE_RENDERSTATUS_Paused;
53 CFX_Matrix rm;
54 rm.SetReverse(m_Transform);
55 CFX_RectF rtDocClip = m_pRenderDevice->GetClipRect();
56 if (rtDocClip.IsEmpty()) {
57 rtDocClip.left = rtDocClip.top = 0;
58 rtDocClip.width = (FX_FLOAT)m_pRenderDevice->GetWidth();
59 rtDocClip.height = (FX_FLOAT)m_pRenderDevice->GetHeight();
60 }
61 rm.TransformRect(rtDocClip);
62 IFDE_VisualSet* pVisualSet;
63 FDE_TEXTEDITPIECE* pPiece;
64 int32_t iCount = 0;
65 while (true) {
66 pPiece = m_pIterator->GetNext(pVisualSet);
67 if (!pPiece || !pVisualSet) {
68 eStatus = FDE_RENDERSTATUS_Done;
69 break;
70 }
71 if (!rtDocClip.IntersectWith(pVisualSet->GetRect(*pPiece)))
72 continue;
73
74 switch (pVisualSet->GetType()) {
75 case FDE_VISUALOBJ_Text:
76 RenderText(static_cast<IFDE_TextSet*>(pVisualSet), pPiece);
77 iCount += 5;
78 break;
79 case FDE_VISUALOBJ_Canvas:
80 ASSERT(false);
81 break;
82 default:
83 break;
84 }
85 if (iCount >= 100 && pPause && pPause->NeedToPauseNow()) {
86 eStatus = FDE_RENDERSTATUS_Paused;
87 break;
88 }
89 }
90 return m_eStatus = eStatus;
91 }
92
StopRender()93 void CFDE_RenderContext::StopRender() {
94 m_eStatus = FDE_RENDERSTATUS_Reset;
95 m_pRenderDevice = nullptr;
96 m_Transform.SetIdentity();
97 m_pIterator.reset();
98 m_pBrush.reset();
99 m_CharPos.clear();
100 }
101
RenderText(IFDE_TextSet * pTextSet,FDE_TEXTEDITPIECE * pText)102 void CFDE_RenderContext::RenderText(IFDE_TextSet* pTextSet,
103 FDE_TEXTEDITPIECE* pText) {
104 ASSERT(m_pRenderDevice);
105 ASSERT(pTextSet && pText);
106
107 CFX_RetainPtr<CFGAS_GEFont> pFont = pTextSet->GetFont();
108 if (!pFont)
109 return;
110
111 int32_t iCount = pTextSet->GetDisplayPos(*pText, nullptr, false);
112 if (iCount < 1)
113 return;
114
115 if (!m_pBrush)
116 m_pBrush = pdfium::MakeUnique<CFDE_Brush>();
117
118 if (m_CharPos.size() < static_cast<size_t>(iCount))
119 m_CharPos.resize(iCount, FXTEXT_CHARPOS());
120
121 iCount = pTextSet->GetDisplayPos(*pText, m_CharPos.data(), false);
122 FX_FLOAT fFontSize = pTextSet->GetFontSize();
123 FX_ARGB dwColor = pTextSet->GetFontColor();
124 m_pBrush->SetColor(dwColor);
125 m_pRenderDevice->DrawString(m_pBrush.get(), pFont, m_CharPos.data(), iCount,
126 fFontSize, &m_Transform);
127 }
128
129