1 // Copyright 2017 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/dib/cfx_dibitmap.h" 8 9 #include <limits> 10 #include <memory> 11 #include <utility> 12 13 #include "core/fxcodec/fx_codec.h" 14 #include "core/fxge/cfx_cliprgn.h" 15 #include "core/fxge/dib/cfx_scanlinecompositor.h" 16 #include "third_party/base/ptr_util.h" 17 18 #define MAX_OOM_LIMIT 12000000 19 20 namespace { 21 22 const int8_t g_ChannelOffset[] = {0, 2, 1, 0, 0, 1, 2, 3, 3}; 23 24 } // namespace 25 26 CFX_DIBitmap::CFX_DIBitmap() { 27 m_pPalette = nullptr; 28 #ifdef _SKIA_SUPPORT_PATHS_ 29 m_nFormat = Format::kCleared; 30 #endif 31 } 32 33 bool CFX_DIBitmap::Create(int width, 34 int height, 35 FXDIB_Format format, 36 uint8_t* pBuffer, 37 uint32_t pitch) { 38 m_pBuffer = nullptr; 39 m_bpp = static_cast<uint8_t>(format); 40 m_AlphaFlag = static_cast<uint8_t>(format >> 8); 41 m_Width = 0; 42 m_Height = 0; 43 m_Pitch = 0; 44 45 uint32_t calculatedSize; 46 if (!CFX_DIBitmap::CalculatePitchAndSize(height, width, format, &pitch, 47 &calculatedSize)) 48 return false; 49 50 if (pBuffer) { 51 m_pBuffer.Reset(pBuffer); 52 } else { 53 size_t bufferSize = calculatedSize + 4; 54 size_t oomlimit = MAX_OOM_LIMIT; 55 if (bufferSize >= oomlimit) { 56 m_pBuffer = std::unique_ptr<uint8_t, FxFreeDeleter>( 57 FX_TryAlloc(uint8_t, bufferSize)); 58 if (!m_pBuffer) 59 return false; 60 } else { 61 m_pBuffer = std::unique_ptr<uint8_t, FxFreeDeleter>( 62 FX_Alloc(uint8_t, bufferSize)); 63 } 64 } 65 m_Width = width; 66 m_Height = height; 67 m_Pitch = pitch; 68 if (!HasAlpha() || format == FXDIB_Argb) 69 return true; 70 71 if (BuildAlphaMask()) 72 return true; 73 74 if (pBuffer) 75 return true; 76 77 m_pBuffer = nullptr; 78 m_Width = 0; 79 m_Height = 0; 80 m_Pitch = 0; 81 return false; 82 } 83 84 bool CFX_DIBitmap::Copy(const RetainPtr<CFX_DIBSource>& pSrc) { 85 if (m_pBuffer) 86 return false; 87 88 if (!Create(pSrc->GetWidth(), pSrc->GetHeight(), pSrc->GetFormat())) 89 return false; 90 91 SetPalette(pSrc->GetPalette()); 92 SetAlphaMask(pSrc->m_pAlphaMask, nullptr); 93 for (int row = 0; row < pSrc->GetHeight(); row++) 94 memcpy(m_pBuffer.Get() + row * m_Pitch, pSrc->GetScanline(row), m_Pitch); 95 return true; 96 } 97 98 CFX_DIBitmap::~CFX_DIBitmap() {} 99 100 uint8_t* CFX_DIBitmap::GetBuffer() const { 101 return m_pBuffer.Get(); 102 } 103 104 const uint8_t* CFX_DIBitmap::GetScanline(int line) const { 105 return m_pBuffer.Get() ? m_pBuffer.Get() + line * m_Pitch : nullptr; 106 } 107 108 void CFX_DIBitmap::TakeOver(RetainPtr<CFX_DIBitmap>&& pSrcBitmap) { 109 m_pBuffer = std::move(pSrcBitmap->m_pBuffer); 110 m_pPalette = std::move(pSrcBitmap->m_pPalette); 111 m_pAlphaMask = pSrcBitmap->m_pAlphaMask; 112 pSrcBitmap->m_pBuffer = nullptr; 113 pSrcBitmap->m_pAlphaMask = nullptr; 114 m_bpp = pSrcBitmap->m_bpp; 115 m_AlphaFlag = pSrcBitmap->m_AlphaFlag; 116 m_Width = pSrcBitmap->m_Width; 117 m_Height = pSrcBitmap->m_Height; 118 m_Pitch = pSrcBitmap->m_Pitch; 119 } 120 121 void CFX_DIBitmap::Clear(uint32_t color) { 122 if (!m_pBuffer) 123 return; 124 125 uint8_t* pBuffer = m_pBuffer.Get(); 126 switch (GetFormat()) { 127 case FXDIB_1bppMask: 128 memset(pBuffer, (color & 0xff000000) ? 0xff : 0, m_Pitch * m_Height); 129 break; 130 case FXDIB_1bppRgb: { 131 int index = FindPalette(color); 132 memset(pBuffer, index ? 0xff : 0, m_Pitch * m_Height); 133 break; 134 } 135 case FXDIB_8bppMask: 136 memset(pBuffer, color >> 24, m_Pitch * m_Height); 137 break; 138 case FXDIB_8bppRgb: { 139 int index = FindPalette(color); 140 memset(pBuffer, index, m_Pitch * m_Height); 141 break; 142 } 143 case FXDIB_Rgb: 144 case FXDIB_Rgba: { 145 int a; 146 int r; 147 int g; 148 int b; 149 std::tie(a, r, g, b) = ArgbDecode(color); 150 if (r == g && g == b) { 151 memset(pBuffer, r, m_Pitch * m_Height); 152 } else { 153 int byte_pos = 0; 154 for (int col = 0; col < m_Width; col++) { 155 pBuffer[byte_pos++] = b; 156 pBuffer[byte_pos++] = g; 157 pBuffer[byte_pos++] = r; 158 } 159 for (int row = 1; row < m_Height; row++) { 160 memcpy(pBuffer + row * m_Pitch, pBuffer, m_Pitch); 161 } 162 } 163 break; 164 } 165 case FXDIB_Rgb32: 166 case FXDIB_Argb: { 167 color = IsCmykImage() ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); 168 #ifdef _SKIA_SUPPORT_ 169 if (FXDIB_Rgb32 == GetFormat() && !IsCmykImage()) 170 color |= 0xFF000000; 171 #endif 172 for (int i = 0; i < m_Width; i++) 173 reinterpret_cast<uint32_t*>(pBuffer)[i] = color; 174 for (int row = 1; row < m_Height; row++) 175 memcpy(pBuffer + row * m_Pitch, pBuffer, m_Pitch); 176 break; 177 } 178 default: 179 break; 180 } 181 } 182 183 bool CFX_DIBitmap::TransferBitmap(int dest_left, 184 int dest_top, 185 int width, 186 int height, 187 const RetainPtr<CFX_DIBSource>& pSrcBitmap, 188 int src_left, 189 int src_top) { 190 if (!m_pBuffer) 191 return false; 192 193 GetOverlapRect(dest_left, dest_top, width, height, pSrcBitmap->GetWidth(), 194 pSrcBitmap->GetHeight(), src_left, src_top, nullptr); 195 if (width == 0 || height == 0) 196 return true; 197 198 FXDIB_Format dest_format = GetFormat(); 199 FXDIB_Format src_format = pSrcBitmap->GetFormat(); 200 if (dest_format == src_format) { 201 if (GetBPP() == 1) { 202 for (int row = 0; row < height; row++) { 203 uint8_t* dest_scan = m_pBuffer.Get() + (dest_top + row) * m_Pitch; 204 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row); 205 for (int col = 0; col < width; col++) { 206 if (src_scan[(src_left + col) / 8] & 207 (1 << (7 - (src_left + col) % 8))) { 208 dest_scan[(dest_left + col) / 8] |= 1 209 << (7 - (dest_left + col) % 8); 210 } else { 211 dest_scan[(dest_left + col) / 8] &= 212 ~(1 << (7 - (dest_left + col) % 8)); 213 } 214 } 215 } 216 } else { 217 int Bpp = GetBPP() / 8; 218 for (int row = 0; row < height; row++) { 219 uint8_t* dest_scan = 220 m_pBuffer.Get() + (dest_top + row) * m_Pitch + dest_left * Bpp; 221 const uint8_t* src_scan = 222 pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp; 223 memcpy(dest_scan, src_scan, width * Bpp); 224 } 225 } 226 } else { 227 if (m_pPalette) 228 return false; 229 230 if (m_bpp == 8) 231 dest_format = FXDIB_8bppMask; 232 233 uint8_t* dest_buf = 234 m_pBuffer.Get() + dest_top * m_Pitch + dest_left * GetBPP() / 8; 235 std::unique_ptr<uint32_t, FxFreeDeleter> d_plt; 236 if (!ConvertBuffer(dest_format, dest_buf, m_Pitch, width, height, 237 pSrcBitmap, src_left, src_top, &d_plt)) { 238 return false; 239 } 240 } 241 return true; 242 } 243 244 bool CFX_DIBitmap::LoadChannel(FXDIB_Channel destChannel, 245 const RetainPtr<CFX_DIBSource>& pSrcBitmap, 246 FXDIB_Channel srcChannel) { 247 if (!m_pBuffer) 248 return false; 249 250 RetainPtr<CFX_DIBSource> pSrcClone = pSrcBitmap; 251 int srcOffset; 252 if (srcChannel == FXDIB_Alpha) { 253 if (!pSrcBitmap->HasAlpha() && !pSrcBitmap->IsAlphaMask()) 254 return false; 255 256 if (pSrcBitmap->GetBPP() == 1) { 257 pSrcClone = pSrcBitmap->CloneConvert(FXDIB_8bppMask); 258 if (!pSrcClone) 259 return false; 260 } 261 srcOffset = pSrcBitmap->GetFormat() == FXDIB_Argb ? 3 : 0; 262 } else { 263 if (pSrcBitmap->IsAlphaMask()) 264 return false; 265 266 if (pSrcBitmap->GetBPP() < 24) { 267 if (pSrcBitmap->IsCmykImage()) { 268 pSrcClone = pSrcBitmap->CloneConvert(static_cast<FXDIB_Format>( 269 (pSrcBitmap->GetFormat() & 0xff00) | 0x20)); 270 } else { 271 pSrcClone = pSrcBitmap->CloneConvert(static_cast<FXDIB_Format>( 272 (pSrcBitmap->GetFormat() & 0xff00) | 0x18)); 273 } 274 if (!pSrcClone) 275 return false; 276 } 277 srcOffset = g_ChannelOffset[srcChannel]; 278 } 279 int destOffset = 0; 280 if (destChannel == FXDIB_Alpha) { 281 if (IsAlphaMask()) { 282 if (!ConvertFormat(FXDIB_8bppMask)) 283 return false; 284 } else { 285 if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) 286 return false; 287 288 if (GetFormat() == FXDIB_Argb) 289 destOffset = 3; 290 } 291 } else { 292 if (IsAlphaMask()) 293 return false; 294 295 if (GetBPP() < 24) { 296 if (HasAlpha()) { 297 if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) 298 return false; 299 #if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ 300 } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb32)) { 301 #else 302 } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb)) { 303 #endif 304 return false; 305 } 306 } 307 destOffset = g_ChannelOffset[destChannel]; 308 } 309 if (srcChannel == FXDIB_Alpha && pSrcClone->m_pAlphaMask) { 310 RetainPtr<CFX_DIBSource> pAlphaMask = pSrcClone->m_pAlphaMask; 311 if (pSrcClone->GetWidth() != m_Width || 312 pSrcClone->GetHeight() != m_Height) { 313 if (pAlphaMask) { 314 pAlphaMask = pAlphaMask->StretchTo(m_Width, m_Height, 0, nullptr); 315 if (!pAlphaMask) 316 return false; 317 } 318 } 319 pSrcClone = std::move(pAlphaMask); 320 srcOffset = 0; 321 } else if (pSrcClone->GetWidth() != m_Width || 322 pSrcClone->GetHeight() != m_Height) { 323 RetainPtr<CFX_DIBitmap> pSrcMatched = 324 pSrcClone->StretchTo(m_Width, m_Height, 0, nullptr); 325 if (!pSrcMatched) 326 return false; 327 328 pSrcClone = std::move(pSrcMatched); 329 } 330 RetainPtr<CFX_DIBitmap> pDst(this); 331 if (destChannel == FXDIB_Alpha && m_pAlphaMask) { 332 pDst = m_pAlphaMask; 333 destOffset = 0; 334 } 335 int srcBytes = pSrcClone->GetBPP() / 8; 336 int destBytes = pDst->GetBPP() / 8; 337 for (int row = 0; row < m_Height; row++) { 338 uint8_t* dest_pos = (uint8_t*)pDst->GetScanline(row) + destOffset; 339 const uint8_t* src_pos = pSrcClone->GetScanline(row) + srcOffset; 340 for (int col = 0; col < m_Width; col++) { 341 *dest_pos = *src_pos; 342 dest_pos += destBytes; 343 src_pos += srcBytes; 344 } 345 } 346 return true; 347 } 348 349 bool CFX_DIBitmap::LoadChannel(FXDIB_Channel destChannel, int value) { 350 if (!m_pBuffer) 351 return false; 352 353 int destOffset; 354 if (destChannel == FXDIB_Alpha) { 355 if (IsAlphaMask()) { 356 if (!ConvertFormat(FXDIB_8bppMask)) { 357 return false; 358 } 359 destOffset = 0; 360 } else { 361 destOffset = 0; 362 if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) { 363 return false; 364 } 365 if (GetFormat() == FXDIB_Argb) { 366 destOffset = 3; 367 } 368 } 369 } else { 370 if (IsAlphaMask()) { 371 return false; 372 } 373 if (GetBPP() < 24) { 374 if (HasAlpha()) { 375 if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyka : FXDIB_Argb)) { 376 return false; 377 } 378 #if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ 379 } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb)) { 380 #else 381 } else if (!ConvertFormat(IsCmykImage() ? FXDIB_Cmyk : FXDIB_Rgb32)) { 382 #endif 383 return false; 384 } 385 } 386 destOffset = g_ChannelOffset[destChannel]; 387 } 388 int Bpp = GetBPP() / 8; 389 if (Bpp == 1) { 390 memset(m_pBuffer.Get(), value, m_Height * m_Pitch); 391 return true; 392 } 393 if (destChannel == FXDIB_Alpha && m_pAlphaMask) { 394 memset(m_pAlphaMask->GetBuffer(), value, 395 m_pAlphaMask->GetHeight() * m_pAlphaMask->GetPitch()); 396 return true; 397 } 398 for (int row = 0; row < m_Height; row++) { 399 uint8_t* scan_line = m_pBuffer.Get() + row * m_Pitch + destOffset; 400 for (int col = 0; col < m_Width; col++) { 401 *scan_line = value; 402 scan_line += Bpp; 403 } 404 } 405 return true; 406 } 407 408 bool CFX_DIBitmap::MultiplyAlpha(const RetainPtr<CFX_DIBSource>& pSrcBitmap) { 409 if (!m_pBuffer) 410 return false; 411 412 ASSERT(pSrcBitmap->IsAlphaMask()); 413 if (!pSrcBitmap->IsAlphaMask()) 414 return false; 415 416 if (!IsAlphaMask() && !HasAlpha()) 417 return LoadChannel(FXDIB_Alpha, pSrcBitmap, FXDIB_Alpha); 418 419 RetainPtr<CFX_DIBitmap> pSrcClone = pSrcBitmap.As<CFX_DIBitmap>(); 420 if (pSrcBitmap->GetWidth() != m_Width || 421 pSrcBitmap->GetHeight() != m_Height) { 422 pSrcClone = pSrcBitmap->StretchTo(m_Width, m_Height, 0, nullptr); 423 if (!pSrcClone) 424 return false; 425 } 426 if (IsAlphaMask()) { 427 if (!ConvertFormat(FXDIB_8bppMask)) 428 return false; 429 430 for (int row = 0; row < m_Height; row++) { 431 uint8_t* dest_scan = m_pBuffer.Get() + m_Pitch * row; 432 uint8_t* src_scan = pSrcClone->m_pBuffer.Get() + pSrcClone->m_Pitch * row; 433 if (pSrcClone->GetBPP() == 1) { 434 for (int col = 0; col < m_Width; col++) { 435 if (!((1 << (7 - col % 8)) & src_scan[col / 8])) 436 dest_scan[col] = 0; 437 } 438 } else { 439 for (int col = 0; col < m_Width; col++) { 440 *dest_scan = (*dest_scan) * src_scan[col] / 255; 441 dest_scan++; 442 } 443 } 444 } 445 } else { 446 if (GetFormat() == FXDIB_Argb) { 447 if (pSrcClone->GetBPP() == 1) 448 return false; 449 450 for (int row = 0; row < m_Height; row++) { 451 uint8_t* dest_scan = m_pBuffer.Get() + m_Pitch * row + 3; 452 uint8_t* src_scan = 453 pSrcClone->m_pBuffer.Get() + pSrcClone->m_Pitch * row; 454 for (int col = 0; col < m_Width; col++) { 455 *dest_scan = (*dest_scan) * src_scan[col] / 255; 456 dest_scan += 4; 457 } 458 } 459 } else { 460 m_pAlphaMask->MultiplyAlpha(pSrcClone); 461 } 462 } 463 return true; 464 } 465 466 bool CFX_DIBitmap::MultiplyAlpha(int alpha) { 467 if (!m_pBuffer) 468 return false; 469 470 switch (GetFormat()) { 471 case FXDIB_1bppMask: 472 if (!ConvertFormat(FXDIB_8bppMask)) { 473 return false; 474 } 475 MultiplyAlpha(alpha); 476 break; 477 case FXDIB_8bppMask: { 478 for (int row = 0; row < m_Height; row++) { 479 uint8_t* scan_line = m_pBuffer.Get() + row * m_Pitch; 480 for (int col = 0; col < m_Width; col++) { 481 scan_line[col] = scan_line[col] * alpha / 255; 482 } 483 } 484 break; 485 } 486 case FXDIB_Argb: { 487 for (int row = 0; row < m_Height; row++) { 488 uint8_t* scan_line = m_pBuffer.Get() + row * m_Pitch + 3; 489 for (int col = 0; col < m_Width; col++) { 490 *scan_line = (*scan_line) * alpha / 255; 491 scan_line += 4; 492 } 493 } 494 break; 495 } 496 default: 497 if (HasAlpha()) { 498 m_pAlphaMask->MultiplyAlpha(alpha); 499 } else if (IsCmykImage()) { 500 if (!ConvertFormat((FXDIB_Format)(GetFormat() | 0x0200))) { 501 return false; 502 } 503 m_pAlphaMask->MultiplyAlpha(alpha); 504 } else { 505 if (!ConvertFormat(FXDIB_Argb)) { 506 return false; 507 } 508 MultiplyAlpha(alpha); 509 } 510 break; 511 } 512 return true; 513 } 514 515 uint32_t CFX_DIBitmap::GetPixel(int x, int y) const { 516 if (!m_pBuffer) 517 return 0; 518 519 uint8_t* pos = m_pBuffer.Get() + y * m_Pitch + x * GetBPP() / 8; 520 switch (GetFormat()) { 521 case FXDIB_1bppMask: { 522 if ((*pos) & (1 << (7 - x % 8))) { 523 return 0xff000000; 524 } 525 return 0; 526 } 527 case FXDIB_1bppRgb: { 528 if ((*pos) & (1 << (7 - x % 8))) { 529 return m_pPalette ? m_pPalette.get()[1] : 0xffffffff; 530 } 531 return m_pPalette ? m_pPalette.get()[0] : 0xff000000; 532 } 533 case FXDIB_8bppMask: 534 return (*pos) << 24; 535 case FXDIB_8bppRgb: 536 return m_pPalette ? m_pPalette.get()[*pos] 537 : (0xff000000 | ((*pos) * 0x10101)); 538 case FXDIB_Rgb: 539 case FXDIB_Rgba: 540 case FXDIB_Rgb32: 541 return FXARGB_GETDIB(pos) | 0xff000000; 542 case FXDIB_Argb: 543 return FXARGB_GETDIB(pos); 544 default: 545 break; 546 } 547 return 0; 548 } 549 550 void CFX_DIBitmap::SetPixel(int x, int y, uint32_t color) { 551 if (!m_pBuffer) 552 return; 553 554 if (x < 0 || x >= m_Width || y < 0 || y >= m_Height) 555 return; 556 557 uint8_t* pos = m_pBuffer.Get() + y * m_Pitch + x * GetBPP() / 8; 558 switch (GetFormat()) { 559 case FXDIB_1bppMask: 560 if (color >> 24) { 561 *pos |= 1 << (7 - x % 8); 562 } else { 563 *pos &= ~(1 << (7 - x % 8)); 564 } 565 break; 566 case FXDIB_1bppRgb: 567 if (m_pPalette) { 568 if (color == m_pPalette.get()[1]) { 569 *pos |= 1 << (7 - x % 8); 570 } else { 571 *pos &= ~(1 << (7 - x % 8)); 572 } 573 } else { 574 if (color == 0xffffffff) { 575 *pos |= 1 << (7 - x % 8); 576 } else { 577 *pos &= ~(1 << (7 - x % 8)); 578 } 579 } 580 break; 581 case FXDIB_8bppMask: 582 *pos = (uint8_t)(color >> 24); 583 break; 584 case FXDIB_8bppRgb: { 585 if (m_pPalette) { 586 for (int i = 0; i < 256; i++) { 587 if (m_pPalette.get()[i] == color) { 588 *pos = (uint8_t)i; 589 return; 590 } 591 } 592 *pos = 0; 593 } else { 594 *pos = FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color)); 595 } 596 break; 597 } 598 case FXDIB_Rgb: 599 case FXDIB_Rgb32: { 600 int alpha = FXARGB_A(color); 601 pos[0] = (FXARGB_B(color) * alpha + pos[0] * (255 - alpha)) / 255; 602 pos[1] = (FXARGB_G(color) * alpha + pos[1] * (255 - alpha)) / 255; 603 pos[2] = (FXARGB_R(color) * alpha + pos[2] * (255 - alpha)) / 255; 604 break; 605 } 606 case FXDIB_Rgba: { 607 pos[0] = FXARGB_B(color); 608 pos[1] = FXARGB_G(color); 609 pos[2] = FXARGB_R(color); 610 break; 611 } 612 case FXDIB_Argb: 613 FXARGB_SETDIB(pos, color); 614 break; 615 default: 616 break; 617 } 618 } 619 620 void CFX_DIBitmap::DownSampleScanline(int line, 621 uint8_t* dest_scan, 622 int dest_bpp, 623 int dest_width, 624 bool bFlipX, 625 int clip_left, 626 int clip_width) const { 627 if (!m_pBuffer) 628 return; 629 630 int src_Bpp = m_bpp / 8; 631 uint8_t* scanline = m_pBuffer.Get() + line * m_Pitch; 632 if (src_Bpp == 0) { 633 for (int i = 0; i < clip_width; i++) { 634 uint32_t dest_x = clip_left + i; 635 uint32_t src_x = dest_x * m_Width / dest_width; 636 if (bFlipX) { 637 src_x = m_Width - src_x - 1; 638 } 639 src_x %= m_Width; 640 dest_scan[i] = (scanline[src_x / 8] & (1 << (7 - src_x % 8))) ? 255 : 0; 641 } 642 } else if (src_Bpp == 1) { 643 for (int i = 0; i < clip_width; i++) { 644 uint32_t dest_x = clip_left + i; 645 uint32_t src_x = dest_x * m_Width / dest_width; 646 if (bFlipX) { 647 src_x = m_Width - src_x - 1; 648 } 649 src_x %= m_Width; 650 int dest_pos = i; 651 if (m_pPalette) { 652 if (!IsCmykImage()) { 653 dest_pos *= 3; 654 FX_ARGB argb = m_pPalette.get()[scanline[src_x]]; 655 dest_scan[dest_pos] = FXARGB_B(argb); 656 dest_scan[dest_pos + 1] = FXARGB_G(argb); 657 dest_scan[dest_pos + 2] = FXARGB_R(argb); 658 } else { 659 dest_pos *= 4; 660 FX_CMYK cmyk = m_pPalette.get()[scanline[src_x]]; 661 dest_scan[dest_pos] = FXSYS_GetCValue(cmyk); 662 dest_scan[dest_pos + 1] = FXSYS_GetMValue(cmyk); 663 dest_scan[dest_pos + 2] = FXSYS_GetYValue(cmyk); 664 dest_scan[dest_pos + 3] = FXSYS_GetKValue(cmyk); 665 } 666 } else { 667 dest_scan[dest_pos] = scanline[src_x]; 668 } 669 } 670 } else { 671 for (int i = 0; i < clip_width; i++) { 672 uint32_t dest_x = clip_left + i; 673 uint32_t src_x = 674 bFlipX ? (m_Width - dest_x * m_Width / dest_width - 1) * src_Bpp 675 : (dest_x * m_Width / dest_width) * src_Bpp; 676 src_x %= m_Width * src_Bpp; 677 int dest_pos = i * src_Bpp; 678 for (int b = 0; b < src_Bpp; b++) { 679 dest_scan[dest_pos + b] = scanline[src_x + b]; 680 } 681 } 682 } 683 } 684 685 void CFX_DIBitmap::ConvertRGBColorScale(uint32_t forecolor, 686 uint32_t backcolor) { 687 int fr = FXSYS_GetRValue(forecolor); 688 int fg = FXSYS_GetGValue(forecolor); 689 int fb = FXSYS_GetBValue(forecolor); 690 int br = FXSYS_GetRValue(backcolor); 691 int bg = FXSYS_GetGValue(backcolor); 692 int bb = FXSYS_GetBValue(backcolor); 693 if (m_bpp <= 8) { 694 if (forecolor == 0 && backcolor == 0xffffff && !m_pPalette) 695 return; 696 if (!m_pPalette) 697 BuildPalette(); 698 int size = 1 << m_bpp; 699 for (int i = 0; i < size; ++i) { 700 int gray = FXRGB2GRAY(FXARGB_R(m_pPalette.get()[i]), 701 FXARGB_G(m_pPalette.get()[i]), 702 FXARGB_B(m_pPalette.get()[i])); 703 m_pPalette.get()[i] = 704 FXARGB_MAKE(0xff, br + (fr - br) * gray / 255, 705 bg + (fg - bg) * gray / 255, bb + (fb - bb) * gray / 255); 706 } 707 return; 708 } 709 if (forecolor == 0 && backcolor == 0xffffff) { 710 for (int row = 0; row < m_Height; ++row) { 711 uint8_t* scanline = m_pBuffer.Get() + row * m_Pitch; 712 int gap = m_bpp / 8 - 2; 713 for (int col = 0; col < m_Width; ++col) { 714 int gray = FXRGB2GRAY(scanline[2], scanline[1], scanline[0]); 715 *scanline++ = gray; 716 *scanline++ = gray; 717 *scanline = gray; 718 scanline += gap; 719 } 720 } 721 return; 722 } 723 for (int row = 0; row < m_Height; ++row) { 724 uint8_t* scanline = m_pBuffer.Get() + row * m_Pitch; 725 int gap = m_bpp / 8 - 2; 726 for (int col = 0; col < m_Width; ++col) { 727 int gray = FXRGB2GRAY(scanline[2], scanline[1], scanline[0]); 728 *scanline++ = bb + (fb - bb) * gray / 255; 729 *scanline++ = bg + (fg - bg) * gray / 255; 730 *scanline = br + (fr - br) * gray / 255; 731 scanline += gap; 732 } 733 } 734 } 735 736 void CFX_DIBitmap::ConvertCMYKColorScale(uint32_t forecolor, 737 uint32_t backcolor) { 738 int fc = FXSYS_GetCValue(forecolor); 739 int fm = FXSYS_GetMValue(forecolor); 740 int fy = FXSYS_GetYValue(forecolor); 741 int fk = FXSYS_GetKValue(forecolor); 742 int bc = FXSYS_GetCValue(backcolor); 743 int bm = FXSYS_GetMValue(backcolor); 744 int by = FXSYS_GetYValue(backcolor); 745 int bk = FXSYS_GetKValue(backcolor); 746 if (m_bpp <= 8) { 747 if (forecolor == 0xff && backcolor == 0 && !m_pPalette) 748 return; 749 if (!m_pPalette) 750 BuildPalette(); 751 int size = 1 << m_bpp; 752 for (int i = 0; i < size; ++i) { 753 uint8_t r; 754 uint8_t g; 755 uint8_t b; 756 std::tie(r, g, b) = 757 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(m_pPalette.get()[i]), 758 FXSYS_GetMValue(m_pPalette.get()[i]), 759 FXSYS_GetYValue(m_pPalette.get()[i]), 760 FXSYS_GetKValue(m_pPalette.get()[i])); 761 int gray = 255 - FXRGB2GRAY(r, g, b); 762 m_pPalette.get()[i] = 763 CmykEncode(bc + (fc - bc) * gray / 255, bm + (fm - bm) * gray / 255, 764 by + (fy - by) * gray / 255, bk + (fk - bk) * gray / 255); 765 } 766 return; 767 } 768 if (forecolor == 0xff && backcolor == 0x00) { 769 for (int row = 0; row < m_Height; ++row) { 770 uint8_t* scanline = m_pBuffer.Get() + row * m_Pitch; 771 for (int col = 0; col < m_Width; ++col) { 772 uint8_t r; 773 uint8_t g; 774 uint8_t b; 775 std::tie(r, g, b) = AdobeCMYK_to_sRGB1(scanline[0], scanline[1], 776 scanline[2], scanline[3]); 777 *scanline++ = 0; 778 *scanline++ = 0; 779 *scanline++ = 0; 780 *scanline++ = 255 - FXRGB2GRAY(r, g, b); 781 } 782 } 783 return; 784 } 785 for (int row = 0; row < m_Height; ++row) { 786 uint8_t* scanline = m_pBuffer.Get() + row * m_Pitch; 787 for (int col = 0; col < m_Width; ++col) { 788 uint8_t r; 789 uint8_t g; 790 uint8_t b; 791 std::tie(r, g, b) = AdobeCMYK_to_sRGB1(scanline[0], scanline[1], 792 scanline[2], scanline[3]); 793 int gray = 255 - FXRGB2GRAY(r, g, b); 794 *scanline++ = bc + (fc - bc) * gray / 255; 795 *scanline++ = bm + (fm - bm) * gray / 255; 796 *scanline++ = by + (fy - by) * gray / 255; 797 *scanline++ = bk + (fk - bk) * gray / 255; 798 } 799 } 800 } 801 802 bool CFX_DIBitmap::ConvertColorScale(uint32_t forecolor, uint32_t backcolor) { 803 ASSERT(!IsAlphaMask()); 804 if (!m_pBuffer || IsAlphaMask()) 805 return false; 806 807 if (IsCmykImage()) 808 ConvertCMYKColorScale(forecolor, backcolor); 809 else 810 ConvertRGBColorScale(forecolor, backcolor); 811 return true; 812 } 813 814 bool CFX_DIBitmap::CalculatePitchAndSize(int height, 815 int width, 816 FXDIB_Format format, 817 uint32_t* pitch, 818 uint32_t* size) { 819 if (width <= 0 || height <= 0) 820 return false; 821 822 if ((INT_MAX - 31) / width < (format & 0xFF)) 823 return false; 824 825 if (!*pitch) 826 *pitch = static_cast<uint32_t>((width * (format & 0xff) + 31) / 32 * 4); 827 828 if ((1 << 30) / *pitch < static_cast<uint32_t>(height)) 829 return false; 830 831 *size = *pitch * static_cast<uint32_t>(height); 832 return true; 833 } 834 835 bool CFX_DIBitmap::CompositeBitmap(int dest_left, 836 int dest_top, 837 int width, 838 int height, 839 const RetainPtr<CFX_DIBSource>& pSrcBitmap, 840 int src_left, 841 int src_top, 842 int blend_type, 843 const CFX_ClipRgn* pClipRgn, 844 bool bRgbByteOrder) { 845 if (!m_pBuffer) 846 return false; 847 848 ASSERT(!pSrcBitmap->IsAlphaMask()); 849 ASSERT(m_bpp >= 8); 850 if (pSrcBitmap->IsAlphaMask() || m_bpp < 8) { 851 return false; 852 } 853 GetOverlapRect(dest_left, dest_top, width, height, pSrcBitmap->GetWidth(), 854 pSrcBitmap->GetHeight(), src_left, src_top, pClipRgn); 855 if (width == 0 || height == 0) { 856 return true; 857 } 858 RetainPtr<CFX_DIBitmap> pClipMask; 859 FX_RECT clip_box; 860 if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) { 861 ASSERT(pClipRgn->GetType() == CFX_ClipRgn::MaskF); 862 pClipMask = pClipRgn->GetMask(); 863 clip_box = pClipRgn->GetBox(); 864 } 865 CFX_ScanlineCompositor compositor; 866 if (!compositor.Init(GetFormat(), pSrcBitmap->GetFormat(), width, 867 pSrcBitmap->GetPalette(), 0, blend_type, 868 pClipMask != nullptr, bRgbByteOrder, 0)) { 869 return false; 870 } 871 int dest_Bpp = m_bpp / 8; 872 int src_Bpp = pSrcBitmap->GetBPP() / 8; 873 bool bRgb = src_Bpp > 1 && !pSrcBitmap->IsCmykImage(); 874 RetainPtr<CFX_DIBitmap> pSrcAlphaMask = pSrcBitmap->m_pAlphaMask; 875 for (int row = 0; row < height; row++) { 876 uint8_t* dest_scan = 877 m_pBuffer.Get() + (dest_top + row) * m_Pitch + dest_left * dest_Bpp; 878 const uint8_t* src_scan = 879 pSrcBitmap->GetScanline(src_top + row) + src_left * src_Bpp; 880 const uint8_t* src_scan_extra_alpha = 881 pSrcAlphaMask ? pSrcAlphaMask->GetScanline(src_top + row) + src_left 882 : nullptr; 883 uint8_t* dst_scan_extra_alpha = 884 m_pAlphaMask 885 ? (uint8_t*)m_pAlphaMask->GetScanline(dest_top + row) + dest_left 886 : nullptr; 887 const uint8_t* clip_scan = nullptr; 888 if (pClipMask) { 889 clip_scan = pClipMask->m_pBuffer.Get() + 890 (dest_top + row - clip_box.top) * pClipMask->m_Pitch + 891 (dest_left - clip_box.left); 892 } 893 if (bRgb) { 894 compositor.CompositeRgbBitmapLine(dest_scan, src_scan, width, clip_scan, 895 src_scan_extra_alpha, 896 dst_scan_extra_alpha); 897 } else { 898 compositor.CompositePalBitmapLine(dest_scan, src_scan, src_left, width, 899 clip_scan, src_scan_extra_alpha, 900 dst_scan_extra_alpha); 901 } 902 } 903 return true; 904 } 905 906 bool CFX_DIBitmap::CompositeMask(int dest_left, 907 int dest_top, 908 int width, 909 int height, 910 const RetainPtr<CFX_DIBSource>& pMask, 911 uint32_t color, 912 int src_left, 913 int src_top, 914 int blend_type, 915 const CFX_ClipRgn* pClipRgn, 916 bool bRgbByteOrder, 917 int alpha_flag) { 918 if (!m_pBuffer) 919 return false; 920 921 ASSERT(pMask->IsAlphaMask()); 922 ASSERT(m_bpp >= 8); 923 if (!pMask->IsAlphaMask() || m_bpp < 8) 924 return false; 925 926 GetOverlapRect(dest_left, dest_top, width, height, pMask->GetWidth(), 927 pMask->GetHeight(), src_left, src_top, pClipRgn); 928 if (width == 0 || height == 0) 929 return true; 930 931 int src_alpha = 932 (uint8_t)(alpha_flag >> 8) ? (alpha_flag & 0xff) : FXARGB_A(color); 933 if (src_alpha == 0) 934 return true; 935 936 RetainPtr<CFX_DIBitmap> pClipMask; 937 FX_RECT clip_box; 938 if (pClipRgn && pClipRgn->GetType() != CFX_ClipRgn::RectI) { 939 ASSERT(pClipRgn->GetType() == CFX_ClipRgn::MaskF); 940 pClipMask = pClipRgn->GetMask(); 941 clip_box = pClipRgn->GetBox(); 942 } 943 int src_bpp = pMask->GetBPP(); 944 int Bpp = GetBPP() / 8; 945 CFX_ScanlineCompositor compositor; 946 if (!compositor.Init(GetFormat(), pMask->GetFormat(), width, nullptr, color, 947 blend_type, pClipMask != nullptr, bRgbByteOrder, 948 alpha_flag)) { 949 return false; 950 } 951 for (int row = 0; row < height; row++) { 952 uint8_t* dest_scan = 953 m_pBuffer.Get() + (dest_top + row) * m_Pitch + dest_left * Bpp; 954 const uint8_t* src_scan = pMask->GetScanline(src_top + row); 955 uint8_t* dst_scan_extra_alpha = 956 m_pAlphaMask 957 ? (uint8_t*)m_pAlphaMask->GetScanline(dest_top + row) + dest_left 958 : nullptr; 959 const uint8_t* clip_scan = nullptr; 960 if (pClipMask) { 961 clip_scan = pClipMask->m_pBuffer.Get() + 962 (dest_top + row - clip_box.top) * pClipMask->m_Pitch + 963 (dest_left - clip_box.left); 964 } 965 if (src_bpp == 1) { 966 compositor.CompositeBitMaskLine(dest_scan, src_scan, src_left, width, 967 clip_scan, dst_scan_extra_alpha); 968 } else { 969 compositor.CompositeByteMaskLine(dest_scan, src_scan + src_left, width, 970 clip_scan, dst_scan_extra_alpha); 971 } 972 } 973 return true; 974 } 975 976 bool CFX_DIBitmap::CompositeRect(int left, 977 int top, 978 int width, 979 int height, 980 uint32_t color, 981 int alpha_flag) { 982 if (!m_pBuffer) 983 return false; 984 985 int src_alpha = (alpha_flag >> 8) ? (alpha_flag & 0xff) : FXARGB_A(color); 986 if (src_alpha == 0) 987 return true; 988 989 FX_RECT rect(left, top, left + width, top + height); 990 rect.Intersect(0, 0, m_Width, m_Height); 991 if (rect.IsEmpty()) 992 return true; 993 994 width = rect.Width(); 995 uint32_t dst_color; 996 if (alpha_flag >> 8) 997 dst_color = FXCMYK_TODIB(color); 998 else 999 dst_color = FXARGB_TODIB(color); 1000 uint8_t* color_p = (uint8_t*)&dst_color; 1001 if (m_bpp == 8) { 1002 uint8_t gray = 255; 1003 if (!IsAlphaMask()) { 1004 if (alpha_flag >> 8) { 1005 uint8_t r; 1006 uint8_t g; 1007 uint8_t b; 1008 std::tie(r, g, b) = 1009 AdobeCMYK_to_sRGB1(color_p[0], color_p[1], color_p[2], color_p[3]); 1010 gray = FXRGB2GRAY(r, g, b); 1011 } else { 1012 gray = (uint8_t)FXRGB2GRAY((int)color_p[2], color_p[1], color_p[0]); 1013 } 1014 if (IsCmykImage()) { 1015 gray = ~gray; 1016 } 1017 } 1018 for (int row = rect.top; row < rect.bottom; row++) { 1019 uint8_t* dest_scan = m_pBuffer.Get() + row * m_Pitch + rect.left; 1020 if (src_alpha == 255) { 1021 memset(dest_scan, gray, width); 1022 } else { 1023 for (int col = 0; col < width; col++) { 1024 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha); 1025 dest_scan++; 1026 } 1027 } 1028 } 1029 return true; 1030 } 1031 if (m_bpp == 1) { 1032 ASSERT(!IsCmykImage() && static_cast<uint8_t>(alpha_flag >> 8) == 0); 1033 int left_shift = rect.left % 8; 1034 int right_shift = rect.right % 8; 1035 int new_width = rect.right / 8 - rect.left / 8; 1036 int index = 0; 1037 if (m_pPalette) { 1038 for (int i = 0; i < 2; i++) { 1039 if (m_pPalette.get()[i] == color) 1040 index = i; 1041 } 1042 } else { 1043 index = (static_cast<uint8_t>(color) == 0xff) ? 1 : 0; 1044 } 1045 for (int row = rect.top; row < rect.bottom; row++) { 1046 uint8_t* dest_scan_top = 1047 const_cast<uint8_t*>(GetScanline(row)) + rect.left / 8; 1048 uint8_t* dest_scan_top_r = 1049 const_cast<uint8_t*>(GetScanline(row)) + rect.right / 8; 1050 uint8_t left_flag = *dest_scan_top & (255 << (8 - left_shift)); 1051 uint8_t right_flag = *dest_scan_top_r & (255 >> right_shift); 1052 if (new_width) { 1053 memset(dest_scan_top + 1, index ? 255 : 0, new_width - 1); 1054 if (!index) { 1055 *dest_scan_top &= left_flag; 1056 *dest_scan_top_r &= right_flag; 1057 } else { 1058 *dest_scan_top |= ~left_flag; 1059 *dest_scan_top_r |= ~right_flag; 1060 } 1061 } else { 1062 if (!index) { 1063 *dest_scan_top &= left_flag | right_flag; 1064 } else { 1065 *dest_scan_top |= ~(left_flag | right_flag); 1066 } 1067 } 1068 } 1069 return true; 1070 } 1071 ASSERT(m_bpp >= 24); 1072 if (m_bpp < 24 || (!(alpha_flag >> 8) && IsCmykImage())) 1073 return false; 1074 if (alpha_flag >> 8 && !IsCmykImage()) { 1075 std::tie(color_p[2], color_p[1], color_p[0]) = 1076 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), 1077 FXSYS_GetYValue(color), FXSYS_GetKValue(color)); 1078 } 1079 if (!IsCmykImage()) 1080 color_p[3] = static_cast<uint8_t>(src_alpha); 1081 int Bpp = m_bpp / 8; 1082 bool bAlpha = HasAlpha(); 1083 bool bArgb = GetFormat() == FXDIB_Argb; 1084 if (src_alpha == 255) { 1085 for (int row = rect.top; row < rect.bottom; row++) { 1086 uint8_t* dest_scan = m_pBuffer.Get() + row * m_Pitch + rect.left * Bpp; 1087 uint8_t* dest_scan_alpha = 1088 m_pAlphaMask ? (uint8_t*)m_pAlphaMask->GetScanline(row) + rect.left 1089 : nullptr; 1090 if (dest_scan_alpha) { 1091 memset(dest_scan_alpha, 0xff, width); 1092 } 1093 if (Bpp == 4) { 1094 uint32_t* scan = (uint32_t*)dest_scan; 1095 for (int col = 0; col < width; col++) { 1096 *scan++ = dst_color; 1097 } 1098 } else { 1099 for (int col = 0; col < width; col++) { 1100 *dest_scan++ = color_p[0]; 1101 *dest_scan++ = color_p[1]; 1102 *dest_scan++ = color_p[2]; 1103 } 1104 } 1105 } 1106 return true; 1107 } 1108 for (int row = rect.top; row < rect.bottom; row++) { 1109 uint8_t* dest_scan = m_pBuffer.Get() + row * m_Pitch + rect.left * Bpp; 1110 if (bAlpha) { 1111 if (bArgb) { 1112 for (int col = 0; col < width; col++) { 1113 uint8_t back_alpha = dest_scan[3]; 1114 if (back_alpha == 0) { 1115 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha, color_p[2], 1116 color_p[1], color_p[0])); 1117 dest_scan += 4; 1118 continue; 1119 } 1120 uint8_t dest_alpha = 1121 back_alpha + src_alpha - back_alpha * src_alpha / 255; 1122 int alpha_ratio = src_alpha * 255 / dest_alpha; 1123 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[0], alpha_ratio); 1124 dest_scan++; 1125 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[1], alpha_ratio); 1126 dest_scan++; 1127 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[2], alpha_ratio); 1128 dest_scan++; 1129 *dest_scan++ = dest_alpha; 1130 } 1131 } else { 1132 uint8_t* dest_scan_alpha = 1133 (uint8_t*)m_pAlphaMask->GetScanline(row) + rect.left; 1134 for (int col = 0; col < width; col++) { 1135 uint8_t back_alpha = *dest_scan_alpha; 1136 if (back_alpha == 0) { 1137 *dest_scan_alpha++ = src_alpha; 1138 memcpy(dest_scan, color_p, Bpp); 1139 dest_scan += Bpp; 1140 continue; 1141 } 1142 uint8_t dest_alpha = 1143 back_alpha + src_alpha - back_alpha * src_alpha / 255; 1144 *dest_scan_alpha++ = dest_alpha; 1145 int alpha_ratio = src_alpha * 255 / dest_alpha; 1146 for (int comps = 0; comps < Bpp; comps++) { 1147 *dest_scan = 1148 FXDIB_ALPHA_MERGE(*dest_scan, color_p[comps], alpha_ratio); 1149 dest_scan++; 1150 } 1151 } 1152 } 1153 } else { 1154 for (int col = 0; col < width; col++) { 1155 for (int comps = 0; comps < Bpp; comps++) { 1156 if (comps == 3) { 1157 *dest_scan++ = 255; 1158 continue; 1159 } 1160 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, color_p[comps], src_alpha); 1161 dest_scan++; 1162 } 1163 } 1164 } 1165 } 1166 return true; 1167 } 1168 1169 bool CFX_DIBitmap::ConvertFormat(FXDIB_Format dest_format) { 1170 FXDIB_Format src_format = GetFormat(); 1171 if (dest_format == src_format) 1172 return true; 1173 1174 if (dest_format == FXDIB_8bppMask && src_format == FXDIB_8bppRgb && 1175 !m_pPalette) { 1176 m_AlphaFlag = 1; 1177 return true; 1178 } 1179 if (dest_format == FXDIB_Argb && src_format == FXDIB_Rgb32) { 1180 m_AlphaFlag = 2; 1181 for (int row = 0; row < m_Height; row++) { 1182 uint8_t* scanline = m_pBuffer.Get() + row * m_Pitch + 3; 1183 for (int col = 0; col < m_Width; col++) { 1184 *scanline = 0xff; 1185 scanline += 4; 1186 } 1187 } 1188 return true; 1189 } 1190 int dest_bpp = dest_format & 0xff; 1191 int dest_pitch = (dest_bpp * m_Width + 31) / 32 * 4; 1192 std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf( 1193 FX_TryAlloc(uint8_t, dest_pitch * m_Height + 4)); 1194 if (!dest_buf) 1195 return false; 1196 1197 RetainPtr<CFX_DIBitmap> pAlphaMask; 1198 if (dest_format == FXDIB_Argb) { 1199 memset(dest_buf.get(), 0xff, dest_pitch * m_Height + 4); 1200 if (m_pAlphaMask) { 1201 for (int row = 0; row < m_Height; row++) { 1202 uint8_t* pDstScanline = dest_buf.get() + row * dest_pitch + 3; 1203 const uint8_t* pSrcScanline = m_pAlphaMask->GetScanline(row); 1204 for (int col = 0; col < m_Width; col++) { 1205 *pDstScanline = *pSrcScanline++; 1206 pDstScanline += 4; 1207 } 1208 } 1209 } 1210 } else if (dest_format & 0x0200) { 1211 if (src_format == FXDIB_Argb) { 1212 pAlphaMask = CloneAlphaMask(); 1213 if (!pAlphaMask) 1214 return false; 1215 } else { 1216 if (!m_pAlphaMask) { 1217 if (!BuildAlphaMask()) 1218 return false; 1219 pAlphaMask = std::move(m_pAlphaMask); 1220 } else { 1221 pAlphaMask = m_pAlphaMask; 1222 } 1223 } 1224 } 1225 bool ret = false; 1226 RetainPtr<CFX_DIBSource> holder(this); 1227 std::unique_ptr<uint32_t, FxFreeDeleter> pal_8bpp; 1228 ret = ConvertBuffer(dest_format, dest_buf.get(), dest_pitch, m_Width, 1229 m_Height, holder, 0, 0, &pal_8bpp); 1230 if (!ret) 1231 return false; 1232 1233 m_pAlphaMask = pAlphaMask; 1234 m_pPalette = std::move(pal_8bpp); 1235 m_pBuffer = std::move(dest_buf); 1236 m_bpp = static_cast<uint8_t>(dest_format); 1237 m_AlphaFlag = static_cast<uint8_t>(dest_format >> 8); 1238 m_Pitch = dest_pitch; 1239 return true; 1240 } 1241