| Index: core/fxge/dib/fx_dib_engine.cpp
|
| diff --git a/core/fxge/dib/fx_dib_engine.cpp b/core/fxge/dib/fx_dib_engine.cpp
|
| index 4604f1fc0c7e0b529cfad5d08732cd27bfc07151..3bdff23f1e72008646692d7b058feb6c80cc08b7 100644
|
| --- a/core/fxge/dib/fx_dib_engine.cpp
|
| +++ b/core/fxge/dib/fx_dib_engine.cpp
|
| @@ -6,12 +6,19 @@
|
|
|
| #include <limits.h>
|
|
|
| +#include <algorithm>
|
| +
|
| #include "core/fxge/dib/dib_int.h"
|
| #include "core/fxge/include/fx_dib.h"
|
| #include "core/fxge/include/fx_ge.h"
|
|
|
| namespace {
|
|
|
| +bool SourceSizeWithinLimit(int width, int height) {
|
| + const int kMaxProgressiveStretchPixels = 1000000;
|
| + return !height || width < kMaxProgressiveStretchPixels / height;
|
| +}
|
| +
|
| FXDIB_Format GetStretchedFormat(const CFX_DIBSource& src) {
|
| FXDIB_Format format = src.GetFormat();
|
| if (format == FXDIB_1bppMask)
|
| @@ -770,40 +777,36 @@ void CStretchEngine::StretchVert() {
|
| }
|
| }
|
|
|
| -CFX_ImageStretcher::CFX_ImageStretcher()
|
| - : m_pStretchEngine(nullptr),
|
| - m_pScanline(nullptr),
|
| - m_pMaskScanline(nullptr) {}
|
| +CFX_ImageStretcher::CFX_ImageStretcher(IFX_ScanlineComposer* pDest,
|
| + const CFX_DIBSource* pSource,
|
| + int dest_width,
|
| + int dest_height,
|
| + const FX_RECT& bitmap_rect,
|
| + uint32_t flags)
|
| + : m_pDest(pDest),
|
| + m_pSource(pSource),
|
| + m_Flags(flags),
|
| + m_bFlipX(FALSE),
|
| + m_bFlipY(FALSE),
|
| + m_DestWidth(dest_width),
|
| + m_DestHeight(dest_height),
|
| + m_ClipRect(bitmap_rect),
|
| + m_DestFormat(GetStretchedFormat(*pSource)),
|
| + m_DestBPP(m_DestFormat & 0xff),
|
| + m_LineIndex(0) {}
|
|
|
| CFX_ImageStretcher::~CFX_ImageStretcher() {
|
| - FX_Free(m_pScanline);
|
| - delete m_pStretchEngine;
|
| - FX_Free(m_pMaskScanline);
|
| }
|
|
|
| -FX_BOOL CFX_ImageStretcher::Start(IFX_ScanlineComposer* pDest,
|
| - const CFX_DIBSource* pSource,
|
| - int dest_width,
|
| - int dest_height,
|
| - const FX_RECT& rect,
|
| - uint32_t flags) {
|
| - if (dest_width == 0 || dest_height == 0)
|
| +FX_BOOL CFX_ImageStretcher::Start() {
|
| + if (m_DestWidth == 0 || m_DestHeight == 0)
|
| return FALSE;
|
|
|
| - m_DestFormat = GetStretchedFormat(*pSource);
|
| - m_DestBPP = m_DestFormat & 0xff;
|
| - m_pDest = pDest;
|
| - m_pSource = pSource;
|
| - m_DestWidth = dest_width;
|
| - m_DestHeight = dest_height;
|
| - m_ClipRect = rect;
|
| - m_Flags = flags;
|
| -
|
| - if (pSource->GetFormat() == FXDIB_1bppRgb && pSource->GetPalette()) {
|
| + if (m_pSource->GetFormat() == FXDIB_1bppRgb && m_pSource->GetPalette()) {
|
| FX_ARGB pal[256];
|
| int a0, r0, g0, b0, a1, r1, g1, b1;
|
| - ArgbDecode(pSource->GetPaletteEntry(0), a0, r0, g0, b0);
|
| - ArgbDecode(pSource->GetPaletteEntry(1), a1, r1, g1, b1);
|
| + ArgbDecode(m_pSource->GetPaletteEntry(0), a0, r0, g0, b0);
|
| + ArgbDecode(m_pSource->GetPaletteEntry(1), a1, r1, g1, b1);
|
| for (int i = 0; i < 256; i++) {
|
| int a = a0 + (a1 - a0) * i / 255;
|
| int r = r0 + (r1 - r0) * i / 255;
|
| @@ -811,14 +814,16 @@ FX_BOOL CFX_ImageStretcher::Start(IFX_ScanlineComposer* pDest,
|
| int b = b0 + (b1 - b0) * i / 255;
|
| pal[i] = ArgbEncode(a, r, g, b);
|
| }
|
| - if (!pDest->SetInfo(rect.Width(), rect.Height(), m_DestFormat, pal)) {
|
| + if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(), m_DestFormat,
|
| + pal)) {
|
| return FALSE;
|
| }
|
| - } else if (pSource->GetFormat() == FXDIB_1bppCmyk && pSource->GetPalette()) {
|
| + } else if (m_pSource->GetFormat() == FXDIB_1bppCmyk &&
|
| + m_pSource->GetPalette()) {
|
| FX_CMYK pal[256];
|
| int c0, m0, y0, k0, c1, m1, y1, k1;
|
| - CmykDecode(pSource->GetPaletteEntry(0), c0, m0, y0, k0);
|
| - CmykDecode(pSource->GetPaletteEntry(1), c1, m1, y1, k1);
|
| + CmykDecode(m_pSource->GetPaletteEntry(0), c0, m0, y0, k0);
|
| + CmykDecode(m_pSource->GetPaletteEntry(1), c1, m1, y1, k1);
|
| for (int i = 0; i < 256; i++) {
|
| int c = c0 + (c1 - c0) * i / 255;
|
| int m = m0 + (m1 - m0) * i / 255;
|
| @@ -826,14 +831,16 @@ FX_BOOL CFX_ImageStretcher::Start(IFX_ScanlineComposer* pDest,
|
| int k = k0 + (k1 - k0) * i / 255;
|
| pal[i] = CmykEncode(c, m, y, k);
|
| }
|
| - if (!pDest->SetInfo(rect.Width(), rect.Height(), m_DestFormat, pal)) {
|
| + if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(), m_DestFormat,
|
| + pal)) {
|
| return FALSE;
|
| }
|
| - } else if (!pDest->SetInfo(rect.Width(), rect.Height(), m_DestFormat, NULL)) {
|
| + } else if (!m_pDest->SetInfo(m_ClipRect.Width(), m_ClipRect.Height(),
|
| + m_DestFormat, nullptr)) {
|
| return FALSE;
|
| }
|
|
|
| - if (flags & FXDIB_DOWNSAMPLE)
|
| + if (m_Flags & FXDIB_DOWNSAMPLE)
|
| return StartQuickStretch();
|
| return StartStretch();
|
| }
|
| @@ -844,25 +851,23 @@ FX_BOOL CFX_ImageStretcher::Continue(IFX_Pause* pPause) {
|
| return ContinueStretch(pPause);
|
| }
|
|
|
| -#define MAX_PROGRESSIVE_STRETCH_PIXELS 1000000
|
| FX_BOOL CFX_ImageStretcher::StartStretch() {
|
| - m_pStretchEngine =
|
| - new CStretchEngine(m_pDest, m_DestFormat, m_DestWidth, m_DestHeight,
|
| - m_ClipRect, m_pSource, m_Flags);
|
| + m_pStretchEngine.reset(new CStretchEngine(m_pDest, m_DestFormat, m_DestWidth,
|
| + m_DestHeight, m_ClipRect, m_pSource,
|
| + m_Flags));
|
| m_pStretchEngine->StartStretchHorz();
|
| - if (m_pSource->GetWidth() * m_pSource->GetHeight() <
|
| - MAX_PROGRESSIVE_STRETCH_PIXELS) {
|
| - m_pStretchEngine->Continue(NULL);
|
| + if (SourceSizeWithinLimit(m_pSource->GetWidth(), m_pSource->GetHeight())) {
|
| + m_pStretchEngine->Continue(nullptr);
|
| return FALSE;
|
| }
|
| return TRUE;
|
| }
|
| +
|
| FX_BOOL CFX_ImageStretcher::ContinueStretch(IFX_Pause* pPause) {
|
| return m_pStretchEngine && m_pStretchEngine->Continue(pPause);
|
| }
|
| +
|
| FX_BOOL CFX_ImageStretcher::StartQuickStretch() {
|
| - m_bFlipX = FALSE;
|
| - m_bFlipY = FALSE;
|
| if (m_DestWidth < 0) {
|
| m_bFlipX = TRUE;
|
| m_DestWidth = -m_DestWidth;
|
| @@ -871,31 +876,32 @@ FX_BOOL CFX_ImageStretcher::StartQuickStretch() {
|
| m_bFlipY = TRUE;
|
| m_DestHeight = -m_DestHeight;
|
| }
|
| - m_LineIndex = 0;
|
| uint32_t size = m_ClipRect.Width();
|
| if (size && m_DestBPP > (int)(INT_MAX / size)) {
|
| return FALSE;
|
| }
|
| size *= m_DestBPP;
|
| - m_pScanline = FX_Alloc(uint8_t, (size / 8 + 3) / 4 * 4);
|
| - if (m_pSource->m_pAlphaMask) {
|
| - m_pMaskScanline = FX_Alloc(uint8_t, (m_ClipRect.Width() + 3) / 4 * 4);
|
| - }
|
| - if (m_pSource->GetWidth() * m_pSource->GetHeight() <
|
| - MAX_PROGRESSIVE_STRETCH_PIXELS) {
|
| - ContinueQuickStretch(NULL);
|
| + 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));
|
| +
|
| + if (SourceSizeWithinLimit(m_pSource->GetWidth(), m_pSource->GetHeight())) {
|
| + ContinueQuickStretch(nullptr);
|
| return FALSE;
|
| }
|
| return TRUE;
|
| }
|
| +
|
| FX_BOOL CFX_ImageStretcher::ContinueQuickStretch(IFX_Pause* pPause) {
|
| - if (!m_pScanline) {
|
| + if (!m_pScanline)
|
| return FALSE;
|
| - }
|
| - int result_width = m_ClipRect.Width(), result_height = m_ClipRect.Height();
|
| +
|
| + int result_width = m_ClipRect.Width();
|
| + int result_height = m_ClipRect.Height();
|
| int src_height = m_pSource->GetHeight();
|
| for (; m_LineIndex < result_height; m_LineIndex++) {
|
| - int dest_y, src_y;
|
| + int dest_y;
|
| + int src_y;
|
| if (m_bFlipY) {
|
| dest_y = result_height - m_LineIndex - 1;
|
| src_y = (m_DestHeight - (dest_y + m_ClipRect.top) - 1) * src_height /
|
| @@ -904,23 +910,20 @@ FX_BOOL CFX_ImageStretcher::ContinueQuickStretch(IFX_Pause* pPause) {
|
| dest_y = m_LineIndex;
|
| src_y = (dest_y + m_ClipRect.top) * src_height / m_DestHeight;
|
| }
|
| - if (src_y >= src_height) {
|
| - src_y = src_height - 1;
|
| - }
|
| - if (src_y < 0) {
|
| - src_y = 0;
|
| - }
|
| - if (m_pSource->SkipToScanline(src_y, pPause)) {
|
| + src_y = std::max(std::min(src_y, src_height - 1), 0);
|
| +
|
| + if (m_pSource->SkipToScanline(src_y, pPause))
|
| return TRUE;
|
| - }
|
| - m_pSource->DownSampleScanline(src_y, m_pScanline, m_DestBPP, m_DestWidth,
|
| - m_bFlipX, m_ClipRect.left, result_width);
|
| +
|
| + m_pSource->DownSampleScanline(src_y, m_pScanline.get(), m_DestBPP,
|
| + m_DestWidth, m_bFlipX, m_ClipRect.left,
|
| + result_width);
|
| if (m_pMaskScanline) {
|
| m_pSource->m_pAlphaMask->DownSampleScanline(
|
| - src_y, m_pMaskScanline, 1, m_DestWidth, m_bFlipX, m_ClipRect.left,
|
| - result_width);
|
| + src_y, m_pMaskScanline.get(), 1, m_DestWidth, m_bFlipX,
|
| + m_ClipRect.left, result_width);
|
| }
|
| - m_pDest->ComposeScanline(dest_y, m_pScanline, m_pMaskScanline);
|
| + m_pDest->ComposeScanline(dest_y, m_pScanline.get(), m_pMaskScanline.get());
|
| }
|
| return FALSE;
|
| }
|
|
|