blob: 27c9fa9bd22d403e88842540fe1913d18e72e548 [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// 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.
Lei Zhang95e854f2015-06-13 00:58:06 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Dan Sinclair764ec512016-03-14 13:35:12 -04007#include "core/fpdfapi/fpdf_render/render_int.h"
Lei Zhange5b0bd12015-06-19 17:15:41 -07008
thestigf41d9dc2016-08-05 22:34:58 -07009#include <memory>
10
dan sinclair61b2fc72016-03-23 19:21:44 -040011#include "core/fpdfapi/fpdf_font/cpdf_type3char.h"
12#include "core/fpdfapi/fpdf_font/cpdf_type3font.h"
Dan Sinclair584b1e62016-03-21 09:15:45 -040013#include "core/fpdfapi/fpdf_page/cpdf_colorstatedata.h"
14#include "core/fpdfapi/fpdf_page/cpdf_graphicstates.h"
Dan Sinclair455a4192016-03-16 09:48:56 -040015#include "core/fpdfapi/fpdf_page/include/cpdf_form.h"
Dan Sinclair584b1e62016-03-21 09:15:45 -040016#include "core/fpdfapi/fpdf_page/include/cpdf_formobject.h"
dan sinclair61b2fc72016-03-23 19:21:44 -040017#include "core/fpdfapi/fpdf_page/include/cpdf_image.h"
Dan Sinclair584b1e62016-03-21 09:15:45 -040018#include "core/fpdfapi/fpdf_page/include/cpdf_imageobject.h"
Dan Sinclair455a4192016-03-16 09:48:56 -040019#include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
Dan Sinclair584b1e62016-03-21 09:15:45 -040020#include "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h"
21#include "core/fpdfapi/fpdf_page/include/cpdf_pathobject.h"
22#include "core/fpdfapi/fpdf_page/include/cpdf_textobject.h"
Dan Sinclair764ec512016-03-14 13:35:12 -040023#include "core/fpdfapi/fpdf_page/pageint.h"
Dan Sinclairaa403d32016-03-15 14:57:22 -040024#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
25#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
26#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
Dan Sinclairaa403d32016-03-15 14:57:22 -040027#include "core/fpdfapi/fpdf_render/cpdf_pagerendercache.h"
npmeadff192016-09-01 13:21:37 -070028#include "core/fpdfapi/fpdf_render/cpdf_type3cache.h"
Dan Sinclairaa403d32016-03-15 14:57:22 -040029#include "core/fpdfapi/fpdf_render/include/cpdf_progressiverenderer.h"
30#include "core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h"
31#include "core/fpdfapi/fpdf_render/include/cpdf_textrenderer.h"
32#include "core/fpdfapi/include/cpdf_modulemgr.h"
dsinclaircac704d2016-07-28 12:59:09 -070033#include "core/fpdfdoc/include/cpdf_occontext.h"
npmd6918992016-08-17 13:22:16 -070034#include "core/fxge/include/cfx_fontcache.h"
npm9ada2d82016-08-10 07:51:38 -070035#include "core/fxge/include/cfx_fxgedevice.h"
36#include "core/fxge/include/cfx_graphstatedata.h"
npm660de3c2016-08-08 08:18:29 -070037#include "core/fxge/include/cfx_pathdata.h"
npm9ada2d82016-08-10 07:51:38 -070038#include "core/fxge/include/cfx_renderdevice.h"
Lei Zhanga9fa50f2015-11-10 09:45:32 -080039
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070040CPDF_DocRenderData::CPDF_DocRenderData(CPDF_Document* pPDFDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -070041 : m_pPDFDoc(pPDFDoc), m_pFontCache(new CFX_FontCache) {}
42
43CPDF_DocRenderData::~CPDF_DocRenderData() {
44 Clear(TRUE);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070045}
Lei Zhang606346f2015-06-19 18:11:07 -070046
Nico Weber9d8ec5a2015-08-04 13:00:21 -070047void CPDF_DocRenderData::Clear(FX_BOOL bRelease) {
48 for (auto it = m_Type3FaceMap.begin(); it != m_Type3FaceMap.end();) {
49 auto curr_it = it++;
50 CPDF_CountedObject<CPDF_Type3Cache>* cache = curr_it->second;
51 if (bRelease || cache->use_count() < 2) {
52 delete cache->get();
53 delete cache;
54 m_Type3FaceMap.erase(curr_it);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070055 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -070056 }
Lei Zhang606346f2015-06-19 18:11:07 -070057
Nico Weber9d8ec5a2015-08-04 13:00:21 -070058 for (auto it = m_TransferFuncMap.begin(); it != m_TransferFuncMap.end();) {
59 auto curr_it = it++;
60 CPDF_CountedObject<CPDF_TransferFunc>* value = curr_it->second;
61 if (bRelease || value->use_count() < 2) {
62 delete value->get();
63 delete value;
64 m_TransferFuncMap.erase(curr_it);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070065 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -070066 }
Lei Zhang606346f2015-06-19 18:11:07 -070067
Nico Weber9d8ec5a2015-08-04 13:00:21 -070068 if (m_pFontCache) {
69 if (bRelease) {
70 delete m_pFontCache;
thestig4997b222016-06-07 10:46:22 -070071 m_pFontCache = nullptr;
Lei Zhang606346f2015-06-19 18:11:07 -070072 } else {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070073 m_pFontCache->FreeCache(FALSE);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070074 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -070075 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070076}
Lei Zhang606346f2015-06-19 18:11:07 -070077
Nico Weber9d8ec5a2015-08-04 13:00:21 -070078CPDF_Type3Cache* CPDF_DocRenderData::GetCachedType3(CPDF_Type3Font* pFont) {
79 CPDF_CountedObject<CPDF_Type3Cache>* pCache;
80 auto it = m_Type3FaceMap.find(pFont);
81 if (it == m_Type3FaceMap.end()) {
82 CPDF_Type3Cache* pType3 = new CPDF_Type3Cache(pFont);
83 pCache = new CPDF_CountedObject<CPDF_Type3Cache>(pType3);
84 m_Type3FaceMap[pFont] = pCache;
85 } else {
86 pCache = it->second;
87 }
88 return pCache->AddRef();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070089}
Lei Zhangfa6eb282015-06-19 17:17:54 -070090
Nico Weber9d8ec5a2015-08-04 13:00:21 -070091void CPDF_DocRenderData::ReleaseCachedType3(CPDF_Type3Font* pFont) {
92 auto it = m_Type3FaceMap.find(pFont);
93 if (it != m_Type3FaceMap.end())
94 it->second->RemoveRef();
95}
Lei Zhangfa6eb282015-06-19 17:17:54 -070096
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070097CPDF_RenderOptions::CPDF_RenderOptions()
Nico Weber9d8ec5a2015-08-04 13:00:21 -070098 : m_ColorMode(RENDER_COLOR_NORMAL),
99 m_Flags(RENDER_CLEARTYPE),
100 m_Interpolation(0),
101 m_AddFlags(0),
thestig4997b222016-06-07 10:46:22 -0700102 m_pOCContext(nullptr),
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700103 m_dwLimitCacheSize(1024 * 1024 * 100),
104 m_HalftoneLimit(-1) {}
105FX_ARGB CPDF_RenderOptions::TranslateColor(FX_ARGB argb) const {
106 if (m_ColorMode == RENDER_COLOR_NORMAL) {
107 return argb;
108 }
109 if (m_ColorMode == RENDER_COLOR_ALPHA) {
110 return argb;
111 }
112 int a, r, g, b;
113 ArgbDecode(argb, a, r, g, b);
114 int gray = FXRGB2GRAY(r, g, b);
115 if (m_ColorMode == RENDER_COLOR_TWOCOLOR) {
116 int color = (r - gray) * (r - gray) + (g - gray) * (g - gray) +
117 (b - gray) * (b - gray);
118 if (gray < 35 && color < 20) {
119 return ArgbEncode(a, m_ForeColor);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700120 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700121 if (gray > 221 && color < 20) {
122 return ArgbEncode(a, m_BackColor);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700123 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700124 return argb;
125 }
126 int fr = FXSYS_GetRValue(m_ForeColor);
127 int fg = FXSYS_GetGValue(m_ForeColor);
128 int fb = FXSYS_GetBValue(m_ForeColor);
129 int br = FXSYS_GetRValue(m_BackColor);
130 int bg = FXSYS_GetGValue(m_BackColor);
131 int bb = FXSYS_GetBValue(m_BackColor);
132 r = (br - fr) * gray / 255 + fr;
133 g = (bg - fg) * gray / 255 + fg;
134 b = (bb - fb) * gray / 255 + fb;
135 return ArgbEncode(a, r, g, b);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700136}
Tom Sepez09dc51a2015-01-29 18:16:16 -0800137
138// static
139int CPDF_RenderStatus::s_CurrentRecursionDepth = 0;
140
Lei Zhang5044cab2015-11-10 10:09:33 -0800141CPDF_RenderStatus::CPDF_RenderStatus()
142 : m_pFormResource(nullptr),
143 m_pPageResource(nullptr),
144 m_pContext(nullptr),
145 m_bStopped(FALSE),
146 m_pDevice(nullptr),
147 m_pCurObj(nullptr),
148 m_pStopObj(nullptr),
149 m_HalftoneLimit(0),
150 m_bPrint(FALSE),
151 m_Transparency(0),
Lei Zhang5044cab2015-11-10 10:09:33 -0800152 m_bDropObjects(FALSE),
153 m_bStdCS(FALSE),
154 m_GroupFamily(0),
155 m_bLoadMask(FALSE),
156 m_pType3Char(nullptr),
157 m_T3FillColor(0),
158 m_curBlend(FXDIB_BLEND_NORMAL) {}
Tom Sepez09dc51a2015-01-29 18:16:16 -0800159
Dan Sinclair764ec512016-03-14 13:35:12 -0400160CPDF_RenderStatus::~CPDF_RenderStatus() {}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700161
162FX_BOOL CPDF_RenderStatus::Initialize(CPDF_RenderContext* pContext,
163 CFX_RenderDevice* pDevice,
Tom Sepez60d909e2015-12-10 15:34:55 -0800164 const CFX_Matrix* pDeviceMatrix,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700165 const CPDF_PageObject* pStopObj,
166 const CPDF_RenderStatus* pParentState,
167 const CPDF_GraphicStates* pInitialStates,
168 const CPDF_RenderOptions* pOptions,
169 int transparency,
170 FX_BOOL bDropObjects,
171 CPDF_Dictionary* pFormResource,
172 FX_BOOL bStdCS,
173 CPDF_Type3Char* pType3Char,
174 FX_ARGB fill_color,
tsepezb5e8f142016-03-25 15:18:35 -0700175 uint32_t GroupFamily,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700176 FX_BOOL bLoadMask) {
177 m_pContext = pContext;
178 m_pDevice = pDevice;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700179 m_bPrint = m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
180 if (pDeviceMatrix) {
181 m_DeviceMatrix = *pDeviceMatrix;
182 }
183 m_pStopObj = pStopObj;
184 if (pOptions) {
185 m_Options = *pOptions;
186 }
187 m_bDropObjects = bDropObjects;
188 m_bStdCS = bStdCS;
189 m_T3FillColor = fill_color;
190 m_pType3Char = pType3Char;
191 m_GroupFamily = GroupFamily;
192 m_bLoadMask = bLoadMask;
193 m_pFormResource = pFormResource;
Tom Sepez71fdc342016-01-22 12:06:32 -0800194 m_pPageResource = m_pContext->GetPageResources();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700195 if (pInitialStates && !m_pType3Char) {
196 m_InitialStates.CopyStates(*pInitialStates);
197 if (pParentState) {
tsepezca90b872016-08-31 10:41:00 -0700198 if (!m_InitialStates.m_ColorState.HasFillColor()) {
199 m_InitialStates.m_ColorState.SetFillRGB(
200 pParentState->m_InitialStates.m_ColorState.GetFillRGB());
201 m_InitialStates.m_ColorState.GetMutableFillColor()->Copy(
202 pParentState->m_InitialStates.m_ColorState.GetFillColor());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700203 }
tsepezca90b872016-08-31 10:41:00 -0700204 if (!m_InitialStates.m_ColorState.HasStrokeColor()) {
205 m_InitialStates.m_ColorState.SetStrokeRGB(
206 pParentState->m_InitialStates.m_ColorState.GetFillRGB());
207 m_InitialStates.m_ColorState.GetMutableStrokeColor()->Copy(
208 pParentState->m_InitialStates.m_ColorState.GetStrokeColor());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700209 }
210 }
211 } else {
212 m_InitialStates.DefaultStates();
213 }
dsinclaird647a6b2016-04-26 13:13:20 -0700214 m_pImageRenderer.reset();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700215 m_Transparency = transparency;
216 return TRUE;
217}
Tom Sepez32c70812016-02-16 17:15:32 -0800218void CPDF_RenderStatus::RenderObjectList(
219 const CPDF_PageObjectHolder* pObjectHolder,
220 const CFX_Matrix* pObj2Device) {
caryclarka27d49a2016-07-06 10:20:25 -0700221#if defined _SKIA_SUPPORT_
222 DebugVerifyDeviceIsPreMultiplied();
223#endif
Tom Sepezd5e7b352016-02-29 11:24:29 -0800224 CFX_FloatRect clip_rect(m_pDevice->GetClipBox());
Tom Sepez60d909e2015-12-10 15:34:55 -0800225 CFX_Matrix device2object;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700226 device2object.SetReverse(*pObj2Device);
227 device2object.TransformRect(clip_rect);
Tom Sepez2398d892016-02-17 16:46:26 -0800228
229 for (const auto& pCurObj : *pObjectHolder->GetPageObjectList()) {
230 if (pCurObj.get() == m_pStopObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700231 m_bStopped = TRUE;
232 return;
233 }
Tom Sepez2398d892016-02-17 16:46:26 -0800234 if (!pCurObj)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700235 continue;
Tom Sepez2398d892016-02-17 16:46:26 -0800236
237 if (pCurObj->m_Left > clip_rect.right ||
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700238 pCurObj->m_Right < clip_rect.left ||
239 pCurObj->m_Bottom > clip_rect.top ||
240 pCurObj->m_Top < clip_rect.bottom) {
241 continue;
242 }
Tom Sepez2398d892016-02-17 16:46:26 -0800243 RenderSingleObject(pCurObj.get(), pObj2Device);
244 if (m_bStopped)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700245 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700246 }
caryclarka27d49a2016-07-06 10:20:25 -0700247#if defined _SKIA_SUPPORT_
248 DebugVerifyDeviceIsPreMultiplied();
249#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700250}
caryclarka27d49a2016-07-06 10:20:25 -0700251
tsepezbbee4452016-09-02 15:22:00 -0700252void CPDF_RenderStatus::RenderSingleObject(CPDF_PageObject* pObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800253 const CFX_Matrix* pObj2Device) {
caryclarka27d49a2016-07-06 10:20:25 -0700254#if defined _SKIA_SUPPORT_
255 DebugVerifyDeviceIsPreMultiplied();
256#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700257 CFX_AutoRestorer<int> restorer(&s_CurrentRecursionDepth);
258 if (++s_CurrentRecursionDepth > kRenderMaxRecursionDepth) {
259 return;
260 }
261 m_pCurObj = pObj;
tsepez83d23512016-08-26 14:56:39 -0700262 if (m_Options.m_pOCContext && pObj->m_ContentMark) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700263 if (!m_Options.m_pOCContext->CheckObjectVisible(pObj)) {
264 return;
265 }
266 }
267 ProcessClipPath(pObj->m_ClipPath, pObj2Device);
268 if (ProcessTransparency(pObj, pObj2Device)) {
269 return;
270 }
271 ProcessObjectNoClip(pObj, pObj2Device);
caryclarka27d49a2016-07-06 10:20:25 -0700272#if defined _SKIA_SUPPORT_
273 DebugVerifyDeviceIsPreMultiplied();
274#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700275}
Lei Zhang5044cab2015-11-10 10:09:33 -0800276
tsepezbbee4452016-09-02 15:22:00 -0700277FX_BOOL CPDF_RenderStatus::ContinueSingleObject(CPDF_PageObject* pObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800278 const CFX_Matrix* pObj2Device,
279 IFX_Pause* pPause) {
dsinclaird647a6b2016-04-26 13:13:20 -0700280 if (m_pImageRenderer) {
281 if (m_pImageRenderer->Continue(pPause))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700282 return TRUE;
Lei Zhang5044cab2015-11-10 10:09:33 -0800283
dsinclaird647a6b2016-04-26 13:13:20 -0700284 if (!m_pImageRenderer->m_Result)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700285 DrawObjWithBackground(pObj, pObj2Device);
dsinclaird647a6b2016-04-26 13:13:20 -0700286 m_pImageRenderer.reset();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700287 return FALSE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700288 }
Lei Zhang5044cab2015-11-10 10:09:33 -0800289
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700290 m_pCurObj = pObj;
tsepez83d23512016-08-26 14:56:39 -0700291 if (m_Options.m_pOCContext && pObj->m_ContentMark &&
Lei Zhang5044cab2015-11-10 10:09:33 -0800292 !m_Options.m_pOCContext->CheckObjectVisible(pObj)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700293 return FALSE;
294 }
Lei Zhang5044cab2015-11-10 10:09:33 -0800295
296 ProcessClipPath(pObj->m_ClipPath, pObj2Device);
297 if (ProcessTransparency(pObj, pObj2Device))
298 return FALSE;
299
Wei Li7cf13c92016-02-19 11:53:03 -0800300 if (pObj->IsImage()) {
dsinclaird647a6b2016-04-26 13:13:20 -0700301 m_pImageRenderer.reset(new CPDF_ImageRenderer);
302 if (!m_pImageRenderer->Start(this, pObj, pObj2Device, FALSE)) {
303 if (!m_pImageRenderer->m_Result)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700304 DrawObjWithBackground(pObj, pObj2Device);
dsinclaird647a6b2016-04-26 13:13:20 -0700305 m_pImageRenderer.reset();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700306 return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700307 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700308 return ContinueSingleObject(pObj, pObj2Device, pPause);
309 }
Lei Zhang5044cab2015-11-10 10:09:33 -0800310
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700311 ProcessObjectNoClip(pObj, pObj2Device);
312 return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700313}
Lei Zhang5044cab2015-11-10 10:09:33 -0800314
Tom Sepez60d909e2015-12-10 15:34:55 -0800315FX_BOOL CPDF_RenderStatus::GetObjectClippedRect(const CPDF_PageObject* pObj,
316 const CFX_Matrix* pObj2Device,
317 FX_BOOL bLogical,
318 FX_RECT& rect) const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700319 rect = pObj->GetBBox(pObj2Device);
320 FX_RECT rtClip = m_pDevice->GetClipBox();
321 if (!bLogical) {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700322 CFX_Matrix dCTM = m_pDevice->GetCTM();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700323 FX_FLOAT a = FXSYS_fabs(dCTM.a);
324 FX_FLOAT d = FXSYS_fabs(dCTM.d);
325 if (a != 1.0f || d != 1.0f) {
326 rect.right = rect.left + (int32_t)FXSYS_ceil((FX_FLOAT)rect.Width() * a);
327 rect.bottom = rect.top + (int32_t)FXSYS_ceil((FX_FLOAT)rect.Height() * d);
328 rtClip.right =
329 rtClip.left + (int32_t)FXSYS_ceil((FX_FLOAT)rtClip.Width() * a);
330 rtClip.bottom =
331 rtClip.top + (int32_t)FXSYS_ceil((FX_FLOAT)rtClip.Height() * d);
332 }
333 }
334 rect.Intersect(rtClip);
335 return rect.IsEmpty();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700336}
thestig490d6122016-05-23 14:56:02 -0700337
tsepezbbee4452016-09-02 15:22:00 -0700338void CPDF_RenderStatus::ProcessObjectNoClip(CPDF_PageObject* pObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800339 const CFX_Matrix* pObj2Device) {
caryclarka27d49a2016-07-06 10:20:25 -0700340#if defined _SKIA_SUPPORT_
341 DebugVerifyDeviceIsPreMultiplied();
342#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700343 FX_BOOL bRet = FALSE;
Wei Li7cf13c92016-02-19 11:53:03 -0800344 switch (pObj->GetType()) {
Tom Sepez8e5cd192016-01-26 13:20:26 -0800345 case CPDF_PageObject::TEXT:
thestig4997b222016-06-07 10:46:22 -0700346 bRet = ProcessText(pObj->AsText(), pObj2Device, nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700347 break;
Tom Sepez8e5cd192016-01-26 13:20:26 -0800348 case CPDF_PageObject::PATH:
Wei Li7cf13c92016-02-19 11:53:03 -0800349 bRet = ProcessPath(pObj->AsPath(), pObj2Device);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700350 break;
Tom Sepez8e5cd192016-01-26 13:20:26 -0800351 case CPDF_PageObject::IMAGE:
Wei Li7cf13c92016-02-19 11:53:03 -0800352 bRet = ProcessImage(pObj->AsImage(), pObj2Device);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700353 break;
Tom Sepez8e5cd192016-01-26 13:20:26 -0800354 case CPDF_PageObject::SHADING:
thestig490d6122016-05-23 14:56:02 -0700355 ProcessShading(pObj->AsShading(), pObj2Device);
356 return;
Tom Sepez8e5cd192016-01-26 13:20:26 -0800357 case CPDF_PageObject::FORM:
Wei Li7cf13c92016-02-19 11:53:03 -0800358 bRet = ProcessForm(pObj->AsForm(), pObj2Device);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700359 break;
360 }
thestig490d6122016-05-23 14:56:02 -0700361 if (!bRet)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700362 DrawObjWithBackground(pObj, pObj2Device);
caryclarka27d49a2016-07-06 10:20:25 -0700363#if defined _SKIA_SUPPORT_
364 DebugVerifyDeviceIsPreMultiplied();
365#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700366}
thestig490d6122016-05-23 14:56:02 -0700367
tsepezbbee4452016-09-02 15:22:00 -0700368FX_BOOL CPDF_RenderStatus::DrawObjWithBlend(CPDF_PageObject* pObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800369 const CFX_Matrix* pObj2Device) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700370 FX_BOOL bRet = FALSE;
Wei Li7cf13c92016-02-19 11:53:03 -0800371 switch (pObj->GetType()) {
Tom Sepez8e5cd192016-01-26 13:20:26 -0800372 case CPDF_PageObject::PATH:
Wei Li7cf13c92016-02-19 11:53:03 -0800373 bRet = ProcessPath(pObj->AsPath(), pObj2Device);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700374 break;
Tom Sepez8e5cd192016-01-26 13:20:26 -0800375 case CPDF_PageObject::IMAGE:
Wei Li7cf13c92016-02-19 11:53:03 -0800376 bRet = ProcessImage(pObj->AsImage(), pObj2Device);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700377 break;
Tom Sepez8e5cd192016-01-26 13:20:26 -0800378 case CPDF_PageObject::FORM:
Wei Li7cf13c92016-02-19 11:53:03 -0800379 bRet = ProcessForm(pObj->AsForm(), pObj2Device);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700380 break;
Tom Sepez8e5cd192016-01-26 13:20:26 -0800381 default:
382 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700383 }
384 return bRet;
385}
386void CPDF_RenderStatus::GetScaledMatrix(CFX_Matrix& matrix) const {
387 CFX_Matrix dCTM = m_pDevice->GetCTM();
388 matrix.a *= FXSYS_fabs(dCTM.a);
389 matrix.d *= FXSYS_fabs(dCTM.d);
390}
tsepezbbee4452016-09-02 15:22:00 -0700391
392void CPDF_RenderStatus::DrawObjWithBackground(CPDF_PageObject* pObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800393 const CFX_Matrix* pObj2Device) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700394 FX_RECT rect;
395 if (GetObjectClippedRect(pObj, pObj2Device, FALSE, rect)) {
396 return;
397 }
398 int res = 300;
Wei Li7cf13c92016-02-19 11:53:03 -0800399 if (pObj->IsImage() &&
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700400 m_pDevice->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
401 res = 0;
402 }
403 CPDF_ScaledRenderBuffer buffer;
Lei Zhang96660d62015-12-14 18:27:25 -0800404 if (!buffer.Initialize(m_pContext, m_pDevice, rect, pObj, &m_Options, res)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700405 return;
406 }
Tom Sepez60d909e2015-12-10 15:34:55 -0800407 CFX_Matrix matrix = *pObj2Device;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700408 matrix.Concat(*buffer.GetMatrix());
409 GetScaledMatrix(matrix);
thestig4997b222016-06-07 10:46:22 -0700410 CPDF_Dictionary* pFormResource = nullptr;
Wei Li7cf13c92016-02-19 11:53:03 -0800411 if (pObj->IsForm()) {
412 const CPDF_FormObject* pFormObj = pObj->AsForm();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700413 if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) {
Wei Li9b761132016-01-29 15:44:20 -0800414 pFormResource = pFormObj->m_pForm->m_pFormDict->GetDictBy("Resources");
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700415 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700416 }
417 CPDF_RenderStatus status;
thestig4997b222016-06-07 10:46:22 -0700418 status.Initialize(m_pContext, buffer.GetDevice(), buffer.GetMatrix(), nullptr,
419 nullptr, nullptr, &m_Options, m_Transparency,
420 m_bDropObjects, pFormResource);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700421 status.RenderSingleObject(pObj, &matrix);
422 buffer.OutputToDevice();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700423}
caryclarka27d49a2016-07-06 10:20:25 -0700424
Wei Li7cf13c92016-02-19 11:53:03 -0800425FX_BOOL CPDF_RenderStatus::ProcessForm(const CPDF_FormObject* pFormObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800426 const CFX_Matrix* pObj2Device) {
caryclarka27d49a2016-07-06 10:20:25 -0700427#if defined _SKIA_SUPPORT_
428 DebugVerifyDeviceIsPreMultiplied();
429#endif
Wei Li9b761132016-01-29 15:44:20 -0800430 CPDF_Dictionary* pOC = pFormObj->m_pForm->m_pFormDict->GetDictBy("OC");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700431 if (pOC && m_Options.m_pOCContext &&
432 !m_Options.m_pOCContext->CheckOCGVisible(pOC)) {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700433 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700434 }
Tom Sepez60d909e2015-12-10 15:34:55 -0800435 CFX_Matrix matrix = pFormObj->m_FormMatrix;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700436 matrix.Concat(*pObj2Device);
thestig4997b222016-06-07 10:46:22 -0700437 CPDF_Dictionary* pResources = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700438 if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) {
Wei Li9b761132016-01-29 15:44:20 -0800439 pResources = pFormObj->m_pForm->m_pFormDict->GetDictBy("Resources");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700440 }
441 CPDF_RenderStatus status;
thestig4997b222016-06-07 10:46:22 -0700442 status.Initialize(m_pContext, m_pDevice, nullptr, m_pStopObj, this, pFormObj,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700443 &m_Options, m_Transparency, m_bDropObjects, pResources,
444 FALSE);
445 status.m_curBlend = m_curBlend;
446 m_pDevice->SaveState();
weili44105d82016-07-06 18:10:35 -0700447 status.RenderObjectList(pFormObj->m_pForm.get(), &matrix);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700448 m_bStopped = status.m_bStopped;
thestig41846a02016-05-26 10:45:30 -0700449 m_pDevice->RestoreState(false);
caryclarka27d49a2016-07-06 10:20:25 -0700450#if defined _SKIA_SUPPORT_
451 DebugVerifyDeviceIsPreMultiplied();
452#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700453 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700454}
caryclarka27d49a2016-07-06 10:20:25 -0700455
Tom Sepez60d909e2015-12-10 15:34:55 -0800456FX_BOOL IsAvailableMatrix(const CFX_Matrix& matrix) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700457 if (matrix.a == 0 || matrix.d == 0) {
458 return matrix.b != 0 && matrix.c != 0;
459 }
460 if (matrix.b == 0 || matrix.c == 0) {
461 return matrix.a != 0 && matrix.d != 0;
462 }
463 return TRUE;
464}
thestigd3e354a2016-05-26 11:04:40 -0700465
tsepezbbee4452016-09-02 15:22:00 -0700466FX_BOOL CPDF_RenderStatus::ProcessPath(CPDF_PathObject* pPathObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800467 const CFX_Matrix* pObj2Device) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700468 int FillType = pPathObj->m_FillType;
469 FX_BOOL bStroke = pPathObj->m_bStroke;
470 ProcessPathPattern(pPathObj, pObj2Device, FillType, bStroke);
thestig2f307662016-06-13 15:02:05 -0700471 if (FillType == 0 && !bStroke)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700472 return TRUE;
thestig2f307662016-06-13 15:02:05 -0700473
474 uint32_t fill_argb = FillType ? GetFillArgb(pPathObj) : 0;
475 uint32_t stroke_argb = bStroke ? GetStrokeArgb(pPathObj) : 0;
Tom Sepez60d909e2015-12-10 15:34:55 -0800476 CFX_Matrix path_matrix = pPathObj->m_Matrix;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700477 path_matrix.Concat(*pObj2Device);
thestig2f307662016-06-13 15:02:05 -0700478 if (!IsAvailableMatrix(path_matrix))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700479 return TRUE;
thestig2f307662016-06-13 15:02:05 -0700480
481 if (FillType && (m_Options.m_Flags & RENDER_RECT_AA))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700482 FillType |= FXFILL_RECT_AA;
thestig2f307662016-06-13 15:02:05 -0700483 if (m_Options.m_Flags & RENDER_FILL_FULLCOVER)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700484 FillType |= FXFILL_FULLCOVER;
thestig2f307662016-06-13 15:02:05 -0700485 if (m_Options.m_Flags & RENDER_NOPATHSMOOTH)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700486 FillType |= FXFILL_NOPATHSMOOTH;
thestig2f307662016-06-13 15:02:05 -0700487 if (bStroke)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700488 FillType |= FX_FILL_STROKE;
tsepezbbee4452016-09-02 15:22:00 -0700489
490 const CPDF_PageObject* pPageObj =
491 static_cast<const CPDF_PageObject*>(pPathObj);
492 if (pPageObj->m_GeneralState.GetStrokeAdjust())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700493 FillType |= FX_STROKE_ADJUST;
thestig2f307662016-06-13 15:02:05 -0700494 if (m_pType3Char)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700495 FillType |= FX_FILL_TEXT_MODE;
thestig2f307662016-06-13 15:02:05 -0700496
tsepez4d9df422016-08-31 10:26:38 -0700497 CPDF_GraphState graphState = pPathObj->m_GraphState;
thestig2f307662016-06-13 15:02:05 -0700498 if (m_Options.m_Flags & RENDER_THINLINE)
tsepez4d9df422016-08-31 10:26:38 -0700499 graphState.SetLineWidth(0);
500 return m_pDevice->DrawPathWithBlend(
501 pPathObj->m_Path.GetObject(), &path_matrix, graphState.GetObject(),
502 fill_argb, stroke_argb, FillType, m_curBlend);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700503}
thestigd3e354a2016-05-26 11:04:40 -0700504
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700505CPDF_TransferFunc* CPDF_RenderStatus::GetTransferFunc(CPDF_Object* pObj) const {
Lei Zhang96660d62015-12-14 18:27:25 -0800506 ASSERT(pObj);
Tom Sepez71fdc342016-01-22 12:06:32 -0800507 CPDF_DocRenderData* pDocCache = m_pContext->GetDocument()->GetRenderData();
Lei Zhang96660d62015-12-14 18:27:25 -0800508 return pDocCache ? pDocCache->GetTransferFunc(pObj) : nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700509}
tsepezbbee4452016-09-02 15:22:00 -0700510
511FX_ARGB CPDF_RenderStatus::GetFillArgb(CPDF_PageObject* pObj,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700512 FX_BOOL bType3) const {
tsepez7d2a8d92016-06-08 11:51:23 -0700513 const CPDF_ColorStateData* pColorData = pObj->m_ColorState.GetObject();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700514 if (m_pType3Char && !bType3 &&
515 (!m_pType3Char->m_bColored ||
516 (m_pType3Char->m_bColored &&
tsepezadbd3292016-08-29 14:07:28 -0700517 (!pColorData || pColorData->m_FillColor.IsNull())))) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700518 return m_T3FillColor;
519 }
tsepezadbd3292016-08-29 14:07:28 -0700520 if (!pColorData || pColorData->m_FillColor.IsNull()) {
tsepez7d2a8d92016-06-08 11:51:23 -0700521 pColorData = m_InitialStates.m_ColorState.GetObject();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700522 }
tsepezadbd3292016-08-29 14:07:28 -0700523 FX_COLORREF rgb = pColorData->m_FillRGB;
tsepezb5e8f142016-03-25 15:18:35 -0700524 if (rgb == (uint32_t)-1) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700525 return 0;
526 }
tsepezbbee4452016-09-02 15:22:00 -0700527 int32_t alpha =
528 static_cast<int32_t>((pObj->m_GeneralState.GetFillAlpha() * 255));
529 if (pObj->m_GeneralState.GetTR()) {
530 if (!pObj->m_GeneralState.GetTransferFunc()) {
531 pObj->m_GeneralState.SetTransferFunc(
532 GetTransferFunc(pObj->m_GeneralState.GetTR()));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700533 }
tsepezbbee4452016-09-02 15:22:00 -0700534 if (pObj->m_GeneralState.GetTransferFunc())
535 rgb = pObj->m_GeneralState.GetTransferFunc()->TranslateColor(rgb);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700536 }
537 return m_Options.TranslateColor(ArgbEncode(alpha, rgb));
538}
tsepezbbee4452016-09-02 15:22:00 -0700539
540FX_ARGB CPDF_RenderStatus::GetStrokeArgb(CPDF_PageObject* pObj) const {
tsepez7d2a8d92016-06-08 11:51:23 -0700541 const CPDF_ColorStateData* pColorData = pObj->m_ColorState.GetObject();
tsepezadbd3292016-08-29 14:07:28 -0700542 if (m_pType3Char && (!m_pType3Char->m_bColored ||
543 (m_pType3Char->m_bColored &&
544 (!pColorData || pColorData->m_StrokeColor.IsNull())))) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700545 return m_T3FillColor;
546 }
tsepezadbd3292016-08-29 14:07:28 -0700547 if (!pColorData || pColorData->m_StrokeColor.IsNull()) {
tsepez7d2a8d92016-06-08 11:51:23 -0700548 pColorData = m_InitialStates.m_ColorState.GetObject();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700549 }
tsepezadbd3292016-08-29 14:07:28 -0700550 FX_COLORREF rgb = pColorData->m_StrokeRGB;
tsepezb5e8f142016-03-25 15:18:35 -0700551 if (rgb == (uint32_t)-1) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700552 return 0;
553 }
tsepezbbee4452016-09-02 15:22:00 -0700554 int32_t alpha = static_cast<int32_t>(pObj->m_GeneralState.GetStrokeAlpha() *
555 255); // not rounded.
556 if (pObj->m_GeneralState.GetTR()) {
557 if (!pObj->m_GeneralState.GetTransferFunc()) {
558 pObj->m_GeneralState.SetTransferFunc(
559 GetTransferFunc(pObj->m_GeneralState.GetTR()));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700560 }
tsepezbbee4452016-09-02 15:22:00 -0700561 if (pObj->m_GeneralState.GetTransferFunc())
562 rgb = pObj->m_GeneralState.GetTransferFunc()->TranslateColor(rgb);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700563 }
564 return m_Options.TranslateColor(ArgbEncode(alpha, rgb));
565}
566void CPDF_RenderStatus::ProcessClipPath(CPDF_ClipPath ClipPath,
Tom Sepez60d909e2015-12-10 15:34:55 -0800567 const CFX_Matrix* pObj2Device) {
tsepez83d23512016-08-26 14:56:39 -0700568 if (!ClipPath) {
569 if (m_LastClipPath) {
thestig41846a02016-05-26 10:45:30 -0700570 m_pDevice->RestoreState(true);
tsepezd24c3a62016-08-29 14:42:36 -0700571 m_LastClipPath.SetNull();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700572 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700573 return;
574 }
Lei Zhang5044cab2015-11-10 10:09:33 -0800575 if (m_LastClipPath == ClipPath)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700576 return;
Lei Zhang5044cab2015-11-10 10:09:33 -0800577
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700578 m_LastClipPath = ClipPath;
thestig41846a02016-05-26 10:45:30 -0700579 m_pDevice->RestoreState(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700580 int nClipPath = ClipPath.GetPathCount();
Lei Zhang5044cab2015-11-10 10:09:33 -0800581 for (int i = 0; i < nClipPath; ++i) {
tsepez7d2a8d92016-06-08 11:51:23 -0700582 const CFX_PathData* pPathData = ClipPath.GetPath(i).GetObject();
Lei Zhang5044cab2015-11-10 10:09:33 -0800583 if (!pPathData)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700584 continue;
Lei Zhang5044cab2015-11-10 10:09:33 -0800585
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700586 if (pPathData->GetPointCount() == 0) {
587 CFX_PathData EmptyPath;
588 EmptyPath.AppendRect(-1, -1, 0, 0);
589 int fill_mode = FXFILL_WINDING;
Lei Zhang5044cab2015-11-10 10:09:33 -0800590 m_pDevice->SetClip_PathFill(&EmptyPath, nullptr, fill_mode);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700591 } else {
592 int ClipType = ClipPath.GetClipType(i);
593 m_pDevice->SetClip_PathFill(pPathData, pObj2Device, ClipType);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700594 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700595 }
596 int textcount = ClipPath.GetTextCount();
Lei Zhang5044cab2015-11-10 10:09:33 -0800597 if (textcount == 0)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700598 return;
Lei Zhang5044cab2015-11-10 10:09:33 -0800599
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700600 if (m_pDevice->GetDeviceClass() == FXDC_DISPLAY &&
601 !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP)) {
602 return;
603 }
Lei Zhang5044cab2015-11-10 10:09:33 -0800604
Lei Zhangaa8bf7e2015-12-24 19:13:32 -0800605 std::unique_ptr<CFX_PathData> pTextClippingPath;
Lei Zhang5044cab2015-11-10 10:09:33 -0800606 for (int i = 0; i < textcount; ++i) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700607 CPDF_TextObject* pText = ClipPath.GetText(i);
Lei Zhang5044cab2015-11-10 10:09:33 -0800608 if (pText) {
609 if (!pTextClippingPath)
610 pTextClippingPath.reset(new CFX_PathData);
611 ProcessText(pText, pObj2Device, pTextClippingPath.get());
612 continue;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700613 }
Lei Zhang5044cab2015-11-10 10:09:33 -0800614
615 if (!pTextClippingPath)
616 continue;
617
618 int fill_mode = FXFILL_WINDING;
619 if (m_Options.m_Flags & RENDER_NOTEXTSMOOTH)
620 fill_mode |= FXFILL_NOPATHSMOOTH;
621 m_pDevice->SetClip_PathFill(pTextClippingPath.get(), nullptr, fill_mode);
622 pTextClippingPath.reset();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700623 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700624}
Lei Zhang5044cab2015-11-10 10:09:33 -0800625
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700626void CPDF_RenderStatus::DrawClipPath(CPDF_ClipPath ClipPath,
Tom Sepez60d909e2015-12-10 15:34:55 -0800627 const CFX_Matrix* pObj2Device) {
tsepez83d23512016-08-26 14:56:39 -0700628 if (!ClipPath)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700629 return;
tsepez83d23512016-08-26 14:56:39 -0700630
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700631 int fill_mode = 0;
632 if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) {
633 fill_mode |= FXFILL_NOPATHSMOOTH;
634 }
635 int nClipPath = ClipPath.GetPathCount();
636 int i;
637 for (i = 0; i < nClipPath; i++) {
tsepez7d2a8d92016-06-08 11:51:23 -0700638 const CFX_PathData* pPathData = ClipPath.GetPath(i).GetObject();
Lei Zhang412e9082015-12-14 18:34:00 -0800639 if (!pPathData) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700640 continue;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700641 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700642 CFX_GraphStateData stroke_state;
643 if (m_Options.m_Flags & RENDER_THINLINE) {
644 stroke_state.m_LineWidth = 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700645 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700646 m_pDevice->DrawPath(pPathData, pObj2Device, &stroke_state, 0, 0xffff0000,
647 fill_mode);
648 }
649}
Wei Li7cf13c92016-02-19 11:53:03 -0800650FX_BOOL CPDF_RenderStatus::SelectClipPath(const CPDF_PathObject* pPathObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800651 const CFX_Matrix* pObj2Device,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700652 FX_BOOL bStroke) {
Tom Sepez60d909e2015-12-10 15:34:55 -0800653 CFX_Matrix path_matrix = pPathObj->m_Matrix;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700654 path_matrix.Concat(*pObj2Device);
655 if (bStroke) {
tsepez7d2a8d92016-06-08 11:51:23 -0700656 CFX_GraphStateData graphState(*pPathObj->m_GraphState.GetObject());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700657 if (m_Options.m_Flags & RENDER_THINLINE) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700658 graphState.m_LineWidth = 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700659 }
tsepez7d2a8d92016-06-08 11:51:23 -0700660 return m_pDevice->SetClip_PathStroke(pPathObj->m_Path.GetObject(),
661 &path_matrix, &graphState);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700662 }
663 int fill_mode = pPathObj->m_FillType;
664 if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) {
665 fill_mode |= FXFILL_NOPATHSMOOTH;
666 }
tsepez7d2a8d92016-06-08 11:51:23 -0700667 return m_pDevice->SetClip_PathFill(pPathObj->m_Path.GetObject(), &path_matrix,
668 fill_mode);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700669}
tsepezbbee4452016-09-02 15:22:00 -0700670FX_BOOL CPDF_RenderStatus::ProcessTransparency(CPDF_PageObject* pPageObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800671 const CFX_Matrix* pObj2Device) {
caryclarka27d49a2016-07-06 10:20:25 -0700672#if defined _SKIA_SUPPORT_
673 DebugVerifyDeviceIsPreMultiplied();
674#endif
tsepezbbee4452016-09-02 15:22:00 -0700675 int blend_type = pPageObj->m_GeneralState.GetBlendType();
676 if (blend_type == FXDIB_BLEND_UNSUPPORTED)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700677 return TRUE;
tsepezbbee4452016-09-02 15:22:00 -0700678
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700679 CPDF_Dictionary* pSMaskDict =
tsepezbbee4452016-09-02 15:22:00 -0700680 ToDictionary(pPageObj->m_GeneralState.GetSoftMask());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700681 if (pSMaskDict) {
Wei Li7cf13c92016-02-19 11:53:03 -0800682 if (pPageObj->IsImage() &&
thestigf41d9dc2016-08-05 22:34:58 -0700683 pPageObj->AsImage()->GetImage()->GetDict()->KeyExist("SMask")) {
thestig4997b222016-06-07 10:46:22 -0700684 pSMaskDict = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700685 }
686 }
thestig4997b222016-06-07 10:46:22 -0700687 CPDF_Dictionary* pFormResource = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700688 FX_FLOAT group_alpha = 1.0f;
689 int Transparency = m_Transparency;
690 FX_BOOL bGroupTransparent = FALSE;
Wei Li7cf13c92016-02-19 11:53:03 -0800691 if (pPageObj->IsForm()) {
692 const CPDF_FormObject* pFormObj = pPageObj->AsForm();
tsepezbbee4452016-09-02 15:22:00 -0700693 group_alpha = pFormObj->m_GeneralState.GetFillAlpha();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700694 Transparency = pFormObj->m_pForm->m_Transparency;
Lei Zhangb0748bb2015-10-19 12:11:49 -0700695 bGroupTransparent = !!(Transparency & PDFTRANS_ISOLATED);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700696 if (pFormObj->m_pForm->m_pFormDict) {
Wei Li9b761132016-01-29 15:44:20 -0800697 pFormResource = pFormObj->m_pForm->m_pFormDict->GetDictBy("Resources");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700698 }
699 }
tsepez83d23512016-08-26 14:56:39 -0700700 bool bTextClip =
701 (pPageObj->m_ClipPath && pPageObj->m_ClipPath.GetTextCount() &&
702 m_pDevice->GetDeviceClass() == FXDC_DISPLAY &&
703 !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP));
Wei Li7cf13c92016-02-19 11:53:03 -0800704 if ((m_Options.m_Flags & RENDER_OVERPRINT) && pPageObj->IsImage() &&
tsepezbbee4452016-09-02 15:22:00 -0700705 pPageObj->m_GeneralState.GetFillOP() &&
706 pPageObj->m_GeneralState.GetStrokeOP()) {
thestig4997b222016-06-07 10:46:22 -0700707 CPDF_Document* pDocument = nullptr;
708 CPDF_Page* pPage = nullptr;
Tom Sepez71fdc342016-01-22 12:06:32 -0800709 if (m_pContext->GetPageCache()) {
710 pPage = m_pContext->GetPageCache()->GetPage();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700711 pDocument = pPage->m_pDocument;
712 } else {
thestigf41d9dc2016-08-05 22:34:58 -0700713 pDocument = pPageObj->AsImage()->GetImage()->GetDocument();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700714 }
thestig4997b222016-06-07 10:46:22 -0700715 CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : nullptr;
tsepezbd567552016-03-29 14:51:50 -0700716 CPDF_Object* pCSObj = pPageObj->AsImage()
thestigf41d9dc2016-08-05 22:34:58 -0700717 ->GetImage()
718 ->GetStream()
tsepezbd567552016-03-29 14:51:50 -0700719 ->GetDict()
720 ->GetDirectObjectBy("ColorSpace");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700721 CPDF_ColorSpace* pColorSpace =
722 pDocument->LoadColorSpace(pCSObj, pPageResources);
723 if (pColorSpace) {
724 int format = pColorSpace->GetFamily();
725 if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION ||
726 format == PDFCS_DEVICEN) {
727 blend_type = FXDIB_BLEND_DARKEN;
728 }
729 pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
730 }
731 }
Lei Zhang412e9082015-12-14 18:34:00 -0800732 if (!pSMaskDict && group_alpha == 1.0f && blend_type == FXDIB_BLEND_NORMAL &&
733 !bTextClip && !bGroupTransparent) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700734 return FALSE;
735 }
tsepez7d89e722016-05-04 13:38:11 -0700736 bool isolated = !!(Transparency & PDFTRANS_ISOLATED);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700737 if (m_bPrint) {
738 FX_BOOL bRet = FALSE;
739 int rendCaps = m_pDevice->GetRenderCaps();
740 if (!((Transparency & PDFTRANS_ISOLATED) || pSMaskDict || bTextClip) &&
741 (rendCaps & FXRC_BLEND_MODE)) {
742 int oldBlend = m_curBlend;
743 m_curBlend = blend_type;
744 bRet = DrawObjWithBlend(pPageObj, pObj2Device);
745 m_curBlend = oldBlend;
746 }
747 if (!bRet) {
748 DrawObjWithBackground(pPageObj, pObj2Device);
749 }
750 return TRUE;
751 }
752 FX_RECT rect = pPageObj->GetBBox(pObj2Device);
753 rect.Intersect(m_pDevice->GetClipBox());
754 if (rect.IsEmpty()) {
755 return TRUE;
756 }
757 CFX_Matrix deviceCTM = m_pDevice->GetCTM();
758 FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a);
759 FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d);
760 int width = FXSYS_round((FX_FLOAT)rect.Width() * scaleX);
761 int height = FXSYS_round((FX_FLOAT)rect.Height() * scaleY);
762 CFX_FxgeDevice bitmap_device;
Lei Zhangaa8bf7e2015-12-24 19:13:32 -0800763 std::unique_ptr<CFX_DIBitmap> oriDevice;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700764 if (!isolated && (m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) {
Lei Zhang5044cab2015-11-10 10:09:33 -0800765 oriDevice.reset(new CFX_DIBitmap);
766 if (!m_pDevice->CreateCompatibleBitmap(oriDevice.get(), width, height))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700767 return TRUE;
Lei Zhang5044cab2015-11-10 10:09:33 -0800768 m_pDevice->GetDIBits(oriDevice.get(), rect.left, rect.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700769 }
thestigbefa4502016-05-26 20:15:19 -0700770 if (!bitmap_device.Create(width, height, FXDIB_Argb, oriDevice.get()))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700771 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700772 CFX_DIBitmap* bitmap = bitmap_device.GetBitmap();
773 bitmap->Clear(0);
Tom Sepez60d909e2015-12-10 15:34:55 -0800774 CFX_Matrix new_matrix = *pObj2Device;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700775 new_matrix.TranslateI(-rect.left, -rect.top);
776 new_matrix.Scale(scaleX, scaleY);
Lei Zhangaa8bf7e2015-12-24 19:13:32 -0800777 std::unique_ptr<CFX_DIBitmap> pTextMask;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700778 if (bTextClip) {
Lei Zhang5044cab2015-11-10 10:09:33 -0800779 pTextMask.reset(new CFX_DIBitmap);
780 if (!pTextMask->Create(width, height, FXDIB_8bppMask))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700781 return TRUE;
Lei Zhang5044cab2015-11-10 10:09:33 -0800782
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700783 pTextMask->Clear(0);
784 CFX_FxgeDevice text_device;
thestigbefa4502016-05-26 20:15:19 -0700785 text_device.Attach(pTextMask.get(), false, nullptr, false);
tsepezb5e8f142016-03-25 15:18:35 -0700786 for (uint32_t i = 0; i < pPageObj->m_ClipPath.GetTextCount(); i++) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700787 CPDF_TextObject* textobj = pPageObj->m_ClipPath.GetText(i);
Lei Zhang412e9082015-12-14 18:34:00 -0800788 if (!textobj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700789 break;
790 }
Tom Sepez60d909e2015-12-10 15:34:55 -0800791 CFX_Matrix text_matrix;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700792 textobj->GetTextMatrix(&text_matrix);
793 CPDF_TextRenderer::DrawTextPath(
794 &text_device, textobj->m_nChars, textobj->m_pCharCodes,
tsepez59601432016-08-29 14:26:57 -0700795 textobj->m_pCharPos, textobj->m_TextState.GetFont(),
796 textobj->m_TextState.GetFontSize(), &text_matrix, &new_matrix,
tsepez7d2a8d92016-06-08 11:51:23 -0700797 textobj->m_GraphState.GetObject(), (FX_ARGB)-1, 0, nullptr, 0);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700798 }
799 }
800 CPDF_RenderStatus bitmap_render;
thestig4997b222016-06-07 10:46:22 -0700801 bitmap_render.Initialize(m_pContext, &bitmap_device, nullptr, m_pStopObj,
802 nullptr, nullptr, &m_Options, 0, m_bDropObjects,
803 pFormResource, TRUE);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700804 bitmap_render.ProcessObjectNoClip(pPageObj, &new_matrix);
805 m_bStopped = bitmap_render.m_bStopped;
806 if (pSMaskDict) {
tsepeze106b502016-09-02 16:53:09 -0700807 CFX_Matrix smask_matrix = *pPageObj->m_GeneralState.GetSMaskMatrix();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700808 smask_matrix.Concat(*pObj2Device);
Lei Zhangaa8bf7e2015-12-24 19:13:32 -0800809 std::unique_ptr<CFX_DIBSource> pSMaskSource(
Lei Zhang5044cab2015-11-10 10:09:33 -0800810 LoadSMask(pSMaskDict, &rect, &smask_matrix));
811 if (pSMaskSource)
812 bitmap->MultiplyAlpha(pSMaskSource.get());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700813 }
814 if (pTextMask) {
Lei Zhang5044cab2015-11-10 10:09:33 -0800815 bitmap->MultiplyAlpha(pTextMask.get());
816 pTextMask.reset();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700817 }
caryclark36e258b2016-06-02 08:59:20 -0700818 int32_t blitAlpha = 255;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700819 if (Transparency & PDFTRANS_GROUP && group_alpha != 1.0f) {
caryclark36e258b2016-06-02 08:59:20 -0700820 blitAlpha = (int32_t)(group_alpha * 255);
821#ifndef _SKIA_SUPPORT_
822 bitmap->MultiplyAlpha(blitAlpha);
823 blitAlpha = 255;
824#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700825 }
826 Transparency = m_Transparency;
Wei Li7cf13c92016-02-19 11:53:03 -0800827 if (pPageObj->IsForm()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700828 Transparency |= PDFTRANS_GROUP;
829 }
caryclark36e258b2016-06-02 08:59:20 -0700830 CompositeDIBitmap(bitmap, rect.left, rect.top, 0, blitAlpha, blend_type,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700831 Transparency);
caryclarka27d49a2016-07-06 10:20:25 -0700832#if defined _SKIA_SUPPORT_
833 DebugVerifyDeviceIsPreMultiplied();
834#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700835 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700836}
Lei Zhang5044cab2015-11-10 10:09:33 -0800837
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700838CFX_DIBitmap* CPDF_RenderStatus::GetBackdrop(const CPDF_PageObject* pObj,
839 const FX_RECT& rect,
840 int& left,
841 int& top,
842 FX_BOOL bBackAlphaRequired) {
843 FX_RECT bbox = rect;
844 bbox.Intersect(m_pDevice->GetClipBox());
845 left = bbox.left;
846 top = bbox.top;
847 CFX_Matrix deviceCTM = m_pDevice->GetCTM();
848 FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a);
849 FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d);
850 int width = FXSYS_round(bbox.Width() * scaleX);
851 int height = FXSYS_round(bbox.Height() * scaleY);
Lei Zhangaa8bf7e2015-12-24 19:13:32 -0800852 std::unique_ptr<CFX_DIBitmap> pBackdrop(new CFX_DIBitmap);
Lei Zhang5044cab2015-11-10 10:09:33 -0800853 if (bBackAlphaRequired && !m_bDropObjects)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700854 pBackdrop->Create(width, height, FXDIB_Argb);
Lei Zhang5044cab2015-11-10 10:09:33 -0800855 else
856 m_pDevice->CreateCompatibleBitmap(pBackdrop.get(), width, height);
857
858 if (!pBackdrop->GetBuffer())
859 return nullptr;
860
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700861 FX_BOOL bNeedDraw;
Lei Zhang5044cab2015-11-10 10:09:33 -0800862 if (pBackdrop->HasAlpha())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700863 bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT);
Lei Zhang5044cab2015-11-10 10:09:33 -0800864 else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700865 bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS);
Lei Zhang5044cab2015-11-10 10:09:33 -0800866
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700867 if (!bNeedDraw) {
Lei Zhang5044cab2015-11-10 10:09:33 -0800868 m_pDevice->GetDIBits(pBackdrop.get(), left, top);
869 return pBackdrop.release();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700870 }
Lei Zhang5044cab2015-11-10 10:09:33 -0800871
Tom Sepez60d909e2015-12-10 15:34:55 -0800872 CFX_Matrix FinalMatrix = m_DeviceMatrix;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700873 FinalMatrix.TranslateI(-left, -top);
874 FinalMatrix.Scale(scaleX, scaleY);
875 pBackdrop->Clear(pBackdrop->HasAlpha() ? 0 : 0xffffffff);
876 CFX_FxgeDevice device;
thestigbefa4502016-05-26 20:15:19 -0700877 device.Attach(pBackdrop.get(), false, nullptr, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700878 m_pContext->Render(&device, pObj, &m_Options, &FinalMatrix);
Lei Zhang5044cab2015-11-10 10:09:33 -0800879 return pBackdrop.release();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700880}
Lei Zhang5044cab2015-11-10 10:09:33 -0800881
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700882void CPDF_RenderContext::GetBackground(CFX_DIBitmap* pBuffer,
883 const CPDF_PageObject* pObj,
884 const CPDF_RenderOptions* pOptions,
Tom Sepez60d909e2015-12-10 15:34:55 -0800885 CFX_Matrix* pFinalMatrix) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700886 CFX_FxgeDevice device;
thestigbefa4502016-05-26 20:15:19 -0700887 device.Attach(pBuffer, false, nullptr, false);
Tom Sepez76510e42015-06-03 16:19:04 -0700888
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700889 FX_RECT rect(0, 0, device.GetWidth(), device.GetHeight());
890 device.FillRect(&rect, 0xffffffff);
891 Render(&device, pObj, pOptions, pFinalMatrix);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700892}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700893CPDF_GraphicStates* CPDF_RenderStatus::CloneObjStates(
894 const CPDF_GraphicStates* pSrcStates,
895 FX_BOOL bStroke) {
tsepezca90b872016-08-31 10:41:00 -0700896 if (!pSrcStates)
thestig4997b222016-06-07 10:46:22 -0700897 return nullptr;
tsepezca90b872016-08-31 10:41:00 -0700898
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700899 CPDF_GraphicStates* pStates = new CPDF_GraphicStates;
900 pStates->CopyStates(*pSrcStates);
tsepez987f3ee2016-08-26 15:17:12 -0700901 const CPDF_Color* pObjColor = bStroke
tsepezadbd3292016-08-29 14:07:28 -0700902 ? pSrcStates->m_ColorState.GetStrokeColor()
903 : pSrcStates->m_ColorState.GetFillColor();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700904 if (!pObjColor->IsNull()) {
tsepezca90b872016-08-31 10:41:00 -0700905 pStates->m_ColorState.SetFillRGB(
906 bStroke ? pSrcStates->m_ColorState.GetStrokeRGB()
907 : pSrcStates->m_ColorState.GetFillRGB());
908 pStates->m_ColorState.SetStrokeRGB(pStates->m_ColorState.GetFillRGB());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700909 }
910 return pStates;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700911}
Tom Sepez71fdc342016-01-22 12:06:32 -0800912
Tom Sepez979ddd82015-12-17 13:41:13 -0800913CPDF_RenderContext::CPDF_RenderContext(CPDF_Page* pPage)
914 : m_pDocument(pPage->m_pDocument),
915 m_pPageResources(pPage->m_pPageResources),
jaepark844c4b22016-07-26 12:35:22 -0700916 m_pPageCache(pPage->GetRenderCache()) {}
Tom Sepez71fdc342016-01-22 12:06:32 -0800917
Tom Sepez979ddd82015-12-17 13:41:13 -0800918CPDF_RenderContext::CPDF_RenderContext(CPDF_Document* pDoc,
919 CPDF_PageRenderCache* pPageCache)
jaepark844c4b22016-07-26 12:35:22 -0700920 : m_pDocument(pDoc), m_pPageResources(nullptr), m_pPageCache(pPageCache) {}
Tom Sepez71fdc342016-01-22 12:06:32 -0800921
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700922CPDF_RenderContext::~CPDF_RenderContext() {}
Tom Sepez71fdc342016-01-22 12:06:32 -0800923
Tom Sepez32c70812016-02-16 17:15:32 -0800924void CPDF_RenderContext::AppendLayer(CPDF_PageObjectHolder* pObjectHolder,
Tom Sepez71fdc342016-01-22 12:06:32 -0800925 const CFX_Matrix* pObject2Device) {
926 Layer* pLayer = m_Layers.AddSpace();
Tom Sepez32c70812016-02-16 17:15:32 -0800927 pLayer->m_pObjectHolder = pObjectHolder;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700928 if (pObject2Device) {
Tom Sepez71fdc342016-01-22 12:06:32 -0800929 pLayer->m_Matrix = *pObject2Device;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700930 } else {
Tom Sepez71fdc342016-01-22 12:06:32 -0800931 pLayer->m_Matrix.SetIdentity();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700932 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700933}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700934void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice,
935 const CPDF_RenderOptions* pOptions,
Tom Sepez60d909e2015-12-10 15:34:55 -0800936 const CFX_Matrix* pLastMatrix) {
thestig4997b222016-06-07 10:46:22 -0700937 Render(pDevice, nullptr, pOptions, pLastMatrix);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700938}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700939void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice,
940 const CPDF_PageObject* pStopObj,
941 const CPDF_RenderOptions* pOptions,
Tom Sepez60d909e2015-12-10 15:34:55 -0800942 const CFX_Matrix* pLastMatrix) {
Tom Sepez71fdc342016-01-22 12:06:32 -0800943 int count = m_Layers.GetSize();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700944 for (int j = 0; j < count; j++) {
945 pDevice->SaveState();
Tom Sepez71fdc342016-01-22 12:06:32 -0800946 Layer* pLayer = m_Layers.GetDataPtr(j);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700947 if (pLastMatrix) {
Tom Sepez71fdc342016-01-22 12:06:32 -0800948 CFX_Matrix FinalMatrix = pLayer->m_Matrix;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700949 FinalMatrix.Concat(*pLastMatrix);
950 CPDF_RenderStatus status;
thestig4997b222016-06-07 10:46:22 -0700951 status.Initialize(this, pDevice, pLastMatrix, pStopObj, nullptr, nullptr,
Tom Sepez32c70812016-02-16 17:15:32 -0800952 pOptions, pLayer->m_pObjectHolder->m_Transparency,
thestig4997b222016-06-07 10:46:22 -0700953 FALSE, nullptr);
Tom Sepez32c70812016-02-16 17:15:32 -0800954 status.RenderObjectList(pLayer->m_pObjectHolder, &FinalMatrix);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700955 if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
956 m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize);
957 }
958 if (status.m_bStopped) {
thestig41846a02016-05-26 10:45:30 -0700959 pDevice->RestoreState(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700960 break;
961 }
962 } else {
963 CPDF_RenderStatus status;
thestig4997b222016-06-07 10:46:22 -0700964 status.Initialize(this, pDevice, nullptr, pStopObj, nullptr, nullptr,
965 pOptions, pLayer->m_pObjectHolder->m_Transparency,
966 FALSE, nullptr);
Tom Sepez32c70812016-02-16 17:15:32 -0800967 status.RenderObjectList(pLayer->m_pObjectHolder, &pLayer->m_Matrix);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700968 if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
969 m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize);
970 }
971 if (status.m_bStopped) {
thestig41846a02016-05-26 10:45:30 -0700972 pDevice->RestoreState(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700973 break;
974 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700975 }
thestig41846a02016-05-26 10:45:30 -0700976 pDevice->RestoreState(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700977 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700978}
Tom Sepezb3b67622015-10-19 16:20:03 -0700979
980CPDF_ProgressiveRenderer::CPDF_ProgressiveRenderer(
981 CPDF_RenderContext* pContext,
982 CFX_RenderDevice* pDevice,
983 const CPDF_RenderOptions* pOptions)
984 : m_Status(Ready),
985 m_pContext(pContext),
986 m_pDevice(pDevice),
987 m_pOptions(pOptions),
988 m_LayerIndex(0),
Tom Sepez2398d892016-02-17 16:46:26 -0800989 m_pCurrentLayer(nullptr) {}
Tom Sepezb3b67622015-10-19 16:20:03 -0700990
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700991CPDF_ProgressiveRenderer::~CPDF_ProgressiveRenderer() {
Tom Sepezb3b67622015-10-19 16:20:03 -0700992 if (m_pRenderStatus)
thestig41846a02016-05-26 10:45:30 -0700993 m_pDevice->RestoreState(false);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700994}
Tom Sepezb3b67622015-10-19 16:20:03 -0700995
996void CPDF_ProgressiveRenderer::Start(IFX_Pause* pPause) {
997 if (!m_pContext || !m_pDevice || m_Status != Ready) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700998 m_Status = Failed;
999 return;
1000 }
1001 m_Status = ToBeContinued;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001002 Continue(pPause);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001003}
Tom Sepezb3b67622015-10-19 16:20:03 -07001004
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001005void CPDF_ProgressiveRenderer::Continue(IFX_Pause* pPause) {
Tom Sepeze6a51382016-02-16 09:17:44 -08001006 while (m_Status == ToBeContinued) {
1007 if (!m_pCurrentLayer) {
1008 if (m_LayerIndex >= m_pContext->CountLayers()) {
1009 m_Status = Done;
1010 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001011 }
Tom Sepeze6a51382016-02-16 09:17:44 -08001012 m_pCurrentLayer = m_pContext->GetLayer(m_LayerIndex);
Tom Sepez2398d892016-02-17 16:46:26 -08001013 m_LastObjectRendered =
1014 m_pCurrentLayer->m_pObjectHolder->GetPageObjectList()->end();
Tom Sepezb3b67622015-10-19 16:20:03 -07001015 m_pRenderStatus.reset(new CPDF_RenderStatus());
1016 m_pRenderStatus->Initialize(
thestig4997b222016-06-07 10:46:22 -07001017 m_pContext, m_pDevice, nullptr, nullptr, nullptr, nullptr, m_pOptions,
1018 m_pCurrentLayer->m_pObjectHolder->m_Transparency, FALSE, nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001019 m_pDevice->SaveState();
Tom Sepezd5e7b352016-02-29 11:24:29 -08001020 m_ClipRect = CFX_FloatRect(m_pDevice->GetClipBox());
Tom Sepez60d909e2015-12-10 15:34:55 -08001021 CFX_Matrix device2object;
Tom Sepeze6a51382016-02-16 09:17:44 -08001022 device2object.SetReverse(m_pCurrentLayer->m_Matrix);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001023 device2object.TransformRect(m_ClipRect);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001024 }
Tom Sepez2398d892016-02-17 16:46:26 -08001025 CPDF_PageObjectList::iterator iter;
1026 CPDF_PageObjectList::iterator iterEnd =
1027 m_pCurrentLayer->m_pObjectHolder->GetPageObjectList()->end();
1028 if (m_LastObjectRendered != iterEnd) {
1029 iter = m_LastObjectRendered;
1030 ++iter;
Tom Sepeze6a51382016-02-16 09:17:44 -08001031 } else {
Tom Sepez2398d892016-02-17 16:46:26 -08001032 iter = m_pCurrentLayer->m_pObjectHolder->GetPageObjectList()->begin();
Tom Sepeze6a51382016-02-16 09:17:44 -08001033 }
1034 int nObjsToGo = kStepLimit;
Tom Sepez2398d892016-02-17 16:46:26 -08001035 while (iter != iterEnd) {
1036 CPDF_PageObject* pCurObj = iter->get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001037 if (pCurObj && pCurObj->m_Left <= m_ClipRect.right &&
1038 pCurObj->m_Right >= m_ClipRect.left &&
1039 pCurObj->m_Bottom <= m_ClipRect.top &&
1040 pCurObj->m_Top >= m_ClipRect.bottom) {
Tom Sepeze6a51382016-02-16 09:17:44 -08001041 if (m_pRenderStatus->ContinueSingleObject(
1042 pCurObj, &m_pCurrentLayer->m_Matrix, pPause)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001043 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001044 }
Wei Li7cf13c92016-02-19 11:53:03 -08001045 if (pCurObj->IsImage() &&
Tom Sepezb3b67622015-10-19 16:20:03 -07001046 m_pRenderStatus->m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001047 m_pContext->GetPageCache()->CacheOptimization(
Tom Sepezb3b67622015-10-19 16:20:03 -07001048 m_pRenderStatus->m_Options.m_dwLimitCacheSize);
Lei Zhang606346f2015-06-19 18:11:07 -07001049 }
Wei Li7cf13c92016-02-19 11:53:03 -08001050 if (pCurObj->IsForm() || pCurObj->IsShading()) {
Tom Sepeze6a51382016-02-16 09:17:44 -08001051 nObjsToGo = 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001052 } else {
Tom Sepeze6a51382016-02-16 09:17:44 -08001053 --nObjsToGo;
Lei Zhang606346f2015-06-19 18:11:07 -07001054 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001055 }
Tom Sepez2398d892016-02-17 16:46:26 -08001056 m_LastObjectRendered = iter;
Tom Sepeze6a51382016-02-16 09:17:44 -08001057 if (nObjsToGo == 0) {
1058 if (pPause && pPause->NeedToPauseNow())
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001059 return;
Tom Sepeze6a51382016-02-16 09:17:44 -08001060 nObjsToGo = kStepLimit;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001061 }
Tom Sepez2398d892016-02-17 16:46:26 -08001062 ++iter;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001063 }
Tom Sepez32c70812016-02-16 17:15:32 -08001064 if (m_pCurrentLayer->m_pObjectHolder->IsParsed()) {
Tom Sepeze6a51382016-02-16 09:17:44 -08001065 m_pRenderStatus.reset();
thestig41846a02016-05-26 10:45:30 -07001066 m_pDevice->RestoreState(false);
Tom Sepeze6a51382016-02-16 09:17:44 -08001067 m_pCurrentLayer = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001068 m_LayerIndex++;
Tom Sepeze6a51382016-02-16 09:17:44 -08001069 if (pPause && pPause->NeedToPauseNow()) {
1070 return;
1071 }
1072 } else {
Tom Sepez32c70812016-02-16 17:15:32 -08001073 m_pCurrentLayer->m_pObjectHolder->ContinueParse(pPause);
1074 if (!m_pCurrentLayer->m_pObjectHolder->IsParsed())
Tom Sepeze6a51382016-02-16 09:17:44 -08001075 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001076 }
1077 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001078}
Tom Sepeze6a51382016-02-16 09:17:44 -08001079
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001080CPDF_TransferFunc* CPDF_DocRenderData::GetTransferFunc(CPDF_Object* pObj) {
1081 if (!pObj)
1082 return nullptr;
Lei Zhang606346f2015-06-19 18:11:07 -07001083
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001084 auto it = m_TransferFuncMap.find(pObj);
1085 if (it != m_TransferFuncMap.end()) {
1086 CPDF_CountedObject<CPDF_TransferFunc>* pTransferCounter = it->second;
Tom Sepez3403db92015-06-15 16:58:19 -07001087 return pTransferCounter->AddRef();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001088 }
1089
Lei Zhangaa8bf7e2015-12-24 19:13:32 -08001090 std::unique_ptr<CPDF_Function> pFuncs[3];
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001091 FX_BOOL bUniTransfer = TRUE;
1092 FX_BOOL bIdentity = TRUE;
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001093 if (CPDF_Array* pArray = pObj->AsArray()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001094 bUniTransfer = FALSE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001095 if (pArray->GetCount() < 3)
1096 return nullptr;
1097
tsepezb5e8f142016-03-25 15:18:35 -07001098 for (uint32_t i = 0; i < 3; ++i) {
thestig490d6122016-05-23 14:56:02 -07001099 pFuncs[2 - i] = CPDF_Function::Load(pArray->GetDirectObjectAt(i));
Lei Zhang5044cab2015-11-10 10:09:33 -08001100 if (!pFuncs[2 - i])
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001101 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001102 }
1103 } else {
thestig490d6122016-05-23 14:56:02 -07001104 pFuncs[0] = CPDF_Function::Load(pObj);
Lei Zhang5044cab2015-11-10 10:09:33 -08001105 if (!pFuncs[0])
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001106 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001107 }
Lei Zhang5044cab2015-11-10 10:09:33 -08001108 CPDF_TransferFunc* pTransfer = new CPDF_TransferFunc(m_pPDFDoc);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001109 CPDF_CountedObject<CPDF_TransferFunc>* pTransferCounter =
1110 new CPDF_CountedObject<CPDF_TransferFunc>(pTransfer);
1111 m_TransferFuncMap[pObj] = pTransferCounter;
1112 static const int kMaxOutputs = 16;
1113 FX_FLOAT output[kMaxOutputs];
1114 FXSYS_memset(output, 0, sizeof(output));
1115 FX_FLOAT input;
1116 int noutput;
1117 for (int v = 0; v < 256; ++v) {
1118 input = (FX_FLOAT)v / 255.0f;
1119 if (bUniTransfer) {
1120 if (pFuncs[0] && pFuncs[0]->CountOutputs() <= kMaxOutputs)
1121 pFuncs[0]->Call(&input, 1, output, noutput);
1122 int o = FXSYS_round(output[0] * 255);
1123 if (o != v)
1124 bIdentity = FALSE;
1125 for (int i = 0; i < 3; ++i) {
1126 pTransfer->m_Samples[i * 256 + v] = o;
1127 }
1128 } else {
1129 for (int i = 0; i < 3; ++i) {
1130 if (pFuncs[i] && pFuncs[i]->CountOutputs() <= kMaxOutputs) {
1131 pFuncs[i]->Call(&input, 1, output, noutput);
1132 int o = FXSYS_round(output[0] * 255);
1133 if (o != v)
1134 bIdentity = FALSE;
1135 pTransfer->m_Samples[i * 256 + v] = o;
1136 } else {
1137 pTransfer->m_Samples[i * 256 + v] = v;
1138 }
1139 }
1140 }
1141 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001142
1143 pTransfer->m_bIdentity = bIdentity;
1144 return pTransferCounter->AddRef();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001145}
Lei Zhang606346f2015-06-19 18:11:07 -07001146
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001147void CPDF_DocRenderData::ReleaseTransferFunc(CPDF_Object* pObj) {
1148 auto it = m_TransferFuncMap.find(pObj);
1149 if (it != m_TransferFuncMap.end())
1150 it->second->RemoveRef();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001151}
Lei Zhang5044cab2015-11-10 10:09:33 -08001152
1153CPDF_DeviceBuffer::CPDF_DeviceBuffer()
1154 : m_pDevice(nullptr), m_pContext(nullptr), m_pObject(nullptr) {}
1155
Dan Sinclair764ec512016-03-14 13:35:12 -04001156CPDF_DeviceBuffer::~CPDF_DeviceBuffer() {}
Lei Zhang5044cab2015-11-10 10:09:33 -08001157
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001158FX_BOOL CPDF_DeviceBuffer::Initialize(CPDF_RenderContext* pContext,
1159 CFX_RenderDevice* pDevice,
1160 FX_RECT* pRect,
1161 const CPDF_PageObject* pObj,
1162 int max_dpi) {
1163 m_pDevice = pDevice;
1164 m_pContext = pContext;
1165 m_Rect = *pRect;
1166 m_pObject = pObj;
1167 m_Matrix.TranslateI(-pRect->left, -pRect->top);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001168#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001169 int horz_size = pDevice->GetDeviceCaps(FXDC_HORZ_SIZE);
1170 int vert_size = pDevice->GetDeviceCaps(FXDC_VERT_SIZE);
1171 if (horz_size && vert_size && max_dpi) {
1172 int dpih =
1173 pDevice->GetDeviceCaps(FXDC_PIXEL_WIDTH) * 254 / (horz_size * 10);
1174 int dpiv =
1175 pDevice->GetDeviceCaps(FXDC_PIXEL_HEIGHT) * 254 / (vert_size * 10);
1176 if (dpih > max_dpi) {
1177 m_Matrix.Scale((FX_FLOAT)(max_dpi) / dpih, 1.0f);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001178 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001179 if (dpiv > max_dpi) {
1180 m_Matrix.Scale(1.0f, (FX_FLOAT)(max_dpi) / (FX_FLOAT)dpiv);
1181 }
1182 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001183#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001184 CFX_Matrix ctm = m_pDevice->GetCTM();
1185 FX_FLOAT fScaleX = FXSYS_fabs(ctm.a);
1186 FX_FLOAT fScaleY = FXSYS_fabs(ctm.d);
1187 m_Matrix.Concat(fScaleX, 0, 0, fScaleY, 0, 0);
1188 CFX_FloatRect rect(*pRect);
1189 m_Matrix.TransformRect(rect);
thestigad5ac752016-08-09 12:09:22 -07001190 FX_RECT bitmap_rect = rect.GetOuterRect();
Lei Zhang5044cab2015-11-10 10:09:33 -08001191 m_pBitmap.reset(new CFX_DIBitmap);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001192 m_pBitmap->Create(bitmap_rect.Width(), bitmap_rect.Height(), FXDIB_Argb);
1193 return TRUE;
1194}
1195void CPDF_DeviceBuffer::OutputToDevice() {
1196 if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) {
1197 if (m_Matrix.a == 1.0f && m_Matrix.d == 1.0f) {
Lei Zhang5044cab2015-11-10 10:09:33 -08001198 m_pDevice->SetDIBits(m_pBitmap.get(), m_Rect.left, m_Rect.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001199 } else {
Lei Zhang5044cab2015-11-10 10:09:33 -08001200 m_pDevice->StretchDIBits(m_pBitmap.get(), m_Rect.left, m_Rect.top,
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001201 m_Rect.Width(), m_Rect.Height());
1202 }
1203 } else {
1204 CFX_DIBitmap buffer;
1205 m_pDevice->CreateCompatibleBitmap(&buffer, m_pBitmap->GetWidth(),
1206 m_pBitmap->GetHeight());
thestig4997b222016-06-07 10:46:22 -07001207 m_pContext->GetBackground(&buffer, m_pObject, nullptr, &m_Matrix);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001208 buffer.CompositeBitmap(0, 0, buffer.GetWidth(), buffer.GetHeight(),
Lei Zhang5044cab2015-11-10 10:09:33 -08001209 m_pBitmap.get(), 0, 0);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001210 m_pDevice->StretchDIBits(&buffer, m_Rect.left, m_Rect.top, m_Rect.Width(),
1211 m_Rect.Height());
1212 }
1213}
Lei Zhang5044cab2015-11-10 10:09:33 -08001214
1215CPDF_ScaledRenderBuffer::CPDF_ScaledRenderBuffer() {}
1216
1217CPDF_ScaledRenderBuffer::~CPDF_ScaledRenderBuffer() {}
1218
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001219#define _FPDFAPI_IMAGESIZE_LIMIT_ (30 * 1024 * 1024)
1220FX_BOOL CPDF_ScaledRenderBuffer::Initialize(CPDF_RenderContext* pContext,
1221 CFX_RenderDevice* pDevice,
Lei Zhang96660d62015-12-14 18:27:25 -08001222 const FX_RECT& pRect,
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001223 const CPDF_PageObject* pObj,
1224 const CPDF_RenderOptions* pOptions,
1225 int max_dpi) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001226 m_pDevice = pDevice;
1227 if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) {
1228 return TRUE;
1229 }
1230 m_pContext = pContext;
Lei Zhang96660d62015-12-14 18:27:25 -08001231 m_Rect = pRect;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001232 m_pObject = pObj;
Lei Zhang96660d62015-12-14 18:27:25 -08001233 m_Matrix.TranslateI(-pRect.left, -pRect.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001234 int horz_size = pDevice->GetDeviceCaps(FXDC_HORZ_SIZE);
1235 int vert_size = pDevice->GetDeviceCaps(FXDC_VERT_SIZE);
1236 if (horz_size && vert_size && max_dpi) {
1237 int dpih =
1238 pDevice->GetDeviceCaps(FXDC_PIXEL_WIDTH) * 254 / (horz_size * 10);
1239 int dpiv =
1240 pDevice->GetDeviceCaps(FXDC_PIXEL_HEIGHT) * 254 / (vert_size * 10);
1241 if (dpih > max_dpi) {
1242 m_Matrix.Scale((FX_FLOAT)(max_dpi) / dpih, 1.0f);
1243 }
1244 if (dpiv > max_dpi) {
1245 m_Matrix.Scale(1.0f, (FX_FLOAT)(max_dpi) / (FX_FLOAT)dpiv);
1246 }
1247 }
Lei Zhang5044cab2015-11-10 10:09:33 -08001248 m_pBitmapDevice.reset(new CFX_FxgeDevice);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001249 FXDIB_Format dibFormat = FXDIB_Rgb;
1250 int32_t bpp = 24;
1251 if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_ALPHA_OUTPUT) {
1252 dibFormat = FXDIB_Argb;
1253 bpp = 32;
1254 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001255 while (1) {
Tom Sepezd5e7b352016-02-29 11:24:29 -08001256 CFX_FloatRect rect(pRect);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001257 m_Matrix.TransformRect(rect);
thestigad5ac752016-08-09 12:09:22 -07001258 FX_RECT bitmap_rect = rect.GetOuterRect();
Tom Sepezd5e7b352016-02-29 11:24:29 -08001259 int32_t iWidth = bitmap_rect.Width();
1260 int32_t iHeight = bitmap_rect.Height();
1261 int32_t iPitch = (iWidth * bpp + 31) / 32 * 4;
1262 if (iWidth * iHeight < 1)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001263 return FALSE;
Tom Sepezd5e7b352016-02-29 11:24:29 -08001264
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001265 if (iPitch * iHeight <= _FPDFAPI_IMAGESIZE_LIMIT_ &&
thestigbefa4502016-05-26 20:15:19 -07001266 m_pBitmapDevice->Create(iWidth, iHeight, dibFormat, nullptr)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001267 break;
1268 }
1269 m_Matrix.Scale(0.5f, 0.5f);
1270 }
1271 m_pContext->GetBackground(m_pBitmapDevice->GetBitmap(), m_pObject, pOptions,
1272 &m_Matrix);
1273 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001274}
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001275void CPDF_ScaledRenderBuffer::OutputToDevice() {
1276 if (m_pBitmapDevice) {
1277 m_pDevice->StretchDIBits(m_pBitmapDevice->GetBitmap(), m_Rect.left,
1278 m_Rect.top, m_Rect.Width(), m_Rect.Height());
1279 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001280}
caryclarka27d49a2016-07-06 10:20:25 -07001281
1282#if defined _SKIA_SUPPORT_
1283void CPDF_RenderStatus::DebugVerifyDeviceIsPreMultiplied() const {
1284 m_pDevice->DebugVerifyBitmapIsPreMultiplied();
1285}
1286#endif