blob: 59c8397f54a1800601dc13e146952b0e7f915eb6 [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_graphicstates.h"
Dan Sinclair455a4192016-03-16 09:48:56 -040014#include "core/fpdfapi/fpdf_page/include/cpdf_form.h"
Dan Sinclair584b1e62016-03-21 09:15:45 -040015#include "core/fpdfapi/fpdf_page/include/cpdf_formobject.h"
dan sinclair61b2fc72016-03-23 19:21:44 -040016#include "core/fpdfapi/fpdf_page/include/cpdf_image.h"
Dan Sinclair584b1e62016-03-21 09:15:45 -040017#include "core/fpdfapi/fpdf_page/include/cpdf_imageobject.h"
Dan Sinclair455a4192016-03-16 09:48:56 -040018#include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
Dan Sinclair584b1e62016-03-21 09:15:45 -040019#include "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h"
20#include "core/fpdfapi/fpdf_page/include/cpdf_pathobject.h"
21#include "core/fpdfapi/fpdf_page/include/cpdf_textobject.h"
Dan Sinclair764ec512016-03-14 13:35:12 -040022#include "core/fpdfapi/fpdf_page/pageint.h"
Dan Sinclairaa403d32016-03-15 14:57:22 -040023#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
24#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
25#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
Dan Sinclairaa403d32016-03-15 14:57:22 -040026#include "core/fpdfapi/fpdf_render/cpdf_pagerendercache.h"
npmeadff192016-09-01 13:21:37 -070027#include "core/fpdfapi/fpdf_render/cpdf_type3cache.h"
Dan Sinclairaa403d32016-03-15 14:57:22 -040028#include "core/fpdfapi/fpdf_render/include/cpdf_progressiverenderer.h"
29#include "core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h"
30#include "core/fpdfapi/fpdf_render/include/cpdf_textrenderer.h"
31#include "core/fpdfapi/include/cpdf_modulemgr.h"
dsinclaircac704d2016-07-28 12:59:09 -070032#include "core/fpdfdoc/include/cpdf_occontext.h"
npmd6918992016-08-17 13:22:16 -070033#include "core/fxge/include/cfx_fontcache.h"
npm9ada2d82016-08-10 07:51:38 -070034#include "core/fxge/include/cfx_fxgedevice.h"
35#include "core/fxge/include/cfx_graphstatedata.h"
npm660de3c2016-08-08 08:18:29 -070036#include "core/fxge/include/cfx_pathdata.h"
npm9ada2d82016-08-10 07:51:38 -070037#include "core/fxge/include/cfx_renderdevice.h"
Lei Zhanga9fa50f2015-11-10 09:45:32 -080038
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070039CPDF_DocRenderData::CPDF_DocRenderData(CPDF_Document* pPDFDoc)
Nico Weber9d8ec5a2015-08-04 13:00:21 -070040 : m_pPDFDoc(pPDFDoc), m_pFontCache(new CFX_FontCache) {}
41
42CPDF_DocRenderData::~CPDF_DocRenderData() {
43 Clear(TRUE);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070044}
Lei Zhang606346f2015-06-19 18:11:07 -070045
Nico Weber9d8ec5a2015-08-04 13:00:21 -070046void CPDF_DocRenderData::Clear(FX_BOOL bRelease) {
47 for (auto it = m_Type3FaceMap.begin(); it != m_Type3FaceMap.end();) {
48 auto curr_it = it++;
49 CPDF_CountedObject<CPDF_Type3Cache>* cache = curr_it->second;
50 if (bRelease || cache->use_count() < 2) {
51 delete cache->get();
52 delete cache;
53 m_Type3FaceMap.erase(curr_it);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070054 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -070055 }
Lei Zhang606346f2015-06-19 18:11:07 -070056
Nico Weber9d8ec5a2015-08-04 13:00:21 -070057 for (auto it = m_TransferFuncMap.begin(); it != m_TransferFuncMap.end();) {
58 auto curr_it = it++;
59 CPDF_CountedObject<CPDF_TransferFunc>* value = curr_it->second;
60 if (bRelease || value->use_count() < 2) {
61 delete value->get();
62 delete value;
63 m_TransferFuncMap.erase(curr_it);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070064 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -070065 }
Lei Zhang606346f2015-06-19 18:11:07 -070066
Nico Weber9d8ec5a2015-08-04 13:00:21 -070067 if (m_pFontCache) {
68 if (bRelease) {
69 delete m_pFontCache;
thestig4997b222016-06-07 10:46:22 -070070 m_pFontCache = nullptr;
Lei Zhang606346f2015-06-19 18:11:07 -070071 } else {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070072 m_pFontCache->FreeCache(FALSE);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070073 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -070074 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070075}
Lei Zhang606346f2015-06-19 18:11:07 -070076
Nico Weber9d8ec5a2015-08-04 13:00:21 -070077CPDF_Type3Cache* CPDF_DocRenderData::GetCachedType3(CPDF_Type3Font* pFont) {
78 CPDF_CountedObject<CPDF_Type3Cache>* pCache;
79 auto it = m_Type3FaceMap.find(pFont);
80 if (it == m_Type3FaceMap.end()) {
81 CPDF_Type3Cache* pType3 = new CPDF_Type3Cache(pFont);
82 pCache = new CPDF_CountedObject<CPDF_Type3Cache>(pType3);
83 m_Type3FaceMap[pFont] = pCache;
84 } else {
85 pCache = it->second;
86 }
87 return pCache->AddRef();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070088}
Lei Zhangfa6eb282015-06-19 17:17:54 -070089
Nico Weber9d8ec5a2015-08-04 13:00:21 -070090void CPDF_DocRenderData::ReleaseCachedType3(CPDF_Type3Font* pFont) {
91 auto it = m_Type3FaceMap.find(pFont);
92 if (it != m_Type3FaceMap.end())
93 it->second->RemoveRef();
94}
Lei Zhangfa6eb282015-06-19 17:17:54 -070095
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070096CPDF_RenderOptions::CPDF_RenderOptions()
Nico Weber9d8ec5a2015-08-04 13:00:21 -070097 : m_ColorMode(RENDER_COLOR_NORMAL),
98 m_Flags(RENDER_CLEARTYPE),
99 m_Interpolation(0),
100 m_AddFlags(0),
thestig4997b222016-06-07 10:46:22 -0700101 m_pOCContext(nullptr),
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700102 m_dwLimitCacheSize(1024 * 1024 * 100),
jaepark75f84a52016-09-09 15:39:09 -0700103 m_HalftoneLimit(-1),
104 m_bDrawAnnots(false) {}
105
106CPDF_RenderOptions::CPDF_RenderOptions(const CPDF_RenderOptions& rhs)
107 : m_ColorMode(rhs.m_ColorMode),
108 m_BackColor(rhs.m_BackColor),
109 m_ForeColor(rhs.m_ForeColor),
110 m_Flags(rhs.m_Flags),
111 m_Interpolation(rhs.m_Interpolation),
112 m_AddFlags(rhs.m_AddFlags),
113 m_pOCContext(rhs.m_pOCContext),
114 m_dwLimitCacheSize(rhs.m_dwLimitCacheSize),
115 m_HalftoneLimit(rhs.m_HalftoneLimit),
116 m_bDrawAnnots(rhs.m_bDrawAnnots) {}
117
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700118FX_ARGB CPDF_RenderOptions::TranslateColor(FX_ARGB argb) const {
119 if (m_ColorMode == RENDER_COLOR_NORMAL) {
120 return argb;
121 }
122 if (m_ColorMode == RENDER_COLOR_ALPHA) {
123 return argb;
124 }
125 int a, r, g, b;
126 ArgbDecode(argb, a, r, g, b);
127 int gray = FXRGB2GRAY(r, g, b);
128 if (m_ColorMode == RENDER_COLOR_TWOCOLOR) {
129 int color = (r - gray) * (r - gray) + (g - gray) * (g - gray) +
130 (b - gray) * (b - gray);
131 if (gray < 35 && color < 20) {
132 return ArgbEncode(a, m_ForeColor);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700133 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700134 if (gray > 221 && color < 20) {
135 return ArgbEncode(a, m_BackColor);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700136 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700137 return argb;
138 }
139 int fr = FXSYS_GetRValue(m_ForeColor);
140 int fg = FXSYS_GetGValue(m_ForeColor);
141 int fb = FXSYS_GetBValue(m_ForeColor);
142 int br = FXSYS_GetRValue(m_BackColor);
143 int bg = FXSYS_GetGValue(m_BackColor);
144 int bb = FXSYS_GetBValue(m_BackColor);
145 r = (br - fr) * gray / 255 + fr;
146 g = (bg - fg) * gray / 255 + fg;
147 b = (bb - fb) * gray / 255 + fb;
148 return ArgbEncode(a, r, g, b);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700149}
Tom Sepez09dc51a2015-01-29 18:16:16 -0800150
151// static
152int CPDF_RenderStatus::s_CurrentRecursionDepth = 0;
153
Lei Zhang5044cab2015-11-10 10:09:33 -0800154CPDF_RenderStatus::CPDF_RenderStatus()
155 : m_pFormResource(nullptr),
156 m_pPageResource(nullptr),
157 m_pContext(nullptr),
158 m_bStopped(FALSE),
159 m_pDevice(nullptr),
160 m_pCurObj(nullptr),
161 m_pStopObj(nullptr),
162 m_HalftoneLimit(0),
163 m_bPrint(FALSE),
164 m_Transparency(0),
Lei Zhang5044cab2015-11-10 10:09:33 -0800165 m_bDropObjects(FALSE),
166 m_bStdCS(FALSE),
167 m_GroupFamily(0),
168 m_bLoadMask(FALSE),
169 m_pType3Char(nullptr),
170 m_T3FillColor(0),
171 m_curBlend(FXDIB_BLEND_NORMAL) {}
Tom Sepez09dc51a2015-01-29 18:16:16 -0800172
Dan Sinclair764ec512016-03-14 13:35:12 -0400173CPDF_RenderStatus::~CPDF_RenderStatus() {}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700174
175FX_BOOL CPDF_RenderStatus::Initialize(CPDF_RenderContext* pContext,
176 CFX_RenderDevice* pDevice,
Tom Sepez60d909e2015-12-10 15:34:55 -0800177 const CFX_Matrix* pDeviceMatrix,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700178 const CPDF_PageObject* pStopObj,
179 const CPDF_RenderStatus* pParentState,
180 const CPDF_GraphicStates* pInitialStates,
181 const CPDF_RenderOptions* pOptions,
182 int transparency,
183 FX_BOOL bDropObjects,
184 CPDF_Dictionary* pFormResource,
185 FX_BOOL bStdCS,
186 CPDF_Type3Char* pType3Char,
187 FX_ARGB fill_color,
tsepezb5e8f142016-03-25 15:18:35 -0700188 uint32_t GroupFamily,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700189 FX_BOOL bLoadMask) {
190 m_pContext = pContext;
191 m_pDevice = pDevice;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700192 m_bPrint = m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
193 if (pDeviceMatrix) {
194 m_DeviceMatrix = *pDeviceMatrix;
195 }
196 m_pStopObj = pStopObj;
197 if (pOptions) {
198 m_Options = *pOptions;
199 }
200 m_bDropObjects = bDropObjects;
201 m_bStdCS = bStdCS;
202 m_T3FillColor = fill_color;
203 m_pType3Char = pType3Char;
204 m_GroupFamily = GroupFamily;
205 m_bLoadMask = bLoadMask;
206 m_pFormResource = pFormResource;
Tom Sepez71fdc342016-01-22 12:06:32 -0800207 m_pPageResource = m_pContext->GetPageResources();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700208 if (pInitialStates && !m_pType3Char) {
209 m_InitialStates.CopyStates(*pInitialStates);
210 if (pParentState) {
tsepezca90b872016-08-31 10:41:00 -0700211 if (!m_InitialStates.m_ColorState.HasFillColor()) {
212 m_InitialStates.m_ColorState.SetFillRGB(
213 pParentState->m_InitialStates.m_ColorState.GetFillRGB());
214 m_InitialStates.m_ColorState.GetMutableFillColor()->Copy(
215 pParentState->m_InitialStates.m_ColorState.GetFillColor());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700216 }
tsepezca90b872016-08-31 10:41:00 -0700217 if (!m_InitialStates.m_ColorState.HasStrokeColor()) {
218 m_InitialStates.m_ColorState.SetStrokeRGB(
219 pParentState->m_InitialStates.m_ColorState.GetFillRGB());
220 m_InitialStates.m_ColorState.GetMutableStrokeColor()->Copy(
221 pParentState->m_InitialStates.m_ColorState.GetStrokeColor());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700222 }
223 }
224 } else {
225 m_InitialStates.DefaultStates();
226 }
dsinclaird647a6b2016-04-26 13:13:20 -0700227 m_pImageRenderer.reset();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700228 m_Transparency = transparency;
229 return TRUE;
230}
Tom Sepez32c70812016-02-16 17:15:32 -0800231void CPDF_RenderStatus::RenderObjectList(
232 const CPDF_PageObjectHolder* pObjectHolder,
233 const CFX_Matrix* pObj2Device) {
caryclarka27d49a2016-07-06 10:20:25 -0700234#if defined _SKIA_SUPPORT_
235 DebugVerifyDeviceIsPreMultiplied();
236#endif
Tom Sepezd5e7b352016-02-29 11:24:29 -0800237 CFX_FloatRect clip_rect(m_pDevice->GetClipBox());
Tom Sepez60d909e2015-12-10 15:34:55 -0800238 CFX_Matrix device2object;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700239 device2object.SetReverse(*pObj2Device);
240 device2object.TransformRect(clip_rect);
Tom Sepez2398d892016-02-17 16:46:26 -0800241
242 for (const auto& pCurObj : *pObjectHolder->GetPageObjectList()) {
243 if (pCurObj.get() == m_pStopObj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700244 m_bStopped = TRUE;
245 return;
246 }
Tom Sepez2398d892016-02-17 16:46:26 -0800247 if (!pCurObj)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700248 continue;
Tom Sepez2398d892016-02-17 16:46:26 -0800249
250 if (pCurObj->m_Left > clip_rect.right ||
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700251 pCurObj->m_Right < clip_rect.left ||
252 pCurObj->m_Bottom > clip_rect.top ||
253 pCurObj->m_Top < clip_rect.bottom) {
254 continue;
255 }
Tom Sepez2398d892016-02-17 16:46:26 -0800256 RenderSingleObject(pCurObj.get(), pObj2Device);
257 if (m_bStopped)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700258 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700259 }
caryclarka27d49a2016-07-06 10:20:25 -0700260#if defined _SKIA_SUPPORT_
261 DebugVerifyDeviceIsPreMultiplied();
262#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700263}
caryclarka27d49a2016-07-06 10:20:25 -0700264
tsepezbbee4452016-09-02 15:22:00 -0700265void CPDF_RenderStatus::RenderSingleObject(CPDF_PageObject* pObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800266 const CFX_Matrix* pObj2Device) {
caryclarka27d49a2016-07-06 10:20:25 -0700267#if defined _SKIA_SUPPORT_
268 DebugVerifyDeviceIsPreMultiplied();
269#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700270 CFX_AutoRestorer<int> restorer(&s_CurrentRecursionDepth);
271 if (++s_CurrentRecursionDepth > kRenderMaxRecursionDepth) {
272 return;
273 }
274 m_pCurObj = pObj;
tsepez83d23512016-08-26 14:56:39 -0700275 if (m_Options.m_pOCContext && pObj->m_ContentMark) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700276 if (!m_Options.m_pOCContext->CheckObjectVisible(pObj)) {
277 return;
278 }
279 }
280 ProcessClipPath(pObj->m_ClipPath, pObj2Device);
281 if (ProcessTransparency(pObj, pObj2Device)) {
282 return;
283 }
284 ProcessObjectNoClip(pObj, pObj2Device);
caryclarka27d49a2016-07-06 10:20:25 -0700285#if defined _SKIA_SUPPORT_
286 DebugVerifyDeviceIsPreMultiplied();
287#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700288}
Lei Zhang5044cab2015-11-10 10:09:33 -0800289
tsepezbbee4452016-09-02 15:22:00 -0700290FX_BOOL CPDF_RenderStatus::ContinueSingleObject(CPDF_PageObject* pObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800291 const CFX_Matrix* pObj2Device,
292 IFX_Pause* pPause) {
dsinclaird647a6b2016-04-26 13:13:20 -0700293 if (m_pImageRenderer) {
294 if (m_pImageRenderer->Continue(pPause))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700295 return TRUE;
Lei Zhang5044cab2015-11-10 10:09:33 -0800296
dsinclaird647a6b2016-04-26 13:13:20 -0700297 if (!m_pImageRenderer->m_Result)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700298 DrawObjWithBackground(pObj, pObj2Device);
dsinclaird647a6b2016-04-26 13:13:20 -0700299 m_pImageRenderer.reset();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700300 return FALSE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700301 }
Lei Zhang5044cab2015-11-10 10:09:33 -0800302
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700303 m_pCurObj = pObj;
tsepez83d23512016-08-26 14:56:39 -0700304 if (m_Options.m_pOCContext && pObj->m_ContentMark &&
Lei Zhang5044cab2015-11-10 10:09:33 -0800305 !m_Options.m_pOCContext->CheckObjectVisible(pObj)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700306 return FALSE;
307 }
Lei Zhang5044cab2015-11-10 10:09:33 -0800308
309 ProcessClipPath(pObj->m_ClipPath, pObj2Device);
310 if (ProcessTransparency(pObj, pObj2Device))
311 return FALSE;
312
Wei Li7cf13c92016-02-19 11:53:03 -0800313 if (pObj->IsImage()) {
dsinclaird647a6b2016-04-26 13:13:20 -0700314 m_pImageRenderer.reset(new CPDF_ImageRenderer);
315 if (!m_pImageRenderer->Start(this, pObj, pObj2Device, FALSE)) {
316 if (!m_pImageRenderer->m_Result)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700317 DrawObjWithBackground(pObj, pObj2Device);
dsinclaird647a6b2016-04-26 13:13:20 -0700318 m_pImageRenderer.reset();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700319 return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700320 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700321 return ContinueSingleObject(pObj, pObj2Device, pPause);
322 }
Lei Zhang5044cab2015-11-10 10:09:33 -0800323
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700324 ProcessObjectNoClip(pObj, pObj2Device);
325 return FALSE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700326}
Lei Zhang5044cab2015-11-10 10:09:33 -0800327
Tom Sepez60d909e2015-12-10 15:34:55 -0800328FX_BOOL CPDF_RenderStatus::GetObjectClippedRect(const CPDF_PageObject* pObj,
329 const CFX_Matrix* pObj2Device,
330 FX_BOOL bLogical,
331 FX_RECT& rect) const {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700332 rect = pObj->GetBBox(pObj2Device);
333 FX_RECT rtClip = m_pDevice->GetClipBox();
334 if (!bLogical) {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700335 CFX_Matrix dCTM = m_pDevice->GetCTM();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700336 FX_FLOAT a = FXSYS_fabs(dCTM.a);
337 FX_FLOAT d = FXSYS_fabs(dCTM.d);
338 if (a != 1.0f || d != 1.0f) {
339 rect.right = rect.left + (int32_t)FXSYS_ceil((FX_FLOAT)rect.Width() * a);
340 rect.bottom = rect.top + (int32_t)FXSYS_ceil((FX_FLOAT)rect.Height() * d);
341 rtClip.right =
342 rtClip.left + (int32_t)FXSYS_ceil((FX_FLOAT)rtClip.Width() * a);
343 rtClip.bottom =
344 rtClip.top + (int32_t)FXSYS_ceil((FX_FLOAT)rtClip.Height() * d);
345 }
346 }
347 rect.Intersect(rtClip);
348 return rect.IsEmpty();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700349}
thestig490d6122016-05-23 14:56:02 -0700350
tsepezbbee4452016-09-02 15:22:00 -0700351void CPDF_RenderStatus::ProcessObjectNoClip(CPDF_PageObject* pObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800352 const CFX_Matrix* pObj2Device) {
caryclarka27d49a2016-07-06 10:20:25 -0700353#if defined _SKIA_SUPPORT_
354 DebugVerifyDeviceIsPreMultiplied();
355#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700356 FX_BOOL bRet = FALSE;
Wei Li7cf13c92016-02-19 11:53:03 -0800357 switch (pObj->GetType()) {
Tom Sepez8e5cd192016-01-26 13:20:26 -0800358 case CPDF_PageObject::TEXT:
thestig4997b222016-06-07 10:46:22 -0700359 bRet = ProcessText(pObj->AsText(), pObj2Device, nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700360 break;
Tom Sepez8e5cd192016-01-26 13:20:26 -0800361 case CPDF_PageObject::PATH:
Wei Li7cf13c92016-02-19 11:53:03 -0800362 bRet = ProcessPath(pObj->AsPath(), pObj2Device);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700363 break;
Tom Sepez8e5cd192016-01-26 13:20:26 -0800364 case CPDF_PageObject::IMAGE:
Wei Li7cf13c92016-02-19 11:53:03 -0800365 bRet = ProcessImage(pObj->AsImage(), pObj2Device);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700366 break;
Tom Sepez8e5cd192016-01-26 13:20:26 -0800367 case CPDF_PageObject::SHADING:
thestig490d6122016-05-23 14:56:02 -0700368 ProcessShading(pObj->AsShading(), pObj2Device);
369 return;
Tom Sepez8e5cd192016-01-26 13:20:26 -0800370 case CPDF_PageObject::FORM:
Wei Li7cf13c92016-02-19 11:53:03 -0800371 bRet = ProcessForm(pObj->AsForm(), pObj2Device);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700372 break;
373 }
thestig490d6122016-05-23 14:56:02 -0700374 if (!bRet)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700375 DrawObjWithBackground(pObj, pObj2Device);
caryclarka27d49a2016-07-06 10:20:25 -0700376#if defined _SKIA_SUPPORT_
377 DebugVerifyDeviceIsPreMultiplied();
378#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700379}
thestig490d6122016-05-23 14:56:02 -0700380
tsepezbbee4452016-09-02 15:22:00 -0700381FX_BOOL CPDF_RenderStatus::DrawObjWithBlend(CPDF_PageObject* pObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800382 const CFX_Matrix* pObj2Device) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700383 FX_BOOL bRet = FALSE;
Wei Li7cf13c92016-02-19 11:53:03 -0800384 switch (pObj->GetType()) {
Tom Sepez8e5cd192016-01-26 13:20:26 -0800385 case CPDF_PageObject::PATH:
Wei Li7cf13c92016-02-19 11:53:03 -0800386 bRet = ProcessPath(pObj->AsPath(), pObj2Device);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700387 break;
Tom Sepez8e5cd192016-01-26 13:20:26 -0800388 case CPDF_PageObject::IMAGE:
Wei Li7cf13c92016-02-19 11:53:03 -0800389 bRet = ProcessImage(pObj->AsImage(), pObj2Device);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700390 break;
Tom Sepez8e5cd192016-01-26 13:20:26 -0800391 case CPDF_PageObject::FORM:
Wei Li7cf13c92016-02-19 11:53:03 -0800392 bRet = ProcessForm(pObj->AsForm(), pObj2Device);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700393 break;
Tom Sepez8e5cd192016-01-26 13:20:26 -0800394 default:
395 break;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700396 }
397 return bRet;
398}
399void CPDF_RenderStatus::GetScaledMatrix(CFX_Matrix& matrix) const {
400 CFX_Matrix dCTM = m_pDevice->GetCTM();
401 matrix.a *= FXSYS_fabs(dCTM.a);
402 matrix.d *= FXSYS_fabs(dCTM.d);
403}
tsepezbbee4452016-09-02 15:22:00 -0700404
405void CPDF_RenderStatus::DrawObjWithBackground(CPDF_PageObject* pObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800406 const CFX_Matrix* pObj2Device) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700407 FX_RECT rect;
408 if (GetObjectClippedRect(pObj, pObj2Device, FALSE, rect)) {
409 return;
410 }
411 int res = 300;
Wei Li7cf13c92016-02-19 11:53:03 -0800412 if (pObj->IsImage() &&
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700413 m_pDevice->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
414 res = 0;
415 }
416 CPDF_ScaledRenderBuffer buffer;
Lei Zhang96660d62015-12-14 18:27:25 -0800417 if (!buffer.Initialize(m_pContext, m_pDevice, rect, pObj, &m_Options, res)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700418 return;
419 }
Tom Sepez60d909e2015-12-10 15:34:55 -0800420 CFX_Matrix matrix = *pObj2Device;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700421 matrix.Concat(*buffer.GetMatrix());
422 GetScaledMatrix(matrix);
thestig4997b222016-06-07 10:46:22 -0700423 CPDF_Dictionary* pFormResource = nullptr;
Wei Li7cf13c92016-02-19 11:53:03 -0800424 if (pObj->IsForm()) {
425 const CPDF_FormObject* pFormObj = pObj->AsForm();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700426 if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) {
dsinclair38fd8442016-09-15 10:15:32 -0700427 pFormResource = pFormObj->m_pForm->m_pFormDict->GetDictFor("Resources");
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700428 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700429 }
430 CPDF_RenderStatus status;
thestig4997b222016-06-07 10:46:22 -0700431 status.Initialize(m_pContext, buffer.GetDevice(), buffer.GetMatrix(), nullptr,
432 nullptr, nullptr, &m_Options, m_Transparency,
433 m_bDropObjects, pFormResource);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700434 status.RenderSingleObject(pObj, &matrix);
435 buffer.OutputToDevice();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700436}
caryclarka27d49a2016-07-06 10:20:25 -0700437
Wei Li7cf13c92016-02-19 11:53:03 -0800438FX_BOOL CPDF_RenderStatus::ProcessForm(const CPDF_FormObject* pFormObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800439 const CFX_Matrix* pObj2Device) {
caryclarka27d49a2016-07-06 10:20:25 -0700440#if defined _SKIA_SUPPORT_
441 DebugVerifyDeviceIsPreMultiplied();
442#endif
dsinclair38fd8442016-09-15 10:15:32 -0700443 CPDF_Dictionary* pOC = pFormObj->m_pForm->m_pFormDict->GetDictFor("OC");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700444 if (pOC && m_Options.m_pOCContext &&
445 !m_Options.m_pOCContext->CheckOCGVisible(pOC)) {
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700446 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700447 }
Tom Sepez60d909e2015-12-10 15:34:55 -0800448 CFX_Matrix matrix = pFormObj->m_FormMatrix;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700449 matrix.Concat(*pObj2Device);
thestig4997b222016-06-07 10:46:22 -0700450 CPDF_Dictionary* pResources = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700451 if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) {
dsinclair38fd8442016-09-15 10:15:32 -0700452 pResources = pFormObj->m_pForm->m_pFormDict->GetDictFor("Resources");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700453 }
454 CPDF_RenderStatus status;
thestig4997b222016-06-07 10:46:22 -0700455 status.Initialize(m_pContext, m_pDevice, nullptr, m_pStopObj, this, pFormObj,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700456 &m_Options, m_Transparency, m_bDropObjects, pResources,
457 FALSE);
458 status.m_curBlend = m_curBlend;
459 m_pDevice->SaveState();
weili44105d82016-07-06 18:10:35 -0700460 status.RenderObjectList(pFormObj->m_pForm.get(), &matrix);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700461 m_bStopped = status.m_bStopped;
thestig41846a02016-05-26 10:45:30 -0700462 m_pDevice->RestoreState(false);
caryclarka27d49a2016-07-06 10:20:25 -0700463#if defined _SKIA_SUPPORT_
464 DebugVerifyDeviceIsPreMultiplied();
465#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700466 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700467}
caryclarka27d49a2016-07-06 10:20:25 -0700468
Tom Sepez60d909e2015-12-10 15:34:55 -0800469FX_BOOL IsAvailableMatrix(const CFX_Matrix& matrix) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700470 if (matrix.a == 0 || matrix.d == 0) {
471 return matrix.b != 0 && matrix.c != 0;
472 }
473 if (matrix.b == 0 || matrix.c == 0) {
474 return matrix.a != 0 && matrix.d != 0;
475 }
476 return TRUE;
477}
thestigd3e354a2016-05-26 11:04:40 -0700478
tsepezbbee4452016-09-02 15:22:00 -0700479FX_BOOL CPDF_RenderStatus::ProcessPath(CPDF_PathObject* pPathObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800480 const CFX_Matrix* pObj2Device) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700481 int FillType = pPathObj->m_FillType;
482 FX_BOOL bStroke = pPathObj->m_bStroke;
483 ProcessPathPattern(pPathObj, pObj2Device, FillType, bStroke);
thestig2f307662016-06-13 15:02:05 -0700484 if (FillType == 0 && !bStroke)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700485 return TRUE;
thestig2f307662016-06-13 15:02:05 -0700486
487 uint32_t fill_argb = FillType ? GetFillArgb(pPathObj) : 0;
488 uint32_t stroke_argb = bStroke ? GetStrokeArgb(pPathObj) : 0;
Tom Sepez60d909e2015-12-10 15:34:55 -0800489 CFX_Matrix path_matrix = pPathObj->m_Matrix;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700490 path_matrix.Concat(*pObj2Device);
thestig2f307662016-06-13 15:02:05 -0700491 if (!IsAvailableMatrix(path_matrix))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700492 return TRUE;
thestig2f307662016-06-13 15:02:05 -0700493
494 if (FillType && (m_Options.m_Flags & RENDER_RECT_AA))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700495 FillType |= FXFILL_RECT_AA;
thestig2f307662016-06-13 15:02:05 -0700496 if (m_Options.m_Flags & RENDER_FILL_FULLCOVER)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700497 FillType |= FXFILL_FULLCOVER;
thestig2f307662016-06-13 15:02:05 -0700498 if (m_Options.m_Flags & RENDER_NOPATHSMOOTH)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700499 FillType |= FXFILL_NOPATHSMOOTH;
thestig2f307662016-06-13 15:02:05 -0700500 if (bStroke)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700501 FillType |= FX_FILL_STROKE;
tsepezbbee4452016-09-02 15:22:00 -0700502
503 const CPDF_PageObject* pPageObj =
504 static_cast<const CPDF_PageObject*>(pPathObj);
505 if (pPageObj->m_GeneralState.GetStrokeAdjust())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700506 FillType |= FX_STROKE_ADJUST;
thestig2f307662016-06-13 15:02:05 -0700507 if (m_pType3Char)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700508 FillType |= FX_FILL_TEXT_MODE;
thestig2f307662016-06-13 15:02:05 -0700509
tsepez7c9f0a12016-09-06 13:02:55 -0700510 CFX_GraphState graphState = pPathObj->m_GraphState;
thestig2f307662016-06-13 15:02:05 -0700511 if (m_Options.m_Flags & RENDER_THINLINE)
tsepez4d9df422016-08-31 10:26:38 -0700512 graphState.SetLineWidth(0);
513 return m_pDevice->DrawPathWithBlend(
514 pPathObj->m_Path.GetObject(), &path_matrix, graphState.GetObject(),
515 fill_argb, stroke_argb, FillType, m_curBlend);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700516}
thestigd3e354a2016-05-26 11:04:40 -0700517
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700518CPDF_TransferFunc* CPDF_RenderStatus::GetTransferFunc(CPDF_Object* pObj) const {
Lei Zhang96660d62015-12-14 18:27:25 -0800519 ASSERT(pObj);
Tom Sepez71fdc342016-01-22 12:06:32 -0800520 CPDF_DocRenderData* pDocCache = m_pContext->GetDocument()->GetRenderData();
Lei Zhang96660d62015-12-14 18:27:25 -0800521 return pDocCache ? pDocCache->GetTransferFunc(pObj) : nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700522}
tsepezbbee4452016-09-02 15:22:00 -0700523
524FX_ARGB CPDF_RenderStatus::GetFillArgb(CPDF_PageObject* pObj,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700525 FX_BOOL bType3) const {
tsepezf40c6f12016-09-06 11:45:32 -0700526 const CPDF_ColorState* pColorState = &pObj->m_ColorState;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700527 if (m_pType3Char && !bType3 &&
528 (!m_pType3Char->m_bColored ||
529 (m_pType3Char->m_bColored &&
tsepezf40c6f12016-09-06 11:45:32 -0700530 (!*pColorState || pColorState->GetFillColor()->IsNull())))) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700531 return m_T3FillColor;
532 }
tsepezf40c6f12016-09-06 11:45:32 -0700533 if (!*pColorState || pColorState->GetFillColor()->IsNull())
534 pColorState = &m_InitialStates.m_ColorState;
535
536 FX_COLORREF rgb = pColorState->GetFillRGB();
537 if (rgb == (uint32_t)-1)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700538 return 0;
tsepezf40c6f12016-09-06 11:45:32 -0700539
tsepezbbee4452016-09-02 15:22:00 -0700540 int32_t alpha =
541 static_cast<int32_t>((pObj->m_GeneralState.GetFillAlpha() * 255));
542 if (pObj->m_GeneralState.GetTR()) {
543 if (!pObj->m_GeneralState.GetTransferFunc()) {
544 pObj->m_GeneralState.SetTransferFunc(
545 GetTransferFunc(pObj->m_GeneralState.GetTR()));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700546 }
tsepezbbee4452016-09-02 15:22:00 -0700547 if (pObj->m_GeneralState.GetTransferFunc())
548 rgb = pObj->m_GeneralState.GetTransferFunc()->TranslateColor(rgb);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700549 }
550 return m_Options.TranslateColor(ArgbEncode(alpha, rgb));
551}
tsepezbbee4452016-09-02 15:22:00 -0700552
553FX_ARGB CPDF_RenderStatus::GetStrokeArgb(CPDF_PageObject* pObj) const {
tsepezf40c6f12016-09-06 11:45:32 -0700554 const CPDF_ColorState* pColorState = &pObj->m_ColorState;
555 if (m_pType3Char &&
556 (!m_pType3Char->m_bColored ||
557 (m_pType3Char->m_bColored &&
558 (!*pColorState || pColorState->GetStrokeColor()->IsNull())))) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700559 return m_T3FillColor;
560 }
tsepezf40c6f12016-09-06 11:45:32 -0700561 if (!*pColorState || pColorState->GetStrokeColor()->IsNull())
562 pColorState = &m_InitialStates.m_ColorState;
563
564 FX_COLORREF rgb = pColorState->GetStrokeRGB();
565 if (rgb == (uint32_t)-1)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700566 return 0;
tsepezf40c6f12016-09-06 11:45:32 -0700567
tsepezbbee4452016-09-02 15:22:00 -0700568 int32_t alpha = static_cast<int32_t>(pObj->m_GeneralState.GetStrokeAlpha() *
569 255); // not rounded.
570 if (pObj->m_GeneralState.GetTR()) {
571 if (!pObj->m_GeneralState.GetTransferFunc()) {
572 pObj->m_GeneralState.SetTransferFunc(
573 GetTransferFunc(pObj->m_GeneralState.GetTR()));
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700574 }
tsepezbbee4452016-09-02 15:22:00 -0700575 if (pObj->m_GeneralState.GetTransferFunc())
576 rgb = pObj->m_GeneralState.GetTransferFunc()->TranslateColor(rgb);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700577 }
578 return m_Options.TranslateColor(ArgbEncode(alpha, rgb));
579}
580void CPDF_RenderStatus::ProcessClipPath(CPDF_ClipPath ClipPath,
Tom Sepez60d909e2015-12-10 15:34:55 -0800581 const CFX_Matrix* pObj2Device) {
tsepez83d23512016-08-26 14:56:39 -0700582 if (!ClipPath) {
583 if (m_LastClipPath) {
thestig41846a02016-05-26 10:45:30 -0700584 m_pDevice->RestoreState(true);
tsepezd24c3a62016-08-29 14:42:36 -0700585 m_LastClipPath.SetNull();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700586 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700587 return;
588 }
Lei Zhang5044cab2015-11-10 10:09:33 -0800589 if (m_LastClipPath == ClipPath)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700590 return;
Lei Zhang5044cab2015-11-10 10:09:33 -0800591
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700592 m_LastClipPath = ClipPath;
thestig41846a02016-05-26 10:45:30 -0700593 m_pDevice->RestoreState(true);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700594 int nClipPath = ClipPath.GetPathCount();
Lei Zhang5044cab2015-11-10 10:09:33 -0800595 for (int i = 0; i < nClipPath; ++i) {
tsepez7d2a8d92016-06-08 11:51:23 -0700596 const CFX_PathData* pPathData = ClipPath.GetPath(i).GetObject();
Lei Zhang5044cab2015-11-10 10:09:33 -0800597 if (!pPathData)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700598 continue;
Lei Zhang5044cab2015-11-10 10:09:33 -0800599
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700600 if (pPathData->GetPointCount() == 0) {
601 CFX_PathData EmptyPath;
602 EmptyPath.AppendRect(-1, -1, 0, 0);
603 int fill_mode = FXFILL_WINDING;
Lei Zhang5044cab2015-11-10 10:09:33 -0800604 m_pDevice->SetClip_PathFill(&EmptyPath, nullptr, fill_mode);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700605 } else {
606 int ClipType = ClipPath.GetClipType(i);
607 m_pDevice->SetClip_PathFill(pPathData, pObj2Device, ClipType);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700608 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700609 }
610 int textcount = ClipPath.GetTextCount();
Lei Zhang5044cab2015-11-10 10:09:33 -0800611 if (textcount == 0)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700612 return;
Lei Zhang5044cab2015-11-10 10:09:33 -0800613
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700614 if (m_pDevice->GetDeviceClass() == FXDC_DISPLAY &&
615 !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP)) {
616 return;
617 }
Lei Zhang5044cab2015-11-10 10:09:33 -0800618
Lei Zhangaa8bf7e2015-12-24 19:13:32 -0800619 std::unique_ptr<CFX_PathData> pTextClippingPath;
Lei Zhang5044cab2015-11-10 10:09:33 -0800620 for (int i = 0; i < textcount; ++i) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700621 CPDF_TextObject* pText = ClipPath.GetText(i);
Lei Zhang5044cab2015-11-10 10:09:33 -0800622 if (pText) {
623 if (!pTextClippingPath)
624 pTextClippingPath.reset(new CFX_PathData);
625 ProcessText(pText, pObj2Device, pTextClippingPath.get());
626 continue;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700627 }
Lei Zhang5044cab2015-11-10 10:09:33 -0800628
629 if (!pTextClippingPath)
630 continue;
631
632 int fill_mode = FXFILL_WINDING;
633 if (m_Options.m_Flags & RENDER_NOTEXTSMOOTH)
634 fill_mode |= FXFILL_NOPATHSMOOTH;
635 m_pDevice->SetClip_PathFill(pTextClippingPath.get(), nullptr, fill_mode);
636 pTextClippingPath.reset();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700637 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700638}
Lei Zhang5044cab2015-11-10 10:09:33 -0800639
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700640void CPDF_RenderStatus::DrawClipPath(CPDF_ClipPath ClipPath,
Tom Sepez60d909e2015-12-10 15:34:55 -0800641 const CFX_Matrix* pObj2Device) {
tsepez83d23512016-08-26 14:56:39 -0700642 if (!ClipPath)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700643 return;
tsepez83d23512016-08-26 14:56:39 -0700644
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700645 int fill_mode = 0;
646 if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) {
647 fill_mode |= FXFILL_NOPATHSMOOTH;
648 }
649 int nClipPath = ClipPath.GetPathCount();
650 int i;
651 for (i = 0; i < nClipPath; i++) {
tsepez7d2a8d92016-06-08 11:51:23 -0700652 const CFX_PathData* pPathData = ClipPath.GetPath(i).GetObject();
Lei Zhang412e9082015-12-14 18:34:00 -0800653 if (!pPathData) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700654 continue;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700655 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700656 CFX_GraphStateData stroke_state;
657 if (m_Options.m_Flags & RENDER_THINLINE) {
658 stroke_state.m_LineWidth = 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700659 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700660 m_pDevice->DrawPath(pPathData, pObj2Device, &stroke_state, 0, 0xffff0000,
661 fill_mode);
662 }
663}
Wei Li7cf13c92016-02-19 11:53:03 -0800664FX_BOOL CPDF_RenderStatus::SelectClipPath(const CPDF_PathObject* pPathObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800665 const CFX_Matrix* pObj2Device,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700666 FX_BOOL bStroke) {
Tom Sepez60d909e2015-12-10 15:34:55 -0800667 CFX_Matrix path_matrix = pPathObj->m_Matrix;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700668 path_matrix.Concat(*pObj2Device);
669 if (bStroke) {
tsepez85a65b32016-09-07 09:35:36 -0700670 CFX_GraphState graphState = pPathObj->m_GraphState;
671 if (m_Options.m_Flags & RENDER_THINLINE)
672 graphState.SetLineWidth(0);
tsepez7d2a8d92016-06-08 11:51:23 -0700673 return m_pDevice->SetClip_PathStroke(pPathObj->m_Path.GetObject(),
tsepez85a65b32016-09-07 09:35:36 -0700674 &path_matrix, graphState.GetObject());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700675 }
676 int fill_mode = pPathObj->m_FillType;
677 if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) {
678 fill_mode |= FXFILL_NOPATHSMOOTH;
679 }
tsepez7d2a8d92016-06-08 11:51:23 -0700680 return m_pDevice->SetClip_PathFill(pPathObj->m_Path.GetObject(), &path_matrix,
681 fill_mode);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700682}
tsepezbbee4452016-09-02 15:22:00 -0700683FX_BOOL CPDF_RenderStatus::ProcessTransparency(CPDF_PageObject* pPageObj,
Tom Sepez60d909e2015-12-10 15:34:55 -0800684 const CFX_Matrix* pObj2Device) {
caryclarka27d49a2016-07-06 10:20:25 -0700685#if defined _SKIA_SUPPORT_
686 DebugVerifyDeviceIsPreMultiplied();
687#endif
tsepezbbee4452016-09-02 15:22:00 -0700688 int blend_type = pPageObj->m_GeneralState.GetBlendType();
689 if (blend_type == FXDIB_BLEND_UNSUPPORTED)
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700690 return TRUE;
tsepezbbee4452016-09-02 15:22:00 -0700691
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700692 CPDF_Dictionary* pSMaskDict =
tsepezbbee4452016-09-02 15:22:00 -0700693 ToDictionary(pPageObj->m_GeneralState.GetSoftMask());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700694 if (pSMaskDict) {
Wei Li7cf13c92016-02-19 11:53:03 -0800695 if (pPageObj->IsImage() &&
thestigf41d9dc2016-08-05 22:34:58 -0700696 pPageObj->AsImage()->GetImage()->GetDict()->KeyExist("SMask")) {
thestig4997b222016-06-07 10:46:22 -0700697 pSMaskDict = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700698 }
699 }
thestig4997b222016-06-07 10:46:22 -0700700 CPDF_Dictionary* pFormResource = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700701 FX_FLOAT group_alpha = 1.0f;
702 int Transparency = m_Transparency;
703 FX_BOOL bGroupTransparent = FALSE;
Wei Li7cf13c92016-02-19 11:53:03 -0800704 if (pPageObj->IsForm()) {
705 const CPDF_FormObject* pFormObj = pPageObj->AsForm();
tsepezbbee4452016-09-02 15:22:00 -0700706 group_alpha = pFormObj->m_GeneralState.GetFillAlpha();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700707 Transparency = pFormObj->m_pForm->m_Transparency;
Lei Zhangb0748bb2015-10-19 12:11:49 -0700708 bGroupTransparent = !!(Transparency & PDFTRANS_ISOLATED);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700709 if (pFormObj->m_pForm->m_pFormDict) {
dsinclair38fd8442016-09-15 10:15:32 -0700710 pFormResource = pFormObj->m_pForm->m_pFormDict->GetDictFor("Resources");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700711 }
712 }
tsepez83d23512016-08-26 14:56:39 -0700713 bool bTextClip =
714 (pPageObj->m_ClipPath && pPageObj->m_ClipPath.GetTextCount() &&
715 m_pDevice->GetDeviceClass() == FXDC_DISPLAY &&
716 !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP));
Wei Li7cf13c92016-02-19 11:53:03 -0800717 if ((m_Options.m_Flags & RENDER_OVERPRINT) && pPageObj->IsImage() &&
tsepezbbee4452016-09-02 15:22:00 -0700718 pPageObj->m_GeneralState.GetFillOP() &&
719 pPageObj->m_GeneralState.GetStrokeOP()) {
thestig4997b222016-06-07 10:46:22 -0700720 CPDF_Document* pDocument = nullptr;
721 CPDF_Page* pPage = nullptr;
Tom Sepez71fdc342016-01-22 12:06:32 -0800722 if (m_pContext->GetPageCache()) {
723 pPage = m_pContext->GetPageCache()->GetPage();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700724 pDocument = pPage->m_pDocument;
725 } else {
thestigf41d9dc2016-08-05 22:34:58 -0700726 pDocument = pPageObj->AsImage()->GetImage()->GetDocument();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700727 }
thestig4997b222016-06-07 10:46:22 -0700728 CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : nullptr;
tsepezbd567552016-03-29 14:51:50 -0700729 CPDF_Object* pCSObj = pPageObj->AsImage()
thestigf41d9dc2016-08-05 22:34:58 -0700730 ->GetImage()
731 ->GetStream()
tsepezbd567552016-03-29 14:51:50 -0700732 ->GetDict()
dsinclair38fd8442016-09-15 10:15:32 -0700733 ->GetDirectObjectFor("ColorSpace");
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700734 CPDF_ColorSpace* pColorSpace =
735 pDocument->LoadColorSpace(pCSObj, pPageResources);
736 if (pColorSpace) {
737 int format = pColorSpace->GetFamily();
738 if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION ||
739 format == PDFCS_DEVICEN) {
740 blend_type = FXDIB_BLEND_DARKEN;
741 }
742 pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
743 }
744 }
Lei Zhang412e9082015-12-14 18:34:00 -0800745 if (!pSMaskDict && group_alpha == 1.0f && blend_type == FXDIB_BLEND_NORMAL &&
746 !bTextClip && !bGroupTransparent) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700747 return FALSE;
748 }
tsepez7d89e722016-05-04 13:38:11 -0700749 bool isolated = !!(Transparency & PDFTRANS_ISOLATED);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700750 if (m_bPrint) {
751 FX_BOOL bRet = FALSE;
752 int rendCaps = m_pDevice->GetRenderCaps();
753 if (!((Transparency & PDFTRANS_ISOLATED) || pSMaskDict || bTextClip) &&
754 (rendCaps & FXRC_BLEND_MODE)) {
755 int oldBlend = m_curBlend;
756 m_curBlend = blend_type;
757 bRet = DrawObjWithBlend(pPageObj, pObj2Device);
758 m_curBlend = oldBlend;
759 }
760 if (!bRet) {
761 DrawObjWithBackground(pPageObj, pObj2Device);
762 }
763 return TRUE;
764 }
765 FX_RECT rect = pPageObj->GetBBox(pObj2Device);
766 rect.Intersect(m_pDevice->GetClipBox());
767 if (rect.IsEmpty()) {
768 return TRUE;
769 }
770 CFX_Matrix deviceCTM = m_pDevice->GetCTM();
771 FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a);
772 FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d);
773 int width = FXSYS_round((FX_FLOAT)rect.Width() * scaleX);
774 int height = FXSYS_round((FX_FLOAT)rect.Height() * scaleY);
775 CFX_FxgeDevice bitmap_device;
Lei Zhangaa8bf7e2015-12-24 19:13:32 -0800776 std::unique_ptr<CFX_DIBitmap> oriDevice;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700777 if (!isolated && (m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) {
Lei Zhang5044cab2015-11-10 10:09:33 -0800778 oriDevice.reset(new CFX_DIBitmap);
779 if (!m_pDevice->CreateCompatibleBitmap(oriDevice.get(), width, height))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700780 return TRUE;
Lei Zhang5044cab2015-11-10 10:09:33 -0800781 m_pDevice->GetDIBits(oriDevice.get(), rect.left, rect.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700782 }
thestigbefa4502016-05-26 20:15:19 -0700783 if (!bitmap_device.Create(width, height, FXDIB_Argb, oriDevice.get()))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700784 return TRUE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700785 CFX_DIBitmap* bitmap = bitmap_device.GetBitmap();
786 bitmap->Clear(0);
Tom Sepez60d909e2015-12-10 15:34:55 -0800787 CFX_Matrix new_matrix = *pObj2Device;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700788 new_matrix.TranslateI(-rect.left, -rect.top);
789 new_matrix.Scale(scaleX, scaleY);
Lei Zhangaa8bf7e2015-12-24 19:13:32 -0800790 std::unique_ptr<CFX_DIBitmap> pTextMask;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700791 if (bTextClip) {
Lei Zhang5044cab2015-11-10 10:09:33 -0800792 pTextMask.reset(new CFX_DIBitmap);
793 if (!pTextMask->Create(width, height, FXDIB_8bppMask))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700794 return TRUE;
Lei Zhang5044cab2015-11-10 10:09:33 -0800795
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700796 pTextMask->Clear(0);
797 CFX_FxgeDevice text_device;
thestigbefa4502016-05-26 20:15:19 -0700798 text_device.Attach(pTextMask.get(), false, nullptr, false);
tsepezb5e8f142016-03-25 15:18:35 -0700799 for (uint32_t i = 0; i < pPageObj->m_ClipPath.GetTextCount(); i++) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700800 CPDF_TextObject* textobj = pPageObj->m_ClipPath.GetText(i);
Lei Zhang412e9082015-12-14 18:34:00 -0800801 if (!textobj) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700802 break;
803 }
Tom Sepez60d909e2015-12-10 15:34:55 -0800804 CFX_Matrix text_matrix;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700805 textobj->GetTextMatrix(&text_matrix);
806 CPDF_TextRenderer::DrawTextPath(
807 &text_device, textobj->m_nChars, textobj->m_pCharCodes,
tsepez59601432016-08-29 14:26:57 -0700808 textobj->m_pCharPos, textobj->m_TextState.GetFont(),
809 textobj->m_TextState.GetFontSize(), &text_matrix, &new_matrix,
tsepez7d2a8d92016-06-08 11:51:23 -0700810 textobj->m_GraphState.GetObject(), (FX_ARGB)-1, 0, nullptr, 0);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700811 }
812 }
813 CPDF_RenderStatus bitmap_render;
thestig4997b222016-06-07 10:46:22 -0700814 bitmap_render.Initialize(m_pContext, &bitmap_device, nullptr, m_pStopObj,
815 nullptr, nullptr, &m_Options, 0, m_bDropObjects,
816 pFormResource, TRUE);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700817 bitmap_render.ProcessObjectNoClip(pPageObj, &new_matrix);
818 m_bStopped = bitmap_render.m_bStopped;
819 if (pSMaskDict) {
tsepeze106b502016-09-02 16:53:09 -0700820 CFX_Matrix smask_matrix = *pPageObj->m_GeneralState.GetSMaskMatrix();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700821 smask_matrix.Concat(*pObj2Device);
Lei Zhangaa8bf7e2015-12-24 19:13:32 -0800822 std::unique_ptr<CFX_DIBSource> pSMaskSource(
Lei Zhang5044cab2015-11-10 10:09:33 -0800823 LoadSMask(pSMaskDict, &rect, &smask_matrix));
824 if (pSMaskSource)
825 bitmap->MultiplyAlpha(pSMaskSource.get());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700826 }
827 if (pTextMask) {
Lei Zhang5044cab2015-11-10 10:09:33 -0800828 bitmap->MultiplyAlpha(pTextMask.get());
829 pTextMask.reset();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700830 }
caryclark36e258b2016-06-02 08:59:20 -0700831 int32_t blitAlpha = 255;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700832 if (Transparency & PDFTRANS_GROUP && group_alpha != 1.0f) {
caryclark36e258b2016-06-02 08:59:20 -0700833 blitAlpha = (int32_t)(group_alpha * 255);
834#ifndef _SKIA_SUPPORT_
835 bitmap->MultiplyAlpha(blitAlpha);
836 blitAlpha = 255;
837#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700838 }
839 Transparency = m_Transparency;
Wei Li7cf13c92016-02-19 11:53:03 -0800840 if (pPageObj->IsForm()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700841 Transparency |= PDFTRANS_GROUP;
842 }
caryclark36e258b2016-06-02 08:59:20 -0700843 CompositeDIBitmap(bitmap, rect.left, rect.top, 0, blitAlpha, blend_type,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700844 Transparency);
caryclarka27d49a2016-07-06 10:20:25 -0700845#if defined _SKIA_SUPPORT_
846 DebugVerifyDeviceIsPreMultiplied();
847#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700848 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700849}
Lei Zhang5044cab2015-11-10 10:09:33 -0800850
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700851CFX_DIBitmap* CPDF_RenderStatus::GetBackdrop(const CPDF_PageObject* pObj,
852 const FX_RECT& rect,
853 int& left,
854 int& top,
855 FX_BOOL bBackAlphaRequired) {
856 FX_RECT bbox = rect;
857 bbox.Intersect(m_pDevice->GetClipBox());
858 left = bbox.left;
859 top = bbox.top;
860 CFX_Matrix deviceCTM = m_pDevice->GetCTM();
861 FX_FLOAT scaleX = FXSYS_fabs(deviceCTM.a);
862 FX_FLOAT scaleY = FXSYS_fabs(deviceCTM.d);
863 int width = FXSYS_round(bbox.Width() * scaleX);
864 int height = FXSYS_round(bbox.Height() * scaleY);
Lei Zhangaa8bf7e2015-12-24 19:13:32 -0800865 std::unique_ptr<CFX_DIBitmap> pBackdrop(new CFX_DIBitmap);
Lei Zhang5044cab2015-11-10 10:09:33 -0800866 if (bBackAlphaRequired && !m_bDropObjects)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700867 pBackdrop->Create(width, height, FXDIB_Argb);
Lei Zhang5044cab2015-11-10 10:09:33 -0800868 else
869 m_pDevice->CreateCompatibleBitmap(pBackdrop.get(), width, height);
870
871 if (!pBackdrop->GetBuffer())
872 return nullptr;
873
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700874 FX_BOOL bNeedDraw;
Lei Zhang5044cab2015-11-10 10:09:33 -0800875 if (pBackdrop->HasAlpha())
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700876 bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT);
Lei Zhang5044cab2015-11-10 10:09:33 -0800877 else
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700878 bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS);
Lei Zhang5044cab2015-11-10 10:09:33 -0800879
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700880 if (!bNeedDraw) {
Lei Zhang5044cab2015-11-10 10:09:33 -0800881 m_pDevice->GetDIBits(pBackdrop.get(), left, top);
882 return pBackdrop.release();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700883 }
Lei Zhang5044cab2015-11-10 10:09:33 -0800884
Tom Sepez60d909e2015-12-10 15:34:55 -0800885 CFX_Matrix FinalMatrix = m_DeviceMatrix;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700886 FinalMatrix.TranslateI(-left, -top);
887 FinalMatrix.Scale(scaleX, scaleY);
888 pBackdrop->Clear(pBackdrop->HasAlpha() ? 0 : 0xffffffff);
889 CFX_FxgeDevice device;
thestigbefa4502016-05-26 20:15:19 -0700890 device.Attach(pBackdrop.get(), false, nullptr, false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700891 m_pContext->Render(&device, pObj, &m_Options, &FinalMatrix);
Lei Zhang5044cab2015-11-10 10:09:33 -0800892 return pBackdrop.release();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700893}
Lei Zhang5044cab2015-11-10 10:09:33 -0800894
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700895void CPDF_RenderContext::GetBackground(CFX_DIBitmap* pBuffer,
896 const CPDF_PageObject* pObj,
897 const CPDF_RenderOptions* pOptions,
Tom Sepez60d909e2015-12-10 15:34:55 -0800898 CFX_Matrix* pFinalMatrix) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700899 CFX_FxgeDevice device;
thestigbefa4502016-05-26 20:15:19 -0700900 device.Attach(pBuffer, false, nullptr, false);
Tom Sepez76510e42015-06-03 16:19:04 -0700901
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700902 FX_RECT rect(0, 0, device.GetWidth(), device.GetHeight());
903 device.FillRect(&rect, 0xffffffff);
904 Render(&device, pObj, pOptions, pFinalMatrix);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700905}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700906CPDF_GraphicStates* CPDF_RenderStatus::CloneObjStates(
907 const CPDF_GraphicStates* pSrcStates,
908 FX_BOOL bStroke) {
tsepezca90b872016-08-31 10:41:00 -0700909 if (!pSrcStates)
thestig4997b222016-06-07 10:46:22 -0700910 return nullptr;
tsepezca90b872016-08-31 10:41:00 -0700911
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700912 CPDF_GraphicStates* pStates = new CPDF_GraphicStates;
913 pStates->CopyStates(*pSrcStates);
tsepez987f3ee2016-08-26 15:17:12 -0700914 const CPDF_Color* pObjColor = bStroke
tsepezadbd3292016-08-29 14:07:28 -0700915 ? pSrcStates->m_ColorState.GetStrokeColor()
916 : pSrcStates->m_ColorState.GetFillColor();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700917 if (!pObjColor->IsNull()) {
tsepezca90b872016-08-31 10:41:00 -0700918 pStates->m_ColorState.SetFillRGB(
919 bStroke ? pSrcStates->m_ColorState.GetStrokeRGB()
920 : pSrcStates->m_ColorState.GetFillRGB());
921 pStates->m_ColorState.SetStrokeRGB(pStates->m_ColorState.GetFillRGB());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700922 }
923 return pStates;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700924}
Tom Sepez71fdc342016-01-22 12:06:32 -0800925
Tom Sepez979ddd82015-12-17 13:41:13 -0800926CPDF_RenderContext::CPDF_RenderContext(CPDF_Page* pPage)
927 : m_pDocument(pPage->m_pDocument),
928 m_pPageResources(pPage->m_pPageResources),
jaepark844c4b22016-07-26 12:35:22 -0700929 m_pPageCache(pPage->GetRenderCache()) {}
Tom Sepez71fdc342016-01-22 12:06:32 -0800930
Tom Sepez979ddd82015-12-17 13:41:13 -0800931CPDF_RenderContext::CPDF_RenderContext(CPDF_Document* pDoc,
932 CPDF_PageRenderCache* pPageCache)
jaepark844c4b22016-07-26 12:35:22 -0700933 : m_pDocument(pDoc), m_pPageResources(nullptr), m_pPageCache(pPageCache) {}
Tom Sepez71fdc342016-01-22 12:06:32 -0800934
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700935CPDF_RenderContext::~CPDF_RenderContext() {}
Tom Sepez71fdc342016-01-22 12:06:32 -0800936
Tom Sepez32c70812016-02-16 17:15:32 -0800937void CPDF_RenderContext::AppendLayer(CPDF_PageObjectHolder* pObjectHolder,
Tom Sepez71fdc342016-01-22 12:06:32 -0800938 const CFX_Matrix* pObject2Device) {
939 Layer* pLayer = m_Layers.AddSpace();
Tom Sepez32c70812016-02-16 17:15:32 -0800940 pLayer->m_pObjectHolder = pObjectHolder;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700941 if (pObject2Device) {
Tom Sepez71fdc342016-01-22 12:06:32 -0800942 pLayer->m_Matrix = *pObject2Device;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700943 } else {
Tom Sepez71fdc342016-01-22 12:06:32 -0800944 pLayer->m_Matrix.SetIdentity();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700945 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700946}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700947void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice,
948 const CPDF_RenderOptions* pOptions,
Tom Sepez60d909e2015-12-10 15:34:55 -0800949 const CFX_Matrix* pLastMatrix) {
thestig4997b222016-06-07 10:46:22 -0700950 Render(pDevice, nullptr, pOptions, pLastMatrix);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700951}
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700952void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice,
953 const CPDF_PageObject* pStopObj,
954 const CPDF_RenderOptions* pOptions,
Tom Sepez60d909e2015-12-10 15:34:55 -0800955 const CFX_Matrix* pLastMatrix) {
Tom Sepez71fdc342016-01-22 12:06:32 -0800956 int count = m_Layers.GetSize();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700957 for (int j = 0; j < count; j++) {
958 pDevice->SaveState();
Tom Sepez71fdc342016-01-22 12:06:32 -0800959 Layer* pLayer = m_Layers.GetDataPtr(j);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700960 if (pLastMatrix) {
Tom Sepez71fdc342016-01-22 12:06:32 -0800961 CFX_Matrix FinalMatrix = pLayer->m_Matrix;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700962 FinalMatrix.Concat(*pLastMatrix);
963 CPDF_RenderStatus status;
thestig4997b222016-06-07 10:46:22 -0700964 status.Initialize(this, pDevice, pLastMatrix, pStopObj, nullptr, nullptr,
Tom Sepez32c70812016-02-16 17:15:32 -0800965 pOptions, pLayer->m_pObjectHolder->m_Transparency,
thestig4997b222016-06-07 10:46:22 -0700966 FALSE, nullptr);
Tom Sepez32c70812016-02-16 17:15:32 -0800967 status.RenderObjectList(pLayer->m_pObjectHolder, &FinalMatrix);
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 }
975 } else {
976 CPDF_RenderStatus status;
thestig4997b222016-06-07 10:46:22 -0700977 status.Initialize(this, pDevice, nullptr, pStopObj, nullptr, nullptr,
978 pOptions, pLayer->m_pObjectHolder->m_Transparency,
979 FALSE, nullptr);
Tom Sepez32c70812016-02-16 17:15:32 -0800980 status.RenderObjectList(pLayer->m_pObjectHolder, &pLayer->m_Matrix);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700981 if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
982 m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize);
983 }
984 if (status.m_bStopped) {
thestig41846a02016-05-26 10:45:30 -0700985 pDevice->RestoreState(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700986 break;
987 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700988 }
thestig41846a02016-05-26 10:45:30 -0700989 pDevice->RestoreState(false);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700990 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700991}
Tom Sepezb3b67622015-10-19 16:20:03 -0700992
993CPDF_ProgressiveRenderer::CPDF_ProgressiveRenderer(
994 CPDF_RenderContext* pContext,
995 CFX_RenderDevice* pDevice,
996 const CPDF_RenderOptions* pOptions)
997 : m_Status(Ready),
998 m_pContext(pContext),
999 m_pDevice(pDevice),
1000 m_pOptions(pOptions),
1001 m_LayerIndex(0),
Tom Sepez2398d892016-02-17 16:46:26 -08001002 m_pCurrentLayer(nullptr) {}
Tom Sepezb3b67622015-10-19 16:20:03 -07001003
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001004CPDF_ProgressiveRenderer::~CPDF_ProgressiveRenderer() {
Tom Sepezb3b67622015-10-19 16:20:03 -07001005 if (m_pRenderStatus)
thestig41846a02016-05-26 10:45:30 -07001006 m_pDevice->RestoreState(false);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001007}
Tom Sepezb3b67622015-10-19 16:20:03 -07001008
1009void CPDF_ProgressiveRenderer::Start(IFX_Pause* pPause) {
1010 if (!m_pContext || !m_pDevice || m_Status != Ready) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001011 m_Status = Failed;
1012 return;
1013 }
1014 m_Status = ToBeContinued;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001015 Continue(pPause);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001016}
Tom Sepezb3b67622015-10-19 16:20:03 -07001017
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001018void CPDF_ProgressiveRenderer::Continue(IFX_Pause* pPause) {
Tom Sepeze6a51382016-02-16 09:17:44 -08001019 while (m_Status == ToBeContinued) {
1020 if (!m_pCurrentLayer) {
1021 if (m_LayerIndex >= m_pContext->CountLayers()) {
1022 m_Status = Done;
1023 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001024 }
Tom Sepeze6a51382016-02-16 09:17:44 -08001025 m_pCurrentLayer = m_pContext->GetLayer(m_LayerIndex);
Tom Sepez2398d892016-02-17 16:46:26 -08001026 m_LastObjectRendered =
1027 m_pCurrentLayer->m_pObjectHolder->GetPageObjectList()->end();
Tom Sepezb3b67622015-10-19 16:20:03 -07001028 m_pRenderStatus.reset(new CPDF_RenderStatus());
1029 m_pRenderStatus->Initialize(
thestig4997b222016-06-07 10:46:22 -07001030 m_pContext, m_pDevice, nullptr, nullptr, nullptr, nullptr, m_pOptions,
1031 m_pCurrentLayer->m_pObjectHolder->m_Transparency, FALSE, nullptr);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001032 m_pDevice->SaveState();
Tom Sepezd5e7b352016-02-29 11:24:29 -08001033 m_ClipRect = CFX_FloatRect(m_pDevice->GetClipBox());
Tom Sepez60d909e2015-12-10 15:34:55 -08001034 CFX_Matrix device2object;
Tom Sepeze6a51382016-02-16 09:17:44 -08001035 device2object.SetReverse(m_pCurrentLayer->m_Matrix);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001036 device2object.TransformRect(m_ClipRect);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001037 }
Tom Sepez2398d892016-02-17 16:46:26 -08001038 CPDF_PageObjectList::iterator iter;
1039 CPDF_PageObjectList::iterator iterEnd =
1040 m_pCurrentLayer->m_pObjectHolder->GetPageObjectList()->end();
1041 if (m_LastObjectRendered != iterEnd) {
1042 iter = m_LastObjectRendered;
1043 ++iter;
Tom Sepeze6a51382016-02-16 09:17:44 -08001044 } else {
Tom Sepez2398d892016-02-17 16:46:26 -08001045 iter = m_pCurrentLayer->m_pObjectHolder->GetPageObjectList()->begin();
Tom Sepeze6a51382016-02-16 09:17:44 -08001046 }
1047 int nObjsToGo = kStepLimit;
Tom Sepez2398d892016-02-17 16:46:26 -08001048 while (iter != iterEnd) {
1049 CPDF_PageObject* pCurObj = iter->get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001050 if (pCurObj && pCurObj->m_Left <= m_ClipRect.right &&
1051 pCurObj->m_Right >= m_ClipRect.left &&
1052 pCurObj->m_Bottom <= m_ClipRect.top &&
1053 pCurObj->m_Top >= m_ClipRect.bottom) {
Tom Sepeze6a51382016-02-16 09:17:44 -08001054 if (m_pRenderStatus->ContinueSingleObject(
1055 pCurObj, &m_pCurrentLayer->m_Matrix, pPause)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001056 return;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001057 }
Wei Li7cf13c92016-02-19 11:53:03 -08001058 if (pCurObj->IsImage() &&
Tom Sepezb3b67622015-10-19 16:20:03 -07001059 m_pRenderStatus->m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001060 m_pContext->GetPageCache()->CacheOptimization(
Tom Sepezb3b67622015-10-19 16:20:03 -07001061 m_pRenderStatus->m_Options.m_dwLimitCacheSize);
Lei Zhang606346f2015-06-19 18:11:07 -07001062 }
Wei Li7cf13c92016-02-19 11:53:03 -08001063 if (pCurObj->IsForm() || pCurObj->IsShading()) {
Tom Sepeze6a51382016-02-16 09:17:44 -08001064 nObjsToGo = 0;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001065 } else {
Tom Sepeze6a51382016-02-16 09:17:44 -08001066 --nObjsToGo;
Lei Zhang606346f2015-06-19 18:11:07 -07001067 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001068 }
Tom Sepez2398d892016-02-17 16:46:26 -08001069 m_LastObjectRendered = iter;
Tom Sepeze6a51382016-02-16 09:17:44 -08001070 if (nObjsToGo == 0) {
1071 if (pPause && pPause->NeedToPauseNow())
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001072 return;
Tom Sepeze6a51382016-02-16 09:17:44 -08001073 nObjsToGo = kStepLimit;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001074 }
Tom Sepez2398d892016-02-17 16:46:26 -08001075 ++iter;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001076 }
Tom Sepez32c70812016-02-16 17:15:32 -08001077 if (m_pCurrentLayer->m_pObjectHolder->IsParsed()) {
Tom Sepeze6a51382016-02-16 09:17:44 -08001078 m_pRenderStatus.reset();
thestig41846a02016-05-26 10:45:30 -07001079 m_pDevice->RestoreState(false);
Tom Sepeze6a51382016-02-16 09:17:44 -08001080 m_pCurrentLayer = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001081 m_LayerIndex++;
Tom Sepeze6a51382016-02-16 09:17:44 -08001082 if (pPause && pPause->NeedToPauseNow()) {
1083 return;
1084 }
1085 } else {
Tom Sepez32c70812016-02-16 17:15:32 -08001086 m_pCurrentLayer->m_pObjectHolder->ContinueParse(pPause);
1087 if (!m_pCurrentLayer->m_pObjectHolder->IsParsed())
Tom Sepeze6a51382016-02-16 09:17:44 -08001088 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001089 }
1090 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001091}
Tom Sepeze6a51382016-02-16 09:17:44 -08001092
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001093CPDF_TransferFunc* CPDF_DocRenderData::GetTransferFunc(CPDF_Object* pObj) {
1094 if (!pObj)
1095 return nullptr;
Lei Zhang606346f2015-06-19 18:11:07 -07001096
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001097 auto it = m_TransferFuncMap.find(pObj);
1098 if (it != m_TransferFuncMap.end()) {
1099 CPDF_CountedObject<CPDF_TransferFunc>* pTransferCounter = it->second;
Tom Sepez3403db92015-06-15 16:58:19 -07001100 return pTransferCounter->AddRef();
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001101 }
1102
Lei Zhangaa8bf7e2015-12-24 19:13:32 -08001103 std::unique_ptr<CPDF_Function> pFuncs[3];
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001104 FX_BOOL bUniTransfer = TRUE;
1105 FX_BOOL bIdentity = TRUE;
Dan Sinclair2b11dc12015-10-22 15:02:06 -04001106 if (CPDF_Array* pArray = pObj->AsArray()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001107 bUniTransfer = FALSE;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001108 if (pArray->GetCount() < 3)
1109 return nullptr;
1110
tsepezb5e8f142016-03-25 15:18:35 -07001111 for (uint32_t i = 0; i < 3; ++i) {
thestig490d6122016-05-23 14:56:02 -07001112 pFuncs[2 - i] = CPDF_Function::Load(pArray->GetDirectObjectAt(i));
Lei Zhang5044cab2015-11-10 10:09:33 -08001113 if (!pFuncs[2 - i])
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001114 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001115 }
1116 } else {
thestig490d6122016-05-23 14:56:02 -07001117 pFuncs[0] = CPDF_Function::Load(pObj);
Lei Zhang5044cab2015-11-10 10:09:33 -08001118 if (!pFuncs[0])
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001119 return nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001120 }
Lei Zhang5044cab2015-11-10 10:09:33 -08001121 CPDF_TransferFunc* pTransfer = new CPDF_TransferFunc(m_pPDFDoc);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001122 CPDF_CountedObject<CPDF_TransferFunc>* pTransferCounter =
1123 new CPDF_CountedObject<CPDF_TransferFunc>(pTransfer);
1124 m_TransferFuncMap[pObj] = pTransferCounter;
1125 static const int kMaxOutputs = 16;
1126 FX_FLOAT output[kMaxOutputs];
1127 FXSYS_memset(output, 0, sizeof(output));
1128 FX_FLOAT input;
1129 int noutput;
1130 for (int v = 0; v < 256; ++v) {
1131 input = (FX_FLOAT)v / 255.0f;
1132 if (bUniTransfer) {
1133 if (pFuncs[0] && pFuncs[0]->CountOutputs() <= kMaxOutputs)
1134 pFuncs[0]->Call(&input, 1, output, noutput);
1135 int o = FXSYS_round(output[0] * 255);
1136 if (o != v)
1137 bIdentity = FALSE;
1138 for (int i = 0; i < 3; ++i) {
1139 pTransfer->m_Samples[i * 256 + v] = o;
1140 }
1141 } else {
1142 for (int i = 0; i < 3; ++i) {
1143 if (pFuncs[i] && pFuncs[i]->CountOutputs() <= kMaxOutputs) {
1144 pFuncs[i]->Call(&input, 1, output, noutput);
1145 int o = FXSYS_round(output[0] * 255);
1146 if (o != v)
1147 bIdentity = FALSE;
1148 pTransfer->m_Samples[i * 256 + v] = o;
1149 } else {
1150 pTransfer->m_Samples[i * 256 + v] = v;
1151 }
1152 }
1153 }
1154 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001155
1156 pTransfer->m_bIdentity = bIdentity;
1157 return pTransferCounter->AddRef();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001158}
Lei Zhang606346f2015-06-19 18:11:07 -07001159
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001160void CPDF_DocRenderData::ReleaseTransferFunc(CPDF_Object* pObj) {
1161 auto it = m_TransferFuncMap.find(pObj);
1162 if (it != m_TransferFuncMap.end())
1163 it->second->RemoveRef();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001164}
Lei Zhang5044cab2015-11-10 10:09:33 -08001165
1166CPDF_DeviceBuffer::CPDF_DeviceBuffer()
1167 : m_pDevice(nullptr), m_pContext(nullptr), m_pObject(nullptr) {}
1168
Dan Sinclair764ec512016-03-14 13:35:12 -04001169CPDF_DeviceBuffer::~CPDF_DeviceBuffer() {}
Lei Zhang5044cab2015-11-10 10:09:33 -08001170
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001171FX_BOOL CPDF_DeviceBuffer::Initialize(CPDF_RenderContext* pContext,
1172 CFX_RenderDevice* pDevice,
1173 FX_RECT* pRect,
1174 const CPDF_PageObject* pObj,
1175 int max_dpi) {
1176 m_pDevice = pDevice;
1177 m_pContext = pContext;
1178 m_Rect = *pRect;
1179 m_pObject = pObj;
1180 m_Matrix.TranslateI(-pRect->left, -pRect->top);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001181#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001182 int horz_size = pDevice->GetDeviceCaps(FXDC_HORZ_SIZE);
1183 int vert_size = pDevice->GetDeviceCaps(FXDC_VERT_SIZE);
1184 if (horz_size && vert_size && max_dpi) {
1185 int dpih =
1186 pDevice->GetDeviceCaps(FXDC_PIXEL_WIDTH) * 254 / (horz_size * 10);
1187 int dpiv =
1188 pDevice->GetDeviceCaps(FXDC_PIXEL_HEIGHT) * 254 / (vert_size * 10);
1189 if (dpih > max_dpi) {
1190 m_Matrix.Scale((FX_FLOAT)(max_dpi) / dpih, 1.0f);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001191 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001192 if (dpiv > max_dpi) {
1193 m_Matrix.Scale(1.0f, (FX_FLOAT)(max_dpi) / (FX_FLOAT)dpiv);
1194 }
1195 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001196#endif
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001197 CFX_Matrix ctm = m_pDevice->GetCTM();
1198 FX_FLOAT fScaleX = FXSYS_fabs(ctm.a);
1199 FX_FLOAT fScaleY = FXSYS_fabs(ctm.d);
1200 m_Matrix.Concat(fScaleX, 0, 0, fScaleY, 0, 0);
1201 CFX_FloatRect rect(*pRect);
1202 m_Matrix.TransformRect(rect);
thestigad5ac752016-08-09 12:09:22 -07001203 FX_RECT bitmap_rect = rect.GetOuterRect();
Lei Zhang5044cab2015-11-10 10:09:33 -08001204 m_pBitmap.reset(new CFX_DIBitmap);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001205 m_pBitmap->Create(bitmap_rect.Width(), bitmap_rect.Height(), FXDIB_Argb);
1206 return TRUE;
1207}
1208void CPDF_DeviceBuffer::OutputToDevice() {
1209 if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) {
1210 if (m_Matrix.a == 1.0f && m_Matrix.d == 1.0f) {
Lei Zhang5044cab2015-11-10 10:09:33 -08001211 m_pDevice->SetDIBits(m_pBitmap.get(), m_Rect.left, m_Rect.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001212 } else {
Lei Zhang5044cab2015-11-10 10:09:33 -08001213 m_pDevice->StretchDIBits(m_pBitmap.get(), m_Rect.left, m_Rect.top,
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001214 m_Rect.Width(), m_Rect.Height());
1215 }
1216 } else {
1217 CFX_DIBitmap buffer;
1218 m_pDevice->CreateCompatibleBitmap(&buffer, m_pBitmap->GetWidth(),
1219 m_pBitmap->GetHeight());
thestig4997b222016-06-07 10:46:22 -07001220 m_pContext->GetBackground(&buffer, m_pObject, nullptr, &m_Matrix);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001221 buffer.CompositeBitmap(0, 0, buffer.GetWidth(), buffer.GetHeight(),
Lei Zhang5044cab2015-11-10 10:09:33 -08001222 m_pBitmap.get(), 0, 0);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001223 m_pDevice->StretchDIBits(&buffer, m_Rect.left, m_Rect.top, m_Rect.Width(),
1224 m_Rect.Height());
1225 }
1226}
Lei Zhang5044cab2015-11-10 10:09:33 -08001227
1228CPDF_ScaledRenderBuffer::CPDF_ScaledRenderBuffer() {}
1229
1230CPDF_ScaledRenderBuffer::~CPDF_ScaledRenderBuffer() {}
1231
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001232#define _FPDFAPI_IMAGESIZE_LIMIT_ (30 * 1024 * 1024)
1233FX_BOOL CPDF_ScaledRenderBuffer::Initialize(CPDF_RenderContext* pContext,
1234 CFX_RenderDevice* pDevice,
Lei Zhang96660d62015-12-14 18:27:25 -08001235 const FX_RECT& pRect,
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001236 const CPDF_PageObject* pObj,
1237 const CPDF_RenderOptions* pOptions,
1238 int max_dpi) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001239 m_pDevice = pDevice;
1240 if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) {
1241 return TRUE;
1242 }
1243 m_pContext = pContext;
Lei Zhang96660d62015-12-14 18:27:25 -08001244 m_Rect = pRect;
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001245 m_pObject = pObj;
Lei Zhang96660d62015-12-14 18:27:25 -08001246 m_Matrix.TranslateI(-pRect.left, -pRect.top);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001247 int horz_size = pDevice->GetDeviceCaps(FXDC_HORZ_SIZE);
1248 int vert_size = pDevice->GetDeviceCaps(FXDC_VERT_SIZE);
1249 if (horz_size && vert_size && max_dpi) {
1250 int dpih =
1251 pDevice->GetDeviceCaps(FXDC_PIXEL_WIDTH) * 254 / (horz_size * 10);
1252 int dpiv =
1253 pDevice->GetDeviceCaps(FXDC_PIXEL_HEIGHT) * 254 / (vert_size * 10);
1254 if (dpih > max_dpi) {
1255 m_Matrix.Scale((FX_FLOAT)(max_dpi) / dpih, 1.0f);
1256 }
1257 if (dpiv > max_dpi) {
1258 m_Matrix.Scale(1.0f, (FX_FLOAT)(max_dpi) / (FX_FLOAT)dpiv);
1259 }
1260 }
Lei Zhang5044cab2015-11-10 10:09:33 -08001261 m_pBitmapDevice.reset(new CFX_FxgeDevice);
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001262 FXDIB_Format dibFormat = FXDIB_Rgb;
1263 int32_t bpp = 24;
1264 if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_ALPHA_OUTPUT) {
1265 dibFormat = FXDIB_Argb;
1266 bpp = 32;
1267 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001268 while (1) {
Tom Sepezd5e7b352016-02-29 11:24:29 -08001269 CFX_FloatRect rect(pRect);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001270 m_Matrix.TransformRect(rect);
thestigad5ac752016-08-09 12:09:22 -07001271 FX_RECT bitmap_rect = rect.GetOuterRect();
Tom Sepezd5e7b352016-02-29 11:24:29 -08001272 int32_t iWidth = bitmap_rect.Width();
1273 int32_t iHeight = bitmap_rect.Height();
1274 int32_t iPitch = (iWidth * bpp + 31) / 32 * 4;
1275 if (iWidth * iHeight < 1)
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001276 return FALSE;
Tom Sepezd5e7b352016-02-29 11:24:29 -08001277
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001278 if (iPitch * iHeight <= _FPDFAPI_IMAGESIZE_LIMIT_ &&
thestigbefa4502016-05-26 20:15:19 -07001279 m_pBitmapDevice->Create(iWidth, iHeight, dibFormat, nullptr)) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001280 break;
1281 }
1282 m_Matrix.Scale(0.5f, 0.5f);
1283 }
1284 m_pContext->GetBackground(m_pBitmapDevice->GetBitmap(), m_pObject, pOptions,
1285 &m_Matrix);
1286 return TRUE;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001287}
Nico Weber9d8ec5a2015-08-04 13:00:21 -07001288void CPDF_ScaledRenderBuffer::OutputToDevice() {
1289 if (m_pBitmapDevice) {
1290 m_pDevice->StretchDIBits(m_pBitmapDevice->GetBitmap(), m_Rect.left,
1291 m_Rect.top, m_Rect.Width(), m_Rect.Height());
1292 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001293}
caryclarka27d49a2016-07-06 10:20:25 -07001294
1295#if defined _SKIA_SUPPORT_
1296void CPDF_RenderStatus::DebugVerifyDeviceIsPreMultiplied() const {
1297 m_pDevice->DebugVerifyBitmapIsPreMultiplied();
1298}
1299#endif