From 30dc6aaf878b2c55efcf7598fdb8886e06d14e01 Mon Sep 17 00:00:00 2001 From: Tom Sepez Date: Tue, 25 Sep 2018 20:06:50 +0000 Subject: Add FxAlignToBoundary<>() template helper function. Because I nearly botched this trivial calculation in the previous CL. Change-Id: I7438f9d3476d93b7899c2d7d761234769f53f9e3 Reviewed-on: https://pdfium-review.googlesource.com/43010 Commit-Queue: Lei Zhang Reviewed-by: Lei Zhang --- core/fxcodec/codec/ccodec_faxmodule.cpp | 2 +- core/fxcodec/codec/ccodec_progressivedecoder.cpp | 8 ++++---- core/fxcodec/jbig2/JBig2_Image.cpp | 2 +- core/fxcrt/cfx_bitstream.cpp | 3 ++- core/fxcrt/fx_memory.h | 7 +++++++ core/fxcrt/fx_memory_unittest.cpp | 23 +++++++++++++++++++++++ core/fxge/dib/cfx_imagestretcher.cpp | 9 +++++---- core/fxge/win32/fx_win32_gdipext.cpp | 12 ++++++------ 8 files changed, 49 insertions(+), 17 deletions(-) diff --git a/core/fxcodec/codec/ccodec_faxmodule.cpp b/core/fxcodec/codec/ccodec_faxmodule.cpp index 423dfe6857..fe9f6a9e2e 100644 --- a/core/fxcodec/codec/ccodec_faxmodule.cpp +++ b/core/fxcodec/codec/ccodec_faxmodule.cpp @@ -530,7 +530,7 @@ uint8_t* CCodec_FaxDecoder::v_GetNextLine() { if (m_bByteAlign && m_bitpos < bitsize) { int bitpos0 = m_bitpos; - int bitpos1 = (m_bitpos + 7) / 8 * 8; + int bitpos1 = FxAlignToBoundary<8>(m_bitpos); while (m_bByteAlign && bitpos0 < bitpos1) { int bit = m_SrcSpan[bitpos0 / 8] & (1 << (7 - bitpos0 % 8)); if (bit != 0) diff --git a/core/fxcodec/codec/ccodec_progressivedecoder.cpp b/core/fxcodec/codec/ccodec_progressivedecoder.cpp index c2d121d35a..16408a2b6a 100644 --- a/core/fxcodec/codec/ccodec_progressivedecoder.cpp +++ b/core/fxcodec/codec/ccodec_progressivedecoder.cpp @@ -839,7 +839,7 @@ FXCODEC_STATUS CCodec_ProgressiveDecoder::BmpStartDecode( return m_status; } GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); - m_ScanlineSize = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; + m_ScanlineSize = FxAlignToBoundary<4>(m_SrcWidth * m_SrcComponents); m_pDecodeBuf.reset(FX_Alloc(uint8_t, m_ScanlineSize)); memset(m_pDecodeBuf.get(), 0, m_ScanlineSize); m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, @@ -971,7 +971,7 @@ FXCODEC_STATUS CCodec_ProgressiveDecoder::GifStartDecode( } m_SrcFormat = FXCodec_8bppRgb; GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); - int scanline_size = (m_SrcWidth + 3) / 4 * 4; + int scanline_size = FxAlignToBoundary<4>(m_SrcWidth); m_pDecodeBuf.reset(FX_Alloc(uint8_t, scanline_size)); memset(m_pDecodeBuf.get(), 0, scanline_size); m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, @@ -1211,7 +1211,7 @@ FXCODEC_STATUS CCodec_ProgressiveDecoder::JpegStartDecode( startStatus = pJpegModule->StartScanline(m_pJpegContext.get(), down_scale); } int scanline_size = (m_SrcWidth + down_scale - 1) / down_scale; - scanline_size = (scanline_size * m_SrcComponents + 3) / 4 * 4; + scanline_size = FxAlignToBoundary<4>(scanline_size * m_SrcComponents); m_pDecodeBuf.reset(FX_Alloc(uint8_t, scanline_size)); memset(m_pDecodeBuf.get(), 0, scanline_size); m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, @@ -1435,7 +1435,7 @@ FXCODEC_STATUS CCodec_ProgressiveDecoder::PngStartDecode( } } GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); - int scanline_size = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; + int scanline_size = FxAlignToBoundary<4>(m_SrcWidth * m_SrcComponents); m_pDecodeBuf.reset(FX_Alloc(uint8_t, scanline_size)); memset(m_pDecodeBuf.get(), 0, scanline_size); m_WeightHorzOO.Calc(m_sizeX, m_clipBox.Width()); diff --git a/core/fxcodec/jbig2/JBig2_Image.cpp b/core/fxcodec/jbig2/JBig2_Image.cpp index 1194b1a402..a2d9f486e1 100644 --- a/core/fxcodec/jbig2/JBig2_Image.cpp +++ b/core/fxcodec/jbig2/JBig2_Image.cpp @@ -44,7 +44,7 @@ CJBig2_Image::CJBig2_Image(int32_t w, int32_t h) { if (w <= 0 || h <= 0 || w > kMaxImagePixels) return; - int32_t stride_pixels = (w + 31) & ~31; + int32_t stride_pixels = FxAlignToBoundary<32>(w); if (h > kMaxImagePixels / stride_pixels) return; diff --git a/core/fxcrt/cfx_bitstream.cpp b/core/fxcrt/cfx_bitstream.cpp index 3d3040d96a..d16fc2f1a4 100644 --- a/core/fxcrt/cfx_bitstream.cpp +++ b/core/fxcrt/cfx_bitstream.cpp @@ -8,6 +8,7 @@ #include +#include "core/fxcrt/fx_memory.h" #include "core/fxcrt/fx_system.h" CFX_BitStream::CFX_BitStream(pdfium::span pData) @@ -18,7 +19,7 @@ CFX_BitStream::CFX_BitStream(pdfium::span pData) CFX_BitStream::~CFX_BitStream() {} void CFX_BitStream::ByteAlign() { - m_BitPos = (m_BitPos + 7) & ~7; + m_BitPos = FxAlignToBoundary<8>(m_BitPos); } uint32_t CFX_BitStream::GetBits(uint32_t nBits) { diff --git a/core/fxcrt/fx_memory.h b/core/fxcrt/fx_memory.h index 707e084211..b39911269b 100644 --- a/core/fxcrt/fx_memory.h +++ b/core/fxcrt/fx_memory.h @@ -130,6 +130,13 @@ inline void FX_Free(void* ptr) { template char (&ArraySizeHelper(T (&array)[N]))[N]; +// Round up to the power-of-two boundary N. +template +inline T FxAlignToBoundary(T size) { + static_assert(N > 0 && (N & (N - 1)) == 0, "Not non-zero power of two"); + return (size + N - 1) & ~(N - 1); +} + // Used with std::unique_ptr to FX_Free raw memory. struct FxFreeDeleter { inline void operator()(void* ptr) const { FX_Free(ptr); } diff --git a/core/fxcrt/fx_memory_unittest.cpp b/core/fxcrt/fx_memory_unittest.cpp index 8c577835d6..eab11113cd 100644 --- a/core/fxcrt/fx_memory_unittest.cpp +++ b/core/fxcrt/fx_memory_unittest.cpp @@ -83,3 +83,26 @@ TEST(fxcrt, DISABLED_FXMEM_DefaultOOM) { EXPECT_FALSE(FXMEM_DefaultRealloc(ptr, kMaxByteAlloc)); FXMEM_DefaultFree(ptr); } + +TEST(fxcrt, FXAlign) { + static_assert(std::numeric_limits::max() % 2 == 1, + "numeric limit must be odd for this test"); + + size_t s0 = 0; + size_t s1 = 1; + size_t s2 = 2; + size_t sbig = std::numeric_limits::max() - 2; + EXPECT_EQ(0u, FxAlignToBoundary<2>(s0)); + EXPECT_EQ(2u, FxAlignToBoundary<2>(s1)); + EXPECT_EQ(2u, FxAlignToBoundary<2>(s2)); + EXPECT_EQ(std::numeric_limits::max() - 1, FxAlignToBoundary<2>(sbig)); + + int i0 = 0; + int i511 = 511; + int i512 = 512; + int ineg = -513; + EXPECT_EQ(0, FxAlignToBoundary<512>(i0)); + EXPECT_EQ(512, FxAlignToBoundary<512>(i511)); + EXPECT_EQ(512, FxAlignToBoundary<512>(i512)); + EXPECT_EQ(-512, FxAlignToBoundary<512>(ineg)); +} diff --git a/core/fxge/dib/cfx_imagestretcher.cpp b/core/fxge/dib/cfx_imagestretcher.cpp index 809d3b12dd..ea4dcaea49 100644 --- a/core/fxge/dib/cfx_imagestretcher.cpp +++ b/core/fxge/dib/cfx_imagestretcher.cpp @@ -160,10 +160,11 @@ bool CFX_ImageStretcher::StartQuickStretch() { return false; size *= m_DestBPP; - m_pScanline.reset(FX_Alloc(uint8_t, (size / 8 + 3) / 4 * 4)); - if (m_pSource->m_pAlphaMask) - m_pMaskScanline.reset(FX_Alloc(uint8_t, (m_ClipRect.Width() + 3) / 4 * 4)); - + m_pScanline.reset(FX_Alloc(uint8_t, FxAlignToBoundary<4>(size / 8))); + if (m_pSource->m_pAlphaMask) { + m_pMaskScanline.reset( + FX_Alloc(uint8_t, FxAlignToBoundary<4>(m_ClipRect.Width()))); + } if (SourceSizeWithinLimit(m_pSource->GetWidth(), m_pSource->GetHeight())) { ContinueQuickStretch(nullptr); return false; diff --git a/core/fxge/win32/fx_win32_gdipext.cpp b/core/fxge/win32/fx_win32_gdipext.cpp index 8d361e7c5e..57780344ab 100644 --- a/core/fxge/win32/fx_win32_gdipext.cpp +++ b/core/fxge/win32/fx_win32_gdipext.cpp @@ -525,7 +525,7 @@ RetainPtr StretchMonoToGray( int result_width = pClipRect->Width(); int result_height = pClipRect->Height(); - int result_pitch = (result_width + 3) / 4 * 4; + int result_pitch = FxAlignToBoundary<4>(result_width); auto pStretched = pdfium::MakeRetain(); if (!pStretched->Create(result_width, result_height, FXDIB_8bppRgb)) return nullptr; @@ -620,10 +620,10 @@ void OutputImageMask(GpGraphics* pGraphics, pBitmap->StretchTo(dest_width, dest_height, false, &image_clip); } GpBitmap* bitmap; - CallFunc(GdipCreateBitmapFromScan0)(image_clip.Width(), image_clip.Height(), - (image_clip.Width() + 3) / 4 * 4, - PixelFormat8bppIndexed, - pStretched->GetBuffer(), &bitmap); + CallFunc(GdipCreateBitmapFromScan0)( + image_clip.Width(), image_clip.Height(), + FxAlignToBoundary<4>(image_clip.Width()), PixelFormat8bppIndexed, + pStretched->GetBuffer(), &bitmap); int a; int r; int g; @@ -772,7 +772,7 @@ GpPen* GdipCreatePenImpl(const CFX_GraphStateData* pGraphState, CallFunc(GdipSetPenLineJoin)(pPen, lineJoin); if (!pGraphState->m_DashArray.empty()) { float* pDashArray = - FX_Alloc(float, (pGraphState->m_DashArray.size() + 1) & ~1); + FX_Alloc(float, FxAlignToBoundary<2>(pGraphState->m_DashArray.size())); int nCount = 0; float on_leftover = 0, off_leftover = 0; for (size_t i = 0; i < pGraphState->m_DashArray.size(); i += 2) { -- cgit v1.2.3