diff options
Diffstat (limited to 'core/fxge/dib')
-rw-r--r-- | core/fxge/dib/fx_dib_engine.cpp | 137 | ||||
-rw-r--r-- | core/fxge/dib/fx_dib_main.cpp | 40 | ||||
-rw-r--r-- | core/fxge/dib/fx_dib_transform.cpp | 94 |
3 files changed, 142 insertions, 129 deletions
diff --git a/core/fxge/dib/fx_dib_engine.cpp b/core/fxge/dib/fx_dib_engine.cpp index 4604f1fc0c..3bdff23f1e 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; } diff --git a/core/fxge/dib/fx_dib_main.cpp b/core/fxge/dib/fx_dib_main.cpp index f781392e67..bf8dd4ecd5 100644 --- a/core/fxge/dib/fx_dib_main.cpp +++ b/core/fxge/dib/fx_dib_main.cpp @@ -1608,9 +1608,9 @@ FX_BOOL CFX_ImageRenderer::Start(CFX_DIBitmap* pDevice, m_ClipBox = pClipRgn ? pClipRgn->GetBox() : FX_RECT(0, 0, pDevice->GetWidth(), pDevice->GetHeight()); m_ClipBox.Intersect(image_rect); - if (m_ClipBox.IsEmpty()) { + if (m_ClipBox.IsEmpty()) return FALSE; - } + m_pDevice = pDevice; m_pClipRgn = pClipRgn; m_MaskColor = mask_color; @@ -1621,7 +1621,7 @@ FX_BOOL CFX_ImageRenderer::Start(CFX_DIBitmap* pDevice, m_pIccTransform = pIccTransform; m_bRgbByteOrder = bRgbByteOrder; m_BlendType = blend_type; - FX_BOOL ret = TRUE; + if ((FXSYS_fabs(m_Matrix.b) >= 0.5f || m_Matrix.a == 0) || (FXSYS_fabs(m_Matrix.c) >= 0.5f || m_Matrix.d == 0)) { if (FXSYS_fabs(m_Matrix.a) < FXSYS_fabs(m_Matrix.b) / 20 && @@ -1636,10 +1636,12 @@ FX_BOOL CFX_ImageRenderer::Start(CFX_DIBitmap* pDevice, m_Composer.Compose(pDevice, pClipRgn, bitmap_alpha, mask_color, m_ClipBox, TRUE, m_Matrix.c > 0, m_Matrix.b < 0, m_bRgbByteOrder, alpha_flag, pIccTransform, m_BlendType); - if (!m_Stretcher.Start(&m_Composer, pSource, dest_height, dest_width, - bitmap_clip, dib_flags)) { + m_Stretcher.reset(new CFX_ImageStretcher(&m_Composer, pSource, + dest_height, dest_width, + bitmap_clip, dib_flags)); + if (!m_Stretcher->Start()) return FALSE; - } + m_Status = 1; return TRUE; } @@ -1648,31 +1650,33 @@ FX_BOOL CFX_ImageRenderer::Start(CFX_DIBitmap* pDevice, m_pTransformer->Start(pSource, &m_Matrix, dib_flags, &m_ClipBox); return TRUE; } + int dest_width = image_rect.Width(); - if (m_Matrix.a < 0) { + if (m_Matrix.a < 0) dest_width = -dest_width; - } + int dest_height = image_rect.Height(); - if (m_Matrix.d > 0) { + if (m_Matrix.d > 0) dest_height = -dest_height; - } - if (dest_width == 0 || dest_height == 0) { + + if (dest_width == 0 || dest_height == 0) return FALSE; - } + FX_RECT bitmap_clip = m_ClipBox; bitmap_clip.Offset(-image_rect.left, -image_rect.top); m_Composer.Compose(pDevice, pClipRgn, bitmap_alpha, mask_color, m_ClipBox, FALSE, FALSE, FALSE, m_bRgbByteOrder, alpha_flag, pIccTransform, m_BlendType); m_Status = 1; - ret = m_Stretcher.Start(&m_Composer, pSource, dest_width, dest_height, - bitmap_clip, dib_flags); - return ret; + m_Stretcher.reset(new CFX_ImageStretcher( + &m_Composer, pSource, dest_width, dest_height, bitmap_clip, dib_flags)); + return m_Stretcher->Start(); } + FX_BOOL CFX_ImageRenderer::Continue(IFX_Pause* pPause) { - if (m_Status == 1) { - return m_Stretcher.Continue(pPause); - } + if (m_Status == 1) + return m_Stretcher->Continue(pPause); + if (m_Status == 2) { if (m_pTransformer->Continue(pPause)) { return TRUE; diff --git a/core/fxge/dib/fx_dib_transform.cpp b/core/fxge/dib/fx_dib_transform.cpp index 18adcea5d2..6aaaac2cb7 100644 --- a/core/fxge/dib/fx_dib_transform.cpp +++ b/core/fxge/dib/fx_dib_transform.cpp @@ -309,33 +309,36 @@ CFX_DIBitmap* CFX_DIBSource::TransformTo(const CFX_Matrix* pDestMatrix, CFX_DIBitmap* pTransformed = transformer.m_Storer.Detach(); return pTransformed; } + CFX_DIBitmap* CFX_DIBSource::StretchTo(int dest_width, int dest_height, uint32_t flags, const FX_RECT* pClip) const { FX_RECT clip_rect(0, 0, FXSYS_abs(dest_width), FXSYS_abs(dest_height)); - if (pClip) { + if (pClip) clip_rect.Intersect(*pClip); - } - if (clip_rect.IsEmpty()) { - return NULL; - } - if (dest_width == m_Width && dest_height == m_Height) { + + if (clip_rect.IsEmpty()) + return nullptr; + + if (dest_width == m_Width && dest_height == m_Height) return Clone(&clip_rect); - } - CFX_ImageStretcher stretcher; + CFX_BitmapStorer storer; - if (stretcher.Start(&storer, this, dest_width, dest_height, clip_rect, - flags)) { - stretcher.Continue(NULL); - } + CFX_ImageStretcher stretcher(&storer, this, dest_width, dest_height, + clip_rect, flags); + if (stretcher.Start()) + stretcher.Continue(nullptr); return storer.Detach(); } + CFX_ImageTransformer::CFX_ImageTransformer() { m_Status = 0; m_pMatrix = NULL; } + CFX_ImageTransformer::~CFX_ImageTransformer() {} + FX_BOOL CFX_ImageTransformer::Start(const CFX_DIBSource* pSrc, const CFX_Matrix* pDestMatrix, int flags, @@ -344,12 +347,12 @@ FX_BOOL CFX_ImageTransformer::Start(const CFX_DIBSource* pSrc, CFX_FloatRect unit_rect = pDestMatrix->GetUnitRect(); FX_RECT result_rect = unit_rect.GetClosestRect(); FX_RECT result_clip = result_rect; - if (pDestClip) { + if (pDestClip) result_clip.Intersect(*pDestClip); - } - if (result_clip.IsEmpty()) { + + if (result_clip.IsEmpty()) return FALSE; - } + m_ResultLeft = result_clip.left; m_ResultTop = result_clip.top; m_ResultWidth = result_clip.Width(); @@ -363,8 +366,9 @@ FX_BOOL CFX_ImageTransformer::Start(const CFX_DIBSource* pSrc, result_clip.Offset(-result_rect.left, -result_rect.top); result_clip = FXDIB_SwapClipBox(result_clip, dest_width, dest_height, pDestMatrix->c > 0, pDestMatrix->b < 0); - m_Stretcher.Start(&m_Storer, pSrc, dest_height, dest_width, result_clip, - flags); + m_Stretcher.reset(new CFX_ImageStretcher(&m_Storer, pSrc, dest_height, + dest_width, result_clip, flags)); + m_Stretcher->Start(); m_Status = 1; return TRUE; } @@ -375,8 +379,9 @@ FX_BOOL CFX_ImageTransformer::Start(const CFX_DIBSource* pSrc, int dest_height = pDestMatrix->d > 0 ? (int)-FXSYS_ceil(pDestMatrix->d) : (int)-FXSYS_floor(pDestMatrix->d); result_clip.Offset(-result_rect.left, -result_rect.top); - m_Stretcher.Start(&m_Storer, pSrc, dest_width, dest_height, result_clip, - flags); + m_Stretcher.reset(new CFX_ImageStretcher(&m_Storer, pSrc, dest_width, + dest_height, result_clip, flags)); + m_Stretcher->Start(); m_Status = 2; return TRUE; } @@ -395,53 +400,54 @@ FX_BOOL CFX_ImageTransformer::Start(const CFX_DIBSource* pSrc, clip_rect_f.Transform(&m_dest2stretch); m_StretchClip = clip_rect_f.GetOutterRect(); m_StretchClip.Intersect(0, 0, stretch_width, stretch_height); - m_Stretcher.Start(&m_Storer, pSrc, stretch_width, stretch_height, - m_StretchClip, flags); + m_Stretcher.reset(new CFX_ImageStretcher( + &m_Storer, pSrc, stretch_width, stretch_height, m_StretchClip, flags)); + m_Stretcher->Start(); m_Status = 3; return TRUE; } FX_BOOL CFX_ImageTransformer::Continue(IFX_Pause* pPause) { if (m_Status == 1) { - if (m_Stretcher.Continue(pPause)) { + if (m_Stretcher->Continue(pPause)) return TRUE; - } + if (m_Storer.GetBitmap()) { m_Storer.Replace( m_Storer.GetBitmap()->SwapXY(m_pMatrix->c > 0, m_pMatrix->b < 0)); } return FALSE; } - if (m_Status == 2) { - return m_Stretcher.Continue(pPause); - } - if (m_Status != 3) { + + if (m_Status == 2) + return m_Stretcher->Continue(pPause); + + if (m_Status != 3) return FALSE; - } - if (m_Stretcher.Continue(pPause)) { + + if (m_Stretcher->Continue(pPause)) return TRUE; - } + int stretch_width = m_StretchClip.Width(); int stretch_height = m_StretchClip.Height(); - if (!m_Storer.GetBitmap()) { + if (!m_Storer.GetBitmap()) return FALSE; - } + const uint8_t* stretch_buf = m_Storer.GetBitmap()->GetBuffer(); - const uint8_t* stretch_buf_mask = NULL; - if (m_Storer.GetBitmap()->m_pAlphaMask) { + const uint8_t* stretch_buf_mask = nullptr; + if (m_Storer.GetBitmap()->m_pAlphaMask) stretch_buf_mask = m_Storer.GetBitmap()->m_pAlphaMask->GetBuffer(); - } + int stretch_pitch = m_Storer.GetBitmap()->GetPitch(); - CFX_DIBitmap* pTransformed = new CFX_DIBitmap; - FXDIB_Format transformF = GetTransformedFormat(m_Stretcher.m_pSource); - if (!pTransformed->Create(m_ResultWidth, m_ResultHeight, transformF)) { - delete pTransformed; + std::unique_ptr<CFX_DIBitmap> pTransformed(new CFX_DIBitmap); + FXDIB_Format transformF = GetTransformedFormat(m_Stretcher->source()); + if (!pTransformed->Create(m_ResultWidth, m_ResultHeight, transformF)) return FALSE; - } + pTransformed->Clear(0); - if (pTransformed->m_pAlphaMask) { + if (pTransformed->m_pAlphaMask) pTransformed->m_pAlphaMask->Clear(0); - } + CFX_Matrix result2stretch(1.0f, 0.0f, 0.0f, 1.0f, (FX_FLOAT)(m_ResultLeft), (FX_FLOAT)(m_ResultTop)); result2stretch.Concat(m_dest2stretch); @@ -943,6 +949,6 @@ FX_BOOL CFX_ImageTransformer::Continue(IFX_Pause* pPause) { } } } - m_Storer.Replace(pTransformed); + m_Storer.Replace(pTransformed.release()); return FALSE; } |