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 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 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 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 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 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 54 CFX_DIBSource::~CFX_DIBSource() { 55 delete m_pAlphaMask; 56 } 57 58 uint8_t* CFX_DIBSource::GetBuffer() const { 59 return nullptr; 60 } 61 62 bool CFX_DIBSource::SkipToScanline(int line, IFX_Pause* pPause) const { 63 return false; 64 } 65 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 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 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 145 CFX_DIBitmap::~CFX_DIBitmap() { 146 if (!m_bExtBuf) 147 FX_Free(m_pBuffer); 148 149 m_pBuffer = nullptr; 150 } 151 152 uint8_t* CFX_DIBitmap::GetBuffer() const { 153 return m_pBuffer; 154 } 155 156 const uint8_t* CFX_DIBitmap::GetScanline(int line) const { 157 return m_pBuffer ? m_pBuffer + line * m_Pitch : nullptr; 158 } 159 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 178 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 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 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 257 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 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 282 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 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 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 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 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 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 588 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 608 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 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}; 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 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 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 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 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 1038 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 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 1143 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. 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 1345 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 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 1432 CFX_DIBExtractor::~CFX_DIBExtractor() {} 1433 1434 CFX_FilteredDIB::CFX_FilteredDIB() : m_pSrc(nullptr) {} 1435 1436 CFX_FilteredDIB::~CFX_FilteredDIB() { 1437 if (m_bAutoDropSrc) { 1438 delete m_pSrc; 1439 } 1440 } 1441 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 1455 const uint8_t* CFX_FilteredDIB::GetScanline(int line) const { 1456 TranslateScanline(m_pSrc->GetScanline(line), &m_Scanline); 1457 return m_Scanline.data(); 1458 } 1459 1460 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 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 1479 CFX_ImageRenderer::~CFX_ImageRenderer() {} 1480 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 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 1604 CFX_BitmapStorer::CFX_BitmapStorer() { 1605 } 1606 1607 CFX_BitmapStorer::~CFX_BitmapStorer() { 1608 } 1609 1610 std::unique_ptr<CFX_DIBitmap> CFX_BitmapStorer::Detach() { 1611 return std::move(m_pBitmap); 1612 } 1613 1614 void CFX_BitmapStorer::Replace(std::unique_ptr<CFX_DIBitmap> pBitmap) { 1615 m_pBitmap = std::move(pBitmap); 1616 } 1617 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 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