OLD | NEW |
| (Empty) |
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 "core/fpdfapi/fpdf_render/render_int.h" | |
8 | |
9 #include <memory> | |
10 #include <utility> | |
11 #include <vector> | |
12 | |
13 #include "core/fpdfapi/fpdf_render/cpdf_pagerendercache.h" | |
14 #include "core/fpdfapi/fpdf_render/cpdf_rendercontext.h" | |
15 #include "core/fpdfapi/fpdf_render/cpdf_renderoptions.h" | |
16 #include "core/fpdfapi/page/cpdf_form.h" | |
17 #include "core/fpdfapi/page/cpdf_image.h" | |
18 #include "core/fpdfapi/page/cpdf_imageobject.h" | |
19 #include "core/fpdfapi/page/cpdf_page.h" | |
20 #include "core/fpdfapi/page/cpdf_shadingpattern.h" | |
21 #include "core/fpdfapi/page/cpdf_tilingpattern.h" | |
22 #include "core/fpdfapi/page/pageint.h" | |
23 #include "core/fpdfapi/parser/cpdf_array.h" | |
24 #include "core/fpdfapi/parser/cpdf_dictionary.h" | |
25 #include "core/fpdfapi/parser/cpdf_document.h" | |
26 #include "core/fpdfdoc/cpdf_occontext.h" | |
27 #include "core/fxcodec/fx_codec.h" | |
28 #include "core/fxcrt/fx_safe_types.h" | |
29 #include "core/fxge/cfx_fxgedevice.h" | |
30 #include "core/fxge/cfx_pathdata.h" | |
31 | |
32 #ifdef _SKIA_SUPPORT_ | |
33 #include "core/fxge/skia/fx_skia_device.h" | |
34 #endif | |
35 | |
36 FX_BOOL CPDF_RenderStatus::ProcessImage(CPDF_ImageObject* pImageObj, | |
37 const CFX_Matrix* pObj2Device) { | |
38 CPDF_ImageRenderer render; | |
39 if (render.Start(this, pImageObj, pObj2Device, m_bStdCS, m_curBlend)) { | |
40 render.Continue(nullptr); | |
41 } | |
42 return render.m_Result; | |
43 } | |
44 void CPDF_RenderStatus::CompositeDIBitmap(CFX_DIBitmap* pDIBitmap, | |
45 int left, | |
46 int top, | |
47 FX_ARGB mask_argb, | |
48 int bitmap_alpha, | |
49 int blend_mode, | |
50 int Transparency) { | |
51 if (!pDIBitmap) { | |
52 return; | |
53 } | |
54 if (blend_mode == FXDIB_BLEND_NORMAL) { | |
55 if (!pDIBitmap->IsAlphaMask()) { | |
56 if (bitmap_alpha < 255) { | |
57 #ifdef _SKIA_SUPPORT_ | |
58 void* dummy; | |
59 CFX_Matrix m(pDIBitmap->GetWidth(), 0, 0, -pDIBitmap->GetHeight(), left, | |
60 top + pDIBitmap->GetHeight()); | |
61 m_pDevice->StartDIBits(pDIBitmap, bitmap_alpha, 0, &m, 0, dummy); | |
62 return; | |
63 #else | |
64 pDIBitmap->MultiplyAlpha(bitmap_alpha); | |
65 #endif | |
66 } | |
67 #ifdef _SKIA_SUPPORT_ | |
68 CFX_SkiaDeviceDriver::PreMultiply(pDIBitmap); | |
69 #endif | |
70 if (m_pDevice->SetDIBits(pDIBitmap, left, top)) { | |
71 return; | |
72 } | |
73 } else { | |
74 uint32_t fill_argb = m_Options.TranslateColor(mask_argb); | |
75 if (bitmap_alpha < 255) { | |
76 ((uint8_t*)&fill_argb)[3] = | |
77 ((uint8_t*)&fill_argb)[3] * bitmap_alpha / 255; | |
78 } | |
79 if (m_pDevice->SetBitMask(pDIBitmap, left, top, fill_argb)) { | |
80 return; | |
81 } | |
82 } | |
83 } | |
84 bool bIsolated = !!(Transparency & PDFTRANS_ISOLATED); | |
85 bool bGroup = !!(Transparency & PDFTRANS_GROUP); | |
86 bool bBackAlphaRequired = blend_mode && bIsolated && !m_bDropObjects; | |
87 bool bGetBackGround = | |
88 ((m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT)) || | |
89 (!(m_pDevice->GetRenderCaps() & FXRC_ALPHA_OUTPUT) && | |
90 (m_pDevice->GetRenderCaps() & FXRC_GET_BITS) && !bBackAlphaRequired); | |
91 if (bGetBackGround) { | |
92 if (bIsolated || !bGroup) { | |
93 if (pDIBitmap->IsAlphaMask()) { | |
94 return; | |
95 } | |
96 m_pDevice->SetDIBitsWithBlend(pDIBitmap, left, top, blend_mode); | |
97 } else { | |
98 FX_RECT rect(left, top, left + pDIBitmap->GetWidth(), | |
99 top + pDIBitmap->GetHeight()); | |
100 rect.Intersect(m_pDevice->GetClipBox()); | |
101 CFX_DIBitmap* pClone = nullptr; | |
102 FX_BOOL bClone = FALSE; | |
103 if (m_pDevice->GetBackDrop() && m_pDevice->GetBitmap()) { | |
104 bClone = TRUE; | |
105 pClone = m_pDevice->GetBackDrop()->Clone(&rect); | |
106 CFX_DIBitmap* pForeBitmap = m_pDevice->GetBitmap(); | |
107 pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), | |
108 pForeBitmap, rect.left, rect.top); | |
109 left = left >= 0 ? 0 : left; | |
110 top = top >= 0 ? 0 : top; | |
111 if (!pDIBitmap->IsAlphaMask()) | |
112 pClone->CompositeBitmap(0, 0, pClone->GetWidth(), pClone->GetHeight(), | |
113 pDIBitmap, left, top, blend_mode); | |
114 else | |
115 pClone->CompositeMask(0, 0, pClone->GetWidth(), pClone->GetHeight(), | |
116 pDIBitmap, mask_argb, left, top, blend_mode); | |
117 } else { | |
118 pClone = pDIBitmap; | |
119 } | |
120 if (m_pDevice->GetBackDrop()) { | |
121 m_pDevice->SetDIBits(pClone, rect.left, rect.top); | |
122 } else { | |
123 if (pDIBitmap->IsAlphaMask()) { | |
124 return; | |
125 } | |
126 m_pDevice->SetDIBitsWithBlend(pDIBitmap, rect.left, rect.top, | |
127 blend_mode); | |
128 } | |
129 if (bClone) { | |
130 delete pClone; | |
131 } | |
132 } | |
133 return; | |
134 } | |
135 int back_left, back_top; | |
136 FX_RECT rect(left, top, left + pDIBitmap->GetWidth(), | |
137 top + pDIBitmap->GetHeight()); | |
138 std::unique_ptr<CFX_DIBitmap> pBackdrop( | |
139 GetBackdrop(m_pCurObj, rect, back_left, back_top, | |
140 blend_mode > FXDIB_BLEND_NORMAL && bIsolated)); | |
141 if (!pBackdrop) | |
142 return; | |
143 | |
144 if (!pDIBitmap->IsAlphaMask()) { | |
145 pBackdrop->CompositeBitmap(left - back_left, top - back_top, | |
146 pDIBitmap->GetWidth(), pDIBitmap->GetHeight(), | |
147 pDIBitmap, 0, 0, blend_mode); | |
148 } else { | |
149 pBackdrop->CompositeMask(left - back_left, top - back_top, | |
150 pDIBitmap->GetWidth(), pDIBitmap->GetHeight(), | |
151 pDIBitmap, mask_argb, 0, 0, blend_mode); | |
152 } | |
153 | |
154 std::unique_ptr<CFX_DIBitmap> pBackdrop1(new CFX_DIBitmap); | |
155 pBackdrop1->Create(pBackdrop->GetWidth(), pBackdrop->GetHeight(), | |
156 FXDIB_Rgb32); | |
157 pBackdrop1->Clear((uint32_t)-1); | |
158 pBackdrop1->CompositeBitmap(0, 0, pBackdrop->GetWidth(), | |
159 pBackdrop->GetHeight(), pBackdrop.get(), 0, 0); | |
160 pBackdrop = std::move(pBackdrop1); | |
161 m_pDevice->SetDIBits(pBackdrop.get(), back_left, back_top); | |
162 } | |
163 | |
164 CPDF_TransferFunc::CPDF_TransferFunc(CPDF_Document* pDoc) : m_pPDFDoc(pDoc) {} | |
165 | |
166 FX_COLORREF CPDF_TransferFunc::TranslateColor(FX_COLORREF rgb) const { | |
167 return FXSYS_RGB(m_Samples[FXSYS_GetRValue(rgb)], | |
168 m_Samples[256 + FXSYS_GetGValue(rgb)], | |
169 m_Samples[512 + FXSYS_GetBValue(rgb)]); | |
170 } | |
171 | |
172 CFX_DIBSource* CPDF_TransferFunc::TranslateImage(const CFX_DIBSource* pSrc, | |
173 FX_BOOL bAutoDropSrc) { | |
174 CPDF_DIBTransferFunc* pDest = new CPDF_DIBTransferFunc(this); | |
175 pDest->LoadSrc(pSrc, bAutoDropSrc); | |
176 return pDest; | |
177 } | |
178 | |
179 CPDF_DIBTransferFunc::~CPDF_DIBTransferFunc() {} | |
180 | |
181 FXDIB_Format CPDF_DIBTransferFunc::GetDestFormat() { | |
182 if (m_pSrc->IsAlphaMask()) { | |
183 return FXDIB_8bppMask; | |
184 } | |
185 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
186 return (m_pSrc->HasAlpha()) ? FXDIB_Argb : FXDIB_Rgb32; | |
187 #else | |
188 return (m_pSrc->HasAlpha()) ? FXDIB_Argb : FXDIB_Rgb; | |
189 #endif | |
190 } | |
191 | |
192 FX_ARGB* CPDF_DIBTransferFunc::GetDestPalette() { | |
193 return nullptr; | |
194 } | |
195 | |
196 CPDF_DIBTransferFunc::CPDF_DIBTransferFunc( | |
197 const CPDF_TransferFunc* pTransferFunc) { | |
198 m_RampR = pTransferFunc->m_Samples; | |
199 m_RampG = &pTransferFunc->m_Samples[256]; | |
200 m_RampB = &pTransferFunc->m_Samples[512]; | |
201 } | |
202 | |
203 void CPDF_DIBTransferFunc::TranslateScanline( | |
204 const uint8_t* src_buf, | |
205 std::vector<uint8_t>* dest_buf) const { | |
206 FX_BOOL bSkip = FALSE; | |
207 switch (m_pSrc->GetFormat()) { | |
208 case FXDIB_1bppRgb: { | |
209 int r0 = m_RampR[0]; | |
210 int g0 = m_RampG[0]; | |
211 int b0 = m_RampB[0]; | |
212 int r1 = m_RampR[255]; | |
213 int g1 = m_RampG[255]; | |
214 int b1 = m_RampB[255]; | |
215 int index = 0; | |
216 for (int i = 0; i < m_Width; i++) { | |
217 if (src_buf[i / 8] & (1 << (7 - i % 8))) { | |
218 (*dest_buf)[index++] = b1; | |
219 (*dest_buf)[index++] = g1; | |
220 (*dest_buf)[index++] = r1; | |
221 } else { | |
222 (*dest_buf)[index++] = b0; | |
223 (*dest_buf)[index++] = g0; | |
224 (*dest_buf)[index++] = r0; | |
225 } | |
226 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
227 index++; | |
228 #endif | |
229 } | |
230 break; | |
231 } | |
232 case FXDIB_1bppMask: { | |
233 int m0 = m_RampR[0]; | |
234 int m1 = m_RampR[255]; | |
235 int index = 0; | |
236 for (int i = 0; i < m_Width; i++) { | |
237 if (src_buf[i / 8] & (1 << (7 - i % 8))) | |
238 (*dest_buf)[index++] = m1; | |
239 else | |
240 (*dest_buf)[index++] = m0; | |
241 } | |
242 break; | |
243 } | |
244 case FXDIB_8bppRgb: { | |
245 FX_ARGB* pPal = m_pSrc->GetPalette(); | |
246 int index = 0; | |
247 for (int i = 0; i < m_Width; i++) { | |
248 if (pPal) { | |
249 FX_ARGB src_argb = pPal[*src_buf]; | |
250 (*dest_buf)[index++] = m_RampB[FXARGB_R(src_argb)]; | |
251 (*dest_buf)[index++] = m_RampG[FXARGB_G(src_argb)]; | |
252 (*dest_buf)[index++] = m_RampR[FXARGB_B(src_argb)]; | |
253 } else { | |
254 uint32_t src_byte = *src_buf; | |
255 (*dest_buf)[index++] = m_RampB[src_byte]; | |
256 (*dest_buf)[index++] = m_RampG[src_byte]; | |
257 (*dest_buf)[index++] = m_RampR[src_byte]; | |
258 } | |
259 src_buf++; | |
260 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
261 index++; | |
262 #endif | |
263 } | |
264 break; | |
265 } | |
266 case FXDIB_8bppMask: { | |
267 int index = 0; | |
268 for (int i = 0; i < m_Width; i++) { | |
269 (*dest_buf)[index++] = m_RampR[*(src_buf++)]; | |
270 } | |
271 break; | |
272 } | |
273 case FXDIB_Rgb: { | |
274 int index = 0; | |
275 for (int i = 0; i < m_Width; i++) { | |
276 (*dest_buf)[index++] = m_RampB[*(src_buf++)]; | |
277 (*dest_buf)[index++] = m_RampG[*(src_buf++)]; | |
278 (*dest_buf)[index++] = m_RampR[*(src_buf++)]; | |
279 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
280 index++; | |
281 #endif | |
282 } | |
283 break; | |
284 } | |
285 case FXDIB_Rgb32: | |
286 bSkip = TRUE; | |
287 case FXDIB_Argb: { | |
288 int index = 0; | |
289 for (int i = 0; i < m_Width; i++) { | |
290 (*dest_buf)[index++] = m_RampB[*(src_buf++)]; | |
291 (*dest_buf)[index++] = m_RampG[*(src_buf++)]; | |
292 (*dest_buf)[index++] = m_RampR[*(src_buf++)]; | |
293 if (!bSkip) { | |
294 (*dest_buf)[index++] = *src_buf; | |
295 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
296 } else { | |
297 index++; | |
298 #endif | |
299 } | |
300 src_buf++; | |
301 } | |
302 break; | |
303 } | |
304 default: | |
305 break; | |
306 } | |
307 } | |
308 | |
309 void CPDF_DIBTransferFunc::TranslateDownSamples(uint8_t* dest_buf, | |
310 const uint8_t* src_buf, | |
311 int pixels, | |
312 int Bpp) const { | |
313 if (Bpp == 8) { | |
314 for (int i = 0; i < pixels; i++) { | |
315 *dest_buf++ = m_RampR[*(src_buf++)]; | |
316 } | |
317 } else if (Bpp == 24) { | |
318 for (int i = 0; i < pixels; i++) { | |
319 *dest_buf++ = m_RampB[*(src_buf++)]; | |
320 *dest_buf++ = m_RampG[*(src_buf++)]; | |
321 *dest_buf++ = m_RampR[*(src_buf++)]; | |
322 } | |
323 } else { | |
324 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
325 if (!m_pSrc->HasAlpha()) { | |
326 for (int i = 0; i < pixels; i++) { | |
327 *dest_buf++ = m_RampB[*(src_buf++)]; | |
328 *dest_buf++ = m_RampG[*(src_buf++)]; | |
329 *dest_buf++ = m_RampR[*(src_buf++)]; | |
330 dest_buf++; | |
331 src_buf++; | |
332 } | |
333 } else { | |
334 #endif | |
335 for (int i = 0; i < pixels; i++) { | |
336 *dest_buf++ = m_RampB[*(src_buf++)]; | |
337 *dest_buf++ = m_RampG[*(src_buf++)]; | |
338 *dest_buf++ = m_RampR[*(src_buf++)]; | |
339 *dest_buf++ = *(src_buf++); | |
340 } | |
341 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ | |
342 } | |
343 #endif | |
344 } | |
345 } | |
346 | |
347 CPDF_ImageRenderer::CPDF_ImageRenderer() { | |
348 m_pRenderStatus = nullptr; | |
349 m_pImageObject = nullptr; | |
350 m_Result = TRUE; | |
351 m_Status = 0; | |
352 m_DeviceHandle = nullptr; | |
353 m_bStdCS = FALSE; | |
354 m_bPatternColor = FALSE; | |
355 m_BlendType = FXDIB_BLEND_NORMAL; | |
356 m_pPattern = nullptr; | |
357 m_pObj2Device = nullptr; | |
358 } | |
359 | |
360 CPDF_ImageRenderer::~CPDF_ImageRenderer() { | |
361 if (m_DeviceHandle) { | |
362 m_pRenderStatus->m_pDevice->CancelDIBits(m_DeviceHandle); | |
363 } | |
364 } | |
365 | |
366 FX_BOOL CPDF_ImageRenderer::StartLoadDIBSource() { | |
367 CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); | |
368 FX_RECT image_rect = image_rect_f.GetOuterRect(); | |
369 if (!image_rect.Valid()) | |
370 return FALSE; | |
371 | |
372 int dest_width = image_rect.Width(); | |
373 int dest_height = image_rect.Height(); | |
374 if (m_ImageMatrix.a < 0) { | |
375 dest_width = -dest_width; | |
376 } | |
377 if (m_ImageMatrix.d > 0) { | |
378 dest_height = -dest_height; | |
379 } | |
380 if (m_Loader.Start(m_pImageObject, | |
381 m_pRenderStatus->m_pContext->GetPageCache(), &m_LoadHandle, | |
382 m_bStdCS, m_pRenderStatus->m_GroupFamily, | |
383 m_pRenderStatus->m_bLoadMask, m_pRenderStatus, dest_width, | |
384 dest_height)) { | |
385 if (m_LoadHandle) { | |
386 m_Status = 4; | |
387 return TRUE; | |
388 } | |
389 } | |
390 return FALSE; | |
391 } | |
392 | |
393 FX_BOOL CPDF_ImageRenderer::StartRenderDIBSource() { | |
394 if (!m_Loader.m_pBitmap) | |
395 return FALSE; | |
396 | |
397 m_BitmapAlpha = | |
398 FXSYS_round(255 * m_pImageObject->m_GeneralState.GetFillAlpha()); | |
399 m_pDIBSource = m_Loader.m_pBitmap; | |
400 if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_ALPHA && | |
401 !m_Loader.m_pMask) { | |
402 return StartBitmapAlpha(); | |
403 } | |
404 if (m_pImageObject->m_GeneralState.GetTR()) { | |
405 if (!m_pImageObject->m_GeneralState.GetTransferFunc()) { | |
406 m_pImageObject->m_GeneralState.SetTransferFunc( | |
407 m_pRenderStatus->GetTransferFunc( | |
408 m_pImageObject->m_GeneralState.GetTR())); | |
409 } | |
410 if (m_pImageObject->m_GeneralState.GetTransferFunc() && | |
411 !m_pImageObject->m_GeneralState.GetTransferFunc()->m_bIdentity) { | |
412 m_pDIBSource = m_Loader.m_pBitmap = | |
413 m_pImageObject->m_GeneralState.GetTransferFunc()->TranslateImage( | |
414 m_Loader.m_pBitmap, !m_Loader.m_bCached); | |
415 if (m_Loader.m_bCached && m_Loader.m_pMask) { | |
416 m_Loader.m_pMask = m_Loader.m_pMask->Clone(); | |
417 } | |
418 m_Loader.m_bCached = FALSE; | |
419 } | |
420 } | |
421 m_FillArgb = 0; | |
422 m_bPatternColor = FALSE; | |
423 m_pPattern = nullptr; | |
424 if (m_pDIBSource->IsAlphaMask()) { | |
425 const CPDF_Color* pColor = m_pImageObject->m_ColorState.GetFillColor(); | |
426 if (pColor && pColor->IsPattern()) { | |
427 m_pPattern = pColor->GetPattern(); | |
428 if (m_pPattern) { | |
429 m_bPatternColor = TRUE; | |
430 } | |
431 } | |
432 m_FillArgb = m_pRenderStatus->GetFillArgb(m_pImageObject); | |
433 } else if (m_pRenderStatus->m_Options.m_ColorMode == RENDER_COLOR_GRAY) { | |
434 m_pClone.reset(m_pDIBSource->Clone()); | |
435 m_pClone->ConvertColorScale(m_pRenderStatus->m_Options.m_BackColor, | |
436 m_pRenderStatus->m_Options.m_ForeColor); | |
437 m_pDIBSource = m_pClone.get(); | |
438 } | |
439 m_Flags = 0; | |
440 if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_DOWNSAMPLE) { | |
441 m_Flags |= RENDER_FORCE_DOWNSAMPLE; | |
442 } else if (m_pRenderStatus->m_Options.m_Flags & RENDER_FORCE_HALFTONE) { | |
443 m_Flags |= RENDER_FORCE_HALFTONE; | |
444 } | |
445 if (m_pRenderStatus->m_pDevice->GetDeviceClass() != FXDC_DISPLAY) { | |
446 CPDF_Object* pFilters = | |
447 m_pImageObject->GetImage()->GetStream()->GetDict()->GetDirectObjectFor( | |
448 "Filter"); | |
449 if (pFilters) { | |
450 if (pFilters->IsName()) { | |
451 CFX_ByteString bsDecodeType = pFilters->GetString(); | |
452 if (bsDecodeType == "DCTDecode" || bsDecodeType == "JPXDecode") { | |
453 m_Flags |= FXRENDER_IMAGE_LOSSY; | |
454 } | |
455 } else if (CPDF_Array* pArray = pFilters->AsArray()) { | |
456 for (size_t i = 0; i < pArray->GetCount(); i++) { | |
457 CFX_ByteString bsDecodeType = pArray->GetStringAt(i); | |
458 if (bsDecodeType == "DCTDecode" || bsDecodeType == "JPXDecode") { | |
459 m_Flags |= FXRENDER_IMAGE_LOSSY; | |
460 break; | |
461 } | |
462 } | |
463 } | |
464 } | |
465 } | |
466 if (m_pRenderStatus->m_Options.m_Flags & RENDER_NOIMAGESMOOTH) { | |
467 m_Flags |= FXDIB_NOSMOOTH; | |
468 } else if (m_pImageObject->GetImage()->IsInterpol()) { | |
469 m_Flags |= FXDIB_INTERPOL; | |
470 } | |
471 if (m_Loader.m_pMask) { | |
472 return DrawMaskedImage(); | |
473 } | |
474 if (m_bPatternColor) { | |
475 return DrawPatternImage(m_pObj2Device); | |
476 } | |
477 if (m_BitmapAlpha == 255 && m_pImageObject->m_GeneralState && | |
478 m_pImageObject->m_GeneralState.GetFillOP() && | |
479 m_pImageObject->m_GeneralState.GetOPMode() == 0 && | |
480 m_pImageObject->m_GeneralState.GetBlendType() == FXDIB_BLEND_NORMAL && | |
481 m_pImageObject->m_GeneralState.GetStrokeAlpha() == 1.0f && | |
482 m_pImageObject->m_GeneralState.GetFillAlpha() == 1.0f) { | |
483 CPDF_Document* pDocument = nullptr; | |
484 CPDF_Page* pPage = nullptr; | |
485 if (m_pRenderStatus->m_pContext->GetPageCache()) { | |
486 pPage = m_pRenderStatus->m_pContext->GetPageCache()->GetPage(); | |
487 pDocument = pPage->m_pDocument; | |
488 } else { | |
489 pDocument = m_pImageObject->GetImage()->GetDocument(); | |
490 } | |
491 CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : nullptr; | |
492 CPDF_Object* pCSObj = | |
493 m_pImageObject->GetImage()->GetStream()->GetDict()->GetDirectObjectFor( | |
494 "ColorSpace"); | |
495 CPDF_ColorSpace* pColorSpace = | |
496 pDocument->LoadColorSpace(pCSObj, pPageResources); | |
497 if (pColorSpace) { | |
498 int format = pColorSpace->GetFamily(); | |
499 if (format == PDFCS_DEVICECMYK || format == PDFCS_SEPARATION || | |
500 format == PDFCS_DEVICEN) { | |
501 m_BlendType = FXDIB_BLEND_DARKEN; | |
502 } | |
503 pDocument->GetPageData()->ReleaseColorSpace(pCSObj); | |
504 } | |
505 } | |
506 return StartDIBSource(); | |
507 } | |
508 | |
509 FX_BOOL CPDF_ImageRenderer::Start(CPDF_RenderStatus* pStatus, | |
510 CPDF_PageObject* pObj, | |
511 const CFX_Matrix* pObj2Device, | |
512 FX_BOOL bStdCS, | |
513 int blendType) { | |
514 m_pRenderStatus = pStatus; | |
515 m_bStdCS = bStdCS; | |
516 m_pImageObject = pObj->AsImage(); | |
517 m_BlendType = blendType; | |
518 m_pObj2Device = pObj2Device; | |
519 CPDF_Dictionary* pOC = m_pImageObject->GetImage()->GetOC(); | |
520 if (pOC && m_pRenderStatus->m_Options.m_pOCContext && | |
521 !m_pRenderStatus->m_Options.m_pOCContext->CheckOCGVisible(pOC)) { | |
522 return FALSE; | |
523 } | |
524 m_ImageMatrix = m_pImageObject->m_Matrix; | |
525 m_ImageMatrix.Concat(*pObj2Device); | |
526 if (StartLoadDIBSource()) { | |
527 return TRUE; | |
528 } | |
529 return StartRenderDIBSource(); | |
530 } | |
531 | |
532 FX_BOOL CPDF_ImageRenderer::Start(CPDF_RenderStatus* pStatus, | |
533 const CFX_DIBSource* pDIBSource, | |
534 FX_ARGB bitmap_argb, | |
535 int bitmap_alpha, | |
536 const CFX_Matrix* pImage2Device, | |
537 uint32_t flags, | |
538 FX_BOOL bStdCS, | |
539 int blendType) { | |
540 m_pRenderStatus = pStatus; | |
541 m_pDIBSource = pDIBSource; | |
542 m_FillArgb = bitmap_argb; | |
543 m_BitmapAlpha = bitmap_alpha; | |
544 m_ImageMatrix = *pImage2Device; | |
545 m_Flags = flags; | |
546 m_bStdCS = bStdCS; | |
547 m_BlendType = blendType; | |
548 return StartDIBSource(); | |
549 } | |
550 | |
551 FX_BOOL CPDF_ImageRenderer::DrawPatternImage(const CFX_Matrix* pObj2Device) { | |
552 if (m_pRenderStatus->m_bPrint && | |
553 !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { | |
554 m_Result = FALSE; | |
555 return FALSE; | |
556 } | |
557 FX_RECT rect = m_ImageMatrix.GetUnitRect().GetOuterRect(); | |
558 rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox()); | |
559 if (rect.IsEmpty()) { | |
560 return FALSE; | |
561 } | |
562 CFX_Matrix new_matrix = m_ImageMatrix; | |
563 new_matrix.TranslateI(-rect.left, -rect.top); | |
564 int width = rect.Width(); | |
565 int height = rect.Height(); | |
566 CFX_FxgeDevice bitmap_device1; | |
567 if (!bitmap_device1.Create(rect.Width(), rect.Height(), FXDIB_Rgb32, nullptr)) | |
568 return TRUE; | |
569 | |
570 bitmap_device1.GetBitmap()->Clear(0xffffff); | |
571 { | |
572 CPDF_RenderStatus bitmap_render; | |
573 bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device1, | |
574 nullptr, nullptr, nullptr, nullptr, | |
575 &m_pRenderStatus->m_Options, 0, | |
576 m_pRenderStatus->m_bDropObjects, nullptr, TRUE); | |
577 CFX_Matrix patternDevice = *pObj2Device; | |
578 patternDevice.Translate((FX_FLOAT)-rect.left, (FX_FLOAT)-rect.top); | |
579 if (CPDF_TilingPattern* pTilingPattern = m_pPattern->AsTilingPattern()) { | |
580 bitmap_render.DrawTilingPattern(pTilingPattern, m_pImageObject, | |
581 &patternDevice, FALSE); | |
582 } else if (CPDF_ShadingPattern* pShadingPattern = | |
583 m_pPattern->AsShadingPattern()) { | |
584 bitmap_render.DrawShadingPattern(pShadingPattern, m_pImageObject, | |
585 &patternDevice, FALSE); | |
586 } | |
587 } | |
588 { | |
589 CFX_FxgeDevice bitmap_device2; | |
590 if (!bitmap_device2.Create(rect.Width(), rect.Height(), FXDIB_8bppRgb, | |
591 nullptr)) { | |
592 return TRUE; | |
593 } | |
594 bitmap_device2.GetBitmap()->Clear(0); | |
595 CPDF_RenderStatus bitmap_render; | |
596 bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device2, | |
597 nullptr, nullptr, nullptr, nullptr, nullptr, 0, | |
598 m_pRenderStatus->m_bDropObjects, nullptr, TRUE); | |
599 CPDF_ImageRenderer image_render; | |
600 if (image_render.Start(&bitmap_render, m_pDIBSource, 0xffffffff, 255, | |
601 &new_matrix, m_Flags, TRUE)) { | |
602 image_render.Continue(nullptr); | |
603 } | |
604 if (m_Loader.m_MatteColor != 0xffffffff) { | |
605 int matte_r = FXARGB_R(m_Loader.m_MatteColor); | |
606 int matte_g = FXARGB_G(m_Loader.m_MatteColor); | |
607 int matte_b = FXARGB_B(m_Loader.m_MatteColor); | |
608 for (int row = 0; row < height; row++) { | |
609 uint8_t* dest_scan = | |
610 (uint8_t*)bitmap_device1.GetBitmap()->GetScanline(row); | |
611 const uint8_t* mask_scan = bitmap_device2.GetBitmap()->GetScanline(row); | |
612 for (int col = 0; col < width; col++) { | |
613 int alpha = *mask_scan++; | |
614 if (alpha) { | |
615 int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b; | |
616 if (orig < 0) { | |
617 orig = 0; | |
618 } else if (orig > 255) { | |
619 orig = 255; | |
620 } | |
621 *dest_scan++ = orig; | |
622 orig = (*dest_scan - matte_g) * 255 / alpha + matte_g; | |
623 if (orig < 0) { | |
624 orig = 0; | |
625 } else if (orig > 255) { | |
626 orig = 255; | |
627 } | |
628 *dest_scan++ = orig; | |
629 orig = (*dest_scan - matte_r) * 255 / alpha + matte_r; | |
630 if (orig < 0) { | |
631 orig = 0; | |
632 } else if (orig > 255) { | |
633 orig = 255; | |
634 } | |
635 *dest_scan++ = orig; | |
636 dest_scan++; | |
637 } else { | |
638 dest_scan += 4; | |
639 } | |
640 } | |
641 } | |
642 } | |
643 bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); | |
644 bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); | |
645 bitmap_device1.GetBitmap()->MultiplyAlpha(255); | |
646 } | |
647 m_pRenderStatus->m_pDevice->SetDIBitsWithBlend( | |
648 bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); | |
649 return FALSE; | |
650 } | |
651 | |
652 FX_BOOL CPDF_ImageRenderer::DrawMaskedImage() { | |
653 if (m_pRenderStatus->m_bPrint && | |
654 !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { | |
655 m_Result = FALSE; | |
656 return FALSE; | |
657 } | |
658 FX_RECT rect = m_ImageMatrix.GetUnitRect().GetOuterRect(); | |
659 rect.Intersect(m_pRenderStatus->m_pDevice->GetClipBox()); | |
660 if (rect.IsEmpty()) { | |
661 return FALSE; | |
662 } | |
663 CFX_Matrix new_matrix = m_ImageMatrix; | |
664 new_matrix.TranslateI(-rect.left, -rect.top); | |
665 int width = rect.Width(); | |
666 int height = rect.Height(); | |
667 CFX_FxgeDevice bitmap_device1; | |
668 if (!bitmap_device1.Create(width, height, FXDIB_Rgb32, nullptr)) | |
669 return TRUE; | |
670 | |
671 #if defined _SKIA_SUPPORT_ | |
672 bitmap_device1.Clear(0xffffff); | |
673 #else | |
674 bitmap_device1.GetBitmap()->Clear(0xffffff); | |
675 #endif | |
676 { | |
677 CPDF_RenderStatus bitmap_render; | |
678 bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device1, | |
679 nullptr, nullptr, nullptr, nullptr, nullptr, 0, | |
680 m_pRenderStatus->m_bDropObjects, nullptr, TRUE); | |
681 CPDF_ImageRenderer image_render; | |
682 if (image_render.Start(&bitmap_render, m_pDIBSource, 0, 255, &new_matrix, | |
683 m_Flags, TRUE)) { | |
684 image_render.Continue(nullptr); | |
685 } | |
686 } | |
687 { | |
688 CFX_FxgeDevice bitmap_device2; | |
689 if (!bitmap_device2.Create(width, height, FXDIB_8bppRgb, nullptr)) | |
690 return TRUE; | |
691 | |
692 #if defined _SKIA_SUPPORT_ | |
693 bitmap_device2.Clear(0); | |
694 #else | |
695 bitmap_device2.GetBitmap()->Clear(0); | |
696 #endif | |
697 CPDF_RenderStatus bitmap_render; | |
698 bitmap_render.Initialize(m_pRenderStatus->m_pContext, &bitmap_device2, | |
699 nullptr, nullptr, nullptr, nullptr, nullptr, 0, | |
700 m_pRenderStatus->m_bDropObjects, nullptr, TRUE); | |
701 CPDF_ImageRenderer image_render; | |
702 if (image_render.Start(&bitmap_render, m_Loader.m_pMask, 0xffffffff, 255, | |
703 &new_matrix, m_Flags, TRUE)) { | |
704 image_render.Continue(nullptr); | |
705 } | |
706 if (m_Loader.m_MatteColor != 0xffffffff) { | |
707 int matte_r = FXARGB_R(m_Loader.m_MatteColor); | |
708 int matte_g = FXARGB_G(m_Loader.m_MatteColor); | |
709 int matte_b = FXARGB_B(m_Loader.m_MatteColor); | |
710 for (int row = 0; row < height; row++) { | |
711 uint8_t* dest_scan = | |
712 (uint8_t*)bitmap_device1.GetBitmap()->GetScanline(row); | |
713 const uint8_t* mask_scan = bitmap_device2.GetBitmap()->GetScanline(row); | |
714 for (int col = 0; col < width; col++) { | |
715 int alpha = *mask_scan++; | |
716 if (alpha) { | |
717 int orig = (*dest_scan - matte_b) * 255 / alpha + matte_b; | |
718 if (orig < 0) { | |
719 orig = 0; | |
720 } else if (orig > 255) { | |
721 orig = 255; | |
722 } | |
723 *dest_scan++ = orig; | |
724 orig = (*dest_scan - matte_g) * 255 / alpha + matte_g; | |
725 if (orig < 0) { | |
726 orig = 0; | |
727 } else if (orig > 255) { | |
728 orig = 255; | |
729 } | |
730 *dest_scan++ = orig; | |
731 orig = (*dest_scan - matte_r) * 255 / alpha + matte_r; | |
732 if (orig < 0) { | |
733 orig = 0; | |
734 } else if (orig > 255) { | |
735 orig = 255; | |
736 } | |
737 *dest_scan++ = orig; | |
738 dest_scan++; | |
739 } else { | |
740 dest_scan += 4; | |
741 } | |
742 } | |
743 } | |
744 } | |
745 #ifdef _SKIA_SUPPORT_ | |
746 m_pRenderStatus->m_pDevice->SetBitsWithMask( | |
747 bitmap_device1.GetBitmap(), bitmap_device2.GetBitmap(), rect.left, | |
748 rect.top, m_BitmapAlpha, m_BlendType); | |
749 } | |
750 #else | |
751 bitmap_device2.GetBitmap()->ConvertFormat(FXDIB_8bppMask); | |
752 bitmap_device1.GetBitmap()->MultiplyAlpha(bitmap_device2.GetBitmap()); | |
753 if (m_BitmapAlpha < 255) { | |
754 bitmap_device1.GetBitmap()->MultiplyAlpha(m_BitmapAlpha); | |
755 } | |
756 } | |
757 m_pRenderStatus->m_pDevice->SetDIBitsWithBlend( | |
758 bitmap_device1.GetBitmap(), rect.left, rect.top, m_BlendType); | |
759 #endif // _SKIA_SUPPORT_ | |
760 return FALSE; | |
761 } | |
762 | |
763 FX_BOOL CPDF_ImageRenderer::StartDIBSource() { | |
764 if (!(m_Flags & RENDER_FORCE_DOWNSAMPLE) && m_pDIBSource->GetBPP() > 1) { | |
765 FX_SAFE_SIZE_T image_size = m_pDIBSource->GetBPP(); | |
766 image_size /= 8; | |
767 image_size *= m_pDIBSource->GetWidth(); | |
768 image_size *= m_pDIBSource->GetHeight(); | |
769 if (!image_size.IsValid()) { | |
770 return FALSE; | |
771 } | |
772 | |
773 if (image_size.ValueOrDie() > FPDF_HUGE_IMAGE_SIZE && | |
774 !(m_Flags & RENDER_FORCE_HALFTONE)) { | |
775 m_Flags |= RENDER_FORCE_DOWNSAMPLE; | |
776 } | |
777 } | |
778 #ifdef _SKIA_SUPPORT_ | |
779 CFX_DIBitmap* premultiplied = m_pDIBSource->Clone(); | |
780 if (m_pDIBSource->HasAlpha()) | |
781 CFX_SkiaDeviceDriver::PreMultiply(premultiplied); | |
782 if (m_pRenderStatus->m_pDevice->StartDIBitsWithBlend( | |
783 premultiplied, m_BitmapAlpha, m_FillArgb, &m_ImageMatrix, m_Flags, | |
784 m_DeviceHandle, m_BlendType)) { | |
785 if (m_DeviceHandle) { | |
786 m_Status = 3; | |
787 return TRUE; | |
788 } | |
789 return FALSE; | |
790 } | |
791 #else | |
792 if (m_pRenderStatus->m_pDevice->StartDIBitsWithBlend( | |
793 m_pDIBSource, m_BitmapAlpha, m_FillArgb, &m_ImageMatrix, m_Flags, | |
794 m_DeviceHandle, m_BlendType)) { | |
795 if (m_DeviceHandle) { | |
796 m_Status = 3; | |
797 return TRUE; | |
798 } | |
799 return FALSE; | |
800 } | |
801 #endif | |
802 CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); | |
803 FX_RECT image_rect = image_rect_f.GetOuterRect(); | |
804 int dest_width = image_rect.Width(); | |
805 int dest_height = image_rect.Height(); | |
806 if ((FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || m_ImageMatrix.a == 0) || | |
807 (FXSYS_fabs(m_ImageMatrix.c) >= 0.5f || m_ImageMatrix.d == 0)) { | |
808 if (m_pRenderStatus->m_bPrint && | |
809 !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { | |
810 m_Result = FALSE; | |
811 return FALSE; | |
812 } | |
813 FX_RECT clip_box = m_pRenderStatus->m_pDevice->GetClipBox(); | |
814 clip_box.Intersect(image_rect); | |
815 m_Status = 2; | |
816 m_pTransformer.reset(new CFX_ImageTransformer(m_pDIBSource, &m_ImageMatrix, | |
817 m_Flags, &clip_box)); | |
818 m_pTransformer->Start(); | |
819 return TRUE; | |
820 } | |
821 if (m_ImageMatrix.a < 0) | |
822 dest_width = -dest_width; | |
823 | |
824 if (m_ImageMatrix.d > 0) | |
825 dest_height = -dest_height; | |
826 | |
827 int dest_left = dest_width > 0 ? image_rect.left : image_rect.right; | |
828 int dest_top = dest_height > 0 ? image_rect.top : image_rect.bottom; | |
829 if (m_pDIBSource->IsOpaqueImage() && m_BitmapAlpha == 255) { | |
830 if (m_pRenderStatus->m_pDevice->StretchDIBitsWithFlagsAndBlend( | |
831 m_pDIBSource, dest_left, dest_top, dest_width, dest_height, m_Flags, | |
832 m_BlendType)) { | |
833 return FALSE; | |
834 } | |
835 } | |
836 if (m_pDIBSource->IsAlphaMask()) { | |
837 if (m_BitmapAlpha != 255) | |
838 m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); | |
839 if (m_pRenderStatus->m_pDevice->StretchBitMaskWithFlags( | |
840 m_pDIBSource, dest_left, dest_top, dest_width, dest_height, | |
841 m_FillArgb, m_Flags)) { | |
842 return FALSE; | |
843 } | |
844 } | |
845 if (m_pRenderStatus->m_bPrint && | |
846 !(m_pRenderStatus->m_pDevice->GetRenderCaps() & FXRC_BLEND_MODE)) { | |
847 m_Result = FALSE; | |
848 return TRUE; | |
849 } | |
850 | |
851 FX_RECT clip_box = m_pRenderStatus->m_pDevice->GetClipBox(); | |
852 FX_RECT dest_rect = clip_box; | |
853 dest_rect.Intersect(image_rect); | |
854 FX_RECT dest_clip( | |
855 dest_rect.left - image_rect.left, dest_rect.top - image_rect.top, | |
856 dest_rect.right - image_rect.left, dest_rect.bottom - image_rect.top); | |
857 std::unique_ptr<CFX_DIBitmap> pStretched( | |
858 m_pDIBSource->StretchTo(dest_width, dest_height, m_Flags, &dest_clip)); | |
859 if (pStretched) { | |
860 m_pRenderStatus->CompositeDIBitmap(pStretched.get(), dest_rect.left, | |
861 dest_rect.top, m_FillArgb, m_BitmapAlpha, | |
862 m_BlendType, FALSE); | |
863 } | |
864 return FALSE; | |
865 } | |
866 | |
867 FX_BOOL CPDF_ImageRenderer::StartBitmapAlpha() { | |
868 if (m_pDIBSource->IsOpaqueImage()) { | |
869 CFX_PathData path; | |
870 path.AppendRect(0, 0, 1, 1); | |
871 path.Transform(&m_ImageMatrix); | |
872 uint32_t fill_color = | |
873 ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha); | |
874 m_pRenderStatus->m_pDevice->DrawPath(&path, nullptr, nullptr, fill_color, 0, | |
875 FXFILL_WINDING); | |
876 } else { | |
877 const CFX_DIBSource* pAlphaMask = m_pDIBSource->IsAlphaMask() | |
878 ? m_pDIBSource | |
879 : m_pDIBSource->GetAlphaMask(); | |
880 if (FXSYS_fabs(m_ImageMatrix.b) >= 0.5f || | |
881 FXSYS_fabs(m_ImageMatrix.c) >= 0.5f) { | |
882 int left, top; | |
883 std::unique_ptr<CFX_DIBitmap> pTransformed( | |
884 pAlphaMask->TransformTo(&m_ImageMatrix, left, top)); | |
885 if (!pTransformed) | |
886 return TRUE; | |
887 | |
888 m_pRenderStatus->m_pDevice->SetBitMask( | |
889 pTransformed.get(), left, top, | |
890 ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha)); | |
891 } else { | |
892 CFX_FloatRect image_rect_f = m_ImageMatrix.GetUnitRect(); | |
893 FX_RECT image_rect = image_rect_f.GetOuterRect(); | |
894 int dest_width = | |
895 m_ImageMatrix.a > 0 ? image_rect.Width() : -image_rect.Width(); | |
896 int dest_height = | |
897 m_ImageMatrix.d > 0 ? -image_rect.Height() : image_rect.Height(); | |
898 int left = dest_width > 0 ? image_rect.left : image_rect.right; | |
899 int top = dest_height > 0 ? image_rect.top : image_rect.bottom; | |
900 m_pRenderStatus->m_pDevice->StretchBitMask( | |
901 pAlphaMask, left, top, dest_width, dest_height, | |
902 ArgbEncode(0xff, m_BitmapAlpha, m_BitmapAlpha, m_BitmapAlpha)); | |
903 } | |
904 if (m_pDIBSource != pAlphaMask) { | |
905 delete pAlphaMask; | |
906 } | |
907 } | |
908 return FALSE; | |
909 } | |
910 | |
911 FX_BOOL CPDF_ImageRenderer::Continue(IFX_Pause* pPause) { | |
912 if (m_Status == 2) { | |
913 if (m_pTransformer->Continue(pPause)) | |
914 return TRUE; | |
915 | |
916 std::unique_ptr<CFX_DIBitmap> pBitmap(m_pTransformer->DetachBitmap()); | |
917 if (!pBitmap) | |
918 return FALSE; | |
919 | |
920 if (pBitmap->IsAlphaMask()) { | |
921 if (m_BitmapAlpha != 255) | |
922 m_FillArgb = FXARGB_MUL_ALPHA(m_FillArgb, m_BitmapAlpha); | |
923 m_Result = m_pRenderStatus->m_pDevice->SetBitMask( | |
924 pBitmap.get(), m_pTransformer->result().left, | |
925 m_pTransformer->result().top, m_FillArgb); | |
926 } else { | |
927 if (m_BitmapAlpha != 255) | |
928 pBitmap->MultiplyAlpha(m_BitmapAlpha); | |
929 m_Result = m_pRenderStatus->m_pDevice->SetDIBitsWithBlend( | |
930 pBitmap.get(), m_pTransformer->result().left, | |
931 m_pTransformer->result().top, m_BlendType); | |
932 } | |
933 return FALSE; | |
934 } | |
935 if (m_Status == 3) | |
936 return m_pRenderStatus->m_pDevice->ContinueDIBits(m_DeviceHandle, pPause); | |
937 | |
938 if (m_Status == 4) { | |
939 if (m_Loader.Continue(m_LoadHandle.get(), pPause)) | |
940 return TRUE; | |
941 | |
942 if (StartRenderDIBSource()) | |
943 return Continue(pPause); | |
944 } | |
945 return FALSE; | |
946 } | |
947 | |
948 CCodec_ScanlineDecoder* FPDFAPI_CreateFlateDecoder( | |
949 const uint8_t* src_buf, | |
950 uint32_t src_size, | |
951 int width, | |
952 int height, | |
953 int nComps, | |
954 int bpc, | |
955 const CPDF_Dictionary* pParams); | |
956 | |
957 CFX_DIBitmap* CPDF_RenderStatus::LoadSMask(CPDF_Dictionary* pSMaskDict, | |
958 FX_RECT* pClipRect, | |
959 const CFX_Matrix* pMatrix) { | |
960 if (!pSMaskDict) | |
961 return nullptr; | |
962 | |
963 CPDF_Stream* pGroup = pSMaskDict->GetStreamFor("G"); | |
964 if (!pGroup) | |
965 return nullptr; | |
966 | |
967 std::unique_ptr<CPDF_Function> pFunc; | |
968 CPDF_Object* pFuncObj = pSMaskDict->GetDirectObjectFor("TR"); | |
969 if (pFuncObj && (pFuncObj->IsDictionary() || pFuncObj->IsStream())) | |
970 pFunc = CPDF_Function::Load(pFuncObj); | |
971 | |
972 CFX_Matrix matrix = *pMatrix; | |
973 matrix.TranslateI(-pClipRect->left, -pClipRect->top); | |
974 | |
975 CPDF_Form form(m_pContext->GetDocument(), m_pContext->GetPageResources(), | |
976 pGroup); | |
977 form.ParseContent(nullptr, nullptr, nullptr); | |
978 | |
979 CFX_FxgeDevice bitmap_device; | |
980 FX_BOOL bLuminosity = pSMaskDict->GetStringFor("S") != "Alpha"; | |
981 int width = pClipRect->right - pClipRect->left; | |
982 int height = pClipRect->bottom - pClipRect->top; | |
983 FXDIB_Format format; | |
984 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || defined _SKIA_SUPPORT_ | |
985 format = bLuminosity ? FXDIB_Rgb32 : FXDIB_8bppMask; | |
986 #else | |
987 format = bLuminosity ? FXDIB_Rgb : FXDIB_8bppMask; | |
988 #endif | |
989 if (!bitmap_device.Create(width, height, format, nullptr)) | |
990 return nullptr; | |
991 | |
992 CFX_DIBitmap& bitmap = *bitmap_device.GetBitmap(); | |
993 int color_space_family = 0; | |
994 if (bLuminosity) { | |
995 CPDF_Array* pBC = pSMaskDict->GetArrayFor("BC"); | |
996 FX_ARGB back_color = 0xff000000; | |
997 if (pBC) { | |
998 CPDF_Object* pCSObj = nullptr; | |
999 CPDF_Dictionary* pDict = pGroup->GetDict(); | |
1000 if (pDict && pDict->GetDictFor("Group")) { | |
1001 pCSObj = pDict->GetDictFor("Group")->GetDirectObjectFor("CS"); | |
1002 } | |
1003 const CPDF_ColorSpace* pCS = | |
1004 m_pContext->GetDocument()->LoadColorSpace(pCSObj); | |
1005 if (pCS) { | |
1006 // Store Color Space Family to use in CPDF_RenderStatus::Initialize. | |
1007 color_space_family = pCS->GetFamily(); | |
1008 | |
1009 FX_FLOAT R, G, B; | |
1010 uint32_t comps = 8; | |
1011 if (pCS->CountComponents() > comps) { | |
1012 comps = pCS->CountComponents(); | |
1013 } | |
1014 CFX_FixedBufGrow<FX_FLOAT, 8> float_array(comps); | |
1015 FX_FLOAT* pFloats = float_array; | |
1016 FX_SAFE_UINT32 num_floats = comps; | |
1017 num_floats *= sizeof(FX_FLOAT); | |
1018 if (!num_floats.IsValid()) { | |
1019 return nullptr; | |
1020 } | |
1021 FXSYS_memset(pFloats, 0, num_floats.ValueOrDie()); | |
1022 size_t count = pBC->GetCount() > 8 ? 8 : pBC->GetCount(); | |
1023 for (size_t i = 0; i < count; i++) { | |
1024 pFloats[i] = pBC->GetNumberAt(i); | |
1025 } | |
1026 pCS->GetRGB(pFloats, R, G, B); | |
1027 back_color = 0xff000000 | ((int32_t)(R * 255) << 16) | | |
1028 ((int32_t)(G * 255) << 8) | (int32_t)(B * 255); | |
1029 m_pContext->GetDocument()->GetPageData()->ReleaseColorSpace(pCSObj); | |
1030 } | |
1031 } | |
1032 bitmap.Clear(back_color); | |
1033 } else { | |
1034 bitmap.Clear(0); | |
1035 } | |
1036 CPDF_Dictionary* pFormResource = nullptr; | |
1037 if (form.m_pFormDict) { | |
1038 pFormResource = form.m_pFormDict->GetDictFor("Resources"); | |
1039 } | |
1040 CPDF_RenderOptions options; | |
1041 options.m_ColorMode = bLuminosity ? RENDER_COLOR_NORMAL : RENDER_COLOR_ALPHA; | |
1042 CPDF_RenderStatus status; | |
1043 status.Initialize(m_pContext, &bitmap_device, nullptr, nullptr, nullptr, | |
1044 nullptr, &options, 0, m_bDropObjects, pFormResource, TRUE, | |
1045 nullptr, 0, color_space_family, bLuminosity); | |
1046 status.RenderObjectList(&form, &matrix); | |
1047 std::unique_ptr<CFX_DIBitmap> pMask(new CFX_DIBitmap); | |
1048 if (!pMask->Create(width, height, FXDIB_8bppMask)) | |
1049 return nullptr; | |
1050 | |
1051 uint8_t* dest_buf = pMask->GetBuffer(); | |
1052 int dest_pitch = pMask->GetPitch(); | |
1053 uint8_t* src_buf = bitmap.GetBuffer(); | |
1054 int src_pitch = bitmap.GetPitch(); | |
1055 std::vector<uint8_t> transfers(256); | |
1056 if (pFunc) { | |
1057 CFX_FixedBufGrow<FX_FLOAT, 16> results(pFunc->CountOutputs()); | |
1058 for (int i = 0; i < 256; i++) { | |
1059 FX_FLOAT input = (FX_FLOAT)i / 255.0f; | |
1060 int nresult; | |
1061 pFunc->Call(&input, 1, results, nresult); | |
1062 transfers[i] = FXSYS_round(results[0] * 255); | |
1063 } | |
1064 } else { | |
1065 for (int i = 0; i < 256; i++) { | |
1066 transfers[i] = i; | |
1067 } | |
1068 } | |
1069 if (bLuminosity) { | |
1070 int Bpp = bitmap.GetBPP() / 8; | |
1071 for (int row = 0; row < height; row++) { | |
1072 uint8_t* dest_pos = dest_buf + row * dest_pitch; | |
1073 uint8_t* src_pos = src_buf + row * src_pitch; | |
1074 for (int col = 0; col < width; col++) { | |
1075 *dest_pos++ = transfers[FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos)]; | |
1076 src_pos += Bpp; | |
1077 } | |
1078 } | |
1079 } else if (pFunc) { | |
1080 int size = dest_pitch * height; | |
1081 for (int i = 0; i < size; i++) { | |
1082 dest_buf[i] = transfers[src_buf[i]]; | |
1083 } | |
1084 } else { | |
1085 FXSYS_memcpy(dest_buf, src_buf, dest_pitch * height); | |
1086 } | |
1087 return pMask.release(); | |
1088 } | |
OLD | NEW |