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
16CFDE_RenderContext::CFDE_RenderContext()
17    : m_eStatus(FDE_RENDERSTATUS_Reset),
18      m_pRenderDevice(nullptr),
19      m_Transform() {
20  m_Transform.SetIdentity();
21}
22
23CFDE_RenderContext::~CFDE_RenderContext() {
24  StopRender();
25}
26
27bool 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
46FDE_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
93void 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
102void 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