summaryrefslogtreecommitdiff
path: root/core/fxge/dib
diff options
context:
space:
mode:
Diffstat (limited to 'core/fxge/dib')
-rw-r--r--core/fxge/dib/fx_dib_engine.cpp137
-rw-r--r--core/fxge/dib/fx_dib_main.cpp40
-rw-r--r--core/fxge/dib/fx_dib_transform.cpp94
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;
}