1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "../../../include/fpdfapi/fpdf_render.h"
8 #include "../../../include/fpdfapi/fpdf_module.h"
9 #include "../fpdf_page/pageint.h"
10 #include "../../../include/fxge/fx_ge.h"
11 #include "../../../include/fxcodec/fx_codec.h"
12 #include "render_int.h"
CPDF_DocRenderData(CPDF_Document * pPDFDoc)13 CPDF_DocRenderData::CPDF_DocRenderData(CPDF_Document* pPDFDoc)
14 : m_pPDFDoc(pPDFDoc)
15 , m_pFontCache(NULL)
16 {
17 }
~CPDF_DocRenderData()18 CPDF_DocRenderData::~CPDF_DocRenderData()
19 {
20 Clear(TRUE);
21 }
Clear(FX_BOOL bRelease)22 void CPDF_DocRenderData::Clear(FX_BOOL bRelease)
23 {
24 FX_POSITION pos;
25 {
26 pos = m_Type3FaceMap.GetStartPosition();
27 while (pos) {
28 CPDF_Font* pFont;
29 CPDF_CountedObject<CPDF_Type3Cache*>* cache;
30 m_Type3FaceMap.GetNextAssoc(pos, pFont, cache);
31 if (bRelease || cache->m_nCount < 2) {
32 delete cache->m_Obj;
33 delete cache;
34 m_Type3FaceMap.RemoveKey(pFont);
35 }
36 }
37 }
38 #ifndef _FPDFAPI_MINI_
39 {
40 pos = m_TransferFuncMap.GetStartPosition();
41 while (pos) {
42 CPDF_Object* key;
43 CPDF_CountedObject<CPDF_TransferFunc*>* value;
44 m_TransferFuncMap.GetNextAssoc(pos, key, value);
45 if (bRelease || value->m_nCount < 2) {
46 delete value->m_Obj;
47 delete value;
48 m_TransferFuncMap.RemoveKey(key);
49 }
50 }
51 }
52 #endif
53 if (m_pFontCache) {
54 if (bRelease) {
55 delete m_pFontCache;
56 m_pFontCache = NULL;
57 } else {
58 m_pFontCache->FreeCache(FALSE);
59 }
60 }
61 }
Initialize()62 FX_BOOL CPDF_DocRenderData::Initialize()
63 {
64 m_pFontCache = FX_NEW CFX_FontCache;
65 return TRUE;
66 }
GetCachedType3(CPDF_Type3Font * pFont)67 CPDF_Type3Cache* CPDF_DocRenderData::GetCachedType3(CPDF_Type3Font* pFont)
68 {
69 CPDF_CountedObject<CPDF_Type3Cache*>* pCache;
70 if (!m_Type3FaceMap.Lookup(pFont, pCache)) {
71 CPDF_Type3Cache* pType3 = FX_NEW CPDF_Type3Cache(pFont);
72 pCache = FX_NEW CPDF_CountedObject<CPDF_Type3Cache*>;
73 pCache->m_Obj = pType3;
74 pCache->m_nCount = 1;
75 m_Type3FaceMap.SetAt(pFont, pCache);
76 }
77 pCache->m_nCount++;
78 return pCache->m_Obj;
79 }
ReleaseCachedType3(CPDF_Type3Font * pFont)80 void CPDF_DocRenderData::ReleaseCachedType3(CPDF_Type3Font* pFont)
81 {
82 CPDF_CountedObject<CPDF_Type3Cache*>* pCache;
83 if (!m_Type3FaceMap.Lookup(pFont, pCache)) {
84 return;
85 }
86 pCache->m_nCount--;
87 }
88 class CPDF_RenderModule : public CPDF_RenderModuleDef
89 {
90 public:
~CPDF_RenderModule()91 virtual ~CPDF_RenderModule() {}
Installed()92 virtual FX_BOOL Installed()
93 {
94 return TRUE;
95 }
96 virtual CPDF_DocRenderData* CreateDocData(CPDF_Document* pDoc);
97 virtual void DestroyDocData(CPDF_DocRenderData* p);
98 virtual void ClearDocData(CPDF_DocRenderData* p);
GetRenderData()99 virtual CPDF_DocRenderData* GetRenderData()
100 {
101 return &m_RenderData;
102 }
CreatePageCache(CPDF_Page * pPage)103 virtual CPDF_PageRenderCache* CreatePageCache(CPDF_Page* pPage)
104 {
105 return FX_NEW CPDF_PageRenderCache(pPage);
106 }
107 virtual void DestroyPageCache(CPDF_PageRenderCache* pCache);
GetConfig()108 virtual CPDF_RenderConfig* GetConfig()
109 {
110 return &m_RenderConfig;
111 }
112 private:
113 CPDF_DocRenderData m_RenderData;
114 CPDF_RenderConfig m_RenderConfig;
115 };
CreateDocData(CPDF_Document * pDoc)116 CPDF_DocRenderData* CPDF_RenderModule::CreateDocData(CPDF_Document* pDoc)
117 {
118 CPDF_DocRenderData* pData = FX_NEW CPDF_DocRenderData(pDoc);
119 pData->Initialize();
120 return pData;
121 }
DestroyDocData(CPDF_DocRenderData * pDocData)122 void CPDF_RenderModule::DestroyDocData(CPDF_DocRenderData* pDocData)
123 {
124 delete pDocData;
125 }
ClearDocData(CPDF_DocRenderData * p)126 void CPDF_RenderModule::ClearDocData(CPDF_DocRenderData* p)
127 {
128 if (p) {
129 p->Clear(FALSE);
130 }
131 }
DestroyPageCache(CPDF_PageRenderCache * pCache)132 void CPDF_RenderModule::DestroyPageCache(CPDF_PageRenderCache* pCache)
133 {
134 delete pCache;
135 }
InitRenderModule()136 void CPDF_ModuleMgr::InitRenderModule()
137 {
138 if (m_pRenderModule) {
139 delete m_pRenderModule;
140 }
141 m_pRenderModule = FX_NEW CPDF_RenderModule;
142 }
CPDF_RenderOptions()143 CPDF_RenderOptions::CPDF_RenderOptions()
144 : m_ColorMode(RENDER_COLOR_NORMAL)
145 , m_Flags(RENDER_CLEARTYPE)
146 , m_Interpolation(0)
147 , m_AddFlags(0)
148 , m_pOCContext(NULL)
149 , m_dwLimitCacheSize(1024 * 1024 * 100)
150 , m_HalftoneLimit(-1)
151 {
152 #if defined(_FPDFAPI_MINI_)
153 m_Flags |= RENDER_LIMITEDIMAGECACHE;
154 #endif
155 }
TranslateColor(FX_ARGB argb) const156 FX_ARGB CPDF_RenderOptions::TranslateColor(FX_ARGB argb) const
157 {
158 if (m_ColorMode == RENDER_COLOR_NORMAL) {
159 return argb;
160 }
161 if (m_ColorMode == RENDER_COLOR_ALPHA) {
162 return argb;
163 }
164 int a, r, g, b;
165 ArgbDecode(argb, a, r, g, b);
166 int gray = FXRGB2GRAY(r, g, b);
167 if (m_ColorMode == RENDER_COLOR_TWOCOLOR) {
168 int color = (r - gray) * (r - gray) + (g - gray) * (g - gray) + (b - gray) * (b - gray);
169 if (gray < 35 && color < 20) {
170 return ArgbEncode(a, m_ForeColor);
171 }
172 if (gray > 221 && color < 20) {
173 return ArgbEncode(a, m_BackColor);
174 }
175 return argb;
176 }
177 int fr = FXSYS_GetRValue(m_ForeColor);
178 int fg = FXSYS_GetGValue(m_ForeColor);
179 int fb = FXSYS_GetBValue(m_ForeColor);
180 int br = FXSYS_GetRValue(m_BackColor);
181 int bg = FXSYS_GetGValue(m_BackColor);
182 int bb = FXSYS_GetBValue(m_BackColor);
183 r = (br - fr) * gray / 255 + fr;
184 g = (bg - fg) * gray / 255 + fg;
185 b = (bb - fb) * gray / 255 + fb;
186 return ArgbEncode(a, r, g, b);
187 }
CPDF_RenderStatus()188 CPDF_RenderStatus::CPDF_RenderStatus()
189 {
190 m_pContext = NULL;
191 m_bStopped = FALSE;
192 m_Level = 0;
193 m_pDevice = NULL;
194 m_pCurObj = NULL;
195 m_pStopObj = NULL;
196 m_HalftoneLimit = 0;
197 m_pObjectRenderer = NULL;
198 m_bPrint = FALSE;
199 m_Transparency = 0;
200 m_DitherBits = 0;
201 m_bDropObjects = FALSE;
202 m_bStdCS = FALSE;
203 m_GroupFamily = 0;
204 m_bLoadMask = FALSE;
205 m_pType3Char = NULL;
206 m_T3FillColor = 0;
207 m_pFormResource = NULL;
208 m_pPageResource = NULL;
209 m_curBlend = FXDIB_BLEND_NORMAL;
210 }
~CPDF_RenderStatus()211 CPDF_RenderStatus::~CPDF_RenderStatus()
212 {
213 if (m_pObjectRenderer) {
214 delete m_pObjectRenderer;
215 }
216 }
Initialize(int level,CPDF_RenderContext * pContext,CFX_RenderDevice * pDevice,const CFX_AffineMatrix * pDeviceMatrix,const CPDF_PageObject * pStopObj,const CPDF_RenderStatus * pParentState,const CPDF_GraphicStates * pInitialStates,const CPDF_RenderOptions * pOptions,int transparency,FX_BOOL bDropObjects,CPDF_Dictionary * pFormResource,FX_BOOL bStdCS,CPDF_Type3Char * pType3Char,FX_ARGB fill_color,FX_DWORD GroupFamily,FX_BOOL bLoadMask)217 FX_BOOL CPDF_RenderStatus::Initialize(int level, CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice,
218 const CFX_AffineMatrix* pDeviceMatrix, const CPDF_PageObject* pStopObj,
219 const CPDF_RenderStatus* pParentState, const CPDF_GraphicStates* pInitialStates,
220 const CPDF_RenderOptions* pOptions, int transparency, FX_BOOL bDropObjects,
221 CPDF_Dictionary* pFormResource, FX_BOOL bStdCS, CPDF_Type3Char* pType3Char,
222 FX_ARGB fill_color, FX_DWORD GroupFamily,
223 FX_BOOL bLoadMask)
224 {
225 m_Level = level;
226 m_pContext = pContext;
227 m_pDevice = pDevice;
228 m_DitherBits = pDevice->GetDeviceCaps(FXDC_DITHER_BITS);
229 m_bPrint = m_pDevice->GetDeviceClass() != FXDC_DISPLAY;
230 if (pDeviceMatrix) {
231 m_DeviceMatrix = *pDeviceMatrix;
232 }
233 m_pStopObj = pStopObj;
234 if (pOptions) {
235 m_Options = *pOptions;
236 }
237 m_bDropObjects = bDropObjects;
238 m_bStdCS = bStdCS;
239 m_T3FillColor = fill_color;
240 m_pType3Char = pType3Char;
241 m_GroupFamily = GroupFamily;
242 m_bLoadMask = bLoadMask;
243 m_pFormResource = pFormResource;
244 m_pPageResource = m_pContext->m_pPageResources;
245 if (pInitialStates && !m_pType3Char) {
246 m_InitialStates.CopyStates(*pInitialStates);
247 if (pParentState) {
248 CPDF_ColorStateData* pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)m_InitialStates.m_ColorState;
249 CPDF_ColorStateData* pParentData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)pParentState->m_InitialStates.m_ColorState;
250 if (!pColorData || pColorData->m_FillColor.IsNull()) {
251 CPDF_ColorStateData* pData = m_InitialStates.m_ColorState.GetModify();
252 pData->m_FillRGB = pParentData->m_FillRGB;
253 pData->m_FillColor.Copy(&pParentData->m_FillColor);
254 }
255 if (!pColorData || pColorData->m_StrokeColor.IsNull()) {
256 CPDF_ColorStateData* pData = m_InitialStates.m_ColorState.GetModify();
257 pData->m_StrokeRGB = pParentData->m_FillRGB;
258 pData->m_StrokeColor.Copy(&pParentData->m_StrokeColor);
259 }
260 }
261 } else {
262 m_InitialStates.DefaultStates();
263 }
264 #if defined(_FPDFAPI_MINI_)||defined(_FXCORE_LIMITED_CPU_)
265 m_HalftoneLimit = CPDF_ModuleMgr::Get()->GetRenderModule()->GetConfig()->m_HalftoneLimit;
266 if (pOptions && pOptions->m_HalftoneLimit >= 0) {
267 m_HalftoneLimit = pOptions->m_HalftoneLimit;
268 }
269 #endif
270 m_pObjectRenderer = NULL;
271 m_Transparency = transparency;
272 return TRUE;
273 }
RenderObjectList(const CPDF_PageObjects * pObjs,const CFX_AffineMatrix * pObj2Device)274 void CPDF_RenderStatus::RenderObjectList(const CPDF_PageObjects* pObjs, const CFX_AffineMatrix* pObj2Device)
275 {
276 if (m_Level > 32) {
277 return;
278 }
279 CFX_FloatRect clip_rect = m_pDevice->GetClipBox();
280 CFX_AffineMatrix device2object;
281 device2object.SetReverse(*pObj2Device);
282 device2object.TransformRect(clip_rect);
283 int index = 0;
284 FX_POSITION pos = pObjs->GetFirstObjectPosition();
285 while(pos) {
286 index ++;
287 CPDF_PageObject* pCurObj = pObjs->GetNextObject(pos);
288 if (pCurObj == m_pStopObj) {
289 m_bStopped = TRUE;
290 return;
291 }
292 if (!pCurObj) {
293 continue;
294 }
295 if(pCurObj == NULL || pCurObj->m_Left > clip_rect.right || pCurObj->m_Right < clip_rect.left ||
296 pCurObj->m_Bottom > clip_rect.top || pCurObj->m_Top < clip_rect.bottom) {
297 continue;
298 }
299 RenderSingleObject(pCurObj, pObj2Device);
300 if (m_bStopped) {
301 return;
302 }
303 }
304 }
RenderSingleObject(const CPDF_PageObject * pObj,const CFX_AffineMatrix * pObj2Device)305 void CPDF_RenderStatus::RenderSingleObject(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device)
306 {
307 if (m_Level > 32) {
308 return;
309 }
310 m_pCurObj = pObj;
311 if (m_Options.m_pOCContext && pObj->m_ContentMark.NotNull())
312 if (!m_Options.m_pOCContext->CheckObjectVisible(pObj)) {
313 return;
314 }
315 ProcessClipPath(pObj->m_ClipPath, pObj2Device);
316 if (ProcessTransparency(pObj, pObj2Device)) {
317 return;
318 }
319 ProcessObjectNoClip(pObj, pObj2Device);
320 }
ContinueSingleObject(const CPDF_PageObject * pObj,const CFX_AffineMatrix * pObj2Device,IFX_Pause * pPause)321 FX_BOOL CPDF_RenderStatus::ContinueSingleObject(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, IFX_Pause* pPause)
322 {
323 if (m_pObjectRenderer) {
324 if (m_pObjectRenderer->Continue(pPause)) {
325 return TRUE;
326 }
327 if (!m_pObjectRenderer->m_Result) {
328 DrawObjWithBackground(pObj, pObj2Device);
329 }
330 #ifdef _FPDFAPI_MINI_
331 if (m_DitherBits) {
332 DitherObjectArea(pObj, pObj2Device);
333 }
334 #endif
335 delete m_pObjectRenderer;
336 m_pObjectRenderer = NULL;
337 return FALSE;
338 }
339 m_pCurObj = pObj;
340 if (m_Options.m_pOCContext && pObj->m_ContentMark.NotNull())
341 if (!m_Options.m_pOCContext->CheckObjectVisible(pObj)) {
342 return FALSE;
343 }
344 ProcessClipPath(pObj->m_ClipPath, pObj2Device);
345 if (ProcessTransparency(pObj, pObj2Device)) {
346 return FALSE;
347 }
348 if (pObj->m_Type == PDFPAGE_IMAGE) {
349 m_pObjectRenderer = IPDF_ObjectRenderer::Create(pObj->m_Type);
350 if (!m_pObjectRenderer->Start(this, pObj, pObj2Device, FALSE)) {
351 if (!m_pObjectRenderer->m_Result) {
352 DrawObjWithBackground(pObj, pObj2Device);
353 }
354 #ifdef _FPDFAPI_MINI_
355 if (m_DitherBits) {
356 DitherObjectArea(pObj, pObj2Device);
357 }
358 #endif
359 delete m_pObjectRenderer;
360 m_pObjectRenderer = NULL;
361 return FALSE;
362 }
363 return ContinueSingleObject(pObj, pObj2Device, pPause);
364 }
365 ProcessObjectNoClip(pObj, pObj2Device);
366 return FALSE;
367 }
Create(int type)368 IPDF_ObjectRenderer* IPDF_ObjectRenderer::Create(int type)
369 {
370 IPDF_ObjectRenderer* pRenderer = NULL;
371 if (type == PDFPAGE_IMAGE) {
372 pRenderer = FX_NEW CPDF_ImageRenderer;
373 }
374 return pRenderer;
375 }
GetObjectClippedRect(const CPDF_PageObject * pObj,const CFX_AffineMatrix * pObj2Device,FX_BOOL bLogical,FX_RECT & rect) const376 FX_BOOL CPDF_RenderStatus::GetObjectClippedRect(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bLogical, FX_RECT &rect) const
377 {
378 rect = pObj->GetBBox(pObj2Device);
379 FX_RECT rtClip = m_pDevice->GetClipBox();
380 if (!bLogical) {
381 CFX_Matrix dCTM = m_pDevice->GetCTM();
382 FX_FLOAT a = FXSYS_fabs(dCTM.a);
383 FX_FLOAT d = FXSYS_fabs(dCTM.d);
384 if (a != 1.0f || d != 1.0f) {
385 rect.right = rect.left + (FX_INT32)FXSYS_ceil((FX_FLOAT)rect.Width() * a);
386 rect.bottom = rect.top + (FX_INT32)FXSYS_ceil((FX_FLOAT)rect.Height() * d);
387 rtClip.right = rtClip.left + (FX_INT32)FXSYS_ceil((FX_FLOAT)rtClip.Width() * a);
388 rtClip.bottom = rtClip.top + (FX_INT32)FXSYS_ceil((FX_FLOAT)rtClip.Height() * d);
389 }
390 }
391 rect.Intersect(rtClip);
392 return rect.IsEmpty();
393 }
DitherObjectArea(const CPDF_PageObject * pObj,const CFX_AffineMatrix * pObj2Device)394 void CPDF_RenderStatus::DitherObjectArea(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device)
395 {
396 CFX_DIBitmap* pBitmap = m_pDevice->GetBitmap();
397 if (pBitmap == NULL) {
398 return;
399 }
400 FX_RECT rect;
401 if (GetObjectClippedRect(pObj, pObj2Device, FALSE, rect)) {
402 return;
403 }
404 if (m_DitherBits == 2) {
405 static FX_ARGB pal[4] = {0, 85, 170, 255};
406 pBitmap->DitherFS(pal, 4, &rect);
407 } else if (m_DitherBits == 3) {
408 static FX_ARGB pal[8] = {0, 36, 73, 109, 146, 182, 219, 255};
409 pBitmap->DitherFS(pal, 8, &rect);
410 } else if (m_DitherBits == 4) {
411 static FX_ARGB pal[16] = {0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255};
412 pBitmap->DitherFS(pal, 16, &rect);
413 }
414 }
ProcessObjectNoClip(const CPDF_PageObject * pObj,const CFX_AffineMatrix * pObj2Device)415 void CPDF_RenderStatus::ProcessObjectNoClip(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device)
416 {
417 FX_BOOL bRet = FALSE;
418 switch (pObj->m_Type) {
419 case PDFPAGE_TEXT:
420 bRet = ProcessText((CPDF_TextObject*)pObj, pObj2Device, NULL);
421 break;
422 case PDFPAGE_PATH:
423 bRet = ProcessPath((CPDF_PathObject*)pObj, pObj2Device);
424 break;
425 case PDFPAGE_IMAGE:
426 bRet = ProcessImage((CPDF_ImageObject*)pObj, pObj2Device);
427 break;
428 case PDFPAGE_SHADING:
429 bRet = ProcessShading((CPDF_ShadingObject*)pObj, pObj2Device);
430 break;
431 case PDFPAGE_FORM:
432 bRet = ProcessForm((CPDF_FormObject*)pObj, pObj2Device);
433 break;
434 #if defined(_FPDFAPI_MINI_)
435 case PDFPAGE_INLINES:
436 bRet = ProcessInlines((CPDF_InlineImages*)pObj, pObj2Device);
437 break;
438 #endif
439 }
440 if (!bRet) {
441 DrawObjWithBackground(pObj, pObj2Device);
442 }
443 }
DrawObjWithBlend(const CPDF_PageObject * pObj,const CFX_AffineMatrix * pObj2Device)444 FX_BOOL CPDF_RenderStatus::DrawObjWithBlend(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device)
445 {
446 FX_BOOL bRet = FALSE;
447 switch (pObj->m_Type) {
448 case PDFPAGE_PATH:
449 bRet = ProcessPath((CPDF_PathObject*)pObj, pObj2Device);
450 break;
451 case PDFPAGE_IMAGE:
452 bRet = ProcessImage((CPDF_ImageObject *)pObj, pObj2Device);
453 break;
454 case PDFPAGE_FORM:
455 bRet = ProcessForm((CPDF_FormObject*)pObj, pObj2Device);
456 break;
457 }
458 return bRet;
459 }
GetScaledMatrix(CFX_Matrix & matrix) const460 void CPDF_RenderStatus::GetScaledMatrix(CFX_Matrix &matrix) const
461 {
462 CFX_Matrix dCTM = m_pDevice->GetCTM();
463 matrix.a *= FXSYS_fabs(dCTM.a);
464 matrix.d *= FXSYS_fabs(dCTM.d);
465 }
DrawObjWithBackground(const CPDF_PageObject * pObj,const CFX_AffineMatrix * pObj2Device)466 void CPDF_RenderStatus::DrawObjWithBackground(const CPDF_PageObject* pObj, const CFX_AffineMatrix* pObj2Device)
467 {
468 #if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_)
469 FX_RECT rect;
470 if (GetObjectClippedRect(pObj, pObj2Device, FALSE, rect)) {
471 return;
472 }
473 int res = 300;
474 if (pObj->m_Type == PDFPAGE_IMAGE && m_pDevice->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
475 res = 0;
476 }
477 CPDF_ScaledRenderBuffer buffer;
478 if (!buffer.Initialize(m_pContext, m_pDevice, &rect, pObj, &m_Options, res)) {
479 return;
480 }
481 CFX_AffineMatrix matrix = *pObj2Device;
482 matrix.Concat(*buffer.GetMatrix());
483 GetScaledMatrix(matrix);
484 CPDF_Dictionary* pFormResource = NULL;
485 if (pObj->m_Type == PDFPAGE_FORM) {
486 CPDF_FormObject* pFormObj = (CPDF_FormObject*)pObj;
487 if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) {
488 pFormResource = pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources"));
489 }
490 }
491 CPDF_RenderStatus status;
492 status.Initialize(m_Level + 1, m_pContext, buffer.GetDevice(), buffer.GetMatrix(), NULL, NULL, NULL, &m_Options, m_Transparency, m_bDropObjects, pFormResource);
493 status.RenderSingleObject(pObj, &matrix);
494 buffer.OutputToDevice();
495 #endif
496 }
ProcessForm(CPDF_FormObject * pFormObj,const CFX_AffineMatrix * pObj2Device)497 FX_BOOL CPDF_RenderStatus::ProcessForm(CPDF_FormObject* pFormObj, const CFX_AffineMatrix* pObj2Device)
498 {
499 CPDF_Dictionary* pOC = pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("OC"));
500 if (pOC && m_Options.m_pOCContext && !m_Options.m_pOCContext->CheckOCGVisible(pOC)) {
501 return TRUE;
502 }
503 CFX_AffineMatrix matrix = pFormObj->m_FormMatrix;
504 matrix.Concat(*pObj2Device);
505 CPDF_Dictionary* pResources = NULL;
506 if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) {
507 pResources = pFormObj->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources"));
508 }
509 CPDF_RenderStatus status;
510 status.Initialize(m_Level + 1, m_pContext, m_pDevice, NULL, m_pStopObj,
511 this, pFormObj, &m_Options, m_Transparency, m_bDropObjects, pResources, TRUE);
512 status.m_curBlend = m_curBlend;
513 m_pDevice->SaveState();
514 status.RenderObjectList(pFormObj->m_pForm, &matrix);
515 m_bStopped = status.m_bStopped;
516 m_pDevice->RestoreState();
517 return TRUE;
518 }
IsAvailableMatrix(const CFX_AffineMatrix & matrix)519 FX_BOOL IsAvailableMatrix(const CFX_AffineMatrix& matrix)
520 {
521 if (matrix.a == 0 || matrix.d == 0) {
522 return matrix.b != 0 && matrix.c != 0;
523 }
524 if (matrix.b == 0 || matrix.c == 0) {
525 return matrix.a != 0 && matrix.d != 0;
526 }
527 return TRUE;
528 }
ProcessPath(CPDF_PathObject * pPathObj,const CFX_AffineMatrix * pObj2Device)529 FX_BOOL CPDF_RenderStatus::ProcessPath(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device)
530 {
531 int FillType = pPathObj->m_FillType;
532 FX_BOOL bStroke = pPathObj->m_bStroke;
533 ProcessPathPattern(pPathObj, pObj2Device, FillType, bStroke);
534 if (FillType == 0 && !bStroke) {
535 return TRUE;
536 }
537 FX_DWORD fill_argb = 0;
538 if (FillType) {
539 fill_argb = GetFillArgb(pPathObj);
540 }
541 FX_DWORD stroke_argb = 0;
542 if (bStroke) {
543 stroke_argb = GetStrokeArgb(pPathObj);
544 }
545 CFX_AffineMatrix path_matrix = pPathObj->m_Matrix;
546 path_matrix.Concat(*pObj2Device);
547 if (!IsAvailableMatrix(path_matrix)) {
548 return TRUE;
549 }
550 if (FillType && (m_Options.m_Flags & RENDER_RECT_AA)) {
551 FillType |= FXFILL_RECT_AA;
552 }
553 if (m_Options.m_Flags & RENDER_FILL_FULLCOVER) {
554 FillType |= FXFILL_FULLCOVER;
555 }
556 if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) {
557 FillType |= FXFILL_NOPATHSMOOTH;
558 }
559 if (bStroke) {
560 FillType |= FX_FILL_STROKE;
561 }
562 #if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_)
563 const CPDF_GeneralStateData* pGeneralData = ((CPDF_PageObject*)pPathObj)->m_GeneralState;
564 if (pGeneralData && pGeneralData->m_StrokeAdjust) {
565 FillType |= FX_STROKE_ADJUST;
566 }
567 #endif
568 if (m_pType3Char) {
569 FillType |= FX_FILL_TEXT_MODE;
570 }
571 CFX_GraphStateData graphState(*pPathObj->m_GraphState);
572 if (m_Options.m_Flags & RENDER_THINLINE) {
573 graphState.m_LineWidth = 0;
574 }
575 return m_pDevice->DrawPath(pPathObj->m_Path, &path_matrix, &graphState, fill_argb, stroke_argb, FillType, 0, NULL, m_curBlend);
576 }
GetTransferFunc(CPDF_Object * pObj) const577 CPDF_TransferFunc* CPDF_RenderStatus::GetTransferFunc(CPDF_Object* pObj) const
578 {
579 ASSERT(pObj != NULL);
580 CPDF_DocRenderData* pDocCache = m_pContext->m_pDocument->GetRenderData();
581 if (!pDocCache) {
582 return NULL;
583 }
584 return pDocCache->GetTransferFunc(pObj);
585 }
GetFillArgb(const CPDF_PageObject * pObj,FX_BOOL bType3) const586 FX_ARGB CPDF_RenderStatus::GetFillArgb(const CPDF_PageObject* pObj, FX_BOOL bType3) const
587 {
588 CPDF_ColorStateData* pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)pObj->m_ColorState;
589 if (m_pType3Char && !bType3 && (!m_pType3Char->m_bColored || (m_pType3Char->m_bColored && (!pColorData || pColorData->m_FillColor.IsNull())))) {
590 return m_T3FillColor;
591 } else if (!pColorData || pColorData->m_FillColor.IsNull()) {
592 pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)m_InitialStates.m_ColorState;
593 }
594 FX_COLORREF rgb = pColorData->m_FillRGB;
595 if (rgb == (FX_DWORD) - 1) {
596 return 0;
597 }
598 const CPDF_GeneralStateData* pGeneralData = pObj->m_GeneralState;
599 int alpha;
600 if (pGeneralData) {
601 alpha = (FX_INT32)(pGeneralData->m_FillAlpha * 255);
602 #ifndef _FPDFAPI_MINI_
603 if (pGeneralData->m_pTR) {
604 if (!pGeneralData->m_pTransferFunc) {
605 ((CPDF_GeneralStateData*)pGeneralData)->m_pTransferFunc = GetTransferFunc(pGeneralData->m_pTR);
606 }
607 if (pGeneralData->m_pTransferFunc) {
608 rgb = pGeneralData->m_pTransferFunc->TranslateColor(rgb);
609 }
610 }
611 #endif
612 } else {
613 alpha = 255;
614 }
615 return m_Options.TranslateColor(ArgbEncode(alpha, rgb));
616 }
GetStrokeArgb(const CPDF_PageObject * pObj) const617 FX_ARGB CPDF_RenderStatus::GetStrokeArgb(const CPDF_PageObject* pObj) const
618 {
619 CPDF_ColorStateData* pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)pObj->m_ColorState;
620 if (m_pType3Char && (!m_pType3Char->m_bColored || (m_pType3Char->m_bColored && (!pColorData || pColorData->m_StrokeColor.IsNull())))) {
621 return m_T3FillColor;
622 } else if (!pColorData || pColorData->m_StrokeColor.IsNull()) {
623 pColorData = (CPDF_ColorStateData*)(const CPDF_ColorStateData*)m_InitialStates.m_ColorState;
624 }
625 FX_COLORREF rgb = pColorData->m_StrokeRGB;
626 if (rgb == (FX_DWORD) - 1) {
627 return 0;
628 }
629 const CPDF_GeneralStateData* pGeneralData = pObj->m_GeneralState;
630 int alpha;
631 if (pGeneralData) {
632 alpha = (FX_INT32)(pGeneralData->m_StrokeAlpha * 255);
633 #ifndef _FPDFAPI_MINI_
634 if (pGeneralData->m_pTR) {
635 if (!pGeneralData->m_pTransferFunc) {
636 ((CPDF_GeneralStateData*)pGeneralData)->m_pTransferFunc = GetTransferFunc(pGeneralData->m_pTR);
637 }
638 if (pGeneralData->m_pTransferFunc) {
639 rgb = pGeneralData->m_pTransferFunc->TranslateColor(rgb);
640 }
641 }
642 #endif
643 } else {
644 alpha = 255;
645 }
646 return m_Options.TranslateColor(ArgbEncode(alpha, rgb));
647 }
ProcessClipPath(CPDF_ClipPath ClipPath,const CFX_AffineMatrix * pObj2Device)648 void CPDF_RenderStatus::ProcessClipPath(CPDF_ClipPath ClipPath, const CFX_AffineMatrix* pObj2Device)
649 {
650 if (ClipPath.IsNull()) {
651 if (m_LastClipPath.IsNull()) {
652 return;
653 }
654 m_pDevice->RestoreState(TRUE);
655 m_LastClipPath.SetNull();
656 return;
657 }
658 if (m_LastClipPath == ClipPath) {
659 return;
660 }
661 m_LastClipPath = ClipPath;
662 m_pDevice->RestoreState(TRUE);
663 int nClipPath = ClipPath.GetPathCount();
664 int i;
665 for (i = 0; i < nClipPath; i++) {
666 const CFX_PathData* pPathData = ClipPath.GetPath(i);
667 if (pPathData == NULL) {
668 continue;
669 }
670 if (pPathData->GetPointCount() == 0) {
671 CFX_PathData EmptyPath;
672 EmptyPath.AppendRect(-1, -1, 0, 0);
673 int fill_mode = FXFILL_WINDING;
674 m_pDevice->SetClip_PathFill(&EmptyPath, NULL, fill_mode);
675 } else {
676 int ClipType = ClipPath.GetClipType(i);
677 m_pDevice->SetClip_PathFill(pPathData, pObj2Device, ClipType);
678 }
679 }
680 int textcount = ClipPath.GetTextCount();
681 if (textcount == 0) {
682 return;
683 }
684 if (m_pDevice->GetDeviceClass() == FXDC_DISPLAY && !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP)) {
685 return;
686 }
687 CFX_PathData* pTextClippingPath = NULL;
688 for (i = 0; i < textcount; i ++) {
689 CPDF_TextObject* pText = ClipPath.GetText(i);
690 if (pText == NULL) {
691 if (pTextClippingPath) {
692 int fill_mode = FXFILL_WINDING;
693 if (m_Options.m_Flags & RENDER_NOTEXTSMOOTH) {
694 fill_mode |= FXFILL_NOPATHSMOOTH;
695 }
696 m_pDevice->SetClip_PathFill(pTextClippingPath, NULL, fill_mode);
697 delete pTextClippingPath;
698 pTextClippingPath = NULL;
699 }
700 } else {
701 if (pTextClippingPath == NULL) {
702 pTextClippingPath = FX_NEW CFX_PathData;
703 }
704 ProcessText(pText, pObj2Device, pTextClippingPath);
705 }
706 }
707 if (pTextClippingPath) {
708 delete pTextClippingPath;
709 }
710 }
DrawClipPath(CPDF_ClipPath ClipPath,const CFX_AffineMatrix * pObj2Device)711 void CPDF_RenderStatus::DrawClipPath(CPDF_ClipPath ClipPath, const CFX_AffineMatrix* pObj2Device)
712 {
713 if (ClipPath.IsNull()) {
714 return;
715 }
716 int fill_mode = 0;
717 if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) {
718 fill_mode |= FXFILL_NOPATHSMOOTH;
719 }
720 int nClipPath = ClipPath.GetPathCount();
721 int i;
722 for (i = 0; i < nClipPath; i++) {
723 const CFX_PathData* pPathData = ClipPath.GetPath(i);
724 if (pPathData == NULL) {
725 continue;
726 }
727 CFX_GraphStateData stroke_state;
728 if (m_Options.m_Flags & RENDER_THINLINE) {
729 stroke_state.m_LineWidth = 0;
730 }
731 m_pDevice->DrawPath(pPathData, pObj2Device, &stroke_state, 0, 0xffff0000, fill_mode);
732 }
733 }
SelectClipPath(CPDF_PathObject * pPathObj,const CFX_AffineMatrix * pObj2Device,FX_BOOL bStroke)734 FX_BOOL CPDF_RenderStatus::SelectClipPath(CPDF_PathObject* pPathObj, const CFX_AffineMatrix* pObj2Device, FX_BOOL bStroke)
735 {
736 CFX_AffineMatrix path_matrix = pPathObj->m_Matrix;
737 path_matrix.Concat(*pObj2Device);
738 if (bStroke) {
739 CFX_GraphStateData graphState(*pPathObj->m_GraphState);
740 if (m_Options.m_Flags & RENDER_THINLINE) {
741 graphState.m_LineWidth = 0;
742 }
743 return m_pDevice->SetClip_PathStroke(pPathObj->m_Path, &path_matrix, &graphState);
744 }
745 int fill_mode = pPathObj->m_FillType;
746 if (m_Options.m_Flags & RENDER_NOPATHSMOOTH) {
747 fill_mode |= FXFILL_NOPATHSMOOTH;
748 }
749 return m_pDevice->SetClip_PathFill(pPathObj->m_Path, &path_matrix, fill_mode);
750 }
ProcessTransparency(const CPDF_PageObject * pPageObj,const CFX_AffineMatrix * pObj2Device)751 FX_BOOL CPDF_RenderStatus::ProcessTransparency(const CPDF_PageObject* pPageObj, const CFX_AffineMatrix* pObj2Device)
752 {
753 const CPDF_GeneralStateData* pGeneralState = pPageObj->m_GeneralState;
754 int blend_type = pGeneralState ? pGeneralState->m_BlendType : FXDIB_BLEND_NORMAL;
755 if (blend_type == FXDIB_BLEND_UNSUPPORTED) {
756 return TRUE;
757 }
758 CPDF_Dictionary* pSMaskDict = pGeneralState ? (CPDF_Dictionary*)pGeneralState->m_pSoftMask : NULL;
759 if (pSMaskDict) {
760 if (pPageObj->m_Type == PDFPAGE_IMAGE &&
761 ((CPDF_ImageObject*)pPageObj)->m_pImage->GetDict()->KeyExist(FX_BSTRC("SMask"))) {
762 pSMaskDict = NULL;
763 }
764 }
765 CPDF_Dictionary* pFormResource = NULL;
766 FX_FLOAT group_alpha = 1.0f;
767 int Transparency = m_Transparency;
768 FX_BOOL bGroupTransparent = FALSE;
769 if (pPageObj->m_Type == PDFPAGE_FORM) {
770 CPDF_FormObject* pFormObj = (CPDF_FormObject*)pPageObj;
771 const CPDF_GeneralStateData *pStateData = pFormObj->m_GeneralState.GetObject();
772 if (pStateData) {
773 group_alpha = pStateData->m_FillAlpha;
774 }
775 Transparency = pFormObj->m_pForm->m_Transparency;
776 bGroupTransparent = Transparency & PDFTRANS_ISOLATED ? TRUE : FALSE;
777 if (pFormObj->m_pForm->m_pFormDict) {
778 pFormResource = pFormObj->m_pForm->m_pFormDict->GetDict("Resources");
779 }
780 }
781 FX_BOOL bTextClip = FALSE;
782 if (pPageObj->m_ClipPath.NotNull() && pPageObj->m_ClipPath.GetTextCount() &&
783 m_pDevice->GetDeviceClass() == FXDC_DISPLAY && !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP)) {
784 bTextClip = TRUE;
785 }
786 if ((m_Options.m_Flags & RENDER_OVERPRINT) && pPageObj->m_Type == PDFPAGE_IMAGE && pGeneralState && pGeneralState->m_FillOP && pGeneralState->m_StrokeOP) {
787 CPDF_Document* pDocument = NULL;
788 CPDF_Page* pPage = NULL;
789 if (m_pContext->m_pPageCache) {
790 pPage = m_pContext->m_pPageCache->GetPage();
791 pDocument = pPage->m_pDocument;
792 } else {
793 pDocument = ((CPDF_ImageObject*)pPageObj)->m_pImage->GetDocument();
794 }
795 CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : NULL;
796 CPDF_Object* pCSObj = ((CPDF_ImageObject*)pPageObj)->m_pImage->GetStream()->GetDict()->GetElementValue(FX_BSTRC("ColorSpace"));
797 CPDF_ColorSpace* pColorSpace = pDocument->LoadColorSpace(pCSObj, pPageResources);
798 if (pColorSpace) {
799 int format = pColorSpace->GetFamily();
800 if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION || format == PDFCS_DEVICEN) {
801 blend_type = FXDIB_BLEND_DARKEN;
802 }
803 pDocument->GetPageData()->ReleaseColorSpace(pCSObj);
804 }
805 }
806 if (pSMaskDict == NULL && group_alpha == 1.0f && blend_type == FXDIB_BLEND_NORMAL && !bTextClip && !bGroupTransparent) {
807 return FALSE;
808 }
809 FX_BOOL isolated = Transparency & PDFTRANS_ISOLATED;
810 if (m_bPrint) {
811 FX_BOOL bRet = FALSE;
812 int rendCaps = m_pDevice->GetRenderCaps();
813 if (!((Transparency & PDFTRANS_ISOLATED) || pSMaskDict || bTextClip) && (rendCaps & FXRC_BLEND_MODE)) {
814 int oldBlend = m_curBlend;
815 m_curBlend = blend_type;
816 bRet = DrawObjWithBlend(pPageObj, pObj2Device);
817 m_curBlend = oldBlend;
818 }
819 if (!bRet) {
820 DrawObjWithBackground(pPageObj, pObj2Device);
821 }
822 return TRUE;
823 }
824 FX_RECT rect = pPageObj->GetBBox(pObj2Device);
825 rect.Intersect(m_pDevice->GetClipBox());
826 if (rect.IsEmpty()) {
827 return TRUE;
828 }
829 CFX_Matrix deviceCTM = m_pDevice->GetCTM();
830 FX_FLOAT scaleX = FXSYS_abs(deviceCTM.a);
831 FX_FLOAT scaleY = FXSYS_abs(deviceCTM.d);
832 int width = FXSYS_round((FX_FLOAT)rect.Width() * scaleX);
833 int height = FXSYS_round((FX_FLOAT)rect.Height() * scaleY);
834 CFX_FxgeDevice bitmap_device;
835 CFX_DIBitmap* oriDevice = NULL;
836 if (!isolated && (m_pDevice->GetRenderCaps() & FXRC_GET_BITS)) {
837 oriDevice = FX_NEW CFX_DIBitmap;
838 if (!m_pDevice->CreateCompatibleBitmap(oriDevice, width, height)) {
839 return TRUE;
840 }
841 m_pDevice->GetDIBits(oriDevice, rect.left, rect.top);
842 }
843 if (!bitmap_device.Create(width, height, FXDIB_Argb, 0, oriDevice)) {
844 return TRUE;
845 }
846 CFX_DIBitmap* bitmap = bitmap_device.GetBitmap();
847 bitmap->Clear(0);
848 CFX_AffineMatrix new_matrix = *pObj2Device;
849 new_matrix.TranslateI(-rect.left, -rect.top);
850 new_matrix.Scale(scaleX, scaleY);
851 CFX_DIBitmap* pTextMask = NULL;
852 if (bTextClip) {
853 pTextMask = FX_NEW CFX_DIBitmap;
854 if (!pTextMask->Create(width, height, FXDIB_8bppMask)) {
855 delete pTextMask;
856 return TRUE;
857 }
858 pTextMask->Clear(0);
859 CFX_FxgeDevice text_device;
860 text_device.Attach(pTextMask);
861 for (FX_DWORD i = 0; i < pPageObj->m_ClipPath.GetTextCount(); i ++) {
862 CPDF_TextObject* textobj = pPageObj->m_ClipPath.GetText(i);
863 if (textobj == NULL) {
864 break;
865 }
866 CFX_AffineMatrix text_matrix;
867 textobj->GetTextMatrix(&text_matrix);
868 CPDF_TextRenderer::DrawTextPath(&text_device, textobj->m_nChars, textobj->m_pCharCodes, textobj->m_pCharPos,
869 textobj->m_TextState.GetFont(), textobj->m_TextState.GetFontSize(),
870 &text_matrix, &new_matrix, textobj->m_GraphState, (FX_ARGB) - 1, 0, NULL);
871 }
872 }
873 CPDF_RenderStatus bitmap_render;
874 bitmap_render.Initialize(m_Level + 1, m_pContext, &bitmap_device, NULL,
875 m_pStopObj, NULL, NULL, &m_Options, 0, m_bDropObjects, pFormResource, TRUE);
876 bitmap_render.ProcessObjectNoClip(pPageObj, &new_matrix);
877 m_bStopped = bitmap_render.m_bStopped;
878 if (pSMaskDict) {
879 CFX_AffineMatrix smask_matrix;
880 FXSYS_memcpy32(&smask_matrix, pGeneralState->m_SMaskMatrix, sizeof smask_matrix);
881 smask_matrix.Concat(*pObj2Device);
882 CFX_DIBSource* pSMaskSource = LoadSMask(pSMaskDict, &rect, &smask_matrix);
883 if (pSMaskSource) {
884 bitmap->MultiplyAlpha(pSMaskSource);
885 delete pSMaskSource;
886 }
887 }
888 if (pTextMask) {
889 bitmap->MultiplyAlpha(pTextMask);
890 delete pTextMask;
891 pTextMask = NULL;
892 }
893 if (Transparency & PDFTRANS_GROUP && group_alpha != 1.0f) {
894 bitmap->MultiplyAlpha((FX_INT32)(group_alpha * 255));
895 }
896 Transparency = m_Transparency;
897 if (pPageObj->m_Type == PDFPAGE_FORM) {
898 Transparency |= PDFTRANS_GROUP;
899 }
900 CompositeDIBitmap(bitmap, rect.left, rect.top, 0, 255, blend_type, Transparency);
901 if (oriDevice) {
902 delete oriDevice;
903 }
904 return TRUE;
905 }
GetBackdrop(const CPDF_PageObject * pObj,const FX_RECT & rect,int & left,int & top,FX_BOOL bBackAlphaRequired)906 CFX_DIBitmap* CPDF_RenderStatus::GetBackdrop(const CPDF_PageObject* pObj, const FX_RECT& rect, int& left, int& top,
907 FX_BOOL bBackAlphaRequired)
908 {
909 FX_RECT bbox = rect;
910 bbox.Intersect(m_pDevice->GetClipBox());
911 left = bbox.left;
912 top = bbox.top;
913 CFX_Matrix deviceCTM = m_pDevice->GetCTM();
914 FX_FLOAT scaleX = FXSYS_abs(deviceCTM.a);
915 FX_FLOAT scaleY = FXSYS_abs(deviceCTM.d);
916 int width = FXSYS_round(bbox.Width() * scaleX);
917 int height = FXSYS_round(bbox.Height() * scaleY);
918 CFX_DIBitmap* pBackdrop = FX_NEW CFX_DIBitmap;
919 if (bBackAlphaRequired && !m_bDropObjects) {
920 pBackdrop->Create(width, height, FXDIB_Argb);
921 } else {
922 m_pDevice->CreateCompatibleBitmap(pBackdrop, width, height);
923 }
924 if (pBackdrop->GetBuffer() == NULL) {
925 delete pBackdrop;
926 return NULL;
927 }
928 FX_BOOL bNeedDraw;
929 if (pBackdrop->HasAlpha()) {
930 bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT);
931 } else {
932 bNeedDraw = !(m_pDevice->GetRenderCaps() & FXRC_GET_BITS);
933 }
934 if (!bNeedDraw) {
935 m_pDevice->GetDIBits(pBackdrop, left, top);
936 return pBackdrop;
937 }
938 CFX_AffineMatrix FinalMatrix = m_DeviceMatrix;
939 FinalMatrix.TranslateI(-left, -top);
940 FinalMatrix.Scale(scaleX, scaleY);
941 pBackdrop->Clear(pBackdrop->HasAlpha() ? 0 : 0xffffffff);
942 CFX_FxgeDevice device;
943 device.Attach(pBackdrop);
944 m_pContext->Render(&device, pObj, &m_Options, &FinalMatrix);
945 return pBackdrop;
946 }
GetBackground(CFX_DIBitmap * pBuffer,const CPDF_PageObject * pObj,const CPDF_RenderOptions * pOptions,CFX_AffineMatrix * pFinalMatrix)947 void CPDF_RenderContext::GetBackground(CFX_DIBitmap* pBuffer, const CPDF_PageObject* pObj,
948 const CPDF_RenderOptions* pOptions, CFX_AffineMatrix* pFinalMatrix)
949 {
950 CFX_FxgeDevice device;
951 device.Attach(pBuffer);
952 if (m_pBackgroundDraw) {
953 m_pBackgroundDraw->OnDrawBackground(&device, pFinalMatrix);
954 } else {
955 FX_RECT rect(0, 0, device.GetWidth(), device.GetHeight());
956 device.FillRect(&rect, 0xffffffff);
957 }
958 Render(&device, pObj, pOptions, pFinalMatrix);
959 }
CloneObjStates(const CPDF_GraphicStates * pSrcStates,FX_BOOL bStroke)960 CPDF_GraphicStates* CPDF_RenderStatus::CloneObjStates(const CPDF_GraphicStates* pSrcStates, FX_BOOL bStroke)
961 {
962 if (!pSrcStates) {
963 return NULL;
964 }
965 CPDF_GraphicStates* pStates = FX_NEW CPDF_GraphicStates;
966 if (!pStates) {
967 return NULL;
968 }
969 pStates->CopyStates(*pSrcStates);
970 CPDF_Color* pObjColor = bStroke ? pSrcStates->m_ColorState.GetStrokeColor() :
971 pSrcStates->m_ColorState.GetFillColor();
972 if (!pObjColor->IsNull()) {
973 CPDF_ColorStateData* pColorData = pStates->m_ColorState.GetModify();
974 pColorData->m_FillRGB = bStroke ? pSrcStates->m_ColorState.GetObject()->m_StrokeRGB :
975 pSrcStates->m_ColorState.GetObject()->m_FillRGB;
976 pColorData->m_StrokeRGB = pColorData->m_FillRGB;
977 }
978 return pStates;
979 }
CPDF_RenderContext()980 CPDF_RenderContext::CPDF_RenderContext()
981 {
982 }
Create(CPDF_Document * pDoc,CPDF_PageRenderCache * pPageCache,CPDF_Dictionary * pPageResources,FX_BOOL bFirstLayer)983 void CPDF_RenderContext::Create(CPDF_Document* pDoc, CPDF_PageRenderCache* pPageCache,
984 CPDF_Dictionary* pPageResources, FX_BOOL bFirstLayer)
985 {
986 m_pBackgroundDraw = NULL;
987 m_pDocument = pDoc;
988 m_pPageResources = pPageResources;
989 m_pPageCache = pPageCache;
990 m_bFirstLayer = bFirstLayer;
991 }
Create(CPDF_Page * pPage,FX_BOOL bFirstLayer)992 void CPDF_RenderContext::Create(CPDF_Page* pPage, FX_BOOL bFirstLayer)
993 {
994 m_pBackgroundDraw = NULL;
995 m_pDocument = pPage->m_pDocument;
996 m_pPageResources = pPage->m_pPageResources;
997 m_pPageCache = pPage->GetRenderCache();
998 m_bFirstLayer = bFirstLayer;
999 }
~CPDF_RenderContext()1000 CPDF_RenderContext::~CPDF_RenderContext()
1001 {
1002 }
Clear()1003 void CPDF_RenderContext::Clear()
1004 {
1005 m_pDocument = NULL;
1006 m_pPageResources = NULL;
1007 m_pPageCache = NULL;
1008 m_pBackgroundDraw = NULL;
1009 m_bFirstLayer = TRUE;
1010 m_ContentList.RemoveAll();
1011 }
AppendObjectList(CPDF_PageObjects * pObjs,const CFX_AffineMatrix * pObject2Device)1012 void CPDF_RenderContext::AppendObjectList(CPDF_PageObjects* pObjs, const CFX_AffineMatrix* pObject2Device)
1013 {
1014 _PDF_RenderItem* pItem = m_ContentList.AddSpace();
1015 pItem->m_pObjectList = pObjs;
1016 if (pObject2Device) {
1017 pItem->m_Matrix = *pObject2Device;
1018 } else {
1019 pItem->m_Matrix.SetIdentity();
1020 }
1021 }
Render(CFX_RenderDevice * pDevice,const CPDF_RenderOptions * pOptions,const CFX_AffineMatrix * pLastMatrix)1022 void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice, const CPDF_RenderOptions* pOptions,
1023 const CFX_AffineMatrix* pLastMatrix)
1024 {
1025 Render(pDevice, NULL, pOptions, pLastMatrix);
1026 }
Render(CFX_RenderDevice * pDevice,const CPDF_PageObject * pStopObj,const CPDF_RenderOptions * pOptions,const CFX_AffineMatrix * pLastMatrix)1027 void CPDF_RenderContext::Render(CFX_RenderDevice* pDevice, const CPDF_PageObject* pStopObj,
1028 const CPDF_RenderOptions* pOptions, const CFX_AffineMatrix* pLastMatrix)
1029 {
1030 int count = m_ContentList.GetSize();
1031 for (int j = 0; j < count; j ++) {
1032 pDevice->SaveState();
1033 _PDF_RenderItem* pItem = m_ContentList.GetDataPtr(j);
1034 if (pLastMatrix) {
1035 CFX_AffineMatrix FinalMatrix = pItem->m_Matrix;
1036 FinalMatrix.Concat(*pLastMatrix);
1037 CPDF_RenderStatus status;
1038 status.Initialize(0, this, pDevice, pLastMatrix, pStopObj, NULL, NULL, pOptions,
1039 pItem->m_pObjectList->m_Transparency, FALSE, NULL);
1040 status.RenderObjectList(pItem->m_pObjectList, &FinalMatrix);
1041 #if !defined(_FPDFAPI_MINI_)
1042 if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
1043 m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize);
1044 }
1045 #endif
1046 if (status.m_bStopped) {
1047 pDevice->RestoreState();
1048 break;
1049 }
1050 } else {
1051 CPDF_RenderStatus status;
1052 status.Initialize(0, this, pDevice, NULL, pStopObj, NULL, NULL, pOptions,
1053 pItem->m_pObjectList->m_Transparency, FALSE, NULL);
1054 status.RenderObjectList(pItem->m_pObjectList, &pItem->m_Matrix);
1055 #if !defined(_FPDFAPI_MINI_)
1056 if (status.m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
1057 m_pPageCache->CacheOptimization(status.m_Options.m_dwLimitCacheSize);
1058 }
1059 #endif
1060 if (status.m_bStopped) {
1061 pDevice->RestoreState();
1062 break;
1063 }
1064 }
1065 pDevice->RestoreState();
1066 }
1067 }
DrawObjectList(CFX_RenderDevice * pDevice,CPDF_PageObjects * pObjs,const CFX_AffineMatrix * pObject2Device,const CPDF_RenderOptions * pOptions)1068 void CPDF_RenderContext::DrawObjectList(CFX_RenderDevice* pDevice, CPDF_PageObjects* pObjs,
1069 const CFX_AffineMatrix* pObject2Device, const CPDF_RenderOptions* pOptions)
1070 {
1071 AppendObjectList(pObjs, pObject2Device);
1072 Render(pDevice, pOptions);
1073 }
CPDF_ProgressiveRenderer()1074 CPDF_ProgressiveRenderer::CPDF_ProgressiveRenderer()
1075 {
1076 m_pRenderer = NULL;
1077 m_pContext = NULL;
1078 m_pDevice = NULL;
1079 m_Status = Ready;
1080 }
~CPDF_ProgressiveRenderer()1081 CPDF_ProgressiveRenderer::~CPDF_ProgressiveRenderer()
1082 {
1083 Clear();
1084 }
Clear()1085 void CPDF_ProgressiveRenderer::Clear()
1086 {
1087 if (m_pRenderer) {
1088 delete m_pRenderer;
1089 m_pDevice->RestoreState();
1090 m_pRenderer = NULL;
1091 }
1092 m_Status = Ready;
1093 }
Start(CPDF_RenderContext * pContext,CFX_RenderDevice * pDevice,const CPDF_RenderOptions * pOptions,IFX_Pause * pPause,FX_BOOL bDropObjects)1094 void CPDF_ProgressiveRenderer::Start(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice,
1095 const CPDF_RenderOptions* pOptions, IFX_Pause* pPause, FX_BOOL bDropObjects)
1096 {
1097 if (m_Status != Ready) {
1098 m_Status = Failed;
1099 return;
1100 }
1101 m_pContext = pContext;
1102 m_pDevice = pDevice;
1103 m_pOptions = pOptions;
1104 m_bDropObjects = bDropObjects;
1105 if (pContext == NULL || pDevice == NULL) {
1106 m_Status = Failed;
1107 return;
1108 }
1109 m_Status = ToBeContinued;
1110 m_ObjectPos = NULL;
1111 m_LayerIndex = 0;
1112 m_ObjectIndex = 0;
1113 m_PrevLastPos = NULL;
1114 Continue(pPause);
1115 }
1116 #ifdef _FPDFAPI_MINI_
1117 #define RENDER_STEP_LIMIT 20
1118 #else
1119 #define RENDER_STEP_LIMIT 100
1120 #endif
Continue(IFX_Pause * pPause)1121 void CPDF_ProgressiveRenderer::Continue(IFX_Pause* pPause)
1122 {
1123 if (m_Status != ToBeContinued) {
1124 return;
1125 }
1126 FX_DWORD nLayers = m_pContext->m_ContentList.GetSize();
1127 for (; m_LayerIndex < nLayers; m_LayerIndex ++) {
1128 _PDF_RenderItem* pItem = m_pContext->m_ContentList.GetDataPtr(m_LayerIndex);
1129 FX_POSITION LastPos = pItem->m_pObjectList->GetLastObjectPosition();
1130 if (m_ObjectPos == NULL) {
1131 if (LastPos == m_PrevLastPos) {
1132 if (!pItem->m_pObjectList->IsParsed()) {
1133 pItem->m_pObjectList->ContinueParse(pPause);
1134 if (!pItem->m_pObjectList->IsParsed()) {
1135 return;
1136 }
1137 LastPos = pItem->m_pObjectList->GetLastObjectPosition();
1138 }
1139 }
1140 if (LastPos == m_PrevLastPos) {
1141 if (m_pRenderer) {
1142 delete m_pRenderer;
1143 m_pRenderer = NULL;
1144 m_pDevice->RestoreState();
1145 m_ObjectPos = NULL;
1146 m_PrevLastPos = NULL;
1147 }
1148 continue;
1149 }
1150 if (m_PrevLastPos) {
1151 m_ObjectPos = m_PrevLastPos;
1152 pItem->m_pObjectList->GetNextObject(m_ObjectPos);
1153 } else {
1154 m_ObjectPos = pItem->m_pObjectList->GetFirstObjectPosition();
1155 }
1156 m_PrevLastPos = LastPos;
1157 }
1158 if (m_pRenderer == NULL) {
1159 m_ObjectPos = pItem->m_pObjectList->GetFirstObjectPosition();
1160 m_ObjectIndex = 0;
1161 m_pRenderer = FX_NEW CPDF_RenderStatus();
1162 m_pRenderer->Initialize(0, m_pContext, m_pDevice, NULL, NULL, NULL, NULL,
1163 m_pOptions, pItem->m_pObjectList->m_Transparency, m_bDropObjects, NULL);
1164 m_pDevice->SaveState();
1165 m_ClipRect = m_pDevice->GetClipBox();
1166 CFX_AffineMatrix device2object;
1167 device2object.SetReverse(pItem->m_Matrix);
1168 device2object.TransformRect(m_ClipRect);
1169 }
1170 int objs_to_go = CPDF_ModuleMgr::Get()->GetRenderModule()->GetConfig()->m_RenderStepLimit;
1171 while (m_ObjectPos) {
1172 CPDF_PageObject* pCurObj = pItem->m_pObjectList->GetObjectAt(m_ObjectPos);
1173 if (pCurObj && pCurObj->m_Left <= m_ClipRect.right && pCurObj->m_Right >= m_ClipRect.left &&
1174 pCurObj->m_Bottom <= m_ClipRect.top && pCurObj->m_Top >= m_ClipRect.bottom) {
1175 if (m_pRenderer->ContinueSingleObject(pCurObj, &pItem->m_Matrix, pPause)) {
1176 return;
1177 }
1178 #if !defined(_FPDFAPI_MINI_)
1179 if (pCurObj->m_Type == PDFPAGE_IMAGE && m_pRenderer->m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
1180 m_pContext->GetPageCache()->CacheOptimization(m_pRenderer->m_Options.m_dwLimitCacheSize);
1181 }
1182 #endif
1183 if (pCurObj->m_Type == PDFPAGE_FORM || pCurObj->m_Type == PDFPAGE_SHADING) {
1184 objs_to_go = 0;
1185 } else {
1186 objs_to_go --;
1187 }
1188 }
1189 m_ObjectIndex ++;
1190 pItem->m_pObjectList->GetNextObject(m_ObjectPos);
1191 if (objs_to_go == 0) {
1192 if (pPause && pPause->NeedToPauseNow()) {
1193 return;
1194 }
1195 objs_to_go = CPDF_ModuleMgr::Get()->GetRenderModule()->GetConfig()->m_RenderStepLimit;
1196 }
1197 }
1198 if (!pItem->m_pObjectList->IsParsed()) {
1199 return;
1200 }
1201 delete m_pRenderer;
1202 m_pRenderer = NULL;
1203 m_pDevice->RestoreState();
1204 m_ObjectPos = NULL;
1205 m_PrevLastPos = NULL;
1206 if (pPause && pPause->NeedToPauseNow()) {
1207 m_LayerIndex++;
1208 return;
1209 }
1210 }
1211 m_Status = Done;
1212 }
EstimateProgress()1213 int CPDF_ProgressiveRenderer::EstimateProgress()
1214 {
1215 if (!m_pContext) {
1216 return 0;
1217 }
1218 FX_DWORD nLayers = m_pContext->m_ContentList.GetSize();
1219 int nTotal = 0, nRendered = 0;
1220 for (FX_DWORD layer = 0; layer < nLayers; layer ++) {
1221 _PDF_RenderItem* pItem = m_pContext->m_ContentList.GetDataPtr(layer);
1222 int nObjs = pItem->m_pObjectList->CountObjects();
1223 if (layer == m_LayerIndex) {
1224 nRendered += m_ObjectIndex;
1225 } else if (layer < m_LayerIndex) {
1226 nRendered += nObjs;
1227 }
1228 nTotal += nObjs;
1229 }
1230 if (nTotal == 0) {
1231 return 0;
1232 }
1233 return 100 * nRendered / nTotal;
1234 }
GetTransferFunc(CPDF_Object * pObj)1235 CPDF_TransferFunc* CPDF_DocRenderData::GetTransferFunc(CPDF_Object* pObj)
1236 {
1237 if (pObj == NULL) {
1238 return NULL;
1239 }
1240 CPDF_CountedObject<CPDF_TransferFunc*>* pTransferCounter;
1241 if (!m_TransferFuncMap.Lookup(pObj, pTransferCounter)) {
1242 CPDF_TransferFunc* pTransfer = NULL;
1243 CPDF_Function* pFuncs[3] = {NULL, NULL, NULL};
1244 FX_BOOL bUniTransfer = TRUE;
1245 int i;
1246 FX_BOOL bIdentity = TRUE;
1247 if (pObj->GetType() == PDFOBJ_ARRAY) {
1248 bUniTransfer = FALSE;
1249 CPDF_Array* pArray = (CPDF_Array*)pObj;
1250 if (pArray->GetCount() < 3) {
1251 return NULL;
1252 }
1253 for (FX_DWORD i = 0; i < 3; i ++) {
1254 pFuncs[2 - i] = CPDF_Function::Load(pArray->GetElementValue(i));
1255 if (pFuncs[2 - i] == NULL) {
1256 return NULL;
1257 }
1258 }
1259 } else {
1260 pFuncs[0] = CPDF_Function::Load(pObj);
1261 if (pFuncs[0] == NULL) {
1262 return NULL;
1263 }
1264 }
1265 pTransfer = FX_NEW CPDF_TransferFunc;
1266 pTransfer->m_pPDFDoc = m_pPDFDoc;
1267 pTransferCounter = FX_NEW CPDF_CountedObject<CPDF_TransferFunc*>;
1268 pTransferCounter->m_nCount = 1;
1269 pTransferCounter->m_Obj = pTransfer;
1270 m_TransferFuncMap.SetAt(pObj, pTransferCounter);
1271 static const int kMaxOutputs = 16;
1272 FX_FLOAT output[kMaxOutputs];
1273 FXSYS_memset32(output, 0, sizeof(output));
1274 FX_FLOAT input;
1275 int noutput;
1276 for (int v = 0; v < 256; v ++) {
1277 input = (FX_FLOAT)v / 255.0f;
1278 if (bUniTransfer) {
1279 if (pFuncs[0] && pFuncs[0]->CountOutputs() <= kMaxOutputs) {
1280 pFuncs[0]->Call(&input, 1, output, noutput);
1281 }
1282 int o = FXSYS_round(output[0] * 255);
1283 if (o != v) {
1284 bIdentity = FALSE;
1285 }
1286 for (i = 0; i < 3; i ++) {
1287 pTransfer->m_Samples[i * 256 + v] = o;
1288 }
1289 } else
1290 for (i = 0; i < 3; i ++) {
1291 if (pFuncs[i] && pFuncs[i]->CountOutputs() <= kMaxOutputs) {
1292 pFuncs[i]->Call(&input, 1, output, noutput);
1293 int o = FXSYS_round(output[0] * 255);
1294 if (o != v) {
1295 bIdentity = FALSE;
1296 }
1297 pTransfer->m_Samples[i * 256 + v] = o;
1298 } else {
1299 pTransfer->m_Samples[i * 256 + v] = v;
1300 }
1301 }
1302 }
1303 for (i = 0; i < 3; i ++)
1304 if (pFuncs[i]) {
1305 delete pFuncs[i];
1306 }
1307 pTransfer->m_bIdentity = bIdentity;
1308 }
1309 pTransferCounter->m_nCount++;
1310 return pTransferCounter->m_Obj;
1311 }
ReleaseTransferFunc(CPDF_Object * pObj)1312 void CPDF_DocRenderData::ReleaseTransferFunc(CPDF_Object* pObj)
1313 {
1314 CPDF_CountedObject<CPDF_TransferFunc*>* pTransferCounter;
1315 if (!m_TransferFuncMap.Lookup(pObj, pTransferCounter)) {
1316 return;
1317 }
1318 pTransferCounter->m_nCount--;
1319 }
CPDF_RenderConfig()1320 CPDF_RenderConfig::CPDF_RenderConfig()
1321 {
1322 m_HalftoneLimit = 0;
1323 #ifdef _FPDFAPI_MINI_
1324 m_RenderStepLimit = 20;
1325 #else
1326 m_RenderStepLimit = 100;
1327 #endif
1328 }
~CPDF_RenderConfig()1329 CPDF_RenderConfig::~CPDF_RenderConfig()
1330 {
1331 }
CPDF_DeviceBuffer()1332 CPDF_DeviceBuffer::CPDF_DeviceBuffer()
1333 {
1334 m_pBitmap = NULL;
1335 m_pDevice = NULL;
1336 m_pContext = NULL;
1337 m_pObject = NULL;
1338 }
~CPDF_DeviceBuffer()1339 CPDF_DeviceBuffer::~CPDF_DeviceBuffer()
1340 {
1341 if (m_pBitmap) {
1342 delete m_pBitmap;
1343 }
1344 }
Initialize(CPDF_RenderContext * pContext,CFX_RenderDevice * pDevice,FX_RECT * pRect,const CPDF_PageObject * pObj,int max_dpi)1345 FX_BOOL CPDF_DeviceBuffer::Initialize(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, FX_RECT* pRect,
1346 const CPDF_PageObject* pObj, int max_dpi)
1347 {
1348 m_pDevice = pDevice;
1349 m_pContext = pContext;
1350 m_Rect = *pRect;
1351 m_pObject = pObj;
1352 m_Matrix.TranslateI(-pRect->left, -pRect->top);
1353 #if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_
1354 int horz_size = pDevice->GetDeviceCaps(FXDC_HORZ_SIZE);
1355 int vert_size = pDevice->GetDeviceCaps(FXDC_VERT_SIZE);
1356 if (horz_size && vert_size && max_dpi) {
1357 int dpih = pDevice->GetDeviceCaps(FXDC_PIXEL_WIDTH) * 254 / (horz_size * 10);
1358 int dpiv = pDevice->GetDeviceCaps(FXDC_PIXEL_HEIGHT) * 254 / (vert_size * 10);
1359 if (dpih > max_dpi) {
1360 m_Matrix.Scale((FX_FLOAT)(max_dpi) / dpih, 1.0f);
1361 }
1362 if (dpiv > max_dpi) {
1363 m_Matrix.Scale(1.0f, (FX_FLOAT)(max_dpi) / (FX_FLOAT)dpiv);
1364 }
1365 }
1366 #ifdef _FPDFAPI_MINI_
1367 m_Matrix.Scale(0.5f, 0.5f);
1368 #endif
1369 #endif
1370 CFX_Matrix ctm = m_pDevice->GetCTM();
1371 FX_FLOAT fScaleX = FXSYS_fabs(ctm.a);
1372 FX_FLOAT fScaleY = FXSYS_fabs(ctm.d);
1373 m_Matrix.Concat(fScaleX, 0, 0, fScaleY, 0, 0);
1374 CFX_FloatRect rect(*pRect);
1375 m_Matrix.TransformRect(rect);
1376 FX_RECT bitmap_rect = rect.GetOutterRect();
1377 m_pBitmap = FX_NEW CFX_DIBitmap;
1378 m_pBitmap->Create(bitmap_rect.Width(), bitmap_rect.Height(), FXDIB_Argb);
1379 return TRUE;
1380 }
OutputToDevice()1381 void CPDF_DeviceBuffer::OutputToDevice()
1382 {
1383 if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) {
1384 if (m_Matrix.a == 1.0f && m_Matrix.d == 1.0f) {
1385 m_pDevice->SetDIBits(m_pBitmap, m_Rect.left, m_Rect.top);
1386 } else {
1387 m_pDevice->StretchDIBits(m_pBitmap, m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height());
1388 }
1389 } else {
1390 #if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_)
1391 CFX_DIBitmap buffer;
1392 m_pDevice->CreateCompatibleBitmap(&buffer, m_pBitmap->GetWidth(), m_pBitmap->GetHeight());
1393 m_pContext->GetBackground(&buffer, m_pObject, NULL, &m_Matrix);
1394 buffer.CompositeBitmap(0, 0, buffer.GetWidth(), buffer.GetHeight(), m_pBitmap, 0, 0);
1395 m_pDevice->StretchDIBits(&buffer, m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height());
1396 #endif
1397 }
1398 }
CPDF_ScaledRenderBuffer()1399 CPDF_ScaledRenderBuffer::CPDF_ScaledRenderBuffer()
1400 {
1401 m_pBitmapDevice = NULL;
1402 }
~CPDF_ScaledRenderBuffer()1403 CPDF_ScaledRenderBuffer::~CPDF_ScaledRenderBuffer()
1404 {
1405 if (m_pBitmapDevice) {
1406 delete m_pBitmapDevice;
1407 }
1408 }
1409 #ifndef _FPDFAPI_MINI_
1410 #define _FPDFAPI_IMAGESIZE_LIMIT_ (30 * 1024 * 1024)
1411 #else
1412 #define _FPDFAPI_IMAGESIZE_LIMIT_ (10 * 1024 * 1024)
1413 #endif
Initialize(CPDF_RenderContext * pContext,CFX_RenderDevice * pDevice,FX_RECT * pRect,const CPDF_PageObject * pObj,const CPDF_RenderOptions * pOptions,int max_dpi)1414 FX_BOOL CPDF_ScaledRenderBuffer::Initialize(CPDF_RenderContext* pContext, CFX_RenderDevice* pDevice, FX_RECT* pRect,
1415 const CPDF_PageObject* pObj, const CPDF_RenderOptions *pOptions, int max_dpi)
1416 {
1417 FXSYS_assert(pRect != NULL);
1418 m_pDevice = pDevice;
1419 if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_GET_BITS) {
1420 return TRUE;
1421 }
1422 m_pContext = pContext;
1423 m_Rect = *pRect;
1424 m_pObject = pObj;
1425 m_Matrix.TranslateI(-pRect->left, -pRect->top);
1426 int horz_size = pDevice->GetDeviceCaps(FXDC_HORZ_SIZE);
1427 int vert_size = pDevice->GetDeviceCaps(FXDC_VERT_SIZE);
1428 if (horz_size && vert_size && max_dpi) {
1429 int dpih = pDevice->GetDeviceCaps(FXDC_PIXEL_WIDTH) * 254 / (horz_size * 10);
1430 int dpiv = pDevice->GetDeviceCaps(FXDC_PIXEL_HEIGHT) * 254 / (vert_size * 10);
1431 if (dpih > max_dpi) {
1432 m_Matrix.Scale((FX_FLOAT)(max_dpi) / dpih, 1.0f);
1433 }
1434 if (dpiv > max_dpi) {
1435 m_Matrix.Scale(1.0f, (FX_FLOAT)(max_dpi) / (FX_FLOAT)dpiv);
1436 }
1437 }
1438 m_pBitmapDevice = FX_NEW CFX_FxgeDevice;
1439 FXDIB_Format dibFormat = FXDIB_Rgb;
1440 FX_INT32 bpp = 24;
1441 if (m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_ALPHA_OUTPUT) {
1442 dibFormat = FXDIB_Argb;
1443 bpp = 32;
1444 }
1445 CFX_FloatRect rect;
1446 FX_INT32 iWidth, iHeight, iPitch;
1447 while (1) {
1448 rect = *pRect;
1449 m_Matrix.TransformRect(rect);
1450 FX_RECT bitmap_rect = rect.GetOutterRect();
1451 iWidth = bitmap_rect.Width();
1452 iHeight = bitmap_rect.Height();
1453 iPitch = (iWidth * bpp + 31) / 32 * 4;
1454 if (iWidth * iHeight < 1) {
1455 return FALSE;
1456 }
1457 if (iPitch * iHeight <= _FPDFAPI_IMAGESIZE_LIMIT_ &&
1458 m_pBitmapDevice->Create(iWidth, iHeight, dibFormat)) {
1459 break;
1460 }
1461 m_Matrix.Scale(0.5f, 0.5f);
1462 }
1463 #if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_)
1464 m_pContext->GetBackground(m_pBitmapDevice->GetBitmap(), m_pObject, pOptions, &m_Matrix);
1465 #endif
1466 return TRUE;
1467 }
OutputToDevice()1468 void CPDF_ScaledRenderBuffer::OutputToDevice()
1469 {
1470 if (m_pBitmapDevice) {
1471 m_pDevice->StretchDIBits(m_pBitmapDevice->GetBitmap(), m_Rect.left, m_Rect.top, m_Rect.Width(), m_Rect.Height());
1472 }
1473 }
CheckObjectVisible(const CPDF_PageObject * pObj)1474 FX_BOOL IPDF_OCContext::CheckObjectVisible(const CPDF_PageObject* pObj)
1475 {
1476 const CPDF_ContentMarkData* pData = pObj->m_ContentMark;
1477 int nItems = pData->CountItems();
1478 for (int i = 0; i < nItems; i ++) {
1479 CPDF_ContentMarkItem& item = pData->GetItem(i);
1480 if (item.GetName() == FX_BSTRC("OC") && item.GetParamType() == CPDF_ContentMarkItem::PropertiesDict) {
1481 CPDF_Dictionary* pOCG = (CPDF_Dictionary*)item.GetParam();
1482 if (!CheckOCGVisible(pOCG)) {
1483 return FALSE;
1484 }
1485 }
1486 }
1487 return TRUE;
1488 }
1489