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/fxge/fx_dib.h"
8
9 #include <limits.h>
10
11 #include <algorithm>
12 #include <memory>
13 #include <utility>
14
15 #include "core/fxcodec/fx_codec.h"
16 #include "core/fxcrt/cfx_maybe_owned.h"
17 #include "core/fxge/cfx_gemodule.h"
18 #include "core/fxge/dib/dib_int.h"
19 #include "core/fxge/ge/cfx_cliprgn.h"
20 #include "third_party/base/ptr_util.h"
21
CmykDecode(uint32_t cmyk,int & c,int & m,int & y,int & k)22 void CmykDecode(uint32_t cmyk, int& c, int& m, int& y, int& k) {
23 c = FXSYS_GetCValue(cmyk);
24 m = FXSYS_GetMValue(cmyk);
25 y = FXSYS_GetYValue(cmyk);
26 k = FXSYS_GetKValue(cmyk);
27 }
28
ArgbDecode(uint32_t argb,int & a,int & r,int & g,int & b)29 void ArgbDecode(uint32_t argb, int& a, int& r, int& g, int& b) {
30 a = FXARGB_A(argb);
31 r = FXARGB_R(argb);
32 g = FXARGB_G(argb);
33 b = FXARGB_B(argb);
34 }
35
ArgbDecode(uint32_t argb,int & a,FX_COLORREF & rgb)36 void ArgbDecode(uint32_t argb, int& a, FX_COLORREF& rgb) {
37 a = FXARGB_A(argb);
38 rgb = FXSYS_RGB(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb));
39 }
40
ArgbEncode(int a,FX_COLORREF rgb)41 uint32_t ArgbEncode(int a, FX_COLORREF rgb) {
42 return FXARGB_MAKE(a, FXSYS_GetRValue(rgb), FXSYS_GetGValue(rgb),
43 FXSYS_GetBValue(rgb));
44 }
45
CFX_DIBSource()46 CFX_DIBSource::CFX_DIBSource()
47 : m_pAlphaMask(nullptr),
48 m_Width(0),
49 m_Height(0),
50 m_bpp(0),
51 m_AlphaFlag(0),
52 m_Pitch(0) {}
53
~CFX_DIBSource()54 CFX_DIBSource::~CFX_DIBSource() {
55 delete m_pAlphaMask;
56 }
57
GetBuffer() const58 uint8_t* CFX_DIBSource::GetBuffer() const {
59 return nullptr;
60 }
61
SkipToScanline(int line,IFX_Pause * pPause) const62 bool CFX_DIBSource::SkipToScanline(int line, IFX_Pause* pPause) const {
63 return false;
64 }
65
CFX_DIBitmap()66 CFX_DIBitmap::CFX_DIBitmap() {
67 m_bExtBuf = false;
68 m_pBuffer = nullptr;
69 m_pPalette = nullptr;
70 #ifdef _SKIA_SUPPORT_PATHS_
71 m_nFormat = Format::kCleared;
72 #endif
73 }
74
75 #define _MAX_OOM_LIMIT_ 12000000
Create(int width,int height,FXDIB_Format format,uint8_t * pBuffer,int pitch)76 bool CFX_DIBitmap::Create(int width,
77 int height,
78 FXDIB_Format format,
79 uint8_t* pBuffer,
80 int pitch) {
81 m_pBuffer = nullptr;
82 m_bpp = (uint8_t)format;
83 m_AlphaFlag = (uint8_t)(format >> 8);
84 m_Width = m_Height = m_Pitch = 0;
85 if (width <= 0 || height <= 0 || pitch < 0) {
86 return false;
87 }
88 if ((INT_MAX - 31) / width < (format & 0xff)) {
89 return false;
90 }
91 if (!pitch) {
92 pitch = (width * (format & 0xff) + 31) / 32 * 4;
93 }
94 if ((1 << 30) / pitch < height) {
95 return false;
96 }
97 if (pBuffer) {
98 m_pBuffer = pBuffer;
99 m_bExtBuf = true;
100 } else {
101 int size = pitch * height + 4;
102 int oomlimit = _MAX_OOM_LIMIT_;
103 if (oomlimit >= 0 && size >= oomlimit) {
104 m_pBuffer = FX_TryAlloc(uint8_t, size);
105 if (!m_pBuffer) {
106 return false;
107 }
108 } else {
109 m_pBuffer = FX_Alloc(uint8_t, size);
110 }
111 }
112 m_Width = width;
113 m_Height = height;
114 m_Pitch = pitch;
115 if (HasAlpha() && format != FXDIB_Argb) {
116 bool ret = true;
117 ret = BuildAlphaMask();
118 if (!ret) {
119 if (!m_bExtBuf) {
120 FX_Free(m_pBuffer);
121 m_pBuffer = nullptr;
122 m_Width = m_Height = m_Pitch = 0;
123 return false;
124 }
125 }
126 }
127 return true;
128 }
129
Copy(const CFX_DIBSource * pSrc)130 bool CFX_DIBitmap::Copy(const CFX_DIBSource* pSrc) {
131 if (m_pBuffer)
132 return false;
133
134 if (!Create(pSrc->GetWidth(), pSrc->GetHeight(), pSrc->GetFormat()))
135 return false;
136
137 SetPalette(pSrc->GetPalette());
138 SetAlphaMask(pSrc->m_pAlphaMask);
139 for (int row = 0; row < pSrc->GetHeight(); row++)
140 FXSYS_memcpy(m_pBuffer + row * m_Pitch, pSrc->GetScanline(row), m_Pitch);
141
142 return true;
143 }
144
~CFX_DIBitmap()145 CFX_DIBitmap::~CFX_DIBitmap() {
146 if (!m_bExtBuf)
147 FX_Free(m_pBuffer);
148
149 m_pBuffer = nullptr;
150 }
151
GetBuffer() const152 uint8_t* CFX_DIBitmap::GetBuffer() const {
153 return m_pBuffer;
154 }
155
GetScanline(int line) const156 const uint8_t* CFX_DIBitmap::GetScanline(int line) const {
157 return m_pBuffer ? m_pBuffer + line * m_Pitch : nullptr;
158 }
159
TakeOver(CFX_DIBitmap * pSrcBitmap)160 void CFX_DIBitmap::TakeOver(CFX_DIBitmap* pSrcBitmap) {
161 if (!m_bExtBuf)
162 FX_Free(m_pBuffer);
163
164 delete m_pAlphaMask;
165 m_pBuffer = pSrcBitmap->m_pBuffer;
166 m_pPalette = std::move(pSrcBitmap->m_pPalette);
167 m_pAlphaMask = pSrcBitmap->m_pAlphaMask;
168 pSrcBitmap->m_pBuffer = nullptr;
169 pSrcBitmap->m_pAlphaMask = nullptr;
170 m_bpp = pSrcBitmap->m_bpp;
171 m_bExtBuf = pSrcBitmap->m_bExtBuf;
172 m_AlphaFlag = pSrcBitmap->m_AlphaFlag;
173 m_Width = pSrcBitmap->m_Width;
174 m_Height = pSrcBitmap->m_Height;
175 m_Pitch = pSrcBitmap->m_Pitch;
176 }
177
Clone(const FX_RECT * pClip) const178 std::unique_ptr<CFX_DIBitmap> CFX_DIBSource::Clone(const FX_RECT* pClip) const {
179 FX_RECT rect(0, 0, m_Width, m_Height);
180 if (pClip) {
181 rect.Intersect(*pClip);
182 if (rect.IsEmpty())
183 return nullptr;
184 }
185 auto pNewBitmap = pdfium::MakeUnique<CFX_DIBitmap>();
186 if (!pNewBitmap->Create(rect.Width(), rect.Height(), GetFormat()))
187 return nullptr;
188
189 pNewBitmap->SetPalette(m_pPalette.get());
190 pNewBitmap->SetAlphaMask(m_pAlphaMask, pClip);
191 if (GetBPP() == 1 && rect.left % 8 != 0) {
192 int left_shift = rect.left % 32;
193 int right_shift = 32 - left_shift;
194 int dword_count = pNewBitmap->m_Pitch / 4;
195 for (int row = rect.top; row < rect.bottom; row++) {
196 uint32_t* src_scan = (uint32_t*)GetScanline(row) + rect.left / 32;
197 uint32_t* dest_scan = (uint32_t*)pNewBitmap->GetScanline(row - rect.top);
198 for (int i = 0; i < dword_count; i++) {
199 dest_scan[i] =
200 (src_scan[i] << left_shift) | (src_scan[i + 1] >> right_shift);
201 }
202 }
203 } else {
204 int copy_len = (pNewBitmap->GetWidth() * pNewBitmap->GetBPP() + 7) / 8;
205 if (m_Pitch < (uint32_t)copy_len)
206 copy_len = m_Pitch;
207
208 for (int row = rect.top; row < rect.bottom; row++) {
209 const uint8_t* src_scan = GetScanline(row) + rect.left * m_bpp / 8;
210 uint8_t* dest_scan = (uint8_t*)pNewBitmap->GetScanline(row - rect.top);
211 FXSYS_memcpy(dest_scan, src_scan, copy_len);
212 }
213 }
214 return pNewBitmap;
215 }
216
BuildPalette()217 void CFX_DIBSource::BuildPalette() {
218 if (m_pPalette)
219 return;
220
221 if (GetBPP() == 1) {
222 m_pPalette.reset(FX_Alloc(uint32_t, 2));
223 if (IsCmykImage()) {
224 m_pPalette.get()[0] = 0xff;
225 m_pPalette.get()[1] = 0;
226 } else {
227 m_pPalette.get()[0] = 0xff000000;
228 m_pPalette.get()[1] = 0xffffffff;
229 }
230 } else if (GetBPP() == 8) {
231 m_pPalette.reset(FX_Alloc(uint32_t, 256));
232 if (IsCmykImage()) {
233 for (int i = 0; i < 256; i++)
234 m_pPalette.get()[i] = 0xff - i;
235 } else {
236 for (int i = 0; i < 256; i++)
237 m_pPalette.get()[i] = 0xff000000 | (i * 0x10101);
238 }
239 }
240 }
241
BuildAlphaMask()242 bool CFX_DIBSource::BuildAlphaMask() {
243 if (m_pAlphaMask) {
244 return true;
245 }
246 m_pAlphaMask = new CFX_DIBitmap;
247 if (!m_pAlphaMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {
248 delete m_pAlphaMask;
249 m_pAlphaMask = nullptr;
250 return false;
251 }
252 FXSYS_memset(m_pAlphaMask->GetBuffer(), 0xff,
253 m_pAlphaMask->GetHeight() * m_pAlphaMask->GetPitch());
254 return true;
255 }
256
GetPaletteEntry(int index) const257 uint32_t CFX_DIBSource::GetPaletteEntry(int index) const {
258 ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask());
259 if (m_pPalette) {
260 return m_pPalette.get()[index];
261 }
262 if (IsCmykImage()) {
263 if (GetBPP() == 1) {
264 return index ? 0 : 0xff;
265 }
266 return 0xff - index;
267 }
268 if (GetBPP() == 1) {
269 return index ? 0xffffffff : 0xff000000;
270 }
271 return index * 0x10101 | 0xff000000;
272 }
273
SetPaletteEntry(int index,uint32_t color)274 void CFX_DIBSource::SetPaletteEntry(int index, uint32_t color) {
275 ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask());
276 if (!m_pPalette) {
277 BuildPalette();
278 }
279 m_pPalette.get()[index] = color;
280 }
281
FindPalette(uint32_t color) const282 int CFX_DIBSource::FindPalette(uint32_t color) const {
283 ASSERT((GetBPP() == 1 || GetBPP() == 8) && !IsAlphaMask());
284 if (!m_pPalette) {
285 if (IsCmykImage()) {
286 if (GetBPP() == 1) {
287 return ((uint8_t)color == 0xff) ? 0 : 1;
288 }
289 return 0xff - (uint8_t)color;
290 }
291 if (GetBPP() == 1) {
292 return ((uint8_t)color == 0xff) ? 1 : 0;
293 }
294 return (uint8_t)color;
295 }
296 int palsize = (1 << GetBPP());
297 for (int i = 0; i < palsize; i++)
298 if (m_pPalette.get()[i] == color) {
299 return i;
300 }
301 return -1;
302 }
303
Clear(uint32_t color)304 void CFX_DIBitmap::Clear(uint32_t color) {
305 if (!m_pBuffer) {
306 return;
307 }
308 switch (GetFormat()) {
309 case FXDIB_1bppMask:
310 FXSYS_memset(m_pBuffer, (color & 0xff000000) ? 0xff : 0,
311 m_Pitch * m_Height);
312 break;
313 case FXDIB_1bppRgb: {
314 int index = FindPalette(color);
315 FXSYS_memset(m_pBuffer, index ? 0xff : 0, m_Pitch * m_Height);
316 break;
317 }
318 case FXDIB_8bppMask:
319 FXSYS_memset(m_pBuffer, color >> 24, m_Pitch * m_Height);
320 break;
321 case FXDIB_8bppRgb: {
322 int index = FindPalette(color);
323 FXSYS_memset(m_pBuffer, index, m_Pitch * m_Height);
324 break;
325 }
326 case FXDIB_Rgb:
327 case FXDIB_Rgba: {
328 int a, r, g, b;
329 ArgbDecode(color, a, r, g, b);
330 if (r == g && g == b) {
331 FXSYS_memset(m_pBuffer, r, m_Pitch * m_Height);
332 } else {
333 int byte_pos = 0;
334 for (int col = 0; col < m_Width; col++) {
335 m_pBuffer[byte_pos++] = b;
336 m_pBuffer[byte_pos++] = g;
337 m_pBuffer[byte_pos++] = r;
338 }
339 for (int row = 1; row < m_Height; row++) {
340 FXSYS_memcpy(m_pBuffer + row * m_Pitch, m_pBuffer, m_Pitch);
341 }
342 }
343 break;
344 }
345 case FXDIB_Rgb32:
346 case FXDIB_Argb: {
347 color = IsCmykImage() ? FXCMYK_TODIB(color) : FXARGB_TODIB(color);
348 #ifdef _SKIA_SUPPORT_
349 if (FXDIB_Rgb32 == GetFormat() && !IsCmykImage()) {
350 color |= 0xFF000000;
351 }
352 #endif
353 for (int i = 0; i < m_Width; i++) {
354 ((uint32_t*)m_pBuffer)[i] = color;
355 }
356 for (int row = 1; row < m_Height; row++) {
357 FXSYS_memcpy(m_pBuffer + row * m_Pitch, m_pBuffer, m_Pitch);
358 }
359 break;
360 }
361 default:
362 break;
363 }
364 }
365
GetOverlapRect(int & dest_left,int & dest_top,int & width,int & height,int src_width,int src_height,int & src_left,int & src_top,const CFX_ClipRgn * pClipRgn)366 void CFX_DIBSource::GetOverlapRect(int& dest_left,
367 int& dest_top,
368 int& width,
369 int& height,
370 int src_width,
371 int src_height,
372 int& src_left,
373 int& src_top,
374 const CFX_ClipRgn* pClipRgn) {
375 if (width == 0 || height == 0) {
376 return;
377 }
378 ASSERT(width > 0 && height > 0);
379 if (dest_left > m_Width || dest_top > m_Height) {
380 width = 0;
381 height = 0;
382 return;
383 }
384 int x_offset = dest_left - src_left;
385 int y_offset = dest_top - src_top;
386 FX_RECT src_rect(src_left, src_top, src_left + width, src_top + height);
387 FX_RECT src_bound(0, 0, src_width, src_height);
388 src_rect.Intersect(src_bound);
389 FX_RECT dest_rect(src_rect.left + x_offset, src_rect.top + y_offset,
390 src_rect.right + x_offset, src_rect.bottom + y_offset);
391 FX_RECT dest_bound(0, 0, m_Width, m_Height);
392 dest_rect.Intersect(dest_bound);
393 if (pClipRgn) {
394 dest_rect.Intersect(pClipRgn->GetBox());
395 }
396 dest_left = dest_rect.left;
397 dest_top = dest_rect.top;
398 src_left = dest_left - x_offset;
399 src_top = dest_top - y_offset;
400 width = dest_rect.right - dest_rect.left;
401 height = dest_rect.bottom - dest_rect.top;
402 }
403
TransferBitmap(int dest_left,int dest_top,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top)404 bool CFX_DIBitmap::TransferBitmap(int dest_left,
405 int dest_top,
406 int width,
407 int height,
408 const CFX_DIBSource* pSrcBitmap,
409 int src_left,
410 int src_top) {
411 if (!m_pBuffer)
412 return false;
413
414 GetOverlapRect(dest_left, dest_top, width, height, pSrcBitmap->GetWidth(),
415 pSrcBitmap->GetHeight(), src_left, src_top, nullptr);
416 if (width == 0 || height == 0)
417 return true;
418
419 FXDIB_Format dest_format = GetFormat();
420 FXDIB_Format src_format = pSrcBitmap->GetFormat();
421 if (dest_format == src_format) {
422 if (GetBPP() == 1) {
423 for (int row = 0; row < height; row++) {
424 uint8_t* dest_scan = m_pBuffer + (dest_top + row) * m_Pitch;
425 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
426 for (int col = 0; col < width; col++) {
427 if (src_scan[(src_left + col) / 8] &
428 (1 << (7 - (src_left + col) % 8))) {
429 dest_scan[(dest_left + col) / 8] |= 1
430 << (7 - (dest_left + col) % 8);
431 } else {
432 dest_scan[(dest_left + col) / 8] &=
433 ~(1 << (7 - (dest_left + col) % 8));
434 }
435 }
436 }
437 } else {
438 int Bpp = GetBPP() / 8;
439 for (int row = 0; row < height; row++) {
440 uint8_t* dest_scan =
441 m_pBuffer + (dest_top + row) * m_Pitch + dest_left * Bpp;
442 const uint8_t* src_scan =
443 pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp;
444 FXSYS_memcpy(dest_scan, src_scan, width * Bpp);
445 }
446 }
447 } else {
448 if (m_pPalette)
449 return false;
450
451 if (m_bpp == 8)
452 dest_format = FXDIB_8bppMask;
453
454 uint8_t* dest_buf =
455 m_pBuffer + dest_top * m_Pitch + dest_left * GetBPP() / 8;
456 std::unique_ptr<uint32_t, FxFreeDeleter> d_plt;
457 if (!ConvertBuffer(dest_format, dest_buf, m_Pitch, width, height,
458 pSrcBitmap, src_left, src_top, &d_plt)) {
459 return false;
460 }
461 }
462 return true;
463 }
464
TransferMask(int dest_left,int dest_top,int width,int height,const CFX_DIBSource * pMask,uint32_t color,int src_left,int src_top,int alpha_flag,void * pIccTransform)465 bool CFX_DIBitmap::TransferMask(int dest_left,
466 int dest_top,
467 int width,
468 int height,
469 const CFX_DIBSource* pMask,
470 uint32_t color,
471 int src_left,
472 int src_top,
473 int alpha_flag,
474 void* pIccTransform) {
475 if (!m_pBuffer) {
476 return false;
477 }
478 ASSERT(HasAlpha() && (m_bpp >= 24));
479 ASSERT(pMask->IsAlphaMask());
480 if (!HasAlpha() || !pMask->IsAlphaMask() || m_bpp < 24) {
481 return false;
482 }
483 GetOverlapRect(dest_left, dest_top, width, height, pMask->GetWidth(),
484 pMask->GetHeight(), src_left, src_top, nullptr);
485 if (width == 0 || height == 0) {
486 return true;
487 }
488 int src_bpp = pMask->GetBPP();
489 int alpha;
490 uint32_t dst_color;
491 if (alpha_flag >> 8) {
492 alpha = alpha_flag & 0xff;
493 dst_color = FXCMYK_TODIB(color);
494 } else {
495 alpha = FXARGB_A(color);
496 dst_color = FXARGB_TODIB(color);
497 }
498 uint8_t* color_p = (uint8_t*)&dst_color;
499 if (pIccTransform && CFX_GEModule::Get()->GetCodecModule() &&
500 CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) {
501 CCodec_IccModule* pIccModule =
502 CFX_GEModule::Get()->GetCodecModule()->GetIccModule();
503 pIccModule->TranslateScanline(pIccTransform, color_p, color_p, 1);
504 } else {
505 if (alpha_flag >> 8 && !IsCmykImage()) {
506 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color),
507 FXSYS_GetYValue(color), FXSYS_GetKValue(color),
508 color_p[2], color_p[1], color_p[0]);
509 } else if (!(alpha_flag >> 8) && IsCmykImage()) {
510 return false;
511 }
512 }
513 if (!IsCmykImage()) {
514 color_p[3] = (uint8_t)alpha;
515 }
516 if (GetFormat() == FXDIB_Argb) {
517 for (int row = 0; row < height; row++) {
518 uint32_t* dest_pos =
519 (uint32_t*)(m_pBuffer + (dest_top + row) * m_Pitch + dest_left * 4);
520 const uint8_t* src_scan = pMask->GetScanline(src_top + row);
521 if (src_bpp == 1) {
522 for (int col = 0; col < width; col++) {
523 int src_bitpos = src_left + col;
524 if (src_scan[src_bitpos / 8] & (1 << (7 - src_bitpos % 8))) {
525 *dest_pos = dst_color;
526 } else {
527 *dest_pos = 0;
528 }
529 dest_pos++;
530 }
531 } else {
532 src_scan += src_left;
533 dst_color = FXARGB_TODIB(dst_color);
534 dst_color &= 0xffffff;
535 for (int col = 0; col < width; col++) {
536 FXARGB_SETDIB(dest_pos++,
537 dst_color | ((alpha * (*src_scan++) / 255) << 24));
538 }
539 }
540 }
541 } else {
542 int comps = m_bpp / 8;
543 for (int row = 0; row < height; row++) {
544 uint8_t* dest_color_pos =
545 m_pBuffer + (dest_top + row) * m_Pitch + dest_left * comps;
546 uint8_t* dest_alpha_pos =
547 (uint8_t*)m_pAlphaMask->GetScanline(dest_top + row) + dest_left;
548 const uint8_t* src_scan = pMask->GetScanline(src_top + row);
549 if (src_bpp == 1) {
550 for (int col = 0; col < width; col++) {
551 int src_bitpos = src_left + col;
552 if (src_scan[src_bitpos / 8] & (1 << (7 - src_bitpos % 8))) {
553 FXSYS_memcpy(dest_color_pos, color_p, comps);
554 *dest_alpha_pos = 0xff;
555 } else {
556 FXSYS_memset(dest_color_pos, 0, comps);
557 *dest_alpha_pos = 0;
558 }
559 dest_color_pos += comps;
560 dest_alpha_pos++;
561 }
562 } else {
563 src_scan += src_left;
564 for (int col = 0; col < width; col++) {
565 FXSYS_memcpy(dest_color_pos, color_p, comps);
566 dest_color_pos += comps;
567 *dest_alpha_pos++ = (alpha * (*src_scan++) / 255);
568 }
569 }
570 }
571 }
572 return true;
573 }
574
SetPalette(const uint32_t * pSrc)575 void CFX_DIBSource::SetPalette(const uint32_t* pSrc) {
576 static const uint32_t kPaletteSize = 256;
577 if (!pSrc || GetBPP() > 8) {
578 m_pPalette.reset();
579 return;
580 }
581 uint32_t pal_size = 1 << GetBPP();
582 if (!m_pPalette)
583 m_pPalette.reset(FX_Alloc(uint32_t, pal_size));
584 pal_size = std::min(pal_size, kPaletteSize);
585 FXSYS_memcpy(m_pPalette.get(), pSrc, pal_size * sizeof(uint32_t));
586 }
587
GetPalette(uint32_t * pal,int alpha) const588 void CFX_DIBSource::GetPalette(uint32_t* pal, int alpha) const {
589 ASSERT(GetBPP() <= 8 && !IsCmykImage());
590 if (GetBPP() == 1) {
591 pal[0] = ((m_pPalette ? m_pPalette.get()[0] : 0xff000000) & 0xffffff) |
592 (alpha << 24);
593 pal[1] = ((m_pPalette ? m_pPalette.get()[1] : 0xffffffff) & 0xffffff) |
594 (alpha << 24);
595 return;
596 }
597 if (m_pPalette) {
598 for (int i = 0; i < 256; i++) {
599 pal[i] = (m_pPalette.get()[i] & 0x00ffffff) | (alpha << 24);
600 }
601 } else {
602 for (int i = 0; i < 256; i++) {
603 pal[i] = (i * 0x10101) | (alpha << 24);
604 }
605 }
606 }
607
CloneAlphaMask(const FX_RECT * pClip) const608 std::unique_ptr<CFX_DIBitmap> CFX_DIBSource::CloneAlphaMask(
609 const FX_RECT* pClip) const {
610 ASSERT(GetFormat() == FXDIB_Argb);
611 FX_RECT rect(0, 0, m_Width, m_Height);
612 if (pClip) {
613 rect.Intersect(*pClip);
614 if (rect.IsEmpty())
615 return nullptr;
616 }
617 auto pMask = pdfium::MakeUnique<CFX_DIBitmap>();
618 if (!pMask->Create(rect.Width(), rect.Height(), FXDIB_8bppMask))
619 return nullptr;
620
621 for (int row = rect.top; row < rect.bottom; row++) {
622 const uint8_t* src_scan = GetScanline(row) + rect.left * 4 + 3;
623 uint8_t* dest_scan =
624 const_cast<uint8_t*>(pMask->GetScanline(row - rect.top));
625 for (int col = rect.left; col < rect.right; col++) {
626 *dest_scan++ = *src_scan;
627 src_scan += 4;
628 }
629 }
630 return pMask;
631 }
632
SetAlphaMask(const CFX_DIBSource * pAlphaMask,const FX_RECT * pClip)633 bool CFX_DIBSource::SetAlphaMask(const CFX_DIBSource* pAlphaMask,
634 const FX_RECT* pClip) {
635 if (!HasAlpha() || GetFormat() == FXDIB_Argb)
636 return false;
637
638 if (!pAlphaMask) {
639 m_pAlphaMask->Clear(0xff000000);
640 return true;
641 }
642 FX_RECT rect(0, 0, pAlphaMask->m_Width, pAlphaMask->m_Height);
643 if (pClip) {
644 rect.Intersect(*pClip);
645 if (rect.IsEmpty() || rect.Width() != m_Width ||
646 rect.Height() != m_Height) {
647 return false;
648 }
649 } else {
650 if (pAlphaMask->m_Width != m_Width || pAlphaMask->m_Height != m_Height)
651 return false;
652 }
653 for (int row = 0; row < m_Height; row++) {
654 FXSYS_memcpy(const_cast<uint8_t*>(m_pAlphaMask->GetScanline(row)),
655 pAlphaMask->GetScanline(row + rect.top) + rect.left,
656 m_pAlphaMask->m_Pitch);
657 }
658 return true;
659 }
660
661 const int g_ChannelOffset[] = {0, 2, 1, 0, 0, 1, 2, 3, 3};
LoadChannel(FXDIB_Channel destChannel,CFX_DIBSource * pSrcBitmap,FXDIB_Channel srcChannel)662 bool CFX_DIBitmap::LoadChannel(FXDIB_Channel destChannel,
663 CFX_DIBSource* pSrcBitmap,
664 FXDIB_Channel srcChannel) {
665 if (!m_pBuffer)
666 return false;
667
668 CFX_MaybeOwned<CFX_DIBSource> pSrcClone(pSrcBitmap);
669 int srcOffset;
670 if (srcChannel == FXDIB_Alpha) {
671 if (!pSrcBitmap->HasAlpha() && !pSrcBitmap->IsAlphaMask())
672 return false;
673
674 if (pSrcBitmap->GetBPP() == 1) {
675 pSrcClone = pSrcBitmap->CloneConvert(FXDIB_8bppMask);
676 if (!pSrcClone)
677 return false;
678 }
679 srcOffset = pSrcBitmap->GetFormat() == FXDIB_Argb ? 3 : 0;
680 } else {
681 if (pSrcBitmap->IsAlphaMask())
682 return false;
683
684 if (pSrcBitmap->GetBPP() < 24) {
685 if (pSrcBitmap->IsCmykImage()) {
686 pSrcClone = pSrcBitmap->CloneConvert(static_cast<FXDIB_Format>(
687 (pSrcBitmap->GetFormat() & 0xff00) | 0x20));
688 } else {
689 pSrcClone = pSrcBitmap->CloneConvert(static_cast<FXDIB_Format>(
690 (pSrcBitmap->GetFormat() & 0xff00) | 0x18));
691 }
692 if (!pSrcClone)
693 return false;
694 }
695 srcOffset = g_ChannelOffset[srcChannel];
696 }
697 int destOffset = 0;
698 if (destChannel == FXDIB_Alpha) {
699 if (IsAlphaMask()) {
700 if (!ConvertFormat(FXDIB_8bppMask))
701 return false;
702 } else {
703 if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb))
704 return false;
705
706 if (GetFormat() == FXDIB_Argb)
707 destOffset = 3;
708 }
709 } else {
710 if (IsAlphaMask())
711 return false;
712
713 if (GetBPP() < 24) {
714 if (HasAlpha()) {
715 if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb))
716 return false;
717 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
718 } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb32)) {
719 #else
720 } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb)) {
721 #endif
722 return false;
723 }
724 }
725 destOffset = g_ChannelOffset[destChannel];
726 }
727 if (srcChannel == FXDIB_Alpha && pSrcClone->m_pAlphaMask) {
728 CFX_MaybeOwned<CFX_DIBSource> pAlphaMask(pSrcClone->m_pAlphaMask);
729 if (pSrcClone->GetWidth() != m_Width ||
730 pSrcClone->GetHeight() != m_Height) {
731 if (pAlphaMask) {
732 pAlphaMask = pAlphaMask->StretchTo(m_Width, m_Height);
733 if (!pAlphaMask)
734 return false;
735 }
736 }
737 pSrcClone = std::move(pAlphaMask);
738 srcOffset = 0;
739 } else if (pSrcClone->GetWidth() != m_Width ||
740 pSrcClone->GetHeight() != m_Height) {
741 std::unique_ptr<CFX_DIBitmap> pSrcMatched =
742 pSrcClone->StretchTo(m_Width, m_Height);
743 if (!pSrcMatched)
744 return false;
745
746 pSrcClone = std::move(pSrcMatched);
747 }
748 CFX_DIBitmap* pDst = this;
749 if (destChannel == FXDIB_Alpha && m_pAlphaMask) {
750 pDst = m_pAlphaMask;
751 destOffset = 0;
752 }
753 int srcBytes = pSrcClone->GetBPP() / 8;
754 int destBytes = pDst->GetBPP() / 8;
755 for (int row = 0; row < m_Height; row++) {
756 uint8_t* dest_pos = (uint8_t*)pDst->GetScanline(row) + destOffset;
757 const uint8_t* src_pos = pSrcClone->GetScanline(row) + srcOffset;
758 for (int col = 0; col < m_Width; col++) {
759 *dest_pos = *src_pos;
760 dest_pos += destBytes;
761 src_pos += srcBytes;
762 }
763 }
764 return true;
765 }
766
LoadChannel(FXDIB_Channel destChannel,int value)767 bool CFX_DIBitmap::LoadChannel(FXDIB_Channel destChannel, int value) {
768 if (!m_pBuffer) {
769 return false;
770 }
771 int destOffset;
772 if (destChannel == FXDIB_Alpha) {
773 if (IsAlphaMask()) {
774 if (!ConvertFormat(FXDIB_8bppMask)) {
775 return false;
776 }
777 destOffset = 0;
778 } else {
779 destOffset = 0;
780 if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) {
781 return false;
782 }
783 if (GetFormat() == FXDIB_Argb) {
784 destOffset = 3;
785 }
786 }
787 } else {
788 if (IsAlphaMask()) {
789 return false;
790 }
791 if (GetBPP() < 24) {
792 if (HasAlpha()) {
793 if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) {
794 return false;
795 }
796 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
797 } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb)) {
798 #else
799 } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb32)) {
800 #endif
801 return false;
802 }
803 }
804 destOffset = g_ChannelOffset[destChannel];
805 }
806 int Bpp = GetBPP() / 8;
807 if (Bpp == 1) {
808 FXSYS_memset(m_pBuffer, value, m_Height * m_Pitch);
809 return true;
810 }
811 if (destChannel == FXDIB_Alpha && m_pAlphaMask) {
812 FXSYS_memset(m_pAlphaMask->GetBuffer(), value,
813 m_pAlphaMask->GetHeight() * m_pAlphaMask->GetPitch());
814 return true;
815 }
816 for (int row = 0; row < m_Height; row++) {
817 uint8_t* scan_line = m_pBuffer + row * m_Pitch + destOffset;
818 for (int col = 0; col < m_Width; col++) {
819 *scan_line = value;
820 scan_line += Bpp;
821 }
822 }
823 return true;
824 }
825
MultiplyAlpha(CFX_DIBSource * pSrcBitmap)826 bool CFX_DIBitmap::MultiplyAlpha(CFX_DIBSource* pSrcBitmap) {
827 if (!m_pBuffer)
828 return false;
829
830 ASSERT(pSrcBitmap->IsAlphaMask());
831 if (!pSrcBitmap->IsAlphaMask())
832 return false;
833
834 if (!IsAlphaMask() && !HasAlpha())
835 return LoadChannel(FXDIB_Alpha, pSrcBitmap, FXDIB_Alpha);
836
837 CFX_MaybeOwned<CFX_DIBitmap> pSrcClone(
838 static_cast<CFX_DIBitmap*>(pSrcBitmap));
839 if (pSrcBitmap->GetWidth() != m_Width ||
840 pSrcBitmap->GetHeight() != m_Height) {
841 pSrcClone = pSrcBitmap->StretchTo(m_Width, m_Height);
842 if (!pSrcClone)
843 return false;
844 }
845 if (IsAlphaMask()) {
846 if (!ConvertFormat(FXDIB_8bppMask))
847 return false;
848
849 for (int row = 0; row < m_Height; row++) {
850 uint8_t* dest_scan = m_pBuffer + m_Pitch * row;
851 uint8_t* src_scan = pSrcClone->m_pBuffer + pSrcClone->m_Pitch * row;
852 if (pSrcClone->GetBPP() == 1) {
853 for (int col = 0; col < m_Width; col++) {
854 if (!((1 << (7 - col % 8)) & src_scan[col / 8]))
855 dest_scan[col] = 0;
856 }
857 } else {
858 for (int col = 0; col < m_Width; col++) {
859 *dest_scan = (*dest_scan) * src_scan[col] / 255;
860 dest_scan++;
861 }
862 }
863 }
864 } else {
865 if (GetFormat() == FXDIB_Argb) {
866 if (pSrcClone->GetBPP() == 1)
867 return false;
868
869 for (int row = 0; row < m_Height; row++) {
870 uint8_t* dest_scan = m_pBuffer + m_Pitch * row + 3;
871 uint8_t* src_scan = pSrcClone->m_pBuffer + pSrcClone->m_Pitch * row;
872 for (int col = 0; col < m_Width; col++) {
873 *dest_scan = (*dest_scan) * src_scan[col] / 255;
874 dest_scan += 4;
875 }
876 }
877 } else {
878 m_pAlphaMask->MultiplyAlpha(pSrcClone.Get());
879 }
880 }
881 return true;
882 }
883
GetGrayData(void * pIccTransform)884 bool CFX_DIBitmap::GetGrayData(void* pIccTransform) {
885 if (!m_pBuffer) {
886 return false;
887 }
888 switch (GetFormat()) {
889 case FXDIB_1bppRgb: {
890 if (!m_pPalette) {
891 return false;
892 }
893 uint8_t gray[2];
894 for (int i = 0; i < 2; i++) {
895 int r = static_cast<uint8_t>(m_pPalette.get()[i] >> 16);
896 int g = static_cast<uint8_t>(m_pPalette.get()[i] >> 8);
897 int b = static_cast<uint8_t>(m_pPalette.get()[i]);
898 gray[i] = static_cast<uint8_t>(FXRGB2GRAY(r, g, b));
899 }
900 CFX_DIBitmap* pMask = new CFX_DIBitmap;
901 if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {
902 delete pMask;
903 return false;
904 }
905 FXSYS_memset(pMask->GetBuffer(), gray[0], pMask->GetPitch() * m_Height);
906 for (int row = 0; row < m_Height; row++) {
907 uint8_t* src_pos = m_pBuffer + row * m_Pitch;
908 uint8_t* dest_pos = (uint8_t*)pMask->GetScanline(row);
909 for (int col = 0; col < m_Width; col++) {
910 if (src_pos[col / 8] & (1 << (7 - col % 8))) {
911 *dest_pos = gray[1];
912 }
913 dest_pos++;
914 }
915 }
916 TakeOver(pMask);
917 delete pMask;
918 break;
919 }
920 case FXDIB_8bppRgb: {
921 if (!m_pPalette) {
922 return false;
923 }
924 uint8_t gray[256];
925 for (int i = 0; i < 256; i++) {
926 int r = static_cast<uint8_t>(m_pPalette.get()[i] >> 16);
927 int g = static_cast<uint8_t>(m_pPalette.get()[i] >> 8);
928 int b = static_cast<uint8_t>(m_pPalette.get()[i]);
929 gray[i] = static_cast<uint8_t>(FXRGB2GRAY(r, g, b));
930 }
931 CFX_DIBitmap* pMask = new CFX_DIBitmap;
932 if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {
933 delete pMask;
934 return false;
935 }
936 for (int row = 0; row < m_Height; row++) {
937 uint8_t* dest_pos = pMask->GetBuffer() + row * pMask->GetPitch();
938 uint8_t* src_pos = m_pBuffer + row * m_Pitch;
939 for (int col = 0; col < m_Width; col++) {
940 *dest_pos++ = gray[*src_pos++];
941 }
942 }
943 TakeOver(pMask);
944 delete pMask;
945 break;
946 }
947 case FXDIB_Rgb: {
948 CFX_DIBitmap* pMask = new CFX_DIBitmap;
949 if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {
950 delete pMask;
951 return false;
952 }
953 for (int row = 0; row < m_Height; row++) {
954 uint8_t* src_pos = m_pBuffer + row * m_Pitch;
955 uint8_t* dest_pos = pMask->GetBuffer() + row * pMask->GetPitch();
956 for (int col = 0; col < m_Width; col++) {
957 *dest_pos++ = FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos);
958 src_pos += 3;
959 }
960 }
961 TakeOver(pMask);
962 delete pMask;
963 break;
964 }
965 case FXDIB_Rgb32: {
966 CFX_DIBitmap* pMask = new CFX_DIBitmap;
967 if (!pMask->Create(m_Width, m_Height, FXDIB_8bppMask)) {
968 delete pMask;
969 return false;
970 }
971 for (int row = 0; row < m_Height; row++) {
972 uint8_t* src_pos = m_pBuffer + row * m_Pitch;
973 uint8_t* dest_pos = pMask->GetBuffer() + row * pMask->GetPitch();
974 for (int col = 0; col < m_Width; col++) {
975 *dest_pos++ = FXRGB2GRAY(src_pos[2], src_pos[1], *src_pos);
976 src_pos += 4;
977 }
978 }
979 TakeOver(pMask);
980 delete pMask;
981 break;
982 }
983 default:
984 return false;
985 }
986 return true;
987 }
988
MultiplyAlpha(int alpha)989 bool CFX_DIBitmap::MultiplyAlpha(int alpha) {
990 if (!m_pBuffer) {
991 return false;
992 }
993 switch (GetFormat()) {
994 case FXDIB_1bppMask:
995 if (!ConvertFormat(FXDIB_8bppMask)) {
996 return false;
997 }
998 MultiplyAlpha(alpha);
999 break;
1000 case FXDIB_8bppMask: {
1001 for (int row = 0; row < m_Height; row++) {
1002 uint8_t* scan_line = m_pBuffer + row * m_Pitch;
1003 for (int col = 0; col < m_Width; col++) {
1004 scan_line[col] = scan_line[col] * alpha / 255;
1005 }
1006 }
1007 break;
1008 }
1009 case FXDIB_Argb: {
1010 for (int row = 0; row < m_Height; row++) {
1011 uint8_t* scan_line = m_pBuffer + row * m_Pitch + 3;
1012 for (int col = 0; col < m_Width; col++) {
1013 *scan_line = (*scan_line) * alpha / 255;
1014 scan_line += 4;
1015 }
1016 }
1017 break;
1018 }
1019 default:
1020 if (HasAlpha()) {
1021 m_pAlphaMask->MultiplyAlpha(alpha);
1022 } else if (IsCmykImage()) {
1023 if (!ConvertFormat((FXDIB_Format)(GetFormat() | 0x0200))) {
1024 return false;
1025 }
1026 m_pAlphaMask->MultiplyAlpha(alpha);
1027 } else {
1028 if (!ConvertFormat(FXDIB_Argb)) {
1029 return false;
1030 }
1031 MultiplyAlpha(alpha);
1032 }
1033 break;
1034 }
1035 return true;
1036 }
1037
GetPixel(int x,int y) const1038 uint32_t CFX_DIBitmap::GetPixel(int x, int y) const {
1039 if (!m_pBuffer) {
1040 return 0;
1041 }
1042 uint8_t* pos = m_pBuffer + y * m_Pitch + x * GetBPP() / 8;
1043 switch (GetFormat()) {
1044 case FXDIB_1bppMask: {
1045 if ((*pos) & (1 << (7 - x % 8))) {
1046 return 0xff000000;
1047 }
1048 return 0;
1049 }
1050 case FXDIB_1bppRgb: {
1051 if ((*pos) & (1 << (7 - x % 8))) {
1052 return m_pPalette ? m_pPalette.get()[1] : 0xffffffff;
1053 }
1054 return m_pPalette ? m_pPalette.get()[0] : 0xff000000;
1055 }
1056 case FXDIB_8bppMask:
1057 return (*pos) << 24;
1058 case FXDIB_8bppRgb:
1059 return m_pPalette ? m_pPalette.get()[*pos]
1060 : (0xff000000 | ((*pos) * 0x10101));
1061 case FXDIB_Rgb:
1062 case FXDIB_Rgba:
1063 case FXDIB_Rgb32:
1064 return FXARGB_GETDIB(pos) | 0xff000000;
1065 case FXDIB_Argb:
1066 return FXARGB_GETDIB(pos);
1067 default:
1068 break;
1069 }
1070 return 0;
1071 }
1072
SetPixel(int x,int y,uint32_t color)1073 void CFX_DIBitmap::SetPixel(int x, int y, uint32_t color) {
1074 if (!m_pBuffer) {
1075 return;
1076 }
1077 if (x < 0 || x >= m_Width || y < 0 || y >= m_Height) {
1078 return;
1079 }
1080 uint8_t* pos = m_pBuffer + y * m_Pitch + x * GetBPP() / 8;
1081 switch (GetFormat()) {
1082 case FXDIB_1bppMask:
1083 if (color >> 24) {
1084 *pos |= 1 << (7 - x % 8);
1085 } else {
1086 *pos &= ~(1 << (7 - x % 8));
1087 }
1088 break;
1089 case FXDIB_1bppRgb:
1090 if (m_pPalette) {
1091 if (color == m_pPalette.get()[1]) {
1092 *pos |= 1 << (7 - x % 8);
1093 } else {
1094 *pos &= ~(1 << (7 - x % 8));
1095 }
1096 } else {
1097 if (color == 0xffffffff) {
1098 *pos |= 1 << (7 - x % 8);
1099 } else {
1100 *pos &= ~(1 << (7 - x % 8));
1101 }
1102 }
1103 break;
1104 case FXDIB_8bppMask:
1105 *pos = (uint8_t)(color >> 24);
1106 break;
1107 case FXDIB_8bppRgb: {
1108 if (m_pPalette) {
1109 for (int i = 0; i < 256; i++) {
1110 if (m_pPalette.get()[i] == color) {
1111 *pos = (uint8_t)i;
1112 return;
1113 }
1114 }
1115 *pos = 0;
1116 } else {
1117 *pos = FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color));
1118 }
1119 break;
1120 }
1121 case FXDIB_Rgb:
1122 case FXDIB_Rgb32: {
1123 int alpha = FXARGB_A(color);
1124 pos[0] = (FXARGB_B(color) * alpha + pos[0] * (255 - alpha)) / 255;
1125 pos[1] = (FXARGB_G(color) * alpha + pos[1] * (255 - alpha)) / 255;
1126 pos[2] = (FXARGB_R(color) * alpha + pos[2] * (255 - alpha)) / 255;
1127 break;
1128 }
1129 case FXDIB_Rgba: {
1130 pos[0] = FXARGB_B(color);
1131 pos[1] = FXARGB_G(color);
1132 pos[2] = FXARGB_R(color);
1133 break;
1134 }
1135 case FXDIB_Argb:
1136 FXARGB_SETDIB(pos, color);
1137 break;
1138 default:
1139 break;
1140 }
1141 }
1142
DownSampleScanline(int line,uint8_t * dest_scan,int dest_bpp,int dest_width,bool bFlipX,int clip_left,int clip_width) const1143 void CFX_DIBitmap::DownSampleScanline(int line,
1144 uint8_t* dest_scan,
1145 int dest_bpp,
1146 int dest_width,
1147 bool bFlipX,
1148 int clip_left,
1149 int clip_width) const {
1150 if (!m_pBuffer) {
1151 return;
1152 }
1153 int src_Bpp = m_bpp / 8;
1154 uint8_t* scanline = m_pBuffer + line * m_Pitch;
1155 if (src_Bpp == 0) {
1156 for (int i = 0; i < clip_width; i++) {
1157 uint32_t dest_x = clip_left + i;
1158 uint32_t src_x = dest_x * m_Width / dest_width;
1159 if (bFlipX) {
1160 src_x = m_Width - src_x - 1;
1161 }
1162 src_x %= m_Width;
1163 dest_scan[i] = (scanline[src_x / 8] & (1 << (7 - src_x % 8))) ? 255 : 0;
1164 }
1165 } else if (src_Bpp == 1) {
1166 for (int i = 0; i < clip_width; i++) {
1167 uint32_t dest_x = clip_left + i;
1168 uint32_t src_x = dest_x * m_Width / dest_width;
1169 if (bFlipX) {
1170 src_x = m_Width - src_x - 1;
1171 }
1172 src_x %= m_Width;
1173 int dest_pos = i;
1174 if (m_pPalette) {
1175 if (!IsCmykImage()) {
1176 dest_pos *= 3;
1177 FX_ARGB argb = m_pPalette.get()[scanline[src_x]];
1178 dest_scan[dest_pos] = FXARGB_B(argb);
1179 dest_scan[dest_pos + 1] = FXARGB_G(argb);
1180 dest_scan[dest_pos + 2] = FXARGB_R(argb);
1181 } else {
1182 dest_pos *= 4;
1183 FX_CMYK cmyk = m_pPalette.get()[scanline[src_x]];
1184 dest_scan[dest_pos] = FXSYS_GetCValue(cmyk);
1185 dest_scan[dest_pos + 1] = FXSYS_GetMValue(cmyk);
1186 dest_scan[dest_pos + 2] = FXSYS_GetYValue(cmyk);
1187 dest_scan[dest_pos + 3] = FXSYS_GetKValue(cmyk);
1188 }
1189 } else {
1190 dest_scan[dest_pos] = scanline[src_x];
1191 }
1192 }
1193 } else {
1194 for (int i = 0; i < clip_width; i++) {
1195 uint32_t dest_x = clip_left + i;
1196 uint32_t src_x =
1197 bFlipX ? (m_Width - dest_x * m_Width / dest_width - 1) * src_Bpp
1198 : (dest_x * m_Width / dest_width) * src_Bpp;
1199 src_x %= m_Width * src_Bpp;
1200 int dest_pos = i * src_Bpp;
1201 for (int b = 0; b < src_Bpp; b++) {
1202 dest_scan[dest_pos + b] = scanline[src_x + b];
1203 }
1204 }
1205 }
1206 }
1207
1208 // TODO(weili): Split this function into two for handling CMYK and RGB
1209 // colors separately.
ConvertColorScale(uint32_t forecolor,uint32_t backcolor)1210 bool CFX_DIBitmap::ConvertColorScale(uint32_t forecolor, uint32_t backcolor) {
1211 ASSERT(!IsAlphaMask());
1212 if (!m_pBuffer || IsAlphaMask()) {
1213 return false;
1214 }
1215 // Values used for CMYK colors.
1216 int fc = 0;
1217 int fm = 0;
1218 int fy = 0;
1219 int fk = 0;
1220 int bc = 0;
1221 int bm = 0;
1222 int by = 0;
1223 int bk = 0;
1224 // Values used for RGB colors.
1225 int fr = 0;
1226 int fg = 0;
1227 int fb = 0;
1228 int br = 0;
1229 int bg = 0;
1230 int bb = 0;
1231 bool isCmykImage = IsCmykImage();
1232 if (isCmykImage) {
1233 fc = FXSYS_GetCValue(forecolor);
1234 fm = FXSYS_GetMValue(forecolor);
1235 fy = FXSYS_GetYValue(forecolor);
1236 fk = FXSYS_GetKValue(forecolor);
1237 bc = FXSYS_GetCValue(backcolor);
1238 bm = FXSYS_GetMValue(backcolor);
1239 by = FXSYS_GetYValue(backcolor);
1240 bk = FXSYS_GetKValue(backcolor);
1241 } else {
1242 fr = FXSYS_GetRValue(forecolor);
1243 fg = FXSYS_GetGValue(forecolor);
1244 fb = FXSYS_GetBValue(forecolor);
1245 br = FXSYS_GetRValue(backcolor);
1246 bg = FXSYS_GetGValue(backcolor);
1247 bb = FXSYS_GetBValue(backcolor);
1248 }
1249 if (m_bpp <= 8) {
1250 if (isCmykImage) {
1251 if (forecolor == 0xff && backcolor == 0 && !m_pPalette) {
1252 return true;
1253 }
1254 } else if (forecolor == 0 && backcolor == 0xffffff && !m_pPalette) {
1255 return true;
1256 }
1257 if (!m_pPalette) {
1258 BuildPalette();
1259 }
1260 int size = 1 << m_bpp;
1261 if (isCmykImage) {
1262 for (int i = 0; i < size; i++) {
1263 uint8_t b, g, r;
1264 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(m_pPalette.get()[i]),
1265 FXSYS_GetMValue(m_pPalette.get()[i]),
1266 FXSYS_GetYValue(m_pPalette.get()[i]),
1267 FXSYS_GetKValue(m_pPalette.get()[i]), r, g, b);
1268 int gray = 255 - FXRGB2GRAY(r, g, b);
1269 m_pPalette.get()[i] = CmykEncode(
1270 bc + (fc - bc) * gray / 255, bm + (fm - bm) * gray / 255,
1271 by + (fy - by) * gray / 255, bk + (fk - bk) * gray / 255);
1272 }
1273 } else {
1274 for (int i = 0; i < size; i++) {
1275 int gray = FXRGB2GRAY(FXARGB_R(m_pPalette.get()[i]),
1276 FXARGB_G(m_pPalette.get()[i]),
1277 FXARGB_B(m_pPalette.get()[i]));
1278 m_pPalette.get()[i] = FXARGB_MAKE(0xff, br + (fr - br) * gray / 255,
1279 bg + (fg - bg) * gray / 255,
1280 bb + (fb - bb) * gray / 255);
1281 }
1282 }
1283 return true;
1284 }
1285 if (isCmykImage) {
1286 if (forecolor == 0xff && backcolor == 0x00) {
1287 for (int row = 0; row < m_Height; row++) {
1288 uint8_t* scanline = m_pBuffer + row * m_Pitch;
1289 for (int col = 0; col < m_Width; col++) {
1290 uint8_t b, g, r;
1291 AdobeCMYK_to_sRGB1(scanline[0], scanline[1], scanline[2], scanline[3],
1292 r, g, b);
1293 *scanline++ = 0;
1294 *scanline++ = 0;
1295 *scanline++ = 0;
1296 *scanline++ = 255 - FXRGB2GRAY(r, g, b);
1297 }
1298 }
1299 return true;
1300 }
1301 } else if (forecolor == 0 && backcolor == 0xffffff) {
1302 for (int row = 0; row < m_Height; row++) {
1303 uint8_t* scanline = m_pBuffer + row * m_Pitch;
1304 int gap = m_bpp / 8 - 2;
1305 for (int col = 0; col < m_Width; col++) {
1306 int gray = FXRGB2GRAY(scanline[2], scanline[1], scanline[0]);
1307 *scanline++ = gray;
1308 *scanline++ = gray;
1309 *scanline = gray;
1310 scanline += gap;
1311 }
1312 }
1313 return true;
1314 }
1315 if (isCmykImage) {
1316 for (int row = 0; row < m_Height; row++) {
1317 uint8_t* scanline = m_pBuffer + row * m_Pitch;
1318 for (int col = 0; col < m_Width; col++) {
1319 uint8_t b, g, r;
1320 AdobeCMYK_to_sRGB1(scanline[0], scanline[1], scanline[2], scanline[3],
1321 r, g, b);
1322 int gray = 255 - FXRGB2GRAY(r, g, b);
1323 *scanline++ = bc + (fc - bc) * gray / 255;
1324 *scanline++ = bm + (fm - bm) * gray / 255;
1325 *scanline++ = by + (fy - by) * gray / 255;
1326 *scanline++ = bk + (fk - bk) * gray / 255;
1327 }
1328 }
1329 } else {
1330 for (int row = 0; row < m_Height; row++) {
1331 uint8_t* scanline = m_pBuffer + row * m_Pitch;
1332 int gap = m_bpp / 8 - 2;
1333 for (int col = 0; col < m_Width; col++) {
1334 int gray = FXRGB2GRAY(scanline[2], scanline[1], scanline[0]);
1335 *scanline++ = bb + (fb - bb) * gray / 255;
1336 *scanline++ = bg + (fg - bg) * gray / 255;
1337 *scanline = br + (fr - br) * gray / 255;
1338 scanline += gap;
1339 }
1340 }
1341 }
1342 return true;
1343 }
1344
FlipImage(bool bXFlip,bool bYFlip) const1345 std::unique_ptr<CFX_DIBitmap> CFX_DIBSource::FlipImage(bool bXFlip,
1346 bool bYFlip) const {
1347 auto pFlipped = pdfium::MakeUnique<CFX_DIBitmap>();
1348 if (!pFlipped->Create(m_Width, m_Height, GetFormat()))
1349 return nullptr;
1350
1351 pFlipped->SetPalette(m_pPalette.get());
1352 uint8_t* pDestBuffer = pFlipped->GetBuffer();
1353 int Bpp = m_bpp / 8;
1354 for (int row = 0; row < m_Height; row++) {
1355 const uint8_t* src_scan = GetScanline(row);
1356 uint8_t* dest_scan =
1357 pDestBuffer + m_Pitch * (bYFlip ? (m_Height - row - 1) : row);
1358 if (!bXFlip) {
1359 FXSYS_memcpy(dest_scan, src_scan, m_Pitch);
1360 continue;
1361 }
1362 if (m_bpp == 1) {
1363 FXSYS_memset(dest_scan, 0, m_Pitch);
1364 for (int col = 0; col < m_Width; col++)
1365 if (src_scan[col / 8] & (1 << (7 - col % 8))) {
1366 int dest_col = m_Width - col - 1;
1367 dest_scan[dest_col / 8] |= (1 << (7 - dest_col % 8));
1368 }
1369 } else {
1370 dest_scan += (m_Width - 1) * Bpp;
1371 if (Bpp == 1) {
1372 for (int col = 0; col < m_Width; col++) {
1373 *dest_scan = *src_scan;
1374 dest_scan--;
1375 src_scan++;
1376 }
1377 } else if (Bpp == 3) {
1378 for (int col = 0; col < m_Width; col++) {
1379 dest_scan[0] = src_scan[0];
1380 dest_scan[1] = src_scan[1];
1381 dest_scan[2] = src_scan[2];
1382 dest_scan -= 3;
1383 src_scan += 3;
1384 }
1385 } else {
1386 ASSERT(Bpp == 4);
1387 for (int col = 0; col < m_Width; col++) {
1388 *(uint32_t*)dest_scan = *(uint32_t*)src_scan;
1389 dest_scan -= 4;
1390 src_scan += 4;
1391 }
1392 }
1393 }
1394 }
1395 if (m_pAlphaMask) {
1396 pDestBuffer = pFlipped->m_pAlphaMask->GetBuffer();
1397 uint32_t dest_pitch = pFlipped->m_pAlphaMask->GetPitch();
1398 for (int row = 0; row < m_Height; row++) {
1399 const uint8_t* src_scan = m_pAlphaMask->GetScanline(row);
1400 uint8_t* dest_scan =
1401 pDestBuffer + dest_pitch * (bYFlip ? (m_Height - row - 1) : row);
1402 if (!bXFlip) {
1403 FXSYS_memcpy(dest_scan, src_scan, dest_pitch);
1404 continue;
1405 }
1406 dest_scan += (m_Width - 1);
1407 for (int col = 0; col < m_Width; col++) {
1408 *dest_scan = *src_scan;
1409 dest_scan--;
1410 src_scan++;
1411 }
1412 }
1413 }
1414 return pFlipped;
1415 }
1416
CFX_DIBExtractor(const CFX_DIBSource * pSrc)1417 CFX_DIBExtractor::CFX_DIBExtractor(const CFX_DIBSource* pSrc) {
1418 if (pSrc->GetBuffer()) {
1419 m_pBitmap = pdfium::MakeUnique<CFX_DIBitmap>();
1420 if (!m_pBitmap->Create(pSrc->GetWidth(), pSrc->GetHeight(),
1421 pSrc->GetFormat(), pSrc->GetBuffer())) {
1422 m_pBitmap.reset();
1423 return;
1424 }
1425 m_pBitmap->SetPalette(pSrc->GetPalette());
1426 m_pBitmap->SetAlphaMask(pSrc->m_pAlphaMask);
1427 } else {
1428 m_pBitmap = pSrc->Clone();
1429 }
1430 }
1431
~CFX_DIBExtractor()1432 CFX_DIBExtractor::~CFX_DIBExtractor() {}
1433
CFX_FilteredDIB()1434 CFX_FilteredDIB::CFX_FilteredDIB() : m_pSrc(nullptr) {}
1435
~CFX_FilteredDIB()1436 CFX_FilteredDIB::~CFX_FilteredDIB() {
1437 if (m_bAutoDropSrc) {
1438 delete m_pSrc;
1439 }
1440 }
1441
LoadSrc(const CFX_DIBSource * pSrc,bool bAutoDropSrc)1442 void CFX_FilteredDIB::LoadSrc(const CFX_DIBSource* pSrc, bool bAutoDropSrc) {
1443 m_pSrc = pSrc;
1444 m_bAutoDropSrc = bAutoDropSrc;
1445 m_Width = pSrc->GetWidth();
1446 m_Height = pSrc->GetHeight();
1447 FXDIB_Format format = GetDestFormat();
1448 m_bpp = (uint8_t)format;
1449 m_AlphaFlag = (uint8_t)(format >> 8);
1450 m_Pitch = (m_Width * (format & 0xff) + 31) / 32 * 4;
1451 m_pPalette.reset(GetDestPalette());
1452 m_Scanline.resize(m_Pitch);
1453 }
1454
GetScanline(int line) const1455 const uint8_t* CFX_FilteredDIB::GetScanline(int line) const {
1456 TranslateScanline(m_pSrc->GetScanline(line), &m_Scanline);
1457 return m_Scanline.data();
1458 }
1459
DownSampleScanline(int line,uint8_t * dest_scan,int dest_bpp,int dest_width,bool bFlipX,int clip_left,int clip_width) const1460 void CFX_FilteredDIB::DownSampleScanline(int line,
1461 uint8_t* dest_scan,
1462 int dest_bpp,
1463 int dest_width,
1464 bool bFlipX,
1465 int clip_left,
1466 int clip_width) const {
1467 m_pSrc->DownSampleScanline(line, dest_scan, dest_bpp, dest_width, bFlipX,
1468 clip_left, clip_width);
1469 TranslateDownSamples(dest_scan, dest_scan, clip_width, dest_bpp);
1470 }
1471
CFX_ImageRenderer()1472 CFX_ImageRenderer::CFX_ImageRenderer() {
1473 m_Status = 0;
1474 m_pIccTransform = nullptr;
1475 m_bRgbByteOrder = false;
1476 m_BlendType = FXDIB_BLEND_NORMAL;
1477 }
1478
~CFX_ImageRenderer()1479 CFX_ImageRenderer::~CFX_ImageRenderer() {}
1480
Start(CFX_DIBitmap * pDevice,const CFX_ClipRgn * pClipRgn,const CFX_DIBSource * pSource,int bitmap_alpha,uint32_t mask_color,const CFX_Matrix * pMatrix,uint32_t dib_flags,bool bRgbByteOrder,int alpha_flag,void * pIccTransform,int blend_type)1481 bool CFX_ImageRenderer::Start(CFX_DIBitmap* pDevice,
1482 const CFX_ClipRgn* pClipRgn,
1483 const CFX_DIBSource* pSource,
1484 int bitmap_alpha,
1485 uint32_t mask_color,
1486 const CFX_Matrix* pMatrix,
1487 uint32_t dib_flags,
1488 bool bRgbByteOrder,
1489 int alpha_flag,
1490 void* pIccTransform,
1491 int blend_type) {
1492 m_Matrix = *pMatrix;
1493 CFX_FloatRect image_rect_f = m_Matrix.GetUnitRect();
1494 FX_RECT image_rect = image_rect_f.GetOuterRect();
1495 m_ClipBox = pClipRgn ? pClipRgn->GetBox() : FX_RECT(0, 0, pDevice->GetWidth(),
1496 pDevice->GetHeight());
1497 m_ClipBox.Intersect(image_rect);
1498 if (m_ClipBox.IsEmpty())
1499 return false;
1500
1501 m_pDevice = pDevice;
1502 m_pClipRgn = pClipRgn;
1503 m_MaskColor = mask_color;
1504 m_BitmapAlpha = bitmap_alpha;
1505 m_Matrix = *pMatrix;
1506 m_Flags = dib_flags;
1507 m_AlphaFlag = alpha_flag;
1508 m_pIccTransform = pIccTransform;
1509 m_bRgbByteOrder = bRgbByteOrder;
1510 m_BlendType = blend_type;
1511
1512 if ((FXSYS_fabs(m_Matrix.b) >= 0.5f || m_Matrix.a == 0) ||
1513 (FXSYS_fabs(m_Matrix.c) >= 0.5f || m_Matrix.d == 0)) {
1514 if (FXSYS_fabs(m_Matrix.a) < FXSYS_fabs(m_Matrix.b) / 20 &&
1515 FXSYS_fabs(m_Matrix.d) < FXSYS_fabs(m_Matrix.c) / 20 &&
1516 FXSYS_fabs(m_Matrix.a) < 0.5f && FXSYS_fabs(m_Matrix.d) < 0.5f) {
1517 int dest_width = image_rect.Width();
1518 int dest_height = image_rect.Height();
1519 FX_RECT bitmap_clip = m_ClipBox;
1520 bitmap_clip.Offset(-image_rect.left, -image_rect.top);
1521 bitmap_clip = FXDIB_SwapClipBox(bitmap_clip, dest_width, dest_height,
1522 m_Matrix.c > 0, m_Matrix.b < 0);
1523 m_Composer.Compose(pDevice, pClipRgn, bitmap_alpha, mask_color, m_ClipBox,
1524 true, m_Matrix.c > 0, m_Matrix.b < 0, m_bRgbByteOrder,
1525 alpha_flag, pIccTransform, m_BlendType);
1526 m_Stretcher = pdfium::MakeUnique<CFX_ImageStretcher>(
1527 &m_Composer, pSource, dest_height, dest_width, bitmap_clip,
1528 dib_flags);
1529 if (!m_Stretcher->Start())
1530 return false;
1531
1532 m_Status = 1;
1533 return true;
1534 }
1535 m_Status = 2;
1536 m_pTransformer.reset(
1537 new CFX_ImageTransformer(pSource, &m_Matrix, dib_flags, &m_ClipBox));
1538 m_pTransformer->Start();
1539 return true;
1540 }
1541
1542 int dest_width = image_rect.Width();
1543 if (m_Matrix.a < 0)
1544 dest_width = -dest_width;
1545
1546 int dest_height = image_rect.Height();
1547 if (m_Matrix.d > 0)
1548 dest_height = -dest_height;
1549
1550 if (dest_width == 0 || dest_height == 0)
1551 return false;
1552
1553 FX_RECT bitmap_clip = m_ClipBox;
1554 bitmap_clip.Offset(-image_rect.left, -image_rect.top);
1555 m_Composer.Compose(pDevice, pClipRgn, bitmap_alpha, mask_color, m_ClipBox,
1556 false, false, false, m_bRgbByteOrder, alpha_flag,
1557 pIccTransform, m_BlendType);
1558 m_Status = 1;
1559 m_Stretcher = pdfium::MakeUnique<CFX_ImageStretcher>(
1560 &m_Composer, pSource, dest_width, dest_height, bitmap_clip, dib_flags);
1561 return m_Stretcher->Start();
1562 }
1563
Continue(IFX_Pause * pPause)1564 bool CFX_ImageRenderer::Continue(IFX_Pause* pPause) {
1565 if (m_Status == 1)
1566 return m_Stretcher->Continue(pPause);
1567
1568 if (m_Status == 2) {
1569 if (m_pTransformer->Continue(pPause))
1570 return true;
1571
1572 std::unique_ptr<CFX_DIBitmap> pBitmap(m_pTransformer->DetachBitmap());
1573 if (!pBitmap || !pBitmap->GetBuffer())
1574 return false;
1575
1576 if (pBitmap->IsAlphaMask()) {
1577 if (m_BitmapAlpha != 255) {
1578 if (m_AlphaFlag >> 8) {
1579 m_AlphaFlag =
1580 (((uint8_t)((m_AlphaFlag & 0xff) * m_BitmapAlpha / 255)) |
1581 ((m_AlphaFlag >> 8) << 8));
1582 } else {
1583 m_MaskColor = FXARGB_MUL_ALPHA(m_MaskColor, m_BitmapAlpha);
1584 }
1585 }
1586 m_pDevice->CompositeMask(
1587 m_pTransformer->result().left, m_pTransformer->result().top,
1588 pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap.get(), m_MaskColor,
1589 0, 0, m_BlendType, m_pClipRgn, m_bRgbByteOrder, m_AlphaFlag,
1590 m_pIccTransform);
1591 } else {
1592 if (m_BitmapAlpha != 255)
1593 pBitmap->MultiplyAlpha(m_BitmapAlpha);
1594 m_pDevice->CompositeBitmap(
1595 m_pTransformer->result().left, m_pTransformer->result().top,
1596 pBitmap->GetWidth(), pBitmap->GetHeight(), pBitmap.get(), 0, 0,
1597 m_BlendType, m_pClipRgn, m_bRgbByteOrder, m_pIccTransform);
1598 }
1599 return false;
1600 }
1601 return false;
1602 }
1603
CFX_BitmapStorer()1604 CFX_BitmapStorer::CFX_BitmapStorer() {
1605 }
1606
~CFX_BitmapStorer()1607 CFX_BitmapStorer::~CFX_BitmapStorer() {
1608 }
1609
Detach()1610 std::unique_ptr<CFX_DIBitmap> CFX_BitmapStorer::Detach() {
1611 return std::move(m_pBitmap);
1612 }
1613
Replace(std::unique_ptr<CFX_DIBitmap> pBitmap)1614 void CFX_BitmapStorer::Replace(std::unique_ptr<CFX_DIBitmap> pBitmap) {
1615 m_pBitmap = std::move(pBitmap);
1616 }
1617
ComposeScanline(int line,const uint8_t * scanline,const uint8_t * scan_extra_alpha)1618 void CFX_BitmapStorer::ComposeScanline(int line,
1619 const uint8_t* scanline,
1620 const uint8_t* scan_extra_alpha) {
1621 uint8_t* dest_buf = const_cast<uint8_t*>(m_pBitmap->GetScanline(line));
1622 uint8_t* dest_alpha_buf =
1623 m_pBitmap->m_pAlphaMask
1624 ? const_cast<uint8_t*>(m_pBitmap->m_pAlphaMask->GetScanline(line))
1625 : nullptr;
1626 if (dest_buf)
1627 FXSYS_memcpy(dest_buf, scanline, m_pBitmap->GetPitch());
1628
1629 if (dest_alpha_buf) {
1630 FXSYS_memcpy(dest_alpha_buf, scan_extra_alpha,
1631 m_pBitmap->m_pAlphaMask->GetPitch());
1632 }
1633 }
1634
SetInfo(int width,int height,FXDIB_Format src_format,uint32_t * pSrcPalette)1635 bool CFX_BitmapStorer::SetInfo(int width,
1636 int height,
1637 FXDIB_Format src_format,
1638 uint32_t* pSrcPalette) {
1639 m_pBitmap = pdfium::MakeUnique<CFX_DIBitmap>();
1640 if (!m_pBitmap->Create(width, height, src_format)) {
1641 m_pBitmap.reset();
1642 return false;
1643 }
1644 if (pSrcPalette)
1645 m_pBitmap->SetPalette(pSrcPalette);
1646 return true;
1647 }
1648