Add CFX_DIBBase::TakePalette()

Give CFX_DIBBase::SetPalette() callers a way to set the palette with a
move instead of a copy. Use it where appropriate, which requires
changing ScanlineComposerIface::SetInfo() to take a vector instead of a
span.

Additionally, change some cfx_dibbase.cpp helper functions to initialize
palettes directly, instead of allocating a vector of a fixed size, and
then copying into it.

Change-Id: I7af470a503c068c1ae7fd5ace6eb99156624e36d
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/115510
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxge/dib/cfx_bitmapcomposer.cpp b/core/fxge/dib/cfx_bitmapcomposer.cpp
index 30c57c3..1b24e6a 100644
--- a/core/fxge/dib/cfx_bitmapcomposer.cpp
+++ b/core/fxge/dib/cfx_bitmapcomposer.cpp
@@ -52,7 +52,7 @@
 bool CFX_BitmapComposer::SetInfo(int width,
                                  int height,
                                  FXDIB_Format src_format,
-                                 pdfium::span<const uint32_t> src_palette) {
+                                 DataVector<uint32_t> src_palette) {
   DCHECK_NE(src_format, FXDIB_Format::k1bppMask);
   DCHECK_NE(src_format, FXDIB_Format::k1bppRgb);
   m_SrcFormat = src_format;
diff --git a/core/fxge/dib/cfx_bitmapcomposer.h b/core/fxge/dib/cfx_bitmapcomposer.h
index f63c8c5..ce5826e 100644
--- a/core/fxge/dib/cfx_bitmapcomposer.h
+++ b/core/fxge/dib/cfx_bitmapcomposer.h
@@ -40,7 +40,7 @@
   bool SetInfo(int width,
                int height,
                FXDIB_Format src_format,
-               pdfium::span<const uint32_t> src_palette) override;
+               DataVector<uint32_t> src_palette) override;
   void ComposeScanline(int line, pdfium::span<const uint8_t> scanline) override;
 
  private:
diff --git a/core/fxge/dib/cfx_bitmapstorer.cpp b/core/fxge/dib/cfx_bitmapstorer.cpp
index 607b0cb..1d3641a 100644
--- a/core/fxge/dib/cfx_bitmapstorer.cpp
+++ b/core/fxge/dib/cfx_bitmapstorer.cpp
@@ -36,15 +36,16 @@
 bool CFX_BitmapStorer::SetInfo(int width,
                                int height,
                                FXDIB_Format src_format,
-                               pdfium::span<const uint32_t> src_palette) {
+                               DataVector<uint32_t> src_palette) {
   DCHECK_NE(src_format, FXDIB_Format::k1bppMask);
   DCHECK_NE(src_format, FXDIB_Format::k1bppRgb);
   auto pBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
   if (!pBitmap->Create(width, height, src_format))
     return false;
 
-  if (!src_palette.empty())
-    pBitmap->SetPalette(src_palette);
+  if (!src_palette.empty()) {
+    pBitmap->TakePalette(std::move(src_palette));
+  }
 
   m_pBitmap = std::move(pBitmap);
   return true;
diff --git a/core/fxge/dib/cfx_bitmapstorer.h b/core/fxge/dib/cfx_bitmapstorer.h
index 7a5e3ff..326a8b0 100644
--- a/core/fxge/dib/cfx_bitmapstorer.h
+++ b/core/fxge/dib/cfx_bitmapstorer.h
@@ -23,7 +23,7 @@
   bool SetInfo(int width,
                int height,
                FXDIB_Format src_format,
-               pdfium::span<const uint32_t> src_palette) override;
+               DataVector<uint32_t> src_palette) override;
 
   RetainPtr<CFX_DIBitmap> GetBitmap() { return m_pBitmap; }
   RetainPtr<CFX_DIBitmap> Detach();
diff --git a/core/fxge/dib/cfx_dibbase.cpp b/core/fxge/dib/cfx_dibbase.cpp
index d191298..f80c19e 100644
--- a/core/fxge/dib/cfx_dibbase.cpp
+++ b/core/fxge/dib/cfx_dibbase.cpp
@@ -295,9 +295,8 @@
   pdfium::span<const uint32_t> src_span = pSrcBitmap->GetPaletteSpan();
   CHECK_LE(plt_size, src_span.size());
 
-  DataVector<uint32_t> dest_palette(256);
-  fxcrt::spancpy(pdfium::make_span(dest_palette), src_span.first(plt_size));
-  return dest_palette;
+  pdfium::span<const uint32_t> src_palette_span = src_span.first(plt_size);
+  return DataVector<uint32_t>(src_palette_span.begin(), src_palette_span.end());
 }
 
 DataVector<uint32_t> ConvertBuffer_Rgb2PltRgb8(
@@ -331,9 +330,9 @@
       }
     }
   }
-  DataVector<uint32_t> dest_palette(256);
-  fxcrt::spancpy(pdfium::make_span(dest_palette), src_palette.GetPalette());
-  return dest_palette;
+
+  pdfium::span<const uint32_t> src_palette_span = src_palette.GetPalette();
+  return DataVector<uint32_t>(src_palette_span.begin(), src_palette_span.end());
 }
 
 void ConvertBuffer_1bppMask2Rgb(FXDIB_Format dest_format,
@@ -852,16 +851,19 @@
 }
 
 void CFX_DIBBase::SetPalette(pdfium::span<const uint32_t> src_palette) {
+  TakePalette(DataVector<uint32_t>(src_palette.begin(), src_palette.end()));
+}
+
+void CFX_DIBBase::TakePalette(DataVector<uint32_t> src_palette) {
   if (src_palette.empty() || GetBPP() > 8) {
     m_palette.clear();
     return;
   }
+
+  m_palette = std::move(src_palette);
   uint32_t pal_size = 1 << GetBPP();
-  if (m_palette.empty())
-    m_palette.resize(pal_size);
-  pal_size = std::min(pal_size, kPaletteSize);
-  for (size_t i = 0; i < pal_size; ++i)
-    m_palette[i] = src_palette[i];
+  CHECK_LE(pal_size, kPaletteSize);
+  m_palette.resize(pal_size);
 }
 
 RetainPtr<CFX_DIBitmap> CFX_DIBBase::CloneAlphaMask() const {
@@ -953,7 +955,7 @@
       ConvertBuffer(dest_format, pClone->GetWritableBuffer(),
                     pClone->GetPitch(), m_Width, m_Height, holder, 0, 0);
   if (!pal_8bpp.empty()) {
-    pClone->SetPalette(pal_8bpp);
+    pClone->TakePalette(std::move(pal_8bpp));
   }
   return pClone;
 }
diff --git a/core/fxge/dib/cfx_dibbase.h b/core/fxge/dib/cfx_dibbase.h
index 4cad3c1..8c4ceab 100644
--- a/core/fxge/dib/cfx_dibbase.h
+++ b/core/fxge/dib/cfx_dibbase.h
@@ -68,6 +68,9 @@
   // Copies into internally-owned palette.
   void SetPalette(pdfium::span<const uint32_t> src_palette);
 
+  // Moves palette into internally-owned palette.
+  void TakePalette(DataVector<uint32_t> src_palette);
+
   RetainPtr<CFX_DIBitmap> Realize() const;
   RetainPtr<CFX_DIBitmap> ClipTo(const FX_RECT& rect) const;
   RetainPtr<CFX_DIBitmap> ConvertTo(FXDIB_Format format) const;
diff --git a/core/fxge/dib/cfx_imagestretcher.cpp b/core/fxge/dib/cfx_imagestretcher.cpp
index f3fdf93..d6e2b34 100644
--- a/core/fxge/dib/cfx_imagestretcher.cpp
+++ b/core/fxge/dib/cfx_imagestretcher.cpp
@@ -8,6 +8,7 @@
 
 #include <utility>
 
+#include "core/fxcrt/data_vector.h"
 #include "core/fxcrt/fx_safe_types.h"
 #include "core/fxge/dib/cfx_dibbase.h"
 #include "core/fxge/dib/cfx_dibitmap.h"
@@ -37,18 +38,11 @@
 }
 
 // Builds a new palette with a size of `CFX_DIBBase::kPaletteSize` from the
-// existing palette in `source`. Note: The caller must make sure that the
-// parameters meet the following conditions:
-//   source       - The format must be `FXDIB_Format::k1bppRgb` and it must
-//                  have a palette.
-//   palette_span - The size must be `CFX_DIBBase::kPaletteSize` to be able
-//                  to hold the new palette.
-
-void BuildPaletteFrom1BppSource(const RetainPtr<const CFX_DIBBase>& source,
-                                pdfium::span<FX_ARGB> palette_span) {
+// existing palette in `source`.
+DataVector<uint32_t> BuildPaletteFrom1BppSource(
+    const RetainPtr<const CFX_DIBBase>& source) {
   DCHECK_EQ(FXDIB_Format::k1bppRgb, source->GetFormat());
   DCHECK(source->HasPalette());
-  DCHECK_EQ(CFX_DIBBase::kPaletteSize, palette_span.size());
 
   int a0;
   int r0;
@@ -63,12 +57,14 @@
   DCHECK_EQ(255, a0);
   DCHECK_EQ(255, a1);
 
+  DataVector<uint32_t> palette(CFX_DIBBase::kPaletteSize);
   for (int i = 0; i < static_cast<int>(CFX_DIBBase::kPaletteSize); ++i) {
     int r = r0 + (r1 - r0) * i / 255;
     int g = g0 + (g1 - g0) * i / 255;
     int b = b0 + (b1 - b0) * i / 255;
-    palette_span[i] = ArgbEncode(255, r, g, b);
+    palette[i] = ArgbEncode(255, r, g, b);
   }
+  return palette;
 }
 
 }  // namespace
@@ -97,10 +93,8 @@
 
   if (m_pSource->GetFormat() == FXDIB_Format::k1bppRgb &&
       m_pSource->HasPalette()) {
-    FX_ARGB pal[CFX_DIBBase::kPaletteSize];
-    BuildPaletteFrom1BppSource(m_pSource, pal);
     if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(), m_DestFormat,
-                          pal)) {
+                          BuildPaletteFrom1BppSource(m_pSource))) {
       return false;
     }
   } else if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(),
diff --git a/core/fxge/dib/scanlinecomposer_iface.h b/core/fxge/dib/scanlinecomposer_iface.h
index ef997cf..e6bbdbe 100644
--- a/core/fxge/dib/scanlinecomposer_iface.h
+++ b/core/fxge/dib/scanlinecomposer_iface.h
@@ -7,6 +7,7 @@
 #ifndef CORE_FXGE_DIB_SCANLINECOMPOSER_IFACE_H_
 #define CORE_FXGE_DIB_SCANLINECOMPOSER_IFACE_H_
 
+#include "core/fxcrt/data_vector.h"
 #include "core/fxge/dib/fx_dib.h"
 #include "third_party/base/containers/span.h"
 
@@ -22,7 +23,7 @@
   virtual bool SetInfo(int width,
                        int height,
                        FXDIB_Format src_format,
-                       pdfium::span<const uint32_t> src_palette) = 0;
+                       DataVector<uint32_t> src_palette) = 0;
 };
 
 #endif  // CORE_FXGE_DIB_SCANLINECOMPOSER_IFACE_H_